Question

I'm running into an issue with nested menus not acting the way I'm anticipating. I've looked through a bunch of stuff on StackOverflow regarding stopPropagation(), but it just doesn't seem to be working.

The site is wordpress based, unfortunately, so I don't have direct control of the HTML generated by the menus on the site. The original goal of this project was to add onClick functionality to the menu items, which Wordpress doesn't natively support. That part works - when I click the menus, events fire. Yay! However, the events of the parent element also fires. And that's causing issues (since the onClick functionality was put in place for click tracking).

Here is the first part of the menu, as it renders by wordpress (shortened for readability):

<ul id="menu-main-menu" class="nav-menu">
    <li id="menu-item-104"><a href="#">Learn About Us</a>
        <ul class="sub-menu">
            <li id="menu-item-266" class=""><a href="#">What We Do</a></li>
            <li id="menu-item-268" class=""><a href="#">Company News</a></li>
            <li id="menu-item-269" class=""><a href="#">Our Leadership</a></li>
            <li id="menu-item-557" class=""><a href="#">Recognition</a></li>
            <li id="menu-item-270" class=""><a href="#">Our Heritage</a></li>
            <li id="menu-item-331" class=""><a href="#">Brand Guidelines</a></li>
        </ul>
    </li>
</ul>

Here's the generated jquery code that is appended to the page for the menu:

jQuery(document).ready(function($) {
    $("li#menu-item-104 a").on("click", function(event) { 
        console.log('Learn About Us menu'); 
    });
    $("li#menu-item-266 a").on("click", function(event) { 
        console.log('What We Do menu'); 
    });
    $("li#menu-item-268 a").on("click", function(event) { 
        console.log('Company News menu'); 
    });
    $("li#menu-item-269 a").on("click", function(event) { 
        console.log('Our Leadership menu'); 
    });
    $("li#menu-item-557 a").on("click", function(event) { 
        console.log('Recognition menu'); 
    });
    $("li#menu-item-270 a").on("click", function(event) { 
        console.log('Our Heritage menu'); 
    });
    $("li#menu-item-331 a").on("click", function(event) { 
        console.log('Brand Guidelines menu'); 
    });
});

When I click on any of the child elements (What we do, company news, etc), The onclick event fires successfully AND the parent element also fires.

So, if I were to click on the 'Company News' menu item, the console would contain this:

Learn About Us menu
Company News menu

The kicker is if I add event.stopImmediatePropagation(); to each of the jquery blocks, only the parent element fires. event.stopPropagation(); doesn't seem to have any effect.

What do I need to add to the jQuery to prevent the parent elements from firing when child elements are called?

Was it helpful?

Solution

The problem is you have used descendant selector instead of child selector to target the anchor element.

$("#menu-item-104 > a").on("click", function (event) {
    console.log('Learn About Us menu');
});
$("#menu-item-266 > a").on("click", function (event) {
    console.log('What We Do menu');
});

Demo: Fiddle

When you say li#menu-item-104 a, it binds the click handler to all anchor elements inside li#menu-item-104, which includes the Learn About Us element and all the sub menu items which is resulting in that handler getting called even when you try to stop the propagation.

Now since the first handler is added to all the anchor elements the stopPropagation() will not have any effect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top