{ image.addEventListener("click", () => { image.classList.add("selec" /> { image.addEventListener("click", () => { image.classList.add("selec" /> { image.addEventListener("click", () => { image.classList.add("selec"/>

Add a class to all sibling element if one of the element gets that same class when clicked?

246 Views Asked by At

const images = document.querySelectorAll(".img_items");

images.forEach((image) => {
  image.addEventListener("click", () => {
    image.classList.add("select");
  });
});
.img_items::after{
  content: ' ' attr(class)
}
<div class="img_container">
  <div class="img_items ">1</div>
  <div class="img_items ">2</div>
  <div class="img_items">3</div>
  <div class="img_items">4</div>
</div>

I tried adding the class to the variable (images) itself on item click event but it didn't add the class to the sibling items.

images.classList.add("select")

How do we achieve this?

2

There are 2 best solutions below

1
Barmar On BEST ANSWER

Add the class to each element in a loop, just like adding the event listener.

const images = document.querySelectorAll(".img_items");

images.forEach((image) => {
  image.addEventListener("click", () => {
    images.forEach(image => image.classList.add("select"));
  });
});
.img_items::after {
  content: ' ' attr(class)
}
<div class="img_container">
  <div class="img_items ">1</div>
  <div class="img_items ">2</div>
  <div class="img_items">3</div>
  <div class="img_items">4</div>
</div>

If you only want to do it for the siblings in the same .img_container, you can use DOM navigation to first select them and loop over them, rather than looping over all images.

const images = document.querySelectorAll(".img_items");

images.forEach((image) => {
  image.addEventListener("click", () => {
    let siblings = image.parentElement.querySelectorAll(".img_items");
    siblings.forEach(image => image.classList.add("select"));
  });
});
.img_items::after {
  content: ' ' attr(class)
}
<div class="img_container">
  <div class="img_items ">1</div>
  <div class="img_items ">2</div>
  <div class="img_items">3</div>
  <div class="img_items">4</div>
</div>
<hr>
<div class="img_container">
  <div class="img_items ">5</div>
  <div class="img_items ">6</div>
  <div class="img_items">7</div>
  <div class="img_items">8</div>
</div>

1
Miss Skooter On

First of all, to explain why you aren't getting the expected behavior:

What your code is doing is looping over all elements that have the img_items class and attaching a click eventListener to each one.

That event listener takes the selected image and adds the class select to that image only.

essentially, your code is equivalent to the following:

images[0].addEventListener("click", () => {
    image[0].classList.add("select");
});

images[1].addEventListener("click", () => {
    image[1].classList.add("select");
});

images[2].addEventListener("click", () => {
    image[2].classList.add("select");
});

images[3].addEventListener("click", () => {
    image[3].classList.add("select");
});

So you are only changing the classlist of the selected element.

Thus, instead, you need to loop through the elements again inside the eventListener like so:

const images = document.querySelectorAll(".img_items");

images.forEach((image) => {
  image.addEventListener("click", () => {
    images.forEach((image) => {
      image.classList.add("select");
    })
  });
});
<div class="img_container">
  <div class="img_items ">img1</div>
  <div class="img_items ">img2</div>
  <div class="img_items">img3</div>
  <div class="img_items">img4</div>
</div>