Выполните цикл по элементам по имени класса, щелкните любой элемент в массиве, но повлияйте только на выбранный элемент?

#javascript #css #arrays #for-loop #foreach

Вопрос:

Я работаю на сайте WordPress, и у меня есть фрагмент html, который повторяется с повторяющимися классами.

Я пытаюсь создать функцию щелчка, но воздействую только на элемент, по которому щелкают. Все на JavaScript.

На данный момент моя функция влияет на все элементы с именем класса. Тестовый код можно найти в моем коде или ниже.

Я могу сделать это без вложенных циклов, как показано здесь. Поэтому я предполагаю, что проблема заключается во втором цикле forEach. Я был бы признателен за любой свет на этот вопрос. Заранее спасибо.

 /**
 *Constructors
 **/
const carousel = document.getElementsByClassName("carousel");
const btns = document.getElementsByClassName("btns");

/**
 *Execute
 **/

Array.from(btns).forEach((i) => {
  i.addEventListener("click", (e) => {
    Array.from(carousel).forEach((n) => {
      if (i.classList.contains("slide-left")) {
        n.scrollLeft -= 20;
      } else if (i.classList.contains("slide-right")) {
        n.scrollLeft  = 20;
      } else {
        alert("ut oh");
      }
    });
  });
}); 
 /*
**Utilities
*/


/*containers*/

.feed-container {
  position: absolute;
  height: 200px;
  width: 100%;
  display: grid;
  grid-template-columns: 1;
  grid-template-rows: 1;
}

.carousel {
  grid-row: 1;
  grid-column: 1/5;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 1;
  grid-gap: 15px;
  align-self: center;
  border: 1px solid #ccc;
  overflow-x: scroll;
  overflow-y: hidden;
}


/*div-buttons*/

div[class*="slide-"] {
  /*opacity: 0;*/
  position: sticky;
  grid-row: 1;
  z-index: 5;
  place-self: center;
  transition: 0.5s;
  padding: 15px;
}

.slide-left {
  grid-column: 1;
}

.slide-right {
  grid-column: 4;
}


/*items*/

div[class*="item-"] {
  grid-row: 1;
  width: 400px;
  height: 200px;
}

.item-1 {
  background: blue;
}

.item-2 {
  background: red;
}

.item-3 {
  background: grey;
}

.item-4 {
  background: yellow;
}


/*scrollbar*/

::-webkit-scrollbar {
  display: none;
}


/*chevrons*/

[class*="chevron-"] {
  box-sizing: border-box;
  position: relative;
  display: block;
  transform: scale(var(--ggs, 1));
  width: 22px;
  height: 22px;
  border: 2px solid transparent;
  border-radius: 25px;
}

[class*="chevron-"]::after {
  content: "";
  display: block;
  box-sizing: border-box;
  position: absolute;
  width: 40px;
  height: 40px;
  border-bottom: 8px solid;
  border-left: 8px solid;
  bottom: 0;
}

.chevron-left::after {
  transform: rotate(45deg);
  left: 15px;
}

.chevron-right::after {
  transform: rotate(-135deg);
  right: 15px;
}


/*
**Exceptions
*/

.btns:hover {
  cursor: pointer;
}

.opaque {
  opacity: 1 !important;
}

.show {
  display: block;
} 
 <div id="wrapper" style="display:grid; grid-template-rows:repeat(2, auto); grid-gap: 100px;">
  <div>
    <h1>Header</h1>
    <div class="feed-container">
      <div class="carousel">
        <div class="item-1"></div>
        <div class="item-2"></div>
        <div class="item-3"></div>
        <div class="item-4"></div>
      </div>
      <div class="slide-left btns">
        <div class="chevron-left"></div>
      </div>
      <div class="slide-right btns">
        <div class="chevron-right"></div>
      </div>
    </div>
  </div>
  <br>
  <div>
    <h1>Header</h1>
    <div class="feed-container">
      <div class="carousel">
        <div class="item-1"></div>
        <div class="item-2"></div>
        <div class="item-3"></div>
        <div class="item-4"></div>
      </div>
      <div class="slide-left btns">
        <div class="chevron-left"></div>
      </div>
      <div class="slide-right btns">
        <div class="chevron-right"></div>
      </div>
    </div>
  </div>
</div> 

Ответ №1:

Это потому, что вы получаете все элементы с именем класса carousel , а затем просматриваете их с каждым щелчком мыши.

    const carousel = document.getElementsByClassName("carousel");
 

Вместо этого вам нужно получить карусели только под родительской кнопкой, когда вы запускаете событие щелчка

например, что-то вроде этого:

 Array.from(btns).forEach((i) => {
    i.addEventListener("click", (e) => {
        const targetElement = e?.target || e?.srcElement;
        const parent = targetElement.parentElement();
        const carousel = Array.from(parent.getElementsByClassName("carousel"));
        
        carousel.forEach((n) => {
            if (i.classList.contains("slide-left")) {
                n.scrollLeft -= 20;
            } else if (i.classList.contains("slide-right")) {
                n.scrollLeft  = 20;
            } else {
                alert("ut oh");
            }
        });
    });
});
 

Комментарии:

1. Спасибо за быстрый ответ. Кое-что из этого для меня ново. Проверит документацию и доложит.

2. Не беспокойтесь, удачи 🙂

Ответ №2:

Я взглянул на следующее, как рекомендую, и, похоже, это сработало.

  • Я создал переменную, которая вызывает родительский код, нажав кнопку «forEach ()». Противопоставьте циклическому прохождению через каждый элемент.

Рабочий пример, codePen

 const carousel = document.querySelectorAll(".carousel");
const btns = document.querySelectorAll(".btns");

 btns.forEach((i) => {
  i.addEventListener("click", () => {
    var x = i.parentNode;
    var y = Array.from(x.querySelectorAll(".carousel"));
    y.forEach((n) => {
      if (i.classList.contains("slide-left")) {
        n.scrollLeft -= 20;
      } else {
        n.scrollLeft  = 20;
      }
    });
  });
});