I am working on a navigation menu with nested sub menus. I was wondering if there is a way I can achieve the menus to be expandable when I click the parent menu item
This is my HTML code, as you guys can see I have 2 ng-repeat inside the parent menu item and another one if the sub menu item has one or more sub menus
<div id="sidebar-wrapper" ng-controller="navigationController" style="overflow-y: auto; margin-top:-20px;" class="hidden-print" ng-hide="hideSidebar()">
<nav role="navigation" class="navbar navbar-default navbar-bigfont" style="border-width: 0">
<ul class="nav nav-pills nav-stacked">
<li class="portal-text-19b" ng-repeat="item in newMenu" ng-class="{active: hightlight === item.title && item.path !== '#'}" ng-show="showItem(item.path, item.allowAll)">
<a style="text-transform: uppercase" href="{{item.path}}" ng-click="item.fn()">
<span class="{{item.icon}}"></span> {{item.title}}
<span style="font-size: 7px;" ng-if="item.childs" class="glyphicon glyphicon-play"></span>
</a>
<ul class="nav nav-pills nav-stacked">
<li style="list-style-type: none;" ng-repeat="child in item.childs" ng-class="{active: hightlight === child.title && child.path !== '#'}" ng-show="showItem(child.path, child.allowAll)">
<a href="{{child.path}}" ng-click="child.fn()">
<span class="{{child.icon}}"></span> {{child.title}}
</a>
<ul class="nav nav-pills nav-stacked">
<li style="list-style-type: none;" ng-repeat="child2 in child.childs" ng-class="{active: hightlight === child2.title && child2.path !== '#'}" ng-show="showItem(child2.path, child2.allowAll)">
<a href="{{child2.path}}" ng-click="child2.fn()">
<span class="{{child2.icon}}"></span> {{child2.title}}
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
You can simply set the inner ul elements as hidden, and then use the following code to show/hide them:
$("ul li").has("ul").click(function() {
$(this).find("ul").toggle();
});
This will toggle hiding and showing the sub ul elements on their parent li click.
Explanation:
It uses .has() method to attach the click event handler to only li having ul children, and .toggle() method to show/hide the child list of the clicked li element.
Demo:
This is a working Demo Snippet:
$("ul li").has("ul").click(function() {
$(this).find("ul").toggle();
});
ul li {
cursor: pointer;
}
ul li ul {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>list item 1</li>
<li>list item 2
<ul>
<li>list item 2-a</li>
<li>list item 2-b</li>
</ul>
</li>
<li>list item 3</li>
<li>list item 4</li>
</ul>
Related
I have this menu of elements, what is the best approach to change the last div element from hidden to visible when one of the elements with class closed changes to open using Jquery, What i want is when i click on one of the li and change it from closed to , i want to change the dynamic ul to display none or block, do i need to loop over all the elements and check their class?
<ul class="groupmenu">
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
</ul>
<div class="dynamic hidden"></div>
First of all, your ul.level1 elements should be wrapped in li elements.
Then, on click of a li.closed element, you could :
toggle the visibility of its ul.level1 child element.
toggle the visibility of your div.dynamic element using !$("ul.level1:not(.hidden)").length. It will return a boolean whose value will be false if there is at least 1 ul.level1 element that does not have the .hidden class. Otherwise it will return true.
$("li.closed").click(function() {
$(this).find("ul.level1").toggleClass("hidden");
$("div.dynamic").toggleClass("hidden",!$("ul.level1:not(.hidden)").length);
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="groupmenu">
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
</ul>
<div class="dynamic hidden">
dynamic
</div>
I'm creating a sub menu using jquery. I have made the code as below. But there is still something that is not working properly. What I want is, when the start, the menu is closed. Currently, all menus are open. How do I do it, can anyone help me?
$('.list-menu > li').click(function () {
var child = $(this).children('ul');
if(child.length===0){
$(this).children().addClass("active");
return;
}
$('.list-menu ul').not(child).slideUp('normal');
child.slideDown('normal');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list-menu">
<li class="menu-1">
Getting Started
<ul class="submenu">
<li id="sub-1">Child 1
</li>
<li id="sub-2">Child 2
</li>
</ul>
</li>
<li class="menu-2">
Controlling How Data is Indexed
<ul class="submenu">
<li id="sub-3">Child 1
</li>
<li id="sub-4">Child 2
</li>
</ul>
</li>
<li class="menu-3">
Uploading and Indexing Data
<ul class="submenu">
<li id="sub-5">Child 1
</li>
<li id="sub-6">Child 2
</li>
</ul>
</li>
<li>
<a href="#">
Querying For More Information
</a>
</li>
</ul>
You can set the child ul elements to display: none on page load using CSS:
ul > li > ul { display: none; }
$('.list-menu > li').click(function() {
var child = $(this).children('ul');
$(this).children().addClass("active");
$('.list-menu ul').not(child).slideUp('normal');
child.slideToggle('normal');
});
ul > li > ul { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list-menu">
<li class="menu-1">
Getting Started
<ul class="submenu">
<li id="sub-1">Child 1
</li>
<li id="sub-2">Child 2
</li>
</ul>
</li>
<li class="menu-2">
Controlling How Data is Indexed
<ul class="submenu">
<li id="sub-3">Child 1
</li>
<li id="sub-4">Child 2
</li>
</ul>
</li>
<li class="menu-3">
Uploading and Indexing Data
<ul class="submenu">
<li id="sub-5">Child 1
</li>
<li id="sub-6">Child 2
</li>
</ul>
</li>
<li>
Querying For More Information
</li>
</ul>
Wondering if anyone can help, please.
I've got some jQuery setup for my sub-menu in WordPress. It works perfectly until I have a sub-menu within a sub-menu. The classes don't change in WordPress so the jQuery no longer works.
Here's my jQuery:
$('.mobile li > .sub-menu').parent().click(function() {
$(".sub-menu").slideUp();
var submenu = $(this).children('.sub-menu');
if ( $(submenu).is(':hidden') ) {
$(submenu).slideDown(200);
} else {
$(submenu).slideUp(200);
}
});
Here's an example of how WordPress outputs the menu code:
<ul id="menu-main-menu" class="mobile">
<li>
Item
<ul class="sub-menu">
<li>
Item
<ul class="sub-menu">
<li>
Item
</li>
</ul>
</li>
</ul>
</li>
</ul>
Any ideas of how to amend my code? Currently when I click the item within the two sub-menu then the parent sub-menu closes.
Try with this simplified handler:
$('.mobile li > a').click(function() {
$(this).siblings('.sub-menu').slideToggle(200);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="menu-main-menu" class="mobile">
<li>
Item
<ul class="sub-menu">
<li>
Item
<ul class="sub-menu">
<li>
Item
</li>
</ul>
</li>
</ul>
</li>
</ul>
I have to change my html code by javascript.
I want to add span tag for a tag if it contains has-children in class for li tag
<span> <a></a> <span class="sub-menu-toggle"></span></span>
it is my code that I can change first step li.has-children
how can I change all ? class=has-children
$('.has-children').each(function(i, e) {
var aTag = $(this).find('a')[0].outerHTML;
var ulTag = $(this).find('ul')[0].outerHTML;
$(this).html('<span>' + aTag + '<span class="sub-menu-toggle"></span></span>' + ulTag);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="site-menu">
<ul style="display: none">
<li class="has-children">
Menu
<ul class="sub-menu">
<li class="has-children">
First Sub Menu
<ul class="sub-menu">
<li class="">
Second Sub Menu
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
How about this?
Use a better selector
wrap
after
$('.has-children>a').each(function() {
$(this).wrap('<span/>')
.after('<span class="sub-menu-toggle"/>');
});
a { text-decoration: none }
span a { text-decoration: underline }
.sub-menu-toggle::after { content: " ʘ" }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="site-menu">
<ul style="display">
<li class="has-children">
Menu
<ul class="sub-menu">
<li class="has-children">
First Sub Menu
<ul class="sub-menu">
<li class="">
Second Sub Menu
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
when i am trying to add toggle function to the child nodes nothing is happening could you help me out.
$(document).ready(function() {
$('label.tree-toggler').click(function() {
$(this).parent().children('ul.tree').toggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav nav-list">
<li><label class="tree-toggler nav-header">WorkLoad</label>
<ul class="nav nav-list tree">
<li><label class="tree1">DME Report</label>
<ul class="tree1">
<li>
Report1
Report2
</li>
</ul>
</li>
<li>CAMB Report</li>
<li>LMAB Report</li>
<li>DMF Notification</li>
<li>LME Forecast Report</li>
</ul>
</li>
</ul>
You can make this work in a generic way by attaching the click event handler only to li elements which have child ul using the :has selector. Then you can toggle() those ul within the click handler.
Also note the handler will need to call stopPropagation() on the event to stop the parent li from closing their child ul elements too. Try this:
$(document).ready(function() {
$('ul > li:has(ul)').click(function(e) {
e.stopPropagation();
$(this).find('> ul').toggle(300);
});
});
ul > li > ul {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav nav-list">
<li>
<label class="nav-header">WorkLoad</label>
<ul class="nav nav-list tree">
<li>
<label class="tree1">DME Report</label>
<ul class="tree1">
<li>
Report1
Report2
</li>
</ul>
</li>
<li>CAMB Report</li>
<li>LMAB Report</li>
<li>DMF Notification</li>
<li>LME Forecast Report</li>
</ul>
</li>
</ul>
This would allow to simplify the above code to:
The code below mostly works as intended, ...
$(document).ready(function() {
$('label.tree-toggler, label.tree1').click(function() {
$(this).parent().children('ul.tree , ul.tree1').toggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav nav-list">
<li><label class="tree-toggler nav-header">WorkLoad</label>
<ul class="nav nav-list tree">
<li><label class="tree1">DME Report</label>
<ul class="tree1">
<li>
Report1
Report2
</li>
</ul>
</li>
<li>CAMB Report</li>
<li>LMAB Report</li>
<li>DMF Notification</li>
<li>LME Forecast Report</li>
</ul>
</li>
</ul>