avoid closing the menu if submenu items is clicked - javascript

This is a multilevel menu. When i click the link "About" it opens the submenu which contains 3 links Johnny, Julie & Jamie.
When i click "About" again, it closes the menu. Clicking the submenu also closes the menu, and that i want to avoid.
How do i avoid closing the opened submenu, if i click the submenu (Johnny, Julie & Jamie) ?
$('li.parent').click(function() {
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>

Alternative to stopPropagation approach for child elements would be adding a small check if the clicked element is the current one (and not it's descendants):
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>

You need to stopPropagation of event on child anchor elements:
$("li.parent a").click(function(e) {
e.stopPropagation();
});

You need to prevent the click on the .sub-nav element to be transmitted to your event handler: https://api.jquery.com/event.stoppropagation/

Related

Display sub menu with javascript

I designed a menu for WordPress as follows:
HTML:
<aside class="menu">
<ul>
<li>
Main
<ul>
<li>
**** Under the first menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
<ul>
<li>
**** Under the second menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
</li>
</li>
</ul>
</li>
</li>
</ul>
</li>
</ul>
<aside>
CSS:
.menu > ul > li > ul {
display: none;
}
And using this script code, I have defined a condition that by clicking on li, if there is ul in it, it will be displayed:
$('.menu').find('li').click(function(evt) {
evt.stopPropagation();
$(this).children('ul').toggle();
});
This code works fine; But when several other li are used inside the li, the condition I put will no longer work and only the first sub-menu will be displayed.
Is there a way to make my script code work properly?
My problem is only related to the script code.
If you want to just have the 2nd level of the menu visible after opening, you need to do your CSS like this:
.menu > ul > li > ul {
display: none;
}
This way you will be selecting direct children of the elemen, more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator
However, if you also want for the 2nd level of menu to be open on click, you need to move your <ul> and put it directly with your <li>, like this:
<aside class="menu">
<ul>
<li>
Main
<ul>
<li>
**** Under the first menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
<ul>
<li>
**** Under the second menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
</li>
</li>
</ul>
</li>
</li>
</ul>
</li>
</ul>
</aside>
and change your CSS to this:
.menu ul > li > ul {
display: none;
}
You should move the ul content you want to be toggleable into the clickable li:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.menu ul li ul {
display: none;
}
</style>
</head>
<body>
<div id="app"></div>
<aside class="menu">
<ul>
<li>
Main
<ul>
<li>
**** Under the first menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
<ul>
<li>
**** Under the second menu ****
<li>
Content first
</li>
<li>
Content second
</li>
<li>
Content third
</li>
</li>
</ul>
</li>
</li>
</ul>
</li>
</ul>
<aside>
</body>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"
></script>
<script >
$('.menu').find('li').click(function(evt) {
evt.stopPropagation();
$(this).children('ul').toggle();
});
</script>
</html>

How to hide li if ul has no have li with class using jquery or javascript

Im trying to hide li if has no have li
Here html :
<li>
My Profile
<ul>
<li>Profile</li>
<li>Edit Profile</li>
</ul>
</li>
<li>
Menu must be hide
<ul>
</ul>
</li>
Get all the ul iterate through them to get the content and if no conetent is available then use parentNode to get the parent li and add class to the parent to hide it
const allULs = document.querySelectorAll("ul");
allULs.forEach(function(a) {
0 === a.innerHTML.trim().length &&
a.parentElement.classList.add("hideParent");
});
.hideParent {
display: none;
}
<li>
My Profile
<ul>
<li>Profile</li>
<li>Edit Profile</li>
</ul>
</li>
<li>
Menu must be hide
<ul>
</ul>
</li>

open one level deep sub-menu, only, on each click using jquery OR javascript

The issue I am having is:
when I click on "menu2", it is showing me sub-menu and all options of sub-menu.
Expected result:
click on "menu2" should open "sub-menu2" only and NO "sub-menu2" options.
click on ""sub-menu2" should open all it's children.
I see there are some question on related to this one but I did not find any question similar to mine.
If you can suggest a way to do this in pure JS/ES that would be great. Currently I am using jQuery.
$('.container > ul > li').on('click', function(){
$('ul',this).toggle(200);
})
div.container > ul ul{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li>menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li>menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</u1>
</li>
</ul>
</li>
</ul>
</div>
YOu just need to use your selector a bit different way, and its done, if need something else, pls let me know
$('.container li').on('click', function(e) {
var ckeckChildVisiblity = $(this).find('>ul').is(':visible');
if (!ckeckChildVisiblity) {
$(this).find('>ul').slideDown();
return false;
} else {
$(this).find('>ul').slideUp();
return false;
}
})
div.container > ul ul{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li>menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li>menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</u1>
</li>
</ul>
</li>
</ul>
</div>
This can be done using toggling immediate children and stop event propagation.
$('.container li').on('click', function(event){
$(this).children("ul").toggle(200)
event.stopPropagation()
})
.menu ul {
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class ="menu">menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li class ="menu">menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>

togggle menu need to open on click and close itself when click the other menu

How can make it make
1- open toggle menu when on click menu (not opened by default)
2- close itself - if click other parent menu
trying to make it work for the project
and i copied from cssdesk
$('.inbox li').click(function(e) {
$('.inbox li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
e.preventDefault();
});
$(document).ready(function () {
$('.tree-toggler').click(function () {
$(this).parent().children('ul.tree').toggle(300);
});
});
<link class="cssdeck" rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" class="cssdeck">
<ul class="inbox-nav nav" style="border-top: 1px solid #eef1f5; margin-top:10px;" >
<li class="">
<a href="javascript:;" id="fldr3">menu 1
</li>
<li class="">
<a data-title="Inbox" data-type="important" href="javascript:;">2nd Menu</a>
</li>
<li class="">
<a data-title="Sent" data-type="sent" href="javascript:;">menu2</a>
</li>
<li class="divider"></li>
<li class="active tree-toggler">
Toggle menu</li>
<ul class="nav nav-list tree">
<li class="">Link</li>
<li class="">Link</li>
</ul>
</li>
</ul>
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
If user click is not neccesary you can do it by CSS, this is an example the 4th menu item has sub menu items
.menu,
.menu-item {
display: inline;
cursor: default;
}
.menu-item.has-subItem {
position: absolute;
}
.menu-item ul {
display: none;
position: absolute;
top: 15px;
left: 0;
padding: 0;
}
.menu-item:hover ul {
display: inline;
}
<ul class='menu'>
<li class='menu-item'>Item 1</li>
<li class='menu-item'>Item 2</li>
<li class='menu-item'>Item 3</li>
<li class='menu-item has-subItem'>Item 4
<ul>
<li class='sub-item'>sub 1</li>
<li class='sub-item'>sub 2</li>
<li class='sub-item'>sub 3</li>
</ul>
</li>
</ul>
In your $('.inbox li').click() function use jquery's .hide() function on the ul.tree element. Since .hide() won't do anything if the element is already hidden, you don't need to check if it needs to be hidden.
(Similarly, you can pull the $this.addClass('active'); statement out of the if, since it simply won't do anything if the class is already added!)

Link with hover dropdown menu for Mobile Devices

I've found an issue I just can't seem to solve.
I've got a navigation, 5 links in total. One of the links has a dropdown menu when you hover over it showing 3 more links.
Fine when a mouse is involved. But when you start using touch devices, the parent link consumes all gestures and taps, and the viewer is shown the dropdown for a fraction of a second before being taken to the parent's link page.
I'm wondering if there's a way of making it so the first touch of the parent link shows the dropdown menu, then a second touch would go to that link. touching anything else would just hide the dropdown.
<ul id="main-menu">
<li>Link</li>
<li>Link</li>
<li>Link
<ul class="sub-menu">
<li>Sub Link</li>
<li>Sub Link</li>
<li>Sub Link</li>
</ul>
</li>
<li>Link</li>
<li>Link</li>
</ul>
Anyone have any ideas? jQuery would be ideal
Something like this perhaps? You may want to customize the behavior of the dropdown, but this shows the basic logic of handling the click events and preventing default behaviour (i.e. following links) if the menu isn't open:
$(function() {
$('#main-menu a').click(function(e) {
var listItem = $(this).closest('li');
if (!listItem.is('.open')) {
// Opening drop-down logic here. e.g. adding 'open' class to <li>
e.preventDefault();
listItem.addClass('open');
}
// Otherwise the default behaviour of the event (clicking the link) will be unaffected
});
});
i have done complete bins for above issue also placed demo link here.
Demo: http://codebins.com/bin/4ldqp72
HTML
<ul id="main-menu">
<li>
<a href="#">
Link
</a>
</li>
<li>
<a href="#">
Link
</a>
</li>
<li>
<a href="#">
Link
</a>
<ul class="sub-menu">
<li>
<a href="#">
Sub Link
</a>
</li>
<li>
<a href="#">
Sub Link
</a>
</li>
<li>
<a href="#">
Sub Link
</a>
</li>
</ul>
</li>
<li>
<a href="#">
Link
</a>
</li>
<li>
<a href="#">
Link
</a>
</li>
</ul>
JQuery
$(function() {
$('ul a').click(function(e) {
$('#main-menu li').removeClass('open');
e.preventDefault();
$(this).closest('li').addClass("open");
var pos = $(this).closest('li.open').offset();
$(this).closest('li.open').find("ul.sub-menu").css('top', pos.top + 'px');
});
});
CSS
#main-menu{
list-style:none;
margin:2px;
padding:2px;
}
li{
border:1px solid #333;
background:#ebcdff;
text-align:center;
width:100px;
}
li:hover{
background:#abcdfd;
}
li:hover a{
color:#ff3322;
}
li a{
text-decoration:none;
color:#2466ff;
}
li.open {
background:#abcdfd;
}
li.open a{
text-decoration:none;
color:#ff3322;
}
ul.sub-menu{
list-style:none;
display:none;
}
li.open > ul{
position:absolute;
left:70px;
display:block;
}
Demo: http://codebins.com/bin/4ldqp72

Categories

Resources