Search code examples
javascripthtmlnodelist

Why does my for loop only affect the first element from my getElementsByClassName NodeList?


I am trying to loop through a NodeList of class hot. I want to change their class names to cool . When I use a for loop it seems that the second <li> doesn't change color. Does anyone know what my mistake is here?

var elements = document.getElementsByClassName('hot');
var i;

for(i = 0; i < elements.length; i++) { 
  elements[i].className = 'cool';
}
*{
  box-sizing: border-box;
}
.hot {
  background-color: red;
  border: 1px solid black;
  padding: 10px;
  margin-top: 1px;
  font-size: 25px;
  list-style-type: none;
}

.cool {
  background-color: blue;
  padding: 10px;
  color: white;
  font-size: 25px;
}
<html>
  <body>
   <div id="page">
      <h1 id="header">List</h1>
      <h2>Buy Greoceries</h2>
      <ul>
         <li id="one" class="hot"><em>Fresh</em>figs</li>
         <li id="two" class="hot">pine nuts</li>
         <li id="three" class="hot">honey</li>
         <li id="four">balsamic vinegear</li>
     </ul>
   </div> 
  </body>
</html>


Solution

  • getElementsByClassName returns a live node list. Once you've changed the class on one element the node list updates to reflect this so your index will always be out.

    One way to mitigate this is to convert the node list to a static node list using Array.slice.call:

    var elements = [].slice.call(document.getElementsByClassName('hot'));
    

    DEMO

    Another way, as you point out, is to use document.querySelectorAll which returns a static node list:

    document.querySelectorAll('.hot');
    

    DEMO