efficient way for a selector - javascript

i got this structure:
<ul class="depth-one">
<li>Category 1 <span class="do">+</span>
<ul class="depth-two">
<li > Category 1.1 <span class="do">+</span>
<ul class="depth-three">
<li>Category 1.2.1</li>
<li>Category 1.2.2</li>
</ul>
</li>
<li> Category 1.2</li>
<li> Category 1.3</li>
</ul>
</li>
<li> Category 2 <span class="do">+</span>
<ul class="depth-two">
<li>Category 2.1</li>
<li>Category 2.2</li>
<li>Category 2.3</li>
</ul>
</li>
<li>Category 3 <span class="do">+</span>
<ul class="depth-two">
<li>Category 3.1</li>
<li>Category 3.2</li>
<li>Category 3.3</li>
</ul>
</li>
</ul>
with that CSS:
ul{
list-style:none;
padding:0;
margin:0;
}
ul li{
width:220px
}
.depth-one{
}
.depth-two{
display:none;
}
.depth-three{
display:none;
}
.do{
float:right;
font-weight:bold;
color:blue;
cursor:pointer;
}
What I want to do is, whenever I click on the class "do" (the spans) I would like to toggle the closet UL element.
How can I pick the closet UL element to the span using jQuery, so I can use the functions slideUp and slideDown to toggle it?
My Idea was to use the function next(), but I think that there is a more generic way to do it.
Thanks in advance!

Well, the .next() is actually perfect
$('.do').on('click', function() {
$(this).next('ul').slideToggle().find('ul:visible').slideUp(); // According to your comment; hide all the visible successors of type ul.
$(this).text( $(this).text() == '+' ? '-' : '+' ); // Alter the caption (which I guess you want to do as well) :-)
});
EDIT: Added hide for all child ul's to match your comment.

You can use the jQuery .next() method
Example:
$(".do").click(function () {
$(this).next("ul").slideToggle()
});

Try this
$(".do").click(function () {
$(this).next().closest("ul").slideToggle();
});
FIDDLE

Related

jQuery create an expandable unordered list with ul li with extra span tag

