How can I modify the below code so that I get only the parent li within the first ul and then with another variable get the sub li of the given sub ul?
$(function () {
var vULSize = $("ul li").size();
console.log(vULSize);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li>First</li>
<li>Second
<ul>
<li>Second Sub 1</li>
<li>Second Sub 2</li>
</ul>
</li>
<li>Third</li>
<li>Third
<ul>
<li>Third Sub 1</li>
<li>Third Sub 2</li>
</ul>
</li>
</ul>
Fiddle: http://jsfiddle.net/0sp9pohr/
You can ignore all li's that are descendants of an li like
$(function() {
var vULSize = $("ul li:not(li li)").size();
snippet.log(vULSize);
});
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>First</li>
<li>Second
<ul>
<li>Second Sub 1</li>
<li>Second Sub 2</li>
</ul>
</li>
<li>Third</li>
<li>Third
<ul>
<li>Third Sub 1</li>
<li>Third Sub 2</li>
</ul>
</li>
</ul>
First you need to wrap it all in something, say for instance a div with the id container. Then you can do something like this:
var vULSize = $("#container > ul > li").length;
The > selector gives you only the direct descendants.
If you want to count the number of list elements one level down, this will give you an array with the result:
var counts = $("#container > ul > li").map(function() {
return $(this).find("li").length
}).get();
As pointed out in comments, you should use .length instead of .size().
Related
Aparently shuffling an array is not so complicated:
How to randomize (shuffle) a JavaScript array?
But what if I have to (Html DOM) lists that are synchronized and I need to shuffle the order of the elements, but they should have the same final order?
For example, initial state:
<!-- List A) -->
<ul>
<li>First title</li>
<li>Second Title</li>
<li>Thrid title</li>
</ul>
<!-- List B) -->
<ul>
<li>First text</li>
<li>Second text</li>
<li>Thhird text</li>
</ul>
After shuffle:
<!-- List A) -->
<ul>
<li>Second title</li>
<li>First Title</li>
<li>Thrid text</li>
</ul>
<!-- List B) -->
<ul>
<li>Second text</li>
<li>First text</li>
<li>Third text</li>
</ul>
How can this be achieved?
Get length of items and loop through it and in loop generate random number and using generated number select an li and append it end of parent.
var ul = document.querySelectorAll("ul");
var length = ul[0].querySelectorAll("li").length;
for (var i=0; i<length; i++){
var rand = Math.floor(Math.random()*(length));
ul.forEach(function(ele){
ele.appendChild(ele.querySelectorAll("li")[rand]);
});
}
<ul>
<li>First title</li>
<li>Second Title</li>
<li>Thrid title</li>
</ul>
<ul>
<li>First text</li>
<li>Second text</li>
<li>Thhird text</li>
</ul>
Also you can use jQuery to write less code
var $ul = $("ul:first li");
$ul.each(function(){
var rand = Math.floor(Math.random()*$ul.length);
$("ul").each(function(i, ele){
$("li", ele).eq(rand).appendTo(ele);
});
});
$("button").click(function(){
var $ul = $("ul:first li");
$ul.each(function(){
var rand = Math.floor(Math.random()*$ul.length);
$("ul").each(function(i, ele){
$("li", ele).eq(rand).appendTo(ele);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>
<ul>
<li>First title</li>
<li>Second Title</li>
<li>Thrid title</li>
</ul>
<ul>
<li>First text</li>
<li>Second text</li>
<li>Thhird text</li>
</ul>
You can easily shuffle an DOM html in various number of ways. One way that is easy to understand is to convert the DOM elements into an array, then randomly splice each element out of its parent array and append them back to the parent DOM element.
In my snippet below, I used jQuery to make the code easier to read, but it can be done with native javascript just as well.
$('#shuffle').click(function(){
var items = []; // start with an empty array
$('#list_a li').each(function(i,d){
items.push(d); // add all li items into the array in their current order
});
$('#list_a').html(''); // clear the ul list
// execute this loop as many times as items.length
for(var i=items.length-1; i>=0; i--) {
var r = Math.floor(Math.random()*items.length); // pick a random array position
var item = items.splice(r,1); // take that item out of the array
$('#list_a').append(item); // append it back to the ul
}
});
ul
{
background-color: #def;
display: inline-block;
border: 1px solid grey;
padding: 30px;
border-radius: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<b>List A</b>
<ul id="list_a">
<li>First Item</li>
<li>Second Item</li>
<li>Third Item</li>
<li>Fourth Item</li>
<li>Fifth Item</li>
</ul>
<button id="shuffle">Shuffle</button>
CMS, that I am using, generates such a code for menu:
<ul>
<li>second level menu</li>
<li>third level menu</li>
<li>third level menu</li>
</ul>
<ul>
<li>second level menu</li>
<li>third level menu</li>
</ul>
...
I would like to change the way of displaying the third level menu. Is it possible to change this code using javascript into:
<ul>
<li>second level menu
<ul>
<li>third level menu</li>
<li>third level menu</li>
</ul>
</li>
</ul>
<ul>
<li>second level menu
<ul>
<li>third level menu</li>
</ul>
</li>
</ul>
...
You need to differentiate li elements, so you can identify then, which should be first or next level elements. Setting data-attributes, I think is a not "so much bad solution".
Btw, below is only a boilerplate code, and will work verily for given structure. You need to grasp the logic - so you can apply it to other problems.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<ul>
<li data-level="2">second level menu</li>
<li data-level="3">third level menu</li>
<li data-level="3">third level menu</li>
</ul>
<ul>
<li data-level="2">second level menu</li>
<li data-level="3">third level menu</li>
</ul>
<script type="text/javascript">
var uls = document.querySelectorAll('ul');
for(var i=0; i<uls.length; i++) {
var children = uls[i].querySelectorAll("li");
var _children = Array.from(children).filter(e=> e.dataset.level == "3");
if (_children.length > 0) {
var newul = document.createElement("ul");
_children.map(e=>newul.appendChild(e));
uls[i].appendChild(newul);
}
}
</script>
</body>
</html>
is it possible, to add auto incremental classes to a list
<ul id="list">
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
</ul>
Now, If I hover on Element 3 then, add auto incremental classes to li like example below...
<ul id="list">
<li class="left2">Element 1</li>
<li class="left1">Element 2</li>
<li>Element 3</li>
<li class="right1">Element 4</li>
<li class="right2">Element 5</li>
</ul>
Again if hover on Element 1 then, add auto incremental classes to li like example below...
<ul id="list">
<li>Element 1</li>
<li class="right1">Element 2</li>
<li class="right2">Element 3</li>
<li class="right3">Element 4</li>
<li class="right4">Element 5</li>
</ul>
sorry about my poor English. Thank you.
$('li').hover(function() {
$('li').removeClass();
var next = $(this).nextAll();
next.each(function(i, v) {
$(this).addClass('right' + (i+1))
})
var prev = $(this).prevAll();
prev.each(function(i, v) {
$(this).addClass('left' + (i+1))
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="list">
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
</ul>
Use .prevAll() and .nextAll()
Description: Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector.
Description: Get all following siblings of each element in the set of matched elements, optionally filtered by a selector.
then iterate on the li and assign the index. make sure to remove the li classes so it wont stack up
Based on example, I cleared all the class in <li> when mouseenter anyone of the <li> and add new class for them.
left1+n will add to previous all <li> and right1+n will add to next all <li>
$("#list > li").on("mouseenter", function(){
$("#list > li").attr("class", "");
$(this).prevAll("li").each(function(i) {
$(this).addClass('left' + (i+1));
});
$(this).nextAll("li").each(function(i) {
$(this).addClass('right' + (i+1));
});
});
I have a navigation that looks like this:
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Basically, everly li can have an infinite amount of children uls. I need to get the number of the highest level
For example, right now I'd be looking for the number 4 as the second li has 4 Levels.
I tried two different methods:
First, my own attempt that failed miserably:
$count = 1;
$('.sub_navigation > .menu > li').each(function() {
countChildren($count);
});
function countChildren() {
$(this).children('ul').each(function() {
$count++;
console.log($count);
});
return($count);
}
Second, a way I took from stack overflow but that didn't work out for me either, only returning 0 everytime:
var arr = []; //populate the length of children into this array.
$('.sub_navigation ul').map(function (i) {
arr[i] = $(this).children('ul').length;
});
var maxValue = Math.max.apply(Math, arr); //get the max value from the array
console.log(maxValue);
Could someone please point me in the right direction? I sadly have no idea how to acieve this at all anymore.
Thanks a lot!
You can use parentsUntil() like
var temp = $('.sub_navigation li').map(function() {
return $(this).parentsUntil('.sub_navigation', 'ul').length;
}).get();
var max = Math.max.apply(Math, temp);
snippet.log('Count: ' + max)
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level
<ul>
<li>Fifth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Instead of going from top to bottom level you could do it the other way.
Check for each li how many ul ancestors it has
var ulAncestorsPerLi = $( '.sub_navigation li' ).map(function(){
return $(this).parentsUntil( '.sub_navigation', 'ul' ).length;
}).get(),
deepestLevel = Math.max.apply( Math, ulAncestorsPerLi );
alert( deepestLevel );
var ulAncestorsPerLi = $('.sub_navigation li').map(function() {
return $(this).parentsUntil('.sub_navigation', 'ul').length;
}).get(),
deepestLevel = Math.max.apply(Math, ulAncestorsPerLi);
alert(deepestLevel);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
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)