I'm trying to get rid of jquery from my page and rewrite some functionalities to pure js. There are 2 lists with class work, containing a few li elements. Each li element should have an action on click to add class 'active' to it.
In jquery it is very simple:
$('.work li').on('click', function () {
var that = $(this);
that.parent().find('li.active').removeClass('active');
$(this).addClass('active');
})
Is there a nicer solution in pure js rather than making something like this with nested loops:
var lists = document.getElementsByClassName('work');
for(var i=0; i<lists.length; i++){
var children = lists[i].querySelectorAll('li');
for(var j=0; j<children.length;j++){
children[j].addEventListener();
}
}
There are 2 lists with class work, containing few li elements. Each li element should have an action on click to add class 'active' to it.
You could create that entire functionality by adding an event listener to all li
s returned by the querySelectorAll
. The querySelectorAll
returns a nodeList and not an array, so need to map it in order to iterate it. However, note that we are still iterating the set.
Example Snippet:
var lists = document.querySelectorAll(".work li"),
doSomething = function() {
[].map.call(lists, function(elem) { elem.classList.remove("active") });
this.classList.add("active");
};
[].map.call(lists, function(elem) {
elem.addEventListener("click", doSomething, false);
});
li { cursor: pointer; }
.active { background-color: yellow; }
<ul class="work"><li>One</li><li>Two</li><li>Three</li></ul>
<ul class="work"><li>Four</li><li>Five</li><li>Six</li></ul>
In fact you could also use event delegation and add event listener only on the ul
and then use the event.target
to handle your routine. This is better than adding an event listener to each and every li
, in case there are many of them. There will be only as many handlers as ul
s.
Is there a nicer solution in pure js rather than making something like this with nested loops
Not really. You have to iterate over the set of elements anyway. Nicer in terms of jazzy, yes. Nicer in terms of avoiding the loops, no. Nicer in terms of efficiency, well yes. Compare the above vanilla javascript code with the jQuery one in your question:
$('.work li').on('click', function () { // internally will iterate and add listener to each li
var that = $(this);
that.parent().find('li.active').removeClass('active'); // go to parent and then find li
$(this).addClass('active');
});
.