I am trying to remove a series of class elements from a page (.whatever in the example), and I would much appreciate if someone explain to me why this script works:
if (window.matchMedia("(min-width: 400px)").matches) {
var elements = document.getElementsByClassName('whatever');
for(var i=0; i<elements.length; i++) {
elements[i].style.display='none';
}
}
…and this one does not work at all:
if (window.matchMedia("(min-width: 400px)").matches) {
var elements = document.getElementsByClassName('whatever');
for(var i=0; i<elements.length; i++) {
elements[i].remove();
}
}
Because .getElementsByClassName() returns a live list, so when you remove an element from the DOM, that list gets actually shifted and your skipping every other element. Compare this to .querySelectorAll(), which does not return a live list; the elements will stay in the list even after removal and the loop will run as expected:
var elements = document.querySelectorAll('.whatever')
var i
for (i = 0; i < elements.length; i++) {
elements[i].remove()
}
The second example doesn’t work because the list of elements updates live. When for example the first element is removed, the elements list updates and what was the second element becomes the first.
One solution to this is to instead loop backwards through the elements.
Another solution that I prefer though, is to use a while loop instead.
while (elements.length > 0) {
elements[0].remove();
}