jQuery dropdown menu toggle issue - javascript

When I click on open it toggles all of the submenus. I want to toggle only the exact ul under the li.
$(document).ready(function(){
$(".has-children>a").click(function(event){
event.preventDefault();
});
$('.has-children').click(function() {
$(this).find('>ul').toggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
</ul>
</li>
</ul>

You can achieve this by changing find() to children() to target only direct children of the li.
$(document).ready(function(){
$(".has-children>a").click(function(event){
event.preventDefault();
});
$('.has-children').click(function() {
$(this).children('ul').toggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
</ul>
</li>
</ul>
This however causes a problem where clicking on children of children will close the menu, so instead you can use a tag and the jQuery next() function to toggle instead of children() or find() like this:
$(document).ready(function() {
$(".has-children>a").click(function(event) {
event.preventDefault();
$(this).next().toggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li class="has-children">
open
<ul class="submenu" style="display:none">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
</ul>
</li>
</ul>
This also makes your script much shorter.

Related

JQuery display menu items one at a time

I have a menu with two menu items and I want to use JQuery to display sub-menu for each menu item when the user clicks on menu item.
What happens is both submenues are displayed (where class="dropdown-content"). How can I modify my code to just display the submenu that is
under the menu item clicked. Is there any way to do that without having to specify id?
Below is my menu:
$('.menu-item').on('click', function() {
$('.dropdown-content').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="nav-mobile">
<li class="menu-item">
<img src="images/img1.png"/>
<a class="hide-on-med-and-down white-text" href='#'><span id="lblLinks">Links</span></a>
<ul id="linksdrop" class="dropdown-content">
<li>Link1</li>
<li>Link2</li>
</ul>
</li>
<li class="menu-item">
<img src="images/img2.png"/>
<a class="hide-on-med-and-down white-text" href='#'><span>User</span></a>
<ul id="userdrop" class="dropdown-content">
<li>My Profile</li>
<li>Log Off</li>
</ul>
</li>
</ul>
you need to use children() function to toggle the children of particular DOM
so use $(this).children("ul").toggle(); to accomplish what you are looking for
$('.menu-item').on('click', function() {
$(this).children("ul").toggle();
});
.dropdown-content{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="nav-mobile">
<li class="menu-item">
<img src="images/img1.png"/>
<a class="hide-on-med-and-down white-text" href='#'>
<span id="lblLinks">Links</span></a>
<ul id="linksdrop" class="dropdown-content">
<li>Link1</li>
<li>Link2</li>
</ul>
</li>
<li class="menu-item">
<img src="images/img2.png"/>
<a class="hide-on-med-and-down white-text" href='#'><span>User</span></a>
<ul id="userdrop" class="dropdown-content">
<li>My Profile</li>
<li>Log Off</li>
</ul>
</li>
</ul>
The main problem is you should use this to identify the li you are cliking, and then use find() to traverse downwards along descendants of DOM elements.
$('.menu-item').on('click', function() {
$(this).find(".dropdown-content").toggle();
});
.dropdown-content{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="nav-mobile">
<li class="menu-item">
<img src="images/img1.png"/>
<a class="hide-on-med-and-down white-text" href='#'><span id="lblLinks">Links</span></a>
<ul id="linksdrop" class="dropdown-content">
<li>Link1</li>
<li>Link2</li>
</ul>
</li>
<li class="menu-item">
<img src="images/img2.png"/>
<a class="hide-on-med-and-down white-text" href='#'><span>User</span></a>
<ul id="userdrop" class="dropdown-content">
<li>My Profile</li>
<li>Log Off</li>
</ul>
</li>
</ul>

How to close a collapsed bar when clicking outside my navigation bar?

I have a nested navigation bar in my site, and it already works, however, I want to close the collapsed bar when clicked outside the bar.
Here is the javascript code I have:
$(document).ready(function() {
$('#nav li').click(function() {
//slide up all the link lists
$(this).children('ul').slideToggle();
})
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="collapse navbar-collapse navbar-right" role="navigation">
<ul id="nav" class="nav navbar-nav">
<li class="current">Home
</li>
<li>About
<ul>
<li>Link1
</li>
<li>Link2
</li>
</ul>
</li>
<li>Etc
<ul>
<li>Link1
</li>
<li>Link2
</li>
<li>Link3
</li>
</ul>
</li>
<li>Etc2
<ul>
<li>Link1
</li>
<li>Link2
</li>
<li>Link3
</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</nav>
you can use this code
$('body').on('click touchstart', function(e) {
if ($(".classname").is(":visible")) {
if ($(e.target).closest(".classname").length == 0 && !$(e.target).hasClass('active')) {
closeMobileMenu(menuobj);
}
}
});
What about something like this:
$(document).click(function(event) {
if(!$(event.target).closest('#nav').length) {
$('#nav li').children('ul').slideToggle();
}
});

DOM traversal from a span element inside an anchor to list

I can't figure how to travers the DOM, starting from <span class = "open-menu-link">, I want to reach <ul class="sub-menu"> .
The script
<script> $('.open-menu-link').click(function(e){
alert(e.currentTarget);
});
</script>
return a Object HTMLSpanElement, but if I code e.currentTarget.parentNode; it returns http://localhost/mysite/home.php. Doing e.currentTarget.children; I get Object HTMLCollection, but if I try e.currentTarget.children[1] I get undefined... so how can I reach <ul class="sub-menu">?
The snippet is the follow:
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
$(function() {
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">
Haschildren <span class="open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
There are couple of options:
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
The <span class = "open-menu-link"> in your code has only one child i.e text node + this is the reason why e.currentTarget.children[1] is giving you undefined.
Coming to the dom traversal, you should start with node <li class="menu-item-has-children"> . Well that is what I can infer from your question.
You need to use preventDefault() because you'r class is a link. By clicking, it'll redirect you to the link.
$('.open-menu-link').click(function(e) {
console.log($(this).parent().next())
e.preventDefault()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work
</li>
<li class="menu-item-has-children">
Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1
</li>
<li>Child 2
</li>
<li>Child 3
</li>
</ul>
</li>
<li>Careers
</li>
<li>Contact
</li>
</ul>

jQuery - has children without ANY class (not specific class)

So, guys, basically what I need to find:
----> All <li> which has <ul> without ANY class.
In this example I would ONLY want the <li> parent of the commented <ul>:
HTML
<ul id="myList">
<li>
<a>Item 1</a>
<ul class="someClass">
</ul>
</li>
<li> <!--------- Just Need This One ---------->
<a>Item 2</a>
<ul>
</ul>
</li>
<li>
<a>Item 3</a>
<ul class="justAnotherClass">
</ul>
</li>
</ul>
I'm aware of .not("[class]"), and so I tried something like:
$('#myList li').has('ul').not("[class]")
which obviously doesn't work because jQuery is looking for <li>'s which have a nested <ul> but doesn't have any class.
So, guys, can anyone please help? :)
Instead of using
$('#myList li').has('ul').not("[class]")
you can use
$('#myList > li').has('ul:not([class])')
you can also use this selector
$('#myList > li:has(ul:not([class]))')
$('#myList > li:has(ul:not([class]))').css('background' , 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="myList">
<li>
<a>Item 1</a>
<ul class="someClass">
</ul>
</li>
<li>
<a>Item 2</a>
<ul> <!--------- Just Need This One ---------->
</ul>
</li>
<li>
<a>Item 3</a>
<ul class="justAnotherClass">
</ul>
</li>
</ul>
Use filter() over li and then check for children ul without any class with .length,
$('#myList li').filter(function(){
return $('ul:not([class])',this).length > 0 //$('child','context') selector
//or $('> ul:not([class])',this) in case of direct <ul>
});
var $li = $('#myList li').filter(function(){
return $('ul:not([class])',this).length > 0 //$('child','context') selector
});
console.log($li)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul id="myList">
<li>
<a>Item 1</a>
<ul class="someClass">
</ul>
</li>
<li>
<a>Item 2</a>
<ul> <!--------- Just Need This One ---------->
</ul>
</li>
<li>
<a>Item 3</a>
<ul class="justAnotherClass">
</ul>
</li>
</ul>
Try $('#myList li ul').filter(':not([class])'):
console.log($('#myList li ul').filter(':not([class])').html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<ul id="myList">
<li>
<a>Item 1</a>
<ul class="someClass">
</ul>
</li>
<li>
<a>Item 2</a>
<ul> <!--------- Just Need This One ---------->
</ul>
</li>
<li>
<a>Item 3</a>
<ul class="justAnotherClass">
</ul>
</li>
</ul>
I really hate that 'too short to be an answer' ....
$('#myList li > ul:not([class])')
Seems to be the simplest one that does the job ?

Trouble showing content with jQuery's .show()

I have a click handler on the "top level" <li>s that I want to hide all the content below the <li>s and then show the content below the particular <li> that was clicked.
The hiding works, but the showing does not.
$('.menu li').click(function() {
$('.submenu').hide();
var myclass = $('submenu');
$(this).show($submenu)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button>Menu</button>
<ul class="menu">
<li>Football
</li>
<li>cricket
<ul class="submenu">
<li>Shane
</li>
<li>Waqar
</li>
<li>Waseem
</li>
<li>Akhtar
</li>
</ul>
</li>
<li>Hockey
</li>
<li>Baseball
<ul class="submenu">
<li>Shane
</li>
<li>Waqar
</li>
<li>Waseem
</li>
<li>Akhtar
</li>
</ul>
</li>
<div class="clear"></div>
</ul>
</div>
Try this.
It hides the submenu with CSS.
Then it toggles the submenu when you click the list item.
If you only want one submenu to be shown at once, uncomment the line in the js.
$('.menu li').has('.submenu').click(function(e) {
e.preventDefault();
$(this).find('.submenu').slideToggle();
});
.submenu {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button>Menu</button>
<ul class="menu">
<li>Football</li>
<li>cricket
<ul class="submenu">
<li>Shane</li>
<li>Waqar</li>
<li>Waseem</li>
<li>Akhtar</li>
</ul>
</li>
<li>Hockey</li>
<li>Baseball
<ul class="submenu">
<li>Shane</li>
<li>Waqar</li>
<li>Waseem</li>
<li>Akhtar</li>
</ul>
</li>
<div class="clear"></div>
</ul>
</div>
You should try this.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button>Menu</button>
<ul class="menu">
<li>Football</li>
<li>cricket
<ul class="submenu">
<li>Shane</li>
<li>Waqar</li>
<li>Waseem</li>
<li>Akhtar</li>
</ul>
</li>
<li>Hockey</li>
<li>Baseball
<ul class="submenu">
<li>Shane</li>
<li>Waqar</li>
<li>Waseem</li>
<li>Akhtar</li>
</ul>
</li>
<div class="clear"></div>
</ul>
</div>
<script type="text/javascript">
$('.submenu').hide();
$(document).on("click",".menu li",function(){
$(this).find('.submenu').slideToggle();
});
</script>
You are using jQuery and there is toggle() function for show/hide toggle and use like this
$('.submenu').toggle();
and I fixed your script that doesn't work.
$('.menu li').click(function(){
$('.submenu').hide();
$(this).find('.submenu').show();
});
Working fiddle

Categories

Resources