I would like to create an expandable tree with unordered list. The deepness is not limited in my case.
I have to keep the text in the list elements as it is, this way I need to add an extra span element to every parent to have a clickable item.
I have tried to add this span tag with jQuery, and this finds the li objects, but in the result only the first occurrance is visible.
The HTML code is this.
<ul class="list">
<li>
Categories
<ul>
<li>
Parent
<ul>
<li>link 1 link 2 link 3</li>
<li>link 1 link 2 link 3</li>
</ul>
</li>
<li>
Parent
<ul>
<li><a>Child 1</a></li>
<li><a>Child 2</a></li>
<li><a>Child 3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
My jQuery script is below.
$(document).ready(function(){
$(".list").each(function () {
$(this).find('li').each(function(index, element){
var text = $(this).html();
text = "<span class=\"trigger\">+</span> " + text;
$(element).html(text);
});
});
$('.list > li span').click(function(){
$(this).parent().children('ul').toggle();
if($(this).text() == '+') {
$(this).text('-');
}
else {
$(this).text('+');
}
});
});
jsFiddle: https://jsfiddle.net/pegapega/2f20s90v/
My expected result would be for every li element:
<li><span class="trigger">+</span>[original content]</li>
Why the span element is not added to all of the li elements?
I'm unsure exactly why your code example didn't work, but here is an example that does work based on you original.
$('li').each(function(i, e){
$(e).prepend('<span class="trigger">+</span>');
});
$('span').on('click', function(e){
$(e.target).next('ul').toggleClass('show');
if( $(e.target).text() == '+') {
$(e.target).text('-');
} else {
$(e.target).text('+');
}
});
span.trigger {
cursor: pointer;
}
ul {
display: none;
list-style-type: none;
padding-left: 30px;
font-size: 18px;
font-family: "Open Sans", sans-serif;
}
ul.show {
display: block;
}
ul.list {
display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>
Root
<ul>
<li>
Parent
<ul>
<li>link 1 link 2 link 3</li>
<li>link 1 link 2 link 3</li>
</ul>
</li>
<li>
Parent
<ul>
<li><a>Child 1</a></li>
<li><a>Child 2</a></li>
<li><a>Child 3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
Stackoverflows snippet editor seemed to have some problem with toggle() so I just replaced it with toggleClass() just so the example would work.

select li element based on the ul

how I can select the second ul li element, I have this structure:
HTML
<ul>
<li></li>
<ul>
<li>I want to select this</li>
</ul>
</ul>
Firstly your HTML is invalid. You cannot have ul as a child of another ul. It must be within an li. Also the text within the ul must also be within a li.
<ul>
<li>
<ul>
<li>I want to select this</li>
</ul>
</li>
</ul>
To then select this in jQuery you can use:
$('ul > li > ul > li:first');
You could also use the less strict: ul ul li:first, depending on how rigidly you need to adhere to the HTML structure you defined.
the structure you provided is not proper, the child <ul> tag should go inside an <li> tag.
then the structure will be like
<ul class="ul">
<li></li>
<li>
<ul>
<li>I want to select this </li>
</ul>
</li>
</ul>
then you can get that child <ul> using jquery as
$(".ul li ul");
hope this helps.
Try this snippet with multiple options.
console.log($('ul > ul > li:eq(0)').text());
//OR
console.log($('ul').find('ul > li:eq(0)').text());
//OR
console.log($('ul').children('ul').find('li:eq(0)').text());
//OR
console.log($('ul > ul').find('li:eq(0)').text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul><b>First ul</b>
<li>First li</li>
<ul> <b>Second ul</b>
<li>First li in second ul</li>
</ul>
</ul>
First you must add a class or an id to your parent ul :
<ul class="root">
<li></li>
<ul>
I want to select this <li></li>
</ul>
</ul>
Then, either your choose to select the 2nd one because it will always be the second (index 1) :
$(".root").find("li").eq(1)
Or you add a class to your <li>:
<ul class="root">
<li></li>
<ul>
I want to select this <li class="myLi"></li>
</ul>
</ul>
And then
$(".root").find(".myLi")
You can use querySelector to do that. Check below example.
var li = document.querySelector('ul ul li');
console.log(li.innerHTML);
<ul>
<li>Not this</li>
<ul>
<li>I want to select this</li>
</ul>
</ul>

Jquery to create hierarchy with unordered list

I have an unordered list that when clicked shows their children. I am trying to add the feature where when there are children shown from a parent and a sibling of that parent is clicked, the other children close while the new ones open. Here is what I have so far:
<ul class="list">
<li> <a>Categories</a>
<ul>
<li> <a>Parent</a>
<ul>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
</ul>
</li>
<li> <a>Parent</a>
<ul>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
</ul>
</li>
<li> <a>Parent</a>
<ul>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
</ul>
</li>
<li> <a>Parent</a>
<ul>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
<li><a>Child</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
This is my jquery:
$(document).ready(function(){
$('.list > li a').click(function(){
$(this).parent().children('ul').toggle();
});
Here is a jfiddle: https://jsfiddle.net/hmsvox5a/
Now if you click parent, the children show up. If you click another parent, its children appear as well. This leaves two sets of children open. I am trying to get the first set of children to close when I open the second. When I try to hide the siblings children, It messes up the whole jquery. Any ideas?
I'm not going to lie and tell you that this will scale or that it isn't awful, but this was the first thing I thought of off the top of my head. There are many ways to solve this.
$(document).ready(function(){
$('.list > li a').click(function(){
$('.open').parent().children('ul').toggle();
$('.open').removeClass('open');
$(this).addClass('open').parent().children('ul').toggle();
});
});
I believe what you want is this perhaps?
$(document).ready(function(){
$('.list > li a').click(function(){
$(this).parent('li').siblings('li').children('ul').hide();
$(this).siblings('ul').toggle().children().show();
});
});
test it out here: http://jsfiddle.net/vgwrqr6c/
I prefer to use CSS on the children to show items when its parent is shown. Then this efficient script works.
It keeps a reference to the last selected parent so it doesn't have to search the whole dom.
$(document).ready(function(){
var $selected;
$('.list > li a').click(function(){
if($selected){
$selected.remove class("open");
}
$selected = $(this).parent();
$selected.add class("open");
});
});
CSS would be something like this.
li ul{ display:none;}
li.open ul{ display: block}

Multiple level selection bar

I am trying to do a multilevel selection bar. But I am not sure how to create this type of bar. I have tried to use the common navigation bar method, but is doesn't work out the way i wanted.
I want to do something like this, and here is the photo for references:
Any suggestion on how to do it? Or any similar examples? (Please show in fiddle example.)
Thank you!
You want to create a multi-level unordered list, with each list item that has children, containing another unordered list. E.G.
<ul class="parent">
<li>
Category
<ul class="child">
<li>
Sub-category
<ul class="grandchild">
<li>
Sub-sub-category
<ul class="great-grandchild">
<li>
sub-sub-sub category
</li>
</ul>
</li>
</ul>
</li>
<li>
Sub-category 2
</li>
</ul>
</li>
<li>Category 2</li>
<li>Category 3</li>
<li>Category 4</li>
<li>Category 5</li>
</ul>
then you would hide all of the children/grandchildren etc with css, and show them on parent:hover/active
ul:not('.parent') {
display: none;
}
ul.parent > li:hover > ul,
ul.child > li:hover > ul,
ul.grandchild > li:hover > ul,
ul.great-grandchild > li:hover > ul {
display: block;
}

Get <li> with child <ul> from <ul> child of <li>

I have a very simple example of a menu here:
<ul id="1">
<li>First</li>
<li>Second
<ul id="2">
<li>Second - 1</li>
<li>Second - 2</li>
<li>Second - 3
<ul id="3">
<li>Aaa</li>
<li>Bbb</li>
<li>Ccc</li>
</ul>
</li>
</ul>
</li>
<li>Third</li>
</ul>
I need to get the <li> that has a child <ul> and that is a child of <ul> who is a child of <li>, and apply a style to it.
I know it sounds complicated, but in the example above I want to get only the <li> that says "Second - 3" which is inside a ul, which is a child of a li and has a child ul. I don't want to get any other <li>s.
I can't do this without getting also the li which says "Second", and I don't want that.
$("li > ul").addClass('whatever');
Use $("li ul li:has(ul)")
e.g:
$(function(){
var items = $("li ul li:has(ul)");
alert(items.html());
});
Working example: http://jsfiddle.net/EXzaa/
Try this:
$("li > ul > li").each(function(){
if ( $(this).find("ul").length > 0){
$(this).css({"font-weight":"bold"});
}
});
Unless I get you wrong this is simple. Try something like this:
$('#3').parent('li').addClass('whatever');
This will select the parent node of the ul element with the id = 3 (only if it is an li element)

Categories

Resources