Get all LI elements in array - javascript

How can i make JS select every LI element inside a UL tag and put them into an array?
<div id="navbar">
<ul>
<li id="navbar-One">One</li>
<li id="navbar-Two">Two</li>
<li id="navbar-Three">Three</li>
<li id="navbar-Four">Four</li>
<li id="navbar-Five">Five</li>
</ul>
</div>
Can i make it so JS gets each of them into an array eg
navbar['0'] would return document.getElementById("navbar-One")?

You can get a NodeList to iterate through by using getElementsByTagName(), like this:
var lis = document.getElementById("navbar").getElementsByTagName("li");
You can test it out here. This is a NodeList not an array, but it does have a .length and you can iterate over it like an array.

After some years have passed, you can do that now with ES6 Array.from (or spread syntax):
const navbar = Array.from(document.querySelectorAll('#navbar>ul>li'));
console.log('Get first: ', navbar[0].textContent);
// If you need to iterate once over all these nodes, you can use the callback function:
console.log('Iterate with Array.from callback argument:');
Array.from(document.querySelectorAll('#navbar>ul>li'),li => console.log(li.textContent))
// ... or a for...of loop:
console.log('Iterate with for...of:');
for (const li of document.querySelectorAll('#navbar>ul>li')) {
console.log(li.textContent);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<div id="navbar">
<ul>
<li id="navbar-One">One</li>
<li id="navbar-Two">Two</li>
<li id="navbar-Three">Three</li>
</ul>
</div>

QuerySelectorAll will get all the matching elements with defined selector. Here on the example I've used element's name(li tag) to get all of the li present inside the div with navbar element.
let navbar = document
.getElementById("navbar")
.querySelectorAll('li');
navbar.forEach((item, index) => {
console.log({ index, item })
});
<div id="navbar">
<ul>
<li id="navbar-One">One</li>
<li id="navbar-Two">Two</li>
<li id="navbar-Three">Three</li>
<li id="navbar-Four">Four</li>
<li id="navbar-Five">Five</li>
</ul>
</div>

If you want all the li tags in an array even when they are in different ul tags then you can simply do
var lis = document.getElementByTagName('li');
and if you want to get particular div tag li's then:
var lis = document.getElementById('divID').getElementByTagName('li');
else if you want to search a ul first and then its li tags then you can do:
var uls = document.getElementsByTagName('ul');
for(var i=0;i<uls.length;i++){
var lis=uls[i].getElementsByTagName('li');
for(var j=0;j<lis.length;j++){
console.log(lis[j].innerHTML);
}
}

var allElmnts = document.querySelectorAll("ul");
var arr = [];
arr.length = allElmnts.length;
for(var i = 0; i < allElmnts.length; i++){
arr[i] = allElmnts[i];
}

Related

How to get all list items from an unordered list in HTML with JavaScript or jQuery?

How to reach ul list each value by js or jq to use it to reach any parts in html ?
var nav = document.getElementsByClassName('navigation'),
item = nav.getElementsbyTagName('li'),
i;
for(i =0;i<item.length;i++ ){
console.log(item[i].childNodes);
i++;
}
This snippet will help you understand how to capture and use the values inside a ul tag. In this example I put the values inside an array and then printed them. This example is completed by jQuery.
let myArray = [];
function putListToMyArray(){
$('#myUl > li').each(function(){
myArray.push($(this).text());
});
$('#willAppend').html(myArray);
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<ul id="myUl">
<li>something 1...</li>
<li>something 2...</li>
<li>something 3...</li>
<li>something 4...</li>
<li>something 5...</li>
</ul>
<button onClick="putListToMyArray()">Put them in an array</button>
<hr />
<span id="willAppend">Array will append here...</span>
You have some alternatives:
querySelectorAll()
This method returns a NodeList
Suppose you have a simple list you can get the node values like this:
// Get all nodes with querySelectorAll
const elements = document.querySelectorAll('li');
// Iterate over elements
elements.forEach(element =>
// Add click event to every node
element.addEventListener('click', () => {
console.log(element.innerText);
}));
// Log values
elements.forEach(element => console.log(element.innerText));
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
If you want to reduce the li elements you can assign a class like this:
// Get all nodes with querySelectorAll
const elements = document.querySelectorAll('li.menu');
elements.forEach(element => console.log(element.innerText));
<ul>
<li class="menu">1</li>
<li class="menu">2</li>
<li class="menu">3</li>
</ul>
getElementByClassName()
This method returns an html collection
Here you can get the same result, but you need to assign a class name to the li elements:
// Get elements by class name
const elements = document.getElementsByClassName('menu');
// Iterate over the html collection
for(let i = 0; i < elements.length ; i++){
// Add event listener to click event
elements[i].addEventListener('click', () => {
// Log values
console.log(elements[i].innerText);
})
}
// Log values
for(let i = 0; i < elements.length ; i++){
console.log(elements[i].innerText);
}
<ul>
<li class="menu">1</li>
<li class="menu">2</li>
<li class="menu">3</li>
</ul>

using loop to change class of DOM elements

I am trying to create a loop that will change the class of every item in a list, but it seems that each time the loop access the list, it get's shorter after each itteration
for example:
html code:
for(let i = 0; i<document.getElementsByClassName('list').length;i++){
document.getElementsByClassName('list')[i].className="student";
}
<ul class="list">
<li>John</li>
<li>Pete</li>
</ul>
<ul class="list">
<li>David</li>
<li>Sarah</li>
<li>Dan</li>
</ul>
Can someone please explain why is it happening?
Thanks!
getElementsByClassName returns a live html collection. So when you alter index [0] it is dropped from the collection. So the item that was in [1] is not at [0].
You either loop backwards, you use a while loop, or use modern way with querySelectorAll
I think #epascarello answer explains, this is the additional part with querySelectorAll
getElementsByClassName returns a live html collection. So when you
alter index [0] it is dropped from the collection. So the item that
was in 1 is not at [0].
You either loop backwards, you use a while loop, or use modern way
with querySelectorAll
you can use querySelectorAll
let c = document.querySelectorAll("ul");
let i;
for (i in c) {
c[i].className = 'student';
}
.student{
color: red;
}
<ul class="list">
<li>John</li>
<li>Pete</li>
</ul>
<ul class="list">
<li>David</li>
<li>Sarah</li>
<li>Dan</li>
</ul>
The problem is that you are using the parent element, you should get all li and not anul.
Try this:
const listItems = document.querySelectorAll('.list li')
for(let i = 0; i < listItems.length; i++) {
listItems[i].classList.add("student");
}
You can use higher order function:
[...document.getElementsByClassName("list")].forEach((element) => {
element.className = "student";
});
two things can be improved in your code; first using storing result of document.getElementsByClassName in a variable and since reading DOM is expensive, and second thing is to use querySelectorAll instead of getElementsByClassName; here is your code re-written:
let elements = document.querySelectorAll('.list');
setTimeout(()=>{
for(let i = 0; i<elements.length;i++){
elements[i].className="student";
}
}, 2000)
.list{color: red}
.student{color: blue}
<ul class="list">
<li>John</li>
<li>Pete</li>
</ul>
<ul class="list">
<li>David</li>
<li>Sarah</li>
<li>Dan</li>
</ul>

Javascript to get the active li class name

I need to get the class name of the active <li> on different checkout steps on my page as they are called by javascript.
For example:
Step1
<ul class="checkout-bar">
<li class="active first"></li>
<li class="next"></li>
<li class="last"></li>
</ul>
Step2
<ul class="checkout-bar">
<li class="visited first"></li>
<li class="active"></li>
<li class="last"></li>
</ul>
Step3
<ul class="checkout-bar">
<li class="visited first"></li>
<li class="visited "></li>
<li class="active last"></li>
</ul>
So i need to be able to pass to the datalayer at each step:
step1
"active first"
Step2
"active"
Step3
"active last"
I've tried this but it doesn't work:
function() {
var element=document.querySelector('ul.checkout-bar > li');
return element ? element.value : undefined;
}
You should filter the "li" elements with "active" class and return classList.value:
function foo() {
var element=document.querySelector('ul.checkout-bar > li.active');
return element ? element.classList.value : undefined;
}
You missed 1st thing in querySelector is you didnot mention active class. 2nd thing is that you make use of value(no such property in javascript for HTML elements other than input, instead make use of innerText and innerHTML attribute to get required content) and condition. I would like to suggest code like below. But remember querySlector always create an array of element and will always point first element.
<ul class="checkout-bar">
<li class="active first">hello1</li>
<li class="next">hello2</li>
<li class="last">hello3</li>
</ul>
<script>
alert(activeText());
function activeText()
{
var element=document.querySelector('ul.checkout-bar > li.active');
return (typeof element != 'undefined')?element.innerText : undefined;
}
</script>
If you need to have the classList of an element, be aware that it is not a String, nor is it an Array, it's a DOMTokenList which is a set of whitespace delimited token (a token apparently is a string without quotes.) The best way to approach one is to think of it as an array-like object with its own set of methods.
Demo
Details commented in Demo
//~~~~~~~~~~~~~~~~~~~~~~~~setActive()~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* setActive() function is provided in order to make this Demo interactive. It is not the primary part of the answer, so I will forego the step-by-srep explination. */
/* Anytime a list item is clicked, setActive() will toggle .active class and add the .visited class as well. */
document.querySelector('.checkout-bar').onclick = setActive;
const lis = document.querySelectorAll('li');
function setActive(e) {
if (e.target.tagName === "LI") {
for (let i = 0; i < lis.length; i++) {
lis[i].classList.remove('active');
}
e.target.classList.add('active', 'visited');
}
console.log(getClasses(".active", items));
}
//~~~~~~~~~~~~~getClasses(selector, items)~~~~~~~~~~~~~~~~~~~~~~~
/* Create an array of strings that represent the classes you want
|| to find on any given selector.
*/
var items = ["active", "visited", "first", "middle", "last"];
/* 1st parameter is a selector of the element you wish to examine
|| 2nd parameter is an array of classes you want to search for
*/
/* A classList is accessed through the DOMTokenList interface.
|| A DOMTolkenList is not a string nor is it an array, it is a set
|| of tokens delimited by a space. It's best to regard a DTL as an
|| array-like object.
*/
/* getClasses() function will collect/compare the classList of any
|| given element by a selector (needs to be selector syntax) to an
|| array of classNames. It will return an array of matches.
*/
function getClasses(selector, items) {
let node = document.querySelector(selector);
let list = node.classList;
var matches = [];
items.forEach(function(item) {
if (list.contains(item)) {
matches.push(item);
}
});
return matches;
}
var result = getClasses(".active", items);
console.log(result);
li {
list-style: none;
cursor: pointer;
line-height: 2;
}
.visited {
color: tomato
}
.active {
background: #333;
color: #fc0;
}
/* For Demo Purposes Only */
.as-console-wrapper.as-console-wrapper {
max-height: 75px
}
<ul class="checkout-bar">
<li class="first">First</li>
<li class="middle">Middle</li>
<li class="last active">Last</li>
</ul>
If you want to get active element classes,content or Dom try this :
function() {
‍‍var element=document.querySelector('ul.checkout-bar > li.active');
// If you want class list in string divided by space :
var classList= element ? element.classList.toString() : undefined;
// If you want active element ;
var activeElem=element?element:undefined;
// If want text content of active element :
var content=element?element.textContent:undefined;
// Return variable that want :
return classList;
}
you can try this to get the second class name in the class attribute.
Consider below sample
<ul class="checkout-bar">
<li class="active first"></li>
<li class="next"></li>
<li class="last"></li>
</ul>
<script>
var nam=$('.checkout-bar li.active').attr('class').split(' ')[1];
console.log(nam); //will return "first" as class name since li having
//class active has another class after active is "first"
</script>

Find the place of an element

I have a list
<ul>
<li class="list_1">a</li>
<li class="list_2">b</li>
<li class="list_3">c</li>
<li class="list_4">d</li>
</ul>
This is in a carousel, so that the list items change position (1-2-3-4, 2-3-4-1, 3-4-1-2, 4-1-2-3,...)
How can I find out, using javascript, which item is in, let's say, second and third position?
In the beginning, the list_2 and list_3 are in second and third position, after one cycle, the list_3 and list_4 are in second and third position, etc.
How to find out what list is in those positions, while I cycle through? For starters I just need to see it displayed in console with console.log(), something like:
On 2nd place is list_3, and on third is list_4.
Tried with this but doesn't work:
var $list_items = $(this).find('ul li');
$list_items.each(function(i,j){
$(this).addClass('list_' + (i+1));
console.log($list_items.eq(2).attr('class'));
});
I'm using $(this) because my original lists are enclosed in a div, and originally lists had no class, so I added them.
One approach is to use map() and index() to create an array of the element's class-name and index, obviously this depends on what, precisely, you want to find; but your question is somewhat vague on the result you want:
function mapIndices() {
// iterate over the 'ul li' elements, forming a map:
return $('ul li').map(function() {
// returning the className (classes) of the element and its index amongst
// siblings:
return this.className + ': ' + $(this).index();
// converting to an Array:
}).get();
};
// this is just a simple trigger to move the elements,
// to demonstrate binding the function:
$('#change').on('click', function() {
var ul = $('ul');
ul.find('li:first-child').appendTo(ul);
console.log(mapIndices());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="change">advance positions</button>
<ul>
<li class="list_1">a</li>
<li class="list_2">b</li>
<li class="list_3">c</li>
<li class="list_4">d</li>
</ul>
If, however, you simply want to find out which element is in a specific position:
$('#change').on('click', function() {
var ul = $('ul');
ul.find('li:first-child').appendTo(ul);
// bear in mind that JavaScript has zero-based indexing,
// 2 is the index of third element, not the second:
console.log(ul.find('li').eq(2));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="change">advance positions</button>
<ul>
<li class="list_1">a</li>
<li class="list_2">b</li>
<li class="list_3">c</li>
<li class="list_4">d</li>
</ul>
References:
eq().
find().
get().
index().
map().
on().
Array manipulation:
var arr = $('li').get(); // http://api.jquery.com/get/
// var arr = ["aa","bb","cc","dd"]; // you can try also using this guy
function doIt(){
if(this.id==="next") arr.push( arr.shift() ); // send first to last
else arr.unshift( arr.pop() ); // send last to first
$('ul').html( arr );
}
$('#prev, #next').on('click', doIt);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="prev">PREV</button>
<button id="next">NEXT</button>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>-----------</li>
</ul>
First give an id/class to the ul:
<ul id="mylist">
<li class="list_1">a</li>
<li class="list_2">b</li>
<li class="list_3">c</li>
<li class="list_4">d</li>
</ul>
Using jQuery to access the 'li' element at 2nd position:
var second_li = $('#mylist').find('li')[1]; // to access 2nd li use index 1
var second_li_class = $(second_li).attr('class'); // second_li_class will be equal to 'list_2'
var second_li_content = $(second_li).html(); // second_li_content will be equal to 'b'

How do I use the DOM to modify this?

How do I modify the style of the li element using DOM?
<div id="tabbed-boosts">
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</div>
getElementById('tabbed-boosts').childNodes will get me to the UL, how do I modify the LI?
Also needs to work in IE6...
var lis = document.getElementById( 'tabbed-boosts' ).getElementsByTagName( 'li' );
for ( var i = 0; i < lis.length; i++ )
{
lis[i].style.backgroundColor = '#' + Math.round( Math.random() * 0xFFFFFF ).toString( 16 );
}
The issue with using document.getElementById( 'tabbed-boosts' ).getElementsByTagName( 'li' ) will show up if you start using nested lists. Using childNodes property will give you access to the direct children of that particular ul element. For example
<ul id='tabbed-boosts'>
<li>...</li>
<li>
<ul>
<li> ... </li>
</ul>
</li>
<li>... </li>
</ul>
using getElementsByTag will return ALL the 'li' elements within tabbed-boosts sub-tree, where childNodes will only return the first level 'li' elements. In the example above you'd receive a collection of 4 elements using getElementById, including the nested LI whereas you would only receive a collection of 3 li elements using myUl.childNodes (shown below)
var myUl = document.getElementById('tabbed-boosts');
var myLi = myUl.childNodes;
for(var i = 0; i<myLi.length; i++)
{
myLi[i].style....;
// do whatever you want to the li items;
}

Categories