Remove a class name from multiple elements with pure JavaScript
This post examines all the ways multiple DOM elements can be manipulated. That can be done with a `while` loop or with recursion when using a live HTMLCollection.
A common issue for the commando coder is to manipulate multiple elements, it requires usually a loop, but not necessary if going the purely functional way by using recursion.
Here’s the manipulated HTML:
<div class="something active">foo</div>
<div class="something active">bar</div>
<div class="something active">baz</div>
<div class="something active">fooz</div>
<button class="button">Deactivate</button>
We want to remove those .active
classes when the “Deactivate” button is clicked.
For loop
First let’s use the imperative for
loop as a starting point.
var els = document.querySelectorAll('.something.active')
var button = document.querySelector('.button')
button.addEventListener('click', _removeClasses)
function _removeClasses() {
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('active')
}
}
That’s not too bad, but we can do better, we can use Document.getElementsByClassName()
to fetch the elements. Because: it returns an array-like object that is a live HTMLCollection
.
What does that mean actually? The bible says:
An HTMLCollection in the HTML DOM is live; it is automatically updated when the underlying document is changed.
The below while
loop will illustrate that better.
While loop
// This gives us a live `HTMLCollection`
var els = document.getElementsByClassName('something active')
var button = document.querySelector('.button')
button.addEventListener('click', _removeClasses)
function _removeClasses () {
while (els[0]) {
els[0].classList.remove('active')
}
}
Breakdown:
document.getElementsByClassName()
- Returns a live
HTMLCollection
rather than anodeList
. while (els[0])
- Goes on as long as there’s juice left in the collection
els[0].classList.remove('active')
- When a class name is removed, the element is removed from the collection, hence “live”.
Whenever there is a while
loop, recursion can be used instead.
Recursive function
As a reminder: recursion happens when a function calls itself. Here the _removeClasses
function calls itself after the if (els[0])
stop condition:
var els = document.getElementsByClassName('something active')
var button = document.querySelector('.button')
button.addEventListener('click', _removeClasses)
function _removeClasses() {
els[0].classList.remove('active')
if (els[0]) _removeClasses()
}
Every recursive function can be broken into 3 parts:
- The business logic:
els[0].classList.remove('active')
- The stop condition:
if (els[0])
- The recursion itself:
_removeClasses()
Demo
Conclusions
For me this was an eye opener in HTMLCollection
s. Hope it also helped you, drop a comment if you have something to add.
Comments
I tried to add the class back but can’t seem to make it work
var el = document.getElementsByClassName('something')
var btn2 = document.querySelector('.button2')
function _addClasses() {
console.log('I am clicked');
el[0].classList.add('active');
if (el[0]) _addClasses();
}
It worked with the for loop though
function _addClasses() {
for (var i = 0; i < el.length; i++) {
el[i].classList.add(‘active’);
}
}