0

Suppose I call getElementsByClassName() and store the result in a variable like so:

var editButtons = document.getElementsByClassName("editButtonDisabled");

Then I iterate through that variable (which is a nodelist, so .item(i) is used and not [i]) and change the class name of each item:

for (var i = 0; i < editButtons.length; i++) {

    var editButton = editButtons.item(i);
    editButton.className = "editButtonEnabled";

}

For some reason the loop skips over all the odd-indexed members of editButtons and only applies the class name change to the even-numbered ones, as though the length of editButtons is being mutated by changing the properties of its members, which shouldn't be the expected behavior in my opinion.

I know I can get around this by just throwing all the elements into an array first and then looping through it again, but that requires writing two loops when only one should be necessary, and I'm curious as to why it's doing this in the first place.

joeyp
  • 111
  • 2

1 Answers1

-1

Yes, because editButtons.length changes after each iteration, you should put the length in a variable:

for (var i = 0, length = editButtons.length; i < length; i++) {
    var editButton = editButtons.item(i);

    editButton.className = "editButtonEnabled";

}

EDIT:

I was wrong about my solution and about length. In fact when the first button class is changes the button is popped out of the array and when the i is incremented the second button (witch now is at index 0) is skipped and so on.

The solution is to iterate in reverse:

function changeClassName() {
  var buttons = document.getElementsByClassName('editButtonDisabled');

  for (var i = buttons.length - 1; i >= 0; i--) {
    var button = buttons[i];

    button.className = 'editButtonEnabled';
  }
}
button {
  display: block;
  margin-bottom: .5em;
}
.editButtonDisabled {
  background: red;
}
.editButtonEnabled {
  background: green;
}
<button onclick="changeClassName()">changeClassName()</button>

<button class="editButtonDisabled">Button 01</button>
<button class="editButtonDisabled">Button 02</button>
<button class="editButtonEnabled">Button 03</button>
<button class="editButtonDisabled">Button 04</button>
<button class="editButtonDisabled">Button 05</button>
<button class="editButtonDisabled">Button 06</button>
<button class="editButtonEnabled">Button 07</button>
<button class="editButtonDisabled">Button 08</button>
<button class="editButtonDisabled">Button 09</button>
<button class="editButtonDisabled">Button 10</button>
Ionut
  • 1,729
  • 4
  • 23
  • 50
  • 1
    That's not enough; you're still skipping the changed indices. – SLaks Jan 18 '16 at 23:13
  • I'm more curious as to why editButtons.length changes. Since I'm not calling `getElementsByClassName()` again, the variable that stored the original nodelist returned by it shouldn't have had its length changed, I would expect. – joeyp Jan 18 '16 at 23:16
  • @joeyp every time you change the class name of a button, the button is removed from the array and the array gets smaller. But my idea was wrong. I updated my answer with a reverse iteration example – Ionut Jan 19 '16 at 13:51