How to toggle nested lists using button - javascript

I've created a list with nesting and added a button to every parent <li> element. The list looks like this:
$("#pr1").append("<button id='bnt-cat13' class='buttons-filter'>expnd1</button>");
$("#pr2").append("<button id='bnt-cat13' class='buttons-filter'>expnd2</button>");
$("#pr3").append("<button id='bnt-cat13' class='buttons-filter'>expnd3</button>");
$(document).ready(function() {
$("button").click(function() {
$('li > ul').toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="categories">
<li>1</li>
<li class="parent" id="pr1">2
<ul class="children">
<li>2.1</li>
</ul>
</li>
<li>3</li>
<li class="parent" id="pr2">4
<ul class="children">
<li>4.1</li>
<li class="parent" id="pr3">4.2
<ul class="children">
<li>4.2.1</li>
</ul>
</li>
</ul>
</li>
<li>5</li>
</ul>
But this one toggles all list, instead of toggling only separate nested list?
How to show/hide only separate nested lists clicking the buttons?
Thanks in advance.

As for the main question - instead of each li > ul elements, you have to toggle only the ul element which is right before a button. So you should use .prev()
$("button").click(function() {
$(this).prev().toggle();
});
$("#pr1").append("<button id='bnt-cat131' class='buttons-filter'>expnd1</button>");
$("#pr2").append("<button id='bnt-cat132' class='buttons-filter'>expnd2</button>");
$("#pr3").append("<button id='bnt-cat133' class='buttons-filter'>expnd3</button>");
$(document).ready(function() {
$("button").click(function() {
$(this).prev().toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="categories">
<li>1</li>
<li class="parent" id="pr1">2
<ul class="children">
<li>2.1</li>
</ul>
</li>
<li>3</li>
<li class="parent" id="pr2">4
<ul class="children">
<li>4.1</li>
<li class="parent" id="pr3">4.2
<ul class="children">
<li>4.2.1</li>
</ul>
</li>
</ul>
</li>
<li>5</li>
</ul>
Your code has another issue that should be fixed - each button has the same id attribute (bnt-cat13).
The id global attribute defines a unique identifier (ID) which must be unique in the whole document.

Change your function into:
(document).ready(function() {
$("button").click(function() {
$(this).parent().children('ul').toggle();
});
});

Related

How to add special attribute to element if has class 'on' or not using jquery?

I have some dynamical list
And if 'LI' element has class name 'on',
add attribute "aria-hidden=false".
Also if LI element has not class name 'on',
add attribute "aria-hidden=true".
This is my code
<ul class="list">
<li>1</li>
<li class="on">1</li>
<li>1</li>
<li>1</li>
</ul>
And this is what I want the code in DOM
<ul class="list">
<li aria-hidden=true>1</li>
<li class="on" aria-hidden=false>1</li>
<li aria-hidden=true>1</li>
<li aria-hidden=true>1</li>
</ul>
How to make it with this code ? Please help
You can use class selector with .filter() to target the desired elements the use .attr() to add the attribure
//Target all LI elements
var li = $('ul.list li');
//Filter li without on class
li.filter(':not(.on)').attr('aria-hidden', true)
//Filter li with on class
li.filter('.on').attr('aria-hidden', false);
//Target all LI elements
var li = $('ul.list li');
//Filter li without on class
li.filter(':not(.on)').attr('aria-hidden', true)
//Filter li with on class
li.filter('.on').attr('aria-hidden', false);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>1</li>
<li class="on">1</li>
<li>1</li>
<li>1</li>
</ul>
$('li').attr('aria-hidden', true);
$('li.on').attr('aria-hidden', false);
//To check if things really changed. Revove it.
console.log($('ul.list').html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>1</li>
<li class="on">1</li>
<li>1</li>
<li>1</li>
</ul>
NOTE: aria-hidden="false" is not recommended, please read this aria - states_and_properties
Try this
$(".list li").not('.on').attr('aria-hidden', true)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>1</li>
<li class="on">1</li>
<li>1</li>
<li>1</li>
</ul>
Use .attr() with callback function to do this work. In callback check that element has class on or not.
$(".list li").attr("aria-hidden", function(){
return $(this).is(".on") ? false : true;
});
[aria-hidden=true] {opacity: 0.5}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>1</li>
<li class="on">1 (.on)</li>
<li>1</li>
<li>1</li>
</ul>
You can do it like this
$("ul.list li").each(function(){
$(this).attr("aria-hidden",!$(this).hasClass("on"));
});
Demo
$("ul.list li").each(function(){
$(this).attr("aria-hidden",!$(this).hasClass("on"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>1</li>
<li class="on">1</li>
<li>1</li>
<li>1</li>
</ul>
this code add aria-hidden=false to item that has class 'on'
$(document).ready(function(){
$('ul.list li.on').attr('aria-hidden', true)
$('ul.list li').attr('aria-hidden', false);
})
ul.list li.on {
background:green
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li >item 1</li>
<li class="on" >item 2</li>
<li >item 3</li>
<li >item 4</li>
</ul>

Get href value while clicking li tag

Following is the code of the Div which is created dynamically.
<div align="right" class="row pagination">
<ul class="pagination pagination">
<li class="prev disabled"><span>Previous Label</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li class="next">Next Label</li>
</ul>
</div>
When I click any <li> tag, I need to take the href value(eg: /some_url?page=2) of corresponding <li> tag.
$("ul.pagination li").click(function(e) {
alert($(this).attr('href'));
});
In the above code, clicking event is firing but i am getting undefined in the alert.
Please help.
but i am getting undefined in the alert.
Yes because you're trying to alert the href of the clicked li when it has no attribute href.
You need to alert the href of the anchor inside the li using a in your selector, or also using .find() like :
alert( $('a', this).attr('href') );
//Or also
alert( $(this).find('a').attr('href') );
You could also attach the click event directly to the child anchors of the il's like :
$("ul.pagination li a").click(function(e) {
alert( $(this).attr('href') );
});
$("ul.pagination li").click(function(e) {
alert($('a', this).attr('href'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div align="right" class="row pagination">
<ul class="pagination pagination">
<li class="prev disabled"><span>Previous Label</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li class="next">Next Label</li>
</ul>
</div>
here is a technique very close to what you had:
$("ul.pagination li a").click(function(e) {
alert($(this).attr('href'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div align="right" class="row pagination">
<ul class="pagination pagination">
<li class="prev disabled"><span>Previous Label</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li class="next">Next Label</li>
</ul>
</div>
$(this) inside your function call is referring to li element and not the a. You need to find a inside li and then get the attribute href like this
$("ul.pagination li").click(function(e) {
alert($(this).find('a').attr('href') );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div align="right" class="row pagination">
<ul class="pagination pagination">
<li class="prev disabled"><span>Previous Label</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li class="next">Next Label</li>
</ul>
</div>
because elements are created dynamically,
You should provide a selector to the on function:
$(document).on('click', 'ul.pagination li', function(e) {
alert($(this).children('a').attr('href'));
});
children() vs find()
The .children() method differs from .find() in that .children() only travels a single level down the DOM tree while .find() can traverse down multiple levels to select descendant elements (grandchildren, etc.) as well

Jquery show or hide children link if it is available

I have a question on Jquery. If I click on Link1, which does not have any ul.children and the class current_page_item will be added(not shown in this code as it will be added automatically by Wordpress), then ul.children in Link2 should be hidden.
If i click on Link 2, which will have both class page_item_has_children current_page_item, in this case ul.children should be shown. I have tried my code bellow, which is i know it is absolutely wrong. Please give me your advices. Many thanks.
if($(.navigation).hasClass(page_item_has_children)){
(.navigation .page_item_has_children .children).hide();
}else if( $(.navigation).hasClass(page_item_has_children) && $(.navigation).hasClass(current_page_item)){
(.navigation .page_item_has_children .children).show();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="navigation">
<li>Link1</li>
<li class="page_item_has_children current_page_item">Link2
<ul class="children">
<li class="page_item">Link3</li>
<li class="page_item ">Link4</li>
</ul>
</li>
</ul>
This solution is a bit more towards your scenario (edited based on comment):
$(".navigation li").on("click", function() {
if ($(this).hasClass("page_item_has_children") && $(this).hasClass("current_page_item")) {
$(".navigation .children").show();
} else {
$(".navigation .children").hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="navigation">
<li>Link1
</li>
<li class="page_item_has_children current_page_item links">Link2
<ul class="children">
<li class="page_item">Link3
</li>
<li class="page_item ">Link4
</li>
</ul>
</li>
</ul>
How about simply hiding all nested UL elements, then simply showing the children of the clicked one?
$(".navigation li").each(function() {
// When we first load, hide all nested menus.
$(this).children("ul").hide();
if (localStorage.menuNumber) {
$(".navigation li").eq(localStorage.menuNumber).children().show();
}
})
.on("click", function() {
// When any top-level ul is clicked, hide the
// nested menus then show the current one.
$(this).parent().children().find("ul").hide();
$(this).children().show();
// We also want to persist this selection,
// should the user refresh...
localStorage.menuNumber = $(this).index;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="navigation">
<li>Link1
</li>
<li class="page_item_has_children current_page_item">Link2
<ul class="children">
<li class="page_item">Link3
</li>
<li class="page_item ">Link4
</li>
</ul>
</li>
</ul>
Edited it so that when it initially loads, all nested uls are hidden. Hope this helps! And edited again, to store the clicked menu in local storage. Sadly, for security reasons, this won't work here. See it as a fiddle: https://jsfiddle.net/snowMonkey/fnuvvLwb/

removing html tags but keep the inner html

I have a nav menu which have a mega menu.It has several markup to make it a mega menu.But i want to remove some of the markups when in small viewport.
So my markups are
<ul class="megamenu-wrapper">
<li>
<ul>
<li>Home</li>
<li>Abort</li>
<li>Contact</li>
</ul>
</li>
<li>
<ul>
<li>gang</li>
<li>menu</li>
<li>food</li>
</ul>
</li>
</ul>
what i want
<ul class="megamenu-wrapper">
<li>Home</li>
<li>Abort</li>
<li>Contact</li>
<li>gang</li>
<li>menu</li>
<li>food</li>
</ul>
i have two mega-menu-wrapper
What i have tried
var megaContents = $('.megamenu-wrapper li ul').contents();
$('.megamenu-wrapper li ul').replaceWith( megaContents );
It makes a same list in two each mega menu and in each megamenu there is about 5 times repetation of each elements.
Anyone please help.
Use
//Fimd child ul li and append it to main ul
$('.megamenu-wrapper > li > ul > li').appendTo('.megamenu-wrapper');
//Remove li having ul
$('.megamenu-wrapper > li:has(ul)').remove();;
$(document).ready(function() {
$('.megamenu-wrapper > li > ul > li').appendTo('.megamenu-wrapper'); +
$('.megamenu-wrapper > li:has(ul)').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="megamenu-wrapper">
<li>
<ul>
<li>Home
</li>
<li>Abort
</li>
<li>Contact
</li>
</ul>
</li>
<li>
<ul>
<li>gang
</li>
<li>menu
</li>
<li>food
</li>
</ul>
</li>
</ul>
use .each() if you have multiple menus
$('.megamenu-wrapper') each(function () {
$(this).find('> li > ul > li').appendTo(this);
$(this).find(' > li:has(ul)').remove();
});
DEMO
With your current markup, you can use append() which will take the children li with anchors and append them as direct children of .megamenu-wrapper
Then, use remove() to remove the former parent li elements which now contain empty ul children
$('.megamenu-wrapper').append($('li:has(a)'));
$('.megamenu-wrapper').children('li:has(ul)').remove();
Update
For multiple menus, you can use the snippet above, but wrap it in an each() call
$('.megamenu-wrapper').each(function(){
$(this).append($(this).find('li:has(a)'));
$(this).children('li:has(ul)').remove();
});
$('.megamenu-wrapper').each(function(){
$(this).append($(this).find('li:has(a)'));
$(this).children('li:has(ul)').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul class="megamenu-wrapper">
<li>
<ul>
<li>Home</li>
<li>Abort</li>
<li>Contact</li>
</ul>
</li>
<li>
<ul>
<li>gang</li>
<li>menu</li>
<li>food</li>
</ul>
</li>
</ul>
<ul class="megamenu-wrapper">
<li>
<ul>
<li>Home</li>
<li>Abort</li>
<li>Contact</li>
</ul>
</li>
<li>
<ul>
<li>gang</li>
<li>menu</li>
<li>food</li>
</ul>
</li>
</ul>

How to get a previous DIV with jQuery

I want to animate an element (.item-i) after I click on another element(.item-1) which is following below. Now I don't know, how to get to this element.
I want only the exact above element animated, not both above, only the first element above.
I made an easy show up in http://jsfiddle.net/Eef4v/1/. The YellowBG is the "animation".
Here is my JS code:
$('.item-1').click(function() {
$(this).closest('.item-i').css( "background", "yellow" );
});
And my HTML Markup:
<ul id="one" class="level-1">
<li class="item-i">I</li>
<li class="item-ii">II
<ul class="level-2">
<li class="item-a">A</li>
<li class="item-b">B
<ul class="level-3">
<li class="item-1">1</li>
<li class="item-2">2</li>
<li class="item-3">3</li>
</ul>
</li>
<li class="item-c">C</li>
</ul>
</li>
<li class="item-iii">III</li>
</ul>
<ul id="Ul1" class="level-1">
<li class="item-i">I</li>
<li class="item-ii">II
<ul class="level-2">
<li class="item-a">A</li>
<li class="item-b">B
<ul class="level-3">
<li class="item-1">1</li>
<li class="item-2">2</li>
<li class="item-3">3</li>
</ul>
</li>
<li class="item-c">C</li>
</ul>
</li>
<li class="item-iii">III</li>
</ul>
Use:
$(this).closest('.item-ii').prev().css( "background", "yellow" );
Working Demo
For Toggling background color:
$(this).closest('.item-ii').prev().toggleClass("highlight");
CSS:
.highlight {background: yellow;}
Demo with ToggleClass
Two ways to get .item-i to highlight.
$(this).parents('.level-1').find('.item-i').css( "background", "yellow" );
but if you have multiple .item-i classes under your .level-1 then they would all turn yellow.
Working Demo
You could also write a find algorithm that goes through each parent of .item-1 and finds the closest item-i
$('.item-1').click(function () {
$(this).parents().each(function(index,elem){
var query = $(elem).find('.item-i');
if(query.length > 0)
{
query.first().css("background-color", "yellow");
return false;
}
});
});
Working Algorithm demo

Categories

Resources