0Day Forums
How to make addEventListener 'click' work on two menu items with same class - Printable Version

+- 0Day Forums (https://zeroday.vip)
+-- Forum: Coding (https://zeroday.vip/Forum-Coding)
+--- Forum: CMS (https://zeroday.vip/Forum-CMS)
+---- Forum: WordPress (https://zeroday.vip/Forum-WordPress)
+---- Thread: How to make addEventListener 'click' work on two menu items with same class (/Thread-How-to-make-addEventListener-39-click-39-work-on-two-menu-items-with-same-class)



How to make addEventListener 'click' work on two menu items with same class - wunderkind491940 - 07-27-2023

Page:

[To see links please register here]


Here's [a fiddle][1]

The first menu item called "**Behandlinger**" is set up with this JS (courtesy of [biberman][2]) to make the submenu emerge and retract properly.

```js
var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
if (item == parentItem){
return true;
}
item = item.parentNode;
}
return false;
}

menuTrigger.addEventListener('click', function() {
submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
submenu.style.height = 0;
}
});

document.addEventListener('keyup', function(e) {
if ( e.key == 'Escape' ) {
submenu.style.height = 0;
}
});
```

**Why is this not working on mobile?** I wish for the submenu (```.behandlinger-meny```) height set to ```55px``` when the menu item Behandlinger (```.behandlinger-item```) is clicked. It works perfectly, except **not on the menu item click on mobile**.

---

Realized the mobile menu has a ```<nav>``` of its own, which may affect the event listener. I have updated both the fiddle and the simplified structure below as well as the core question. Seems really close to a simple solution now.

Simplified structure:

```css
.behandlinger-meny {
height: 0;
transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
overflow: hidden;
}
```

```html
<div id="wrapper">
<header>

<nav class="main-menu">
<ul>
<li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

<nav class="mobile-main-menu">
<ul>
<li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

</header>

<section> <!-- Separated to follow page scroll -->
<div id="behandlinger"> <!-- Scroll to position on item click -->
<nav class="behandlinger-meny">
<script></script> <!-- Script in question -->
<ul>
<li><a>Sub item 1</a></li>
<li><a>Sub item 2</a></li>
<li><a>Sub item 3</a></li>
</ul>
</nav>
</div>
</section>

<main>

</main>
</div>
```

Runnable version:

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
if (item == parentItem){
return true;
}
item = item.parentNode;
}
return false;
}

menuTrigger.addEventListener('click', function() {
submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
submenu.style.height = 0;
}
});

document.addEventListener('keyup', function(e) {
if ( e.key == 'Escape' ) {
submenu.style.height = 0;
}
});

<!-- language: lang-css -->

.behandlinger-meny {
height: 0;
transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
overflow: hidden;
}

<!-- language: lang-html -->

<div id="wrapper">
<header>

<nav class="main-menu">
<ul>
<li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

<nav class="mobile-main-menu">
<ul>
<li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

</header>

<section> <!-- Separated to follow page scroll -->
<div id="behandlinger"> <!-- Scroll to position on item click -->
<nav class="behandlinger-meny">
<script></script> <!-- Script in question -->
<ul>
<li><a>Sub item 1</a></li>
<li><a>Sub item 2</a></li>
<li><a>Sub item 3</a></li>
</ul>
</nav>
</div>
</section>

<main>

</main>
</div>

<!-- end snippet -->


[1]:

[To see links please register here]

[2]:

[To see links please register here]




RE: How to make addEventListener 'click' work on two menu items with same class - Prosubceiling333 - 07-27-2023

Since you have two triggers and your event listener is only attached to the first with ```querySelector``` the second trigger has no listener.

You can use ```querySelectorAll``` and attach the event listener in a for loop to each selected trigger. Because you want a transition you have to use 'max-height' instead of 'height' since transition doesn't work with height.

For closing the submenu when clicking somewhere else (except trigger or submenu) i made a function *isRelated()* that checks if the click target is the trigger itself, the submenu or a child of both.

**Working example** with multiple triggers (jQuery example below):

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

document.addEventListener('DOMContentLoaded', function() {

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelectorAll('.behandlinger-item');

function isRelated(item, parentSelector) {
while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY') {
parents = document.querySelectorAll(parentSelector);
for (i = 0; i < parents.length; i++) {
if (item == parents[i]) {
return true;
}
}
item = item.parentNode;
}
return false;
}

for (i = 0; i < menuTrigger.length; i++) {
menuTrigger[i].addEventListener('click', function() {
submenu.style.maxHeight = '1000px';
});
}

document.querySelector('body').addEventListener('click', function(e) {
if (!isRelated(e.target, '.behandlinger-item') && !isRelated(e.target, '.behandlinger-meny')) {
submenu.style.maxHeight = 0;
}
});

document.addEventListener('keyup', function(e) {
if (e.key == 'Escape') {
submenu.style.maxHeight = 0;
}
});

});

<!-- language: lang-css -->

header {
display: flex;
}

.behandlinger-meny {
max-height: 0;
width: 150px;
background-color: #ddd;
transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
overflow: hidden;
}

<!-- language: lang-html -->

<div id="wrapper">

<header>
<nav class="main-menu">
<ul>
<li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

<nav class="mobile-main-menu">
<ul>
<li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>

<section>
<div id="behandlinger">
<nav class="behandlinger-meny">
<ul>
<li><a>Sub item 1</a></li>
<li><a>Sub item 2</a></li>
<li><a>Sub item 3</a></li>
</ul>
</nav>
</div>
</section>

<main>

</main>

</div>

<!-- end snippet -->

---
**jQuery example:**

<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

$().ready(function() {

var submenu = $('.behandlinger-meny');

$('.behandlinger-item').on('click', function() {
submenu.css('maxHeight', '1000px');
});

$('body').on('click', function(e) {
if (!$(e.target).parents().is('.behandlinger-item')
&& !$(e.target).parents().is('.behandlinger-meny')) {
submenu.css('maxHeight', 0);
}
});

$(document).on('keyup', function(e) {
if (e.key == 'Escape') {
submenu.css('maxHeight', 0);
}
});

});

<!-- language: lang-css -->

header {
display: flex;
}

.behandlinger-meny {
max-height: 0;
width: 150px;
background-color: #ddd;
transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
overflow: hidden;
}

<!-- language: lang-html -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="wrapper">

<header>
<nav class="main-menu">
<ul>
<li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>

<nav class="mobile-main-menu">
<ul>
<li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>

<section>
<div id="behandlinger">
<nav class="behandlinger-meny">
<ul>
<li><a>Sub item 1</a></li>
<li><a>Sub item 2</a></li>
<li><a>Sub item 3</a></li>
</ul>
</nav>
</div>
</section>

<main>

</main>

</div>

<!-- end snippet -->