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>
Related
Markup:
<ul>
<li role="presentation" class="active">
How to Install for iPad
</li>
<li role="presentation">
How to Install for Mac
</li>
<li role="presentation">
How to Install for PC
</li>
</ul>
When I use document.querySelectorAll('[role="presentation"]'); the result is array
[li.active,li,li]
How can I remove .active class and attach it to any other of these li with plain JS w/o JQuery the more simplest way?
Try this:
// remove active class from all elements
document.querySelectorAll('[role="presentation"]').forEach(function (el){
el.classList.remove("active");
});
// add class 'active' to last element
document.querySelectorAll('[role="presentation"]:last-of-type')[0].classList.add("active")
Notes:
'classList' will not work in IE9;
I think you have to modify adding class row, depending on your needs.
You can try something like this:
var ele = document.querySelectorAll('[role="presentation"]');
ele[0].classList.remove("active"); //Remove active class for first element
ele[ele.length- 1].classList.add("active"); //Apply active class for last element
console.log(ele)
var eleLi = document.querySelectorAll('[role="presentation"]');
for (var i = 0; i < eleLi.length; i++) {
//remove class active
eleLi[i].classList.remove('active');
}
//x is an index of li that you want to add the class. Such as 0,1,2
var x = eleLi.length - 1;
//add class active
eleLi[x].classList.add('active');
it is fairly simple.
I want to make a current class and put it on a link that is currently active
like this : <li class="li current"><a>Link1</a></li>
but before that, the JS should get all of element with class="li", loop through it and remove the class=" current" if any.
after looping end, then add class=" current" to the element which triggers the event.
for example if user clicks on link3 then JS should remove the class=" current" on link1 and then add class=" current" on link3
it would look like this : <li class="li current"><a>link3</a></li>
it looks like I cannot use getElementsByClassName() for event listener. what should I do to make an event listener then?
the HTML
document.addEventListener("DOMContentLoaded",function(){
var et = document.getElementsByClassName("li");
for(i=0; i <et.length; i++){
et[i].addEventListener("click",function(){
funclink(event);
});
};
});
function funclink(event){
//first get all element with class "li" and remove class " current"
//then add class " current" to the element which triggers the event
var slink = document.getElementsByClassName("li");
for(i =0; i < slink.length; i++){
slink[i].className = slink[i].className.replace(" current","");
}
event.currentTarget.className += " current";
}
.current {
color : orange;
}
<ul id="navmenu">
<li class="li current">Home</li>
<li class="li">Call Service
<li class="li"><a class="a-left" href="#">Rental</a></li>
<li class="li"><a class="a-left" href="#">Sales</a></li>
</li>
</ul>
As commented before, you will have to loop over elements to add eventListener. document.getElementsByClassName will return a NodeList.
Also, if you are only calling your function with event param, you can just pass function ref instead.
Also, instead again fetching all lis, just fetch those lis that has class current. This will reduce number of iterations.
You should use classList instead of className. It has many helpful methods like add, remove and toggle.
Edit 1
As you need to retain the selected li even after refresh, you will have to use client storage or query param to tell your JS about the selected element.
For security reasons, SO does not provide access to localStorage, so you will have to copy code and debug on local files.
document.addEventListener("DOMContentLoaded", function() {
var lis = document.getElementsByClassName("li")
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", funclink.bind(lis[i], i));
}
initializeUI();
});
function funclink(index, event) {
var lis = document.querySelectorAll('.li.current');
for(var i = 0; i< lis.length; i++){
lis[i].classList.remove('current');
}
this.classList.add('current');
setIndex(index)
}
function initializeUI(){
var lis = document.querySelectorAll('.li');
var index = parseInt(locatStorage.getItem('liIndex'));
lis[index || 0].classList.add("current");
}
function setIndex(index){
localStorage.setItem("liIndex", index);
}
function blockAnchors(){
var as = document.querySelectorAll('a');
for(var i = 0; i< as.length; i++){
as[i].onclick = function(){
return false
}
}
}
blockAnchors();
.current{
background: #ddd;
}
<ul id="navmenu">
<li class="li">Home</li>
<li class="li">Call Service
<li class="li"><a class="a-left" href="?module=rental">Rental</a></li>
<li class="li"><a class="a-left" href="?module=sales">Sales</a></li>
</li>
</ul>
Note: I have added a blockAnchors to stop navigation on a's click. This is just for demonstration.
Array of elements doesn't have to initialized two times.
Using li class is a useless. Modern browsers (IE8+) can use querySelector() (querySelectorAll()) (similiar functionality to the jQuery selector).
When document is ready we get array of links in #navmenu, we add listeners to them.
funclink function removes all classes from links and then sets class "current" to the element, that has triggered that function.
var slink; //prepare global scope var that will be filled with link elems
document.addEventListener("DOMContentLoaded", function() {//wait for document to be loaded
slink = document.querySelectorAll("#navmenu li");//fill global var with array of link elems
for (i = 0; i < slink.length; i++) {//add click listener to all link elems
slink[i].addEventListener("click", function() {
funclink(event);
});
}
});
function funclink(event) {
for (i = 0; i < slink.length; i++)slink[i].className = ""; //remove all current classes
event.currentTarget.className = "current"; //add current class to the element that triggered fnc
}
a {
color: blue;
}
.current,
.current a {
color: red;
}
<ul id="navmenu">
<li class="current">Home</li>
<li>Call Service
<li><a class="a-left" href="#?module=rental">Rental</a></li>
<li><a class="a-left" href="#?module=sales">Sales</a></li>
</li>
</ul>
There are <li> elements that one of them has class="current". I want to decide which of <li> is current. Here is view:
#{
int k = 10; //this will change in every request
}
<ul class="car">
#foreach (var item in modelCount)
{
<li
#{if (item.Id == k) { <text>class="current"</text>} }>
#item.Name
</li>
}
</ul>
This works, but the first <li> is always current by default. When first element is current by my expression, everything is ok, but otherwise, <ul> has 2 current <li>.
How can I solve this problem with jquery function?
Edit:
I need:
If <li> elements have 2 current classes, to remove the first of them.
function removeDuplicateCurrentClass(){
var currentListElements = [];
$('ul.car li').each(function(){
if($(this).hasClass('current'))
currentListElements.push(this);
});
if(currentListElements.length > 1)
$(currentListElements[0]).removeClass('current');
//if more than one current class exist: remove the first one
}
$(function(){
removeDuplicateCurrentClass();
//or simply
if($('ul.car li.current').length > 1)
$('ul.car li.current:first').removeClass('current');
});
I have menu list that contains:
<ul class="content_menu tabs">
<li class="pager_link_0_active"></li>
<li class="pager_link_1"></li>
<li class="pager_link_2"></li>
<li class="pager_link_3"></li>
<li class="pager_link_4"></li>
<li class="pager_link_5"></li>
<li class="pager_link_6"></li>
<li class="pager_link_7"></li>
<li class="pager_link_8"></li>
</ul>
What I want to do is when particular link is clicked I need to remove active from li class name that contains active (e.g pager_link_0_active) and add active to the li that is clicked (e.g pager_link_2_active)
I know there is one way to make it:
$(".active").removeClass("active");
$(this).addClass("active");
but in my situation, active is not seperated, it is part of class name.
According to standards ul can contain only element but what you want can be achived these way:
$(function () {
$('ul.content_menu.tabs a.tab').click(function () {
var newActive = $(this);
if (newActive.hasClass('active')) {
return;
}
var oldActive = $('ul.content_menu.tabs a.tab.active');
oldActive.removeClass('active');
var oldIndex = $('ul.content_menu.tabs a.tab').index(oldActive);
oldActive.children().attr('class', 'pager_link_' + oldIndex);
var newIndex = $('ul.content_menu.tabs a.tab').index(newActive);
newActive.addClass('active');
newActive.children().attr('class', 'pager_link_' + newIndex + '_active');
});
});
Here is fiddle
It would be better to make it a separate class <li class="pager_link_1 pager_active">, then you can remove and add pager_active easily.
If the LI will always have just one class, try this:
var active_li = $(".active li");
var active_class = active_li.attr("class");
active_li.attr("class", active_attr.replace("_active", "");
var this_li = $(this).children("li");
var this_class = this_li.attr("class");
this_li.attr("class", this_class+"_active");
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];
}