0

I am having some very strange behavior with getElementsByClassName, and I am not sure what is causing it.

If I try to swap all elements from class B to class A, it only swaps certain elements as seen below:

function swapClasses() {
    // Get all elements of class B
    const classBList = document.getElementsByClassName("classb");
    for (var i = 0; i < classBList.length; i++) {
        var classElem = classBList[i];
        // Swap its class from class B to class A
        classElem.className = "classa";
        // Swap the text as well
        classElem.textContent = "Class A";
    }
}
.classa {
    background-color: red;
}

.classb {
    background-color: green;
}
<div class="classa">Class A</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<button onclick="swapClasses();">Swap class B to class A</button>

I have no idea why this happens, and I would love to fix it if possible.

Any help would be appreciated!

MysteryPancake
  • 1,365
  • 1
  • 18
  • 47
  • 1
    getElementsByClassname returns a "live HTMLCollection" ... so by changing `classElem.className = "classa";` you change the collection - suggest you use `document.querySelectorAll(".classb")` and avoid the problem - see [documentation](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName) and read the warning :p – Bravo Nov 24 '20 at 05:58

1 Answers1

2

You can use querySelectorAll and classList instead of the live nodelist you get with getElementsByClassName

function swapClasses() {
  // Get all elements of class B
  document.querySelectorAll(".classb").forEach(div => {
    div.classList.add("classa");
    div.classList.remove("classb");
    // Swap the text as well
    div.textContent = "Class A";
  })
}
.classa {
  background-color: red;
}

.classb {
  background-color: green;
}
<div class="classa">Class A</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<div class="classb">Class B</div>
<button onclick="swapClasses();">Swap class B to class A</button>

Use [...document.querySelectorAll(".classb")].forEach

if you want to support older Edge

mplungjan
  • 169,008
  • 28
  • 173
  • 236