Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript for loop suddenly breaks [duplicate]

Tags:

javascript

I have the following problem.

I generate a list with all the elements with a specific class. After that i'm looping throug them to replace the class.

As you can see here: https://jsfiddle.net/nafxLoLz/ only one of the 2 elements get replaced. The console.log clearly shows that the loop only goes through once. If I comment the 7 javascript code out. (See the fiddle) the loop works fine.

What did I do wrong?

Code:

var list = document.getElementsByClassName("default");
console.log(list.length);
for(var i = 0; i < list.length; i++)
{
  console.log(i);
  list[i].classList.add("red");
  list[i].classList.remove("default");
}
like image 746
BlueFire Avatar asked Dec 23 '22 23:12

BlueFire


2 Answers

getElementsByClassName gets a live nodeList of all the elements with the class default, the nodeList updates as the elements change.

When you remove the class default, the length of the live nodeList changes, so when you start iterating at the start, for every element that has the class removed, the length decreases by 1.

When you get halfway, you've changed half the elements, and you're half way in the loop, and the length is just half, so it stops.

The solution is to iteratte in reverse

var list = document.getElementsByClassName("default");

for(var i=list.length; i--;) {
  list[i].classList.add("red");
  list[i].classList.remove("default");
}

or get a non-live nodeList using querySelectorAll

var list = document.querySelectorAll(".default");
like image 193
adeneo Avatar answered Jan 11 '23 20:01

adeneo


That's because the array-like structure returned by getElementsByClassName is "live", that is, if it doesn't satisfy having that specified class, it gets removed from the array automatically.

The first run was caused by the first item. It gets a red class and removes the default class. The removal of default causes it to get removed from list automatically. Once your loop advances, index is 1 but now there's only 1 item in the list.

like image 27
Joseph Avatar answered Jan 11 '23 20:01

Joseph