I am doing an exercise and have the below html code in which I am trying to add an event listener for Element 1, Element 2, Element 3 and Element 4 to be printed when mouseover. I don’t want the event to be triggered when over their submenus (eg 2.1,4.1 etc..)
<div>
<ul>
<li>Element 1</li>
<li>Element 2
<ul>
<li>Element 2.1</li>
<li>Element 2.2</li>
<li>Element 2.3</li>
<li>Element 2.4</li>
</ul>
</li>
<li>Element 3</li>
<li>Element 4
<ul>
<li>Element 4.1</li>
<li>Element 4.2</li>
<li>Element 4.3</li>
<li>Element 4.4</li>
</ul>
</li>
</ul>
</div>
The event is being triggered no matter which element I hover over, including submenus. I have used below code:
const mainElems = document.querySelectorAll('div > ul > li:not(ul)')
function show(element, event) {
event.stopPropagation();
console.log(element.innerText);
}
mainElems.forEach(element => {
element.addEventListener("mouseover", (event) => show(element, event));
});
I suspect it is because Element 2 and 4 wrap their entire contents with the a single li…does that sound right?
Is my attempt to select the main Elements and exclude their submenus with below code correct?
const mainElems = document.querySelectorAll('div > ul > li:not(ul)')
Why is the event being triggered even when selecting submenus?
2
Answers
This issue you’re facing is due to the event bubbling in the DOM.
To prevent the event from being triggered when hovering over submenus, you can use the
event.target
property to check if the event originated from the mainli
elements or their submenus. Here’s how you can modify your code:Instead of setting up listeners for all elements, you could check to see if element has children and only set listeners for elements without children:
Also see example in codesandbox.