I have built an collapsable tree with li and ul elements. I am using the jQuery.fadeIn and jQuery.fadeOut to collapse respectively show branches in the tree by applying these functions to nested ul elements.
Works nearly perfect, but a small problem appears when collapsed branches are shown: If the branch to show contains collapsed branches itself, the collapse state of these branches will not be preserved meaning that all the child branches will also be shown.
<li id="branch1"> Item 1
<ul style="display:none">
<li> Branch 1
<ul style="display:none">
...
</ul>
</li>
</ul>
</li>
If I now call the following, also the Branch 1 will be faded in.
jQuery("#branch1 ul").fadeIn();
Its because your query is getting both the elements. $('#branch1 ul') returns them both. Use this to get just the first one:
var a= jQuery("#branch1>ul")
a.fadeIn();
It was my problem by applying the function to multiple elements using an incorrect jQuery-selector. The function should work as expected.
Your code structure be like this
<ul>
<li id="branch1"> Item 1 </li>
<ul style="display:none">
<li> Branch 1</li>
<ul style="display:none">
<li> Branch 3</li>
</ul>
</ul>
in this structure your jQuery code will be work .
jQuery("#branch1 ul").fadeIn();
Related
I've been searching a lot for this, without any solution so far. As you might also have seen the topic title might be a little hard to interpret and that's because I'm not quite sure how to explain it shortly.
The problem
Looking at the HTML below, I know the class of the last element called "active" and this element is chosen dynamically in jQuery, based on which site the visitor is on currently - i.e. different elements has this class depending on the site. On another site the li with class first-sub-li could have the class active (or for that matter the li with class first). This class is, as said, added dynamically based on the site with jquery. From here on I wish to identify the parent of the element with active which is a direct descendent of top-parent and add a class called active-parent to this. I.e. in the case below i wish to add the active-parent class to the li with class second.
EDIT: Please note that the "depth" of the list can vary, therefore also requiring a "dynamic" approach to picking out the parent. I completely forgot this in the initial writing.
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li"></li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li">
<ul class="second-sub-sub-ul">
<li class="second-sub-sub-li active"></li> <!-- Here -->
</ul>
</li>
</ul>
</li>
</ul>
So far I've tried the following jQuery without succes as it doesn't identify it.
EDIT 2: This actually does work, but initially it didn't as it apparently was called before the class was loaded, despite appearing later in the javascript document. Wrapping it in a $(window).on("load", function() solves the problem as shown below.
$(window).on("load", function() {
$(".active").closest("#top-parent > li").addClass("active-parent");
});
The original code was just $(".active").closest("#top-parent > li").addClass("active-parent");
You can start traversing up with .parent(), it will excluding the self li.
$(".active").parent().closest("li").addClass("active-parent");
You can use :has() selector
$('#top-parent > li:has(.active)').addClass("active-parent");
$('#top-parent > li:has(.active)').addClass("active-parent");
.active-parent {
background-color: red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li"></li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li">
<ul class="second-sub-sub-ul">
<li class="second-sub-sub-li active"></li>
<!-- Here -->
</ul>
</li>
</ul>
</li>
</ul>
I think this is what you're looking for. Find all li which are direct descendants of topmost-parent and filter that for the one which has a child .active. Apply the class.
$('#top-parent > li').filter(function(e){
return $(this).find('.active').length>0;
}).addClass("active-parent");
.active-parent{background-color:red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li">1.1</li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li active">2.1</li> <!-- Here -->
</ul>
</li>
</ul>
I am quite new to everything about html/js/css. Right now i need a list so i decided to use a list that u can slidetoggle. I looked it up and found how to recreate that effect (the code below):
var subMenu = jQuery(".tableContainer ul li ul li");
var linkClick = jQuery(".tableContainer ul li").filter(":has(ul)");
linkClick.click(function () {
$(this).find('ul li').slideToggle(200);
});
(if you are wondering about the 2 ul and li, it is because i want that list in another list, but that doesn t change the question so i didn t include it in my explanation)
Since i am quite new to this topic, i only understand like 70% of what is happening. But for my project i need to work with the elements of the list(the ones which were hidden and after sliding down visible). I want to do stuff that requires clicking them like highlight on click, but now i encounter the problem, that the code i posted makes the slide effect being triggered not only by the headline, but also by the elements. So i cannot click elements without minimizing the list with the same click (obviously the elements are hidden again then). I hope you guys can explain me how to make the function only be triggered by the head object and not by the whole list element(head and the expanded list).
Look the slide effect is being triggered not only by the headline but also by the elements that are because the concept of event bubbling which basically means in case of click event if you clicked a child element the event is bubbled by default to the parent elements tree till the document level firing any registered event handler. so when you click the element you click the headline too, so you need to add another child element and handle the click on it something like this:-
<div class="tableContainer">
<ul>
<li> <span>menu 1</span>
<ul>
<li>link 1</li>
</ul>
</li>
<li><span> menu 2</span>
<ul>
<li>link 2</li>
</ul>
</li>
<li><span> menu 3</span>
<ul>
<li>link 3</li>
</ul>
</li>
<li> <span>menu 4</span>
<ul>
<li>link 4</li>
</ul>
</li>
</ul>
</div>
$(function() {
var subMenu = jQuery(".tableContainer ul li ul li");
var linkClick = jQuery(".tableContainer span");
console.log(linkClick.length);
linkClick.click(function() {
console.log('clicked');
$(this).siblings('ul').slideToggle(200);
});
});
Full Working Example Here
Hope this answers your question.
this is my site.
this is how I finally make it look like
I want to divide the the menu list items into two sub menu say menu left and right. And then wrap them in a div. This is make it easy for me to style them and this way they would stay responsive as well.
Now, I have been trying to achieve this by
jQuery( ".menu-item-580", ".menu-item-583",".menu-item-584",".menu-item-563").wrapAll("<div class='new' />").after(".menubar-brand");
I have trying this in browser console.
I also tried same above code by using appendTo() instead of after()
But, still no luck.
In your code you're basically doing this:
<ul>
<li>
<div class="new">
<li>
<li>
</div>
<li>
</ul>
which is not a valid markup.
The easiest way to goup <li>s would be to assign different additional css classes to different parts of the list:
<ul>
<li class="group1">
<li class="group1">
<li class="group2">
<li class="group2">
</ul>
Also, have a look at this: Is there a way to group `<li>` elements?
Imagine an unordered list:
<ul id="something">
<li class="parent">parent</li>
<li class="parent">parent</li>
<li class="child">child</li>
<li class="child">child</li>
<li class="parent">parent</li>
<li class="parent">parent</li>
<li class="child">child</li>
<li class="child">child</li>
</ul>
I want to turn the above example into:
<ul id="something">
<li class="parent">parent</li>
<li class="parent">parent</li>
<ul>
<li class="child">child</li>
<li class="child">child</li>
</ul>
<li class="parent">parent</li>
<li class="parent">parent</li>
<ul>
<li class="child">child</li>
<li class="child">child</li>
</ul>
</ul>
I've successfully done this based on a solution found here: https://stackoverflow.com/a/9023265/1447679
$('#Something').children('li.child:not(li.child + li.child)').each(function() {
$(this).nextUntil('li.parent').andSelf().wrapAll('<ul />');
});
If I don't use the :not(selector + selector) it causes strange continual embedding of ul > li > ul > li, etc.
So basically I just want to clearly understand it.
Working
It looks like the code describes step by step what it does.
It selects the first child, and for each of those, collect all its siblings until the next parent, including itself, and wrap that collection into an ul.
or:
Annotated
$('li.child:not(li.child + li.child)') selects each first child (a child that is not preceeded by another child).
For each of those (.each(function() {), collect all its siblings until the next parent (nextUntil('li.parent')), including itself (andSelf), and wrap that collection into an ul (wrapAll('<ul>')).
not(child+child) and nextUntil
So the magic is in the combination of not(li.child + li.child) (which selects the first child of each 'group'), and the nextUntil method (which selects all subsequent children until the next parent).
If you remove the not(..+..), you will get all children and their subsequent siblings, resulting in overlapping groups which all get wrapped. That seriously messes up your HTML.
Other relevant differences
There are a couple of small differences between your version and Dan A's version in the other thread:
First of all, that one works with only one class, because he uses not(li.child) as a selector, so basically everything that is not a child is regarded a parent.
Secondly, he wraps it in <li><ul> instead of just <ul>. This makes sense, because the items are in a list already. The collection of children needs to be wrapped in an li to keep the parent list valid. Elements other than li are not valid as direct children of ul elements. Your code would put an ul inside the parent ul, technically making the HTML invalid. The browser will probably fix this for you though, by adding the implied li.
Basically what the :not(li.child + li.child) seletor does is that it only selects the first occurring li.child element in a group of immediately consecutive li.child elements.
If we dissect the markup, we can see which li.child satisfy the selector:
<ul id="something">
<li class="parent">parent</li>
<li class="parent">parent</li>
<li class="child">child</li> <!-- satisfies, not immediate sibling of li.child -->
<li class="child">child</li> <!-- fails, because is immediate sibling of li.child -->
<li class="parent">parent</li>
<!-- and etc -->
</ul>
To view it in a more direct way:
<ul id="something">
<li class="parent">parent</li>
<li class="parent">parent</li>
<li class="child">child</li> <!-- is not li.child+li.child -->
<li class="child">child</li> <!-- is li.child+li.child -->
<li class="parent">parent</li>
<li class="parent">parent</li>
<li class="child">child</li> <!-- is not li.child+li.child -->
<li class="child">child</li> <!-- is li.child+li.child -->
</ul>
What is happening is you're selecting the li element which have the class .child and whose previous sibling don't have the .child class.
Explanation:
The li.child + li.child selects an li element with the child class, which comes directly after a li element with the child class
The :not() excludes whatever you throw inside the ().
I have a menu and I want an element with a class of active, parent element's sibling element to be clicked automatically on page load.
Here is my HTML:
<li class="level1">
<span class="level1 drop-down clicked">Oranges</span>
<ul class="level2" style="display: block;">
<li class="level2">Peel</li>
<li class="level2">Pips</li>
<li class="level2 active">Pegs</li>
</ul>
</li>
I've tried
jQuery('li.level2.active').parent('li.level1').children('span.level1.drop-down').click();
but it does not work. I'm not sure if I'm using the parent & children method's properly.
Although, jQuery("span.drop-down.level1").click(); does work, but it selects all the elements with that class which I would like to avoid.
Try this:
jQuery('li.active').closest('li.level1').find('span.level1.drop-down').trigger('click');
Because the li.level1 is two steps up, you need .parents(), which selects up multiple levels, instead of .parent(), which is only one.
jQuery('li.level2.active').parents('li.level1').children('span.level1.drop-down').click();
^^^^