0

I have a menu.

I want to add event listener to elements with class "menu-item-has-children"(which should also be a descendant of element with class "mobile-nav")

So I use the following codes:

    function addEventListenerToAll(selector, type, listener)
    {
        [].forEach.call(document.querySelectorAll(selector), function(element) {
            if (element) {
                element.addEventListener(type, listener);
            }
        });
    }
    
        addEventListenerToAll(".mobile-nav .menu-item-has-children", "click", function(event) {
          
          console.log("click event is invoked");
    });

But it seems the code will add the listener to not only the qualified elements, but also the child elements inside the qualified elements.

I embed the codes below. You can see when click "Out customers" item, the child element but not qualified the selector, the "click event is invoked" will also appear. Why?

function addEventListenerToAll(selector, type, listener)
{
    [].forEach.call(document.querySelectorAll(selector), function(element) {
        if (element) {
            element.addEventListener(type, listener);
        }
    });
}
    
addEventListenerToAll(".mobile-nav .menu-item-has-children", "click", function(event) {
    console.log("click event is invoked");
});
.mobile-nav .menu-item-has-children {
    background:green;
}
<nav class="main-navigation mobile-nav" role="navigation" style="display: block;">
    <ul id="menu-main-menu" class="sf-menu mobile-menu">
        <li id="menu-item-1294" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1294">
            <a href="https://www.sybase-recovery.com/company/">
                Company
                <svg class="my-svg-inline--fa my-fa-w-10"><use href="/images/icons/icons.svg#facebook-f"></use></svg>
            </a>
            <ul class="sub-menu" style="display: block;">
                <li id="menu-item-433" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-433">
                    <a href="https://www.sybase-recovery.com/our-customers/">Our Customers</a>
                </li>
            </ul>
        </li>
    </ul>
</nav>
Dai
  • 141,631
  • 28
  • 261
  • 374
alancc
  • 487
  • 2
  • 24
  • 68
  • add `.mobile-nav .menu-item-has-children { background:green; }` style - now you'll see the area your click handler handles – Jaromanda X Jul 04 '23 at 06:07
  • 4
    If you click on a child of an element with a click handler, have you clicked on the handler? I would say yes. It's like visiting LA. Have you also visited the US? Yes. This is just event bubbling. – somethinghere Jul 04 '23 at 06:37
  • @JaromandaX funnily enough, this exact snippet proves this is not the case. The `
  • `'s disc ::marker will also be a target to click events, but it's not part of the element's border-box. Similarly, if the element had a positioned descendant that would put it outside of the element, the events on that descendant would still bubble up **the DOM** until the `
  • `.
  • – Kaiido Jul 04 '23 at 06:54
  • Many events like `click` are propagating. If you only want to handle events that happen on the element directly you need to check the event target, that the target where the event currently is at mtches the element where the event handler is attached at (`e.target !== e.currentTarget`): [How to have click event ONLY fire on parent DIV, not children?](https://stackoverflow.com/questions/9183381/how-to-have-click-event-only-fire-on-parent-div-not-children) – t.niese Jul 04 '23 at 06:57
  • You need to delegate "click" events by creating conditions in which only the desired elements on the event chain react to a "click" event whilst the excluding the undesirable elements by ignoring then. It's best to use `event.target` to single out the clicked element and `.matches()` as the condition. Read about [event delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation). – zer00ne Jul 04 '23 at 06:58
  • @Kaiido - sure, but perhaps OP wasn't aware of how big the clickable area was – Jaromanda X Jul 04 '23 at 07:00