Yong
Yong

Reputation: 41

How to call multiple elements of same class using getElementsByClassName?

This is frustrating.

I am currently doing a practice and I'd like to add a class and remove another class on a div with the class "sap". I have 3 divs with the same class and I intend to use a loop to get all elements with the same class but it doesn't seem to be working and I don't know why.

I am using only vanilla JS.

Can anyone help me out? Thanks for any help rendered.

HTML:

<button onclick="boot()">show</button>
<div class=panel>
<div id="container" class="sap">
  <div class="content"><span>unveil</span></div>
<div class="smooth">
</div>
</div>
<div class="sap">
  <div class="content"><span>unveil</span></div>
<div class="smooth">
</div>
</div>
<div class="sap">
  <div class="content"><span>unveil</span></div>
<div class="smooth">
</div>
</div>
</div>

JS:

function boot(){
  for(var i=0;i<=3;i++){
      var box=document.getElementsByClassName("sap");
    if(box[i].classList.contains("content")){
       box[i].classList.add("flush");
       }}
  }

Upvotes: 0

Views: 1526

Answers (3)

Ivan86
Ivan86

Reputation: 5708

The code you provided works, except there is no div with class content and sap at the same time so when you run the snippet below you won't see any changes (no class will be added to any element):

function boot() {
  var box = document.getElementsByClassName("sap");
  for(var i=0; i < box.length; i++) {
    if(box[i].classList.contains("content")) {
       box[i].classList.add("flush");
    }
  }
}
.flush {
  font-weight: bold;
  color: #09f;
}
<button onclick="boot()">show</button>
<div class=panel>
  <div id="container" class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth"></div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth"></div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
  <div class="smooth">
  </div>
  </div>
</div>

In case you wanted to add the class to an element of class sap that has a child element with class content:

function boot() {
  var box = document.getElementsByClassName("sap");
  for(var i=0; i < box.length; i++) {
    if(box[i].querySelector('.content') !== null) {
      box[i].classList.add("flush");
    }
  }
}
.flush {
  font-weight: bold;
  color: #09f;
}
<button onclick="boot()">show</button>
<div class=panel>
  <div id="container" class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth"></div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth"></div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
  <div class="smooth">
  </div>
  </div>
</div>

Upvotes: 0

KooiInc
KooiInc

Reputation: 122906

It's generally not a good idea to use inline event handlers.

You can use the more modern document.querySelectorAll, spread its (array like) result into an Array and perform the wanted action on that. Or, even shorter, select all .sap > .content in one go and perfom the action. Something like:

document.addEventListener("click", boot);

function boot(evt) {
  // --------------------------------------------------------------------------------    
  // just for this demo snippet
  [...document.querySelectorAll(".flush, .flushAlt")]
    .forEach(elem => 
      elem.classList.remove("flush","flushAlt"));
  // --------------------------------------------------------------------------------    
  if (evt.target.dataset.action === "boot") {
    [...document.querySelectorAll(".sap")] // all div.sap
      .forEach(elem =>
        [...elem.querySelectorAll(".content")] // all div.content *within* div.sap
          .forEach(content => 
            content.classList.add("flush")))
  } else if (evt.target.dataset.action === "bootAlt") {
    // all div.content *within* div.sap in one go
    [...document.querySelectorAll(".sap > .content")]
      .forEach(content => 
            content.classList.add("flushAlt"))
  }
}
.flush {
  color: red;
  background-color: yellow;
  width: 100px;
  margin: 4px;
  padding: 2px;
  text-align: center;
}

.flushAlt {
  color: white;
  background-color: brown;
  width: 100px;
  margin: 4px;
  padding: 2px;
  text-align: center;
}
<button data-action="boot">show</button>
<button data-action="bootAlt">show (alternative)</button>
<div class=panel>
  <div id="container" class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
</div>

Upvotes: 1

brk
brk

Reputation: 50291

Take this var box=document.getElementsByClassName("sap"); outside the loop. This will give the collection of the html elements with this class sap. Then you will like to iterate this collection , so you need not to hard code the number 3. Note in you code you did <=3. It will be < but not <=. Since <= the index starts from 0, so <= will also try to match 4th element which is not there.

Then get the first child of the div.sap using children

function boot() {
  var box = document.getElementsByClassName("sap");
  for (var i = 0; i < box.length; i++) {
    const firstChild = box[i].children[0]
    if (firstChild.classList.contains("content")) {
      firstChild.classList.add("flush");
    }
  }
}
.sap {
  border: 1px solid red;
}

.content {
  color: green;
}

.flush {
  font-size: 20px;
  color: blue;
}
<button onclick="boot()">show</button>
<div class=panel>
  <div id="container" class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
  <div class="sap">
    <div class="content"><span>unveil</span></div>
    <div class="smooth">
    </div>
  </div>
</div>

Upvotes: 0

Related Questions