I have this HTML code
<ul>
<li>link
<ul>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</li>
<li>link
<ul>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</li>
</ul>
now I want -> hide all sub menus -> if I click to main li element -> show current li's sub menu and next if I click to another main li element show sub menu and hide previously displayed sub menu.
Can anyone help me?
You can do it like this DEMO
$('li ul').hide();
$('li a').click(function() {
$(this).next('ul').slideToggle();
$('ul li ul').not($(this).next('ul')).slideUp();
});
You can do something simple like this with click event
$('#main>li>a').click(function() { // bind click event to a tag
$(this)
.next() // get ul inside
.stop() // stop any previous animation
.slideToggle() // toggle the visibility
.end() // back to previous selector , here the clicked element
.parent() // get parent li
.siblings() // get its siblings
.find('ul') // get ul inside them
.stop() // stop any previous animation
.slideUp() // hide them
});
#main>li>ul {
/* hide sub ul initially */
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="main">
<li>link
<ul>
<li>link
</li>
<li>link
</li>
<li>link
</li>
</ul>
</li>
<li>link
<ul>
<li>link
</li>
<li>link
</li>
<li>link
</li>
</ul>
</li>
</ul>
Related
I'm trying to find a way to disable mouseenter when the top-level navigation item is clicked & on pageload and re-enable again when the mouse leaves and enters the element again.
User hovers over element = show submenu
User clicks menu = hide submenu and only show submenu when user leaves menu elements and enters again.
If user is over the element onLoad then only show submenu when user leaves element and enters again.
$('.navmenu li').on('mouseenter', function(e) {
$(e.target).next().addClass('js-hover')
}).on('mouseleave', function(e) {
$(e.target).next().removeClass('js-hover')
});
$('.navmenu').on('click', function(e) {
$(e.target).next().removeClass('js-hover')
location.reload(true);
})
.navmenu .submenu {
display:none;
}
.navmenu li {
display: inline;
}
.navmenu .submenu {
position:absolute;
top:40px;
left:0
}
.navmenu li:hover .js-hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu">
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
<li>
Menu 2
<nav class="submenu">
<ul>
<li>Submenu 4</li>
<li>Submenu 5</li>
<li>Submenu 6</li>
</ul>
</nav>
</li>
</ul>
</nav>
this could be done using variables and storing a state of element (if it should be hidden or not). But since you tried to do this through class attributes, I did the same. Here is simle example of one menu item, everything should be clear.
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu" hidden>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
</ul>
</nav>
and javascript:
$menuLink = $("nav.navmenu li > a");
$menuLink.click(function () {
$(this).addClass("dontHide");
});
$menuLink.mouseenter(function () {
$(this).next("nav.submenu").removeAttr("hidden");
$(this).removeClass("dontHide");
});
$menuLink.mouseleave(function () {
if(!$(this).hasClass("dontHide")) {
$(this).next("nav.submenu").attr("hidden", true);
}
});
Live demo: https://jsfiddle.net/g3fua461/24/
I'm trying to be able to toggle these sub menus one at a time, I'm getting lost in nests and cant quite figure out how to target the correct list item,
I found that I should be using find() instead of children() as it can go deeper in the nest but still no luck in getting it working.
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="drop-nav"> See your products
<ul>
<li class="drop-nav"> Mens
<ul>
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="drop-nav"> Womens
<ul>
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
$(".drop-nav").on("click", function(e){
e.preventDefault();
});
li ul{
display: none;
}
You could use $(this).find('ul').eq(0) to get the ul, but I would delegate the changing of the display to the stylesheet, but use javascript to add a class where applicable. This will give you many more options for the design of your dropdown later.
$(".drop-nav").on("click", function(e) {
e.preventDefault()
// don't allow the event to fire horizontally or vertically up the tree
e.stopImmediatePropagation()
// switch the active class that you can use to display the child
$(this).toggleClass('active')
})
/* don't target ll list items in you page, be more specific */
.drop-nav > ul {
display: none;
}
.drop-nav.active > ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="drop-nav"> See your products
<ul>
<li class="drop-nav"> Mens
<ul>
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="drop-nav"> Womens
<ul>
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
I would add more descriptive class names in your markup, and make them easier to target with CSS and jQuery.
To toggle the menus you could do something like the following:
$(".dropdown-trigger1").on("click", function() {
// Toggle the first menu
$(".dropdown-one").toggleClass("open");
// Close the submenus
$(".dropdown-two").removeClass("open");
});
$(".dropdown-trigger2").on("click", function(e) {
// Prevent a click on a submenu from closing the menu
e.stopPropagation();
// Close any open submenu
$(".dropdown-two").removeClass("open");
// Open the submenu that has been clicked
$(this).find(".dropdown-two").toggleClass("open");
});
li ul {
display: none;
}
.dropdown-one.open {
display: block;
}
.dropdown-two.open {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="dropdown-trigger1"> See your products
<ul class="dropdown-one">
<li class="dropdown-trigger2"> Mens
<ul class="dropdown-two">
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="dropdown-trigger2"> Womens
<ul class="dropdown-two">
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
You haven't described about how you activate each sub-menu, so I will describe solution little bit abstractly. Solution is based on your HTML structure an will work if you wouldn't change it.
$('.drop-nav a').on('click', function() {
// This next method returns next element in DOM that is after clicked a link.
// Based on your HTML it would be ul that holds your sub-menu.
var subMenu = $(this).next();
// Here using subMenu selector to make something with sub-menu...
// Example: adding CSS inline to sub. In your situation it may be something else...
$(subMenu).css({ 'display' : 'block' });
});
I want to create universal tree menu, with ul li ul. And I've made something like this using just CSS:
CSS
.category-list {
}
.category-list li ul {
display: none;
}
.category-list li:hover > ul {
display: block;
}
HTML
<ul class="category-list">
<li>
Category 1
<ul>
<li>Sub-category 1</li>
<li>Sub-cateagory 1</li>
<li>Sub-category 1</li>
</ul>
</li>
<li>
Category 2
<ul>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
</ul>
</li>
</ul>
https://jsfiddle.net/usz9ycmj/1/
--
And I want to make similar effect, but on click, so just current clicked tab displays its parent content.
Even more important for me is the ability to add and remove class on specific action:
.category-list li.current -- while is currently clicked (active)
.category-list li -- removed while different li is clicked (active)
Just, the trigger li has two different states for active and inactive. It changes the colors and arrow from closed to opened to give it a look of a tree menu - I bet You get the point.
I want the simple jquery code, if someone has time to help. feel welcome.
Here is a working code.
Please read the comments and let me know if something not clear.
// listen to the click event
var all_items = $('.category-list>li').click(function(event) {
// stop the propagation - this will abort the function when you click on the child li
event.stopPropagation();
var elm = $(this);
// remove the class from all the items
all_items.not(elm).removeClass('current');
// add class if it's not the current item
elm.toggleClass('current', !elm.is('.current'));
});
.category-list {
}
.category-list li ul {
display: none;
}
.category-list li.current > ul {
display: block;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<ul class="category-list">
<li>
Category 1
<ul>
<li>Sub-category 1</li>
<li>Sub-category 1</li>
<li>Sub-category 1</li>
</ul>
</li>
<li>
Category 2
<ul>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
</ul>
</li>
</ul>
http://jsbin.com/tocewe/edit?html,css,js
I have a menu structure in which sub menus are present as nested lists like this
<nav>
<ul>
<li class="itm">A
<ul>
<li>One</li>
<li>Two
<ul>
<li>Menu Item</li>
<li> Menu Item </li>
<li> Menu Item </li>
</ul>
</li>
<li> Three </li>
<li> Four </li>
</ul>
</li>
<li class="icon"><span class="img"></span></li>
<li class="itm">B</li>
<li class="itm">C</li>
</ul>
</nav>
Nowi want to show the sub menu (sub list) when the cursor hovers over the parent li and for that I am doing this:
$('nav ul li').hover(function () {
console.log(this);
$(this > ul).fadeIn();
}, function () {
$(this > ul).fadeOut();
});
But on hover it showing this error in JS Console: Uncaught ReferenceError: ul is not defined
Your selector is combining this, which is a literal, and what should be a string in a selector (> ul). ul is being treated as a variable, and the ul variable doesn't exist.
Try this:
http://jsfiddle.net/cyzsw/
$(this).children('ul').fadeIn();
HTML:
<ul class="menu">
<li>Text
<ul>
<li>Text
<li>Text
<li>Text
</ul>
</li>
<li>Text</li>
<li>Text</li>
<li>Text</li>
<li>Text
<ul>
<li>Text
<li>Text
<li>Text
</ul>
</li>
<li>Text</li>
</ul>
JS:
$(".menu li a").click(function() {
$(this).parent().find("ul").toggle();
return false;
});
How to make this js work only when <li> has <ul> inside it?
Without adding extra classes.
It should not work when there is no child <ul> inside current <li>.
Example of this available on jsfiddle.net
Its better if you give link to your working example.
Try restricting the parent to bring back the first li, right now it is finding the ul of an li as the top level container then has within it several other ul so the logic is working as written.
$(".menu li a").click(function() {
return !($(this).parents("li:first").find("ul").toggle().length)
});
To perform an action if there's a child ul of the currently-hovered li:
$('li').hover(
function(){
if ($(this).has('ul')) {
// do stuff
}
});
I was going to add that you could also just use the :has selector with a parent > child selector (demo):
$('.menu li:has(ul) > a').click(function() {
$(this).parent().find('ul').toggle();
return false;
});