Reputation: 121
There appear to be a few topics related to this already, but none of their answers seem to quite work for me.
So, I'm building a Wordpress theme and I want it to have the ability to have sub-menus and sub-sub-menus, etc. So I end up with a menu structure a bit like this:
<ul id="menu-main-navigation-menu" class="menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home current-menu-item page_item current_page_item"><a href="" aria-current="page">Home</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Products</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children"><a href="">Services</a>
<ul class="sub-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Basic</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Intermediate</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children"><a href="">Advanced</a>
<ul class="sub-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Advanced Service 1</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="">Advanced Service 2</a></li>
</ul>
</li>
</ul>
</li>
</ul>
So, li's that have child ul's have the class "menu-item-has-children", which is their only distinguishing feature from any other li's.
Now, in jQuery I have tried this:
jQuery(document).on('click','.menu-item-has-children',function(){
jQuery(this).toggleClass('active');
});
But the problem with this is that when I click on a ".menu-item-has-children" that is within a ".menu-item-has-children", I am effectively clicking on both at once, so the sub-sub-menu gets the class ".active" added to it and opens it as it should, but it's parent sub-menu loses it's ".active" class, thereby collapsing both.
My goal is that each time I click on a sub-menu, if it's closed then it should open, or if it's opened it should close. Each time I click on a sub-sub-menu, it should open and close accordingly, but it's parent sub-menu should remain open. This should also work for sub-sub-sub-menus and sub-sub-sub-sub-menus, etc... so I really need a universal solution that will work no matter how deeply nested a sub-menu is.
Upvotes: 0
Views: 736
Reputation: 13840
Take a look at the documentation for event.stopPropagation()
. At a basic level, it prevents the current event from "bubbling up" through parent elements. Here's a super rudimentary example based on the snippets you've provided.
You can also add other checks into your click handler, such as determining whether or not an item has a class, or children - but at a base level, the easiest thing to do is stop propagation through parent elements.
jQuery(document).on('click', '.menu-item-has-children', function(e){
e.stopPropagation();
jQuery(this).toggleClass('active');
});
.menu > li {
display: block;
}
.sub-menu {
display: none;
}
.active > .sub-menu {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="menu-main-navigation-menu" class="menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home current-menu-item page_item current_page_item"><a href="#" aria-current="page">Home</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="#">Products</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children"><a href="#">Services</a>
<ul class="sub-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="#">Basic</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="#">Intermediate</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children"><a href="#">Advanced</a>
<ul class="sub-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="#">Advanced Service 1</a></li>
<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="#">Advanced Service 2</a></li>
</ul>
</li>
</ul>
</li>
</ul>
Upvotes: 1