Reputation: 432
I'm having an issue with submenus within submenus showing when you click on the child li.
The issue i'm experiencing is when you click on the child li to open the sub-submenu, it's not adding the relevant class to the sub-submenu. Here's the jQuery i'm using.
$('.menu-item-has-children').on('click', function() {
var submenu = $(this).children('.sub-menu');
if(submenu.hasClass('menu-open')) {
submenu.removeClass('menu-open');
$(this).removeClass('menu-active');
} else {
$('.sub-menu').removeClass('menu-open');
$('li').removeClass('menu-active');
submenu.addClass('menu-open');
$(this).addClass('menu-active');
}
});
I'm thinking it's probably something to do with it trying to remove the 'menu-open' class from all 'sub-menu' classes when you click on a different li, but i'm confused on how to correct this.
Here's a link to my fiddle which will hopefully illustrate my problem in more detail than I can explain.
https://jsfiddle.net/08gckq8n/
Thanks.
Upvotes: 0
Views: 3046
Reputation: 940
There are some issues with the code but you are on the right direction.
The selector of the click event is set to .menu-item-has-children
, in the code there are two elements like this, the upper one in the hierarchy (lets call it "li wrapper") wrap all the menu links and that's a problem if you want to click each element at a time. take a look at the screenshot at right side of the window, the blue part is the li wrapper element area, every time you will click some link in the menu you will also click the li wrapper element, so you will get two elements in the event instead of one.
Now let's take a closer look at the code:
$('.menu-item-has-children').on('click', function() {
var submenu = $(this).children('.sub-menu');
if(submenu.hasClass('menu-open')) {
submenu.removeClass('menu-open');
$(this).removeClass('menu-active');
} else {
$('.sub-menu').removeClass('menu-open');
$('li').removeClass('menu-active');
submenu.addClass('menu-open');
$(this).addClass('menu-active');
}
});
On click of sub .menu-item-has-children
element submenu
variable will be set for two elements, the last one is the li wrapper.
The sub .menu-item-has-children
element get the right class for it and for his child .sub-menu, but after the second element (li wrapper) comes in, it's removing the classes of the first .menu-item-has-children
element and set the classes again to the li wrapper element.
So what to do from here?
first of all you can set the click event selector to .menu-item-has-children a
to get on click only one element at a time and then call to his li parent in the submenu
variable for finding the .sub-menu
children. i prefer to show you shorter and simpler code:
$('body').on('click', '.menu-item-has-children a', function() {
$(this).parent().find('> .sub-menu, .sub-menu.menu-open').toggleClass('menu-open');
});
On click, we search for the children of the element by finding > .sub-menu, .sub-menu.menu-open
, the first is for the direct .sub-menu
child and the second is for closing .sub-menu
children that already open. we use .toggleClass() for switching between the two situations so we don't need to check for check for the class and add extra actions of adding and removing classes:
https://jsfiddle.net/08gckq8n/84/
Upvotes: 1
Reputation: 11533
Part of the issue you are having is that you are trying to run the on('click')
on the li
and all your .sub-menus
are INSIDE the top-level parent li
. So no matter where you click, you're always clicking on the parent (the top most li
), so you're not getting the results you expect.
Another issue you will run into is that you will not be able to open those links once your links are live, as you'll navigate to the page, rather than opening the sub-menus
.
Here's code that simplifies your JS with a toggleClass
and also appends an element to click on.
var $menu_item = $('.menu-item-has-children');
$menu_item.append('<span class="caret"></span>');
$('.caret').click(function() {
$(this).parent().toggleClass('menu-open');
});
li {
position: relative;
}
li>.caret {
display: inline-block;
position: absolute;
left: 250px;
top: 0;
z-index: 10;
}
.caret::before {
content: '+';
display: block;
width: 25px;
height: 25px;
text-align: center;
font-size: 18px;
}
li.menu-open>.caret::before {
content: '-';
display: block;
}
.sub-menu {
display: none;
position: relative;
}
.menu-open>.sub-menu {
display: block;
z-index: 10;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="site-navigation">
<div class="menu-main-menu-container">
<ul id="primary-menu" class="menu">
<li id="menu-item-8" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-8 menu-active">
<a href="#">Root Menu Item</a>
<ul class="sub-menu">
<li id="menu-item-68" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-68">
<a href="#">Subchild item</a>
</li>
<li id="menu-item-67" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-67">
<a href="#">Subchild item</a>
</li>
<li id="menu-item-229" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-229">
<a href="#">Subchild item with submenu</a>
<ul class="sub-menu">
<li id="menu-item-66" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-66">
<a href="#">Sub-subchild item</a>
</li>
<li id="menu-item-65" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-65">
<a href="#">Sub-subchild item</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</nav>
Here's the working fiddle: https://jsfiddle.net/disinfor/anbau0ya/5/
You will have to do a little styling for the .caret
, but this will get you closer to what you want to do.
You can also adjust the output of the WP nav menu to include the caret
, but that's an entirely different question/solution.
Upvotes: 1