AntonAntonoff
AntonAntonoff

Reputation: 197

The for loop doesn't process each element found by getElementsByClassName

I have a panel with buttons in index.html:

<div>
    <img src="icons/trash.svg" class="toolsPanelActiveButton" id="deleteButton">
    <img src="icons/copy.svg" class="toolsPanelActiveButton" id="copyButton">
</div>
<div>
    <img src="icons/color.svg" class="toolsPanelActiveButton" id="colorButton">
    <img src="icons/copy-format.png" class="toolsPanelActiveButton" id="copyFormatButton" >
    <img src="icons/paste-format.png" class="toolsPanelActiveButton" id="pasteFormatButton">
</div>
<div>
    <img src="icons/addpicture.svg" class="toolsPanelActiveButton" id="addImageButton">
</div>

and styles:

.toolsPanelHiddenButton {
    display: none;
}

I need to hide each button with class "toolsPanelActiveButton". If I use code like this

    var elems = document.getElementsByClassName('toolsPanelActiveButton');

    for (let elem of elems) {
        elem.className="toolsPanelHiddenButton";
    }

I hide only half of elements:

enter image description here

What is the proper method of hiding every element of the selected class?

I'm expecting to have empty panel after using the for loop.

Upvotes: 0

Views: 267

Answers (1)

Pointy
Pointy

Reputation: 414006

The right way to do it is to iterate through with a while:

var elems = document.getElementsByClassName('toolsPanelActiveButton');

while (elems.length) {
    elems[0].className = "toolsPanelHiddenButton";
}

Why? because it's an active node list that you get from .getElementsByClassName(). That means then when you remove the old class, that element is no longer in the list.

Another solution is to use .querySelectorAll(), because it returns a non-live node list:

var elems = document.querySelectorAll('.toolsPanelActiveButton');

for (let elem of elems) {
    elem.className="toolsPanelHiddenButton";
}

Also, for completeness, I think it's a fragile programming practice to directly update the entire class list like this (that is, setting .className). Often, unrelated page features may want to share the class list for elements on the page. If one feature stomps on the entire list of classes, that makes such features not possible. Modern browsers have the .classList object with a convenient API.

Upvotes: 7

Related Questions