Progressive reveal with jQuery - javascript

I have nested unordered list.
<ul id="catalogue">
<li>List
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Item 1.1</li>
<li>Item 1.2
<ul>
<li>Item 1.2.1</li>
<li>Item 1.2.2
<ul>
<li>Item 1.2.2.1</li>
</ul>
</li>
<li>Item 1.2.3</li>
</ul>
</li>
<li>Item 1.3</li>
</ul>
</li>
<li>Item 3</li>
</ul>
</li>
</ul>
At the beginning only the very top level shows, but if you click on each LI, if there's a child UL in it, it should display the next lever, and so on. If you click on the same LI again, the level below should become hidden.
$(document).ready(function () {
$('#catalogue li').each(function () {
$(this).contents().first().wrap("<span/>")
});
$('#catalogue li > span').addClass('brd');
$('ul').hide();
$('#catalogue').show();
$('#catalogue li').click(function () {
var nxt = $(this).children('ul:first')
if ($(nxt).is(":visible")) {
$(nxt).slideUp();
} else {
$(nxt).slideDown();
}
$(this).parent().show();
});
});
If a user clicks on a sibling LI and it has a child UL, that UL should show but any sibling's ones should close.

You need to stop the event from propagating to the parent. Clicking on each li will invoke its own click handler and the event will propagate to its parent li invoke its handler and so on. So you can just stop it at one level by using event.stopPropagation(). And you can use slideToggle to toggle the current state of the element.
Try:
$('#tree li').click(function (e) {
e.stopPropagation();
$(this).children('ul:first').slideToggle();
});
Demo
And if you want to slide up while clicked on its sibling then,
$('#tree li').click(function (e) {
e.stopPropagation();
var $this = $(this);
$this.children('ul:first').slideToggle().end()
.siblings().children('ul:visible').slideUp();
//Code Broken down
//$this.children('ul:first').slideToggle();
//$this.siblings().children('ul:visible').slideUp();
});
Demo

Related

How to make dropdown menu with 3 levels?

I have a simple menu, and I want to do that when you click on the menu items to open a nested list. If you double-click then it must be opened and closed.
Html:
<ul class="menu">
<li class="has-child">Click here
<ul>
<li class="has-child">Click here
<ul>
<li>Level 3</li>
</ul>
</li>
<li>Level 2</li>
<li>Level 2</li>
</ul>
</li>
<li>Level 1</li>
<li>Level 1</li>
</ul>
jQuery:
$('li.has-child').on('click', function () {
var elem = $(this).children('ul');
if (elem.is(':hidden')) {
elem.slideDown(500);
} else {
elem.slideUp(500);
}
});
But when I click on a menu item in the second level, then the first is closed. Why is this happening and how to fix it?
[JSFiddle]
You need to stop the event from propagating from the parent to the child or vice-versa. You can use event.stopPropagation():
$('li.has-child').on('click', function (event) {
event.stopPropagation()
var elem = $(this).children('ul');
if (elem.is(':hidden')) {
elem.slideDown(500);
} else {
elem.slideUp(500);
}
});
you need to use stopPropagation
$(document).ready(function () {
$('li.has-child').on('click', function (event) {
event.stopPropagation();
var elem = $(this).children('ul');
if (elem.is(':hidden')) {
elem.slideDown(500);
} else {
elem.slideUp(500);
}
});
});
This then stops the click bubbling up to the parent li
Fiddle

Jquery Slidetoggle, how to allow to show only one element?

This is my html:
<ul>
<li>
List
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</li>
<li>
List 2
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</li>
</ul>
And this js:
$('ul li ul').hide();
$('ul li').click(function() {
$(this).children().slideToggle();
});
I want to create slidetoggle, for example: when user click "List" and after open this user click List 2 then list one is hiding.
DEMO: http://jsfiddle.net/7dxAb/
I want only one open when user click.
Thanks!
Try this:
$('ul li ul').hide();
$('ul li').click(function() {
var _this = $(this);
_this.children().slideToggle();
$('ul > li').not(_this).children('ul').slideUp();
});
You hide "ul"s in all ListN elements except one that is clicked.
You can slideUp() all the other ul's before the slideToggle() like this:
$('ul li').click(function() {
$(this).parent().find('ul').slideUp();
$(this).children().slideToggle();
});
I'm not sure if this is the most effecient way tho.
Add
$('ul li ul').slideUp();
to the click event. This will hide the other uls.
The finished code would look like:
$('ul li ul').hide();
$('ul li').click(function() {
$('ul li ul').slideUp();
$(this).children().slideToggle();
});
http://jsfiddle.net/yvPFx/2/
Edit: You can use a class to keep track of what is showing.
http://jsfiddle.net/yvPFx/3/
Try this:
$('ul li ul').hide();
$("ul li").click(function () {
$(this).children().slideToggle("slow", function() {
//
});
$(this).siblings().children().slideUp("slow");
});

