简体   繁体   中英

Javascript: Unable to iterate over getElementsByClassName

I am trying the following javascript code. it is taken directly from a w3school example but it is not working for some reason.

<script>
var coll = document.getElementsByClassName("collapsible");
var i;
console.log(coll);
console.log(coll.length);

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.maxHeight){
      content.style.maxHeight = null;
    } else {
      content.style.maxHeight = content.scrollHeight + "px";
    } 
  });
}
</script>

I printed the value of coll and coll.length in console to debug. Coll is coming to be htmlcollection of 10 items as expected. But coll.length is 0. Thats why code is not going inside the for loop. If I force the code to go inside the loop by doing:

for (i = 0; i < 1; i++) {

I am getting following in console:

Uncaught TypeError: Cannot read property 'addEventListener' of undefined

Html code is below:

<button class=\"collapsible\">Open Collapsible</button>
<div class=\"content\"> <p>Lorem ipsum...</p> </div>

getElementsByClassName returns a live HTML collection. That means that you need to create an array from that live HTML collection. For that, use Array.from .

<script>
var coll = Array.from(document.getElementsByClassName("collapsible"));
var i;
console.log(coll);
console.log(coll.length);

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.maxHeight){
      content.style.maxHeight = null;
    } else {
      content.style.maxHeight = content.scrollHeight + "px";
    } 
  });
}
</script>

Edit

@zerkms is right about you needing to make sure the document is ready before running your code:

<script>
document.addEventListener('DOMContentLoaded', () => {
  var coll = Array.from(document.getElementsByClassName("collapsible"));
  var i;
  console.log(coll);
  console.log(coll.length);

  for (i = 0; i < coll.length; i++) {
    coll[i].addEventListener("click", function() {
      this.classList.toggle("active");
      var content = this.nextElementSibling;
      if (content.style.maxHeight){
        content.style.maxHeight = null;
      } else {
        content.style.maxHeight = content.scrollHeight + "px";
      } 
    });
  }
})
</script>

You don't need that Array.from (I was wrong about that) but, hey, doesn't hurt.

BTW, If you wish to use JQuery then this can be achieved eaisly like this:

$(document).on("click", ".collapsible", function () {
       this.classList.toggle("active");
       const content = this.nextElementSibling;
       if (content.style.maxHeight) {
            content.style.maxHeight = "";
       } else {
             content.style.maxHeight = content.scrollHeight + "px";
        }
});

You don't need to read by class and loop around, this code will handle all of them

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM