#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;
}
});
});
});