Copy element's attributes to other element in javascript loop

I have a problem in loop js. I would like to copy data-icon value from .nav class to li in #item-control. Is there anyway easy way to solve it with jquery?
<div id="nav-container">
<ul class="nav">
<li data-icon="images/1.png">Item 1</li>
<li data-icon="images/2.png">Item 2</li>
<li data-icon="images/3.png">Item 3</li>
</ul>
</div>
<div id="item-control">
<li>Item Control 1</li>
<li>Item Control 2</li>
<li>Item Control 3</li>
</div>
What I've tried:
$(document).ready(function () {
var a = 1;
$('#container #nav-container ul.nav li').each(function () {
var item_control = $(this).parent().parent().parent().find('#item-control li');
item_control.addClass('item' + a); //this is what I tried before adding data-icon attributes to #item-control li
a++;
});
});
var $navItems = $('.nav li'),
$itemControlItems = $('#item-control li');
$.each($navItems, function(index, el) {
$($itemControlItems[index]).data('icon', $(el).data('icon'));
});
Fiddle

Navigation Menu using jQuery (from jQuery Cookbook)

The menu is supposed to show sub-items upon hover. Here's the code (from http://docs.jquery.com/Cookbook/Navigation):
<ul id="menu">
<li class="menu">Sub 1
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
<li class="menu">Sub 2
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
</ul>
jQuery code:
$(document).ready(function() {
var toggle = function(direction, display) {
return function() {
var self = this;
var ul = $("ul", this);
if( ul.css("display") == display && !self["block" + direction] ) {
self["block" + direction] = true;
ul["slide" + direction]("slow", function() {
self["block" + direction] = false;
});
}
};
}
$("li.menu").hover(toggle("Down", "none"), toggle("Up", "block"));
$("li.menu ul").hide();
});
What is this in the toggle function above? How is the code working? What is being selected by $("ul", this); ?
The "this" refers to the jQuery object $("li.menu") - when the hover method call applies the toggle function to that object. $("ul", this) selects ul elements that are children of the context provided in the second argument ("this"), thus it selects the ul elements nested within the li.menu elements. Hopefully that makes the hover/toggle functions make sense.

Selecting an element whose parent element does not have a particular class

Assuming, I have the following HTML:
<ul class="topnav">
<li class="">Page 1</li>
<li class="">Page 2</li>
<li class="">Page 3</li>
<li class="">Page 4</li>
<li class="">Page 5</li>
<li class="active">Page 6</li>
</ul>
When the mouse leaves the LI element, it is suppose change the color of the font back to grey except for the A element whose parent LI has a class value of 'active'.
Below is the JQuery code I am trying: (The 'mouseleave' function is not working)
$(".top_nav li a").mouseenter(
function() {
$(this).stop().animate({'color': '#ffffff'}, 'slow');
});
$(".top_nav li a").mouseleave(
function() {
$(this).parent().not(".active").stop().animate({'color': '#a5acb2'}, 'slow');
});
$(this).parent() selects the li element and all other functions apply to this one instead to the a element.
You can do:
$(this).not(".active > a").stop()...
DEMO
Try using .hasClass():
if($(this).parent().hasClass("active")) {
$(this).stop().animate({'color': '#a5acb2'}, 'slow');
}
If your list items can only be assigned the one class, you can do this:
// class not equals 'active'
$(this).parent("[class!='active']");
Otherwise, this should work:
// class contains 'active'
$(this).parent("[class*='active']");
$(".top_nav li a").hover( function () {
$(this).stop().animate({'color': '#ffffff'}, 'slow');
},
function () {
$(this).parent().not(".active").stop().animate({'color': '#a5acb2'}, 'slow');
});

Categories

Resources