@Httdientee

Как назначать класс активному элементу внутри блока независимо от других блоков?

<div class="this-flex">
  <p>Тип материала</p>
  <div class="block-btn">
    <button data-cost="100" class="active">Глянцевая мелованная</button>
    <button data-cost="200">Плотная матовая Xerox Colotech</button>
  </div>
</div>
<div class="this-flex">
  <p>Плотность бумаги</p>
  <div class="block-btn">
    <button data-cost="100" class="active">130 г/м</button>
    <button data-cost="200">170 г/м</button>
    <button data-cost="300">250 г/м</button>
  </div>
</div>

Как сделать, чтобы при нажатии на кнопку, у которой нет класса active, давать ей этот класс, а у кнопки, которая уже имеет active, убирать? При этом лишаться класса должна именно та, которая в одном столбце с кнопкой, по которой был клик.
  • Вопрос задан
  • 135 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Где элементы находятся, что за элементы, какой класс у них надо переключать:

const containerSelector = '.block-btn';
const itemSelector = `${containerSelector} [data-cost]`;
const activeClass = 'active';

Какие тут возможны варианты:

Обработчик клика назначается каждому элементу индивидуально. Перебираем всех соседей (чтобы их получить, надо подняться к контейнеру и внутри него выполнить поиск нужных элементов), переключаем класс в зависимости от равенства текущего и кликнутого элемента:

const onClick = ({ currentTarget: t }) => t
  .closest(containerSelector)
  .querySelectorAll(itemSelector)
  .forEach(n => n.classList.toggle(activeClass, n === t));

document.querySelectorAll(itemSelector).forEach(n => {
  n.addEventListener('click', onClick);
});

Делегированный обработчик клика назначается контейнерам. Проверяем, что кликнут был интересующий нас элемент (пробуем до него подняться от элемента, на котором случилось событие). Если да, ищем внутри контейнера активный элемент, снимаем класс. Кликнутому элементу класс добавляем:

for (const n of document.querySelectorAll(containerSelector)) {
  n.addEventListener('click', onClick);
}

function onClick(e) {
  const item = e.target.closest(itemSelector);
  if (item) {
    this.querySelector(`.${activeClass}`)?.classList.remove(activeClass);
    item.classList.add(activeClass);
  }
}

Делегированный обработчик для всей страницы. От элемента, где случился клик, поднимаемся до элемента, которому должен быть назначен класс, если таковой нашёлся, получаем также и его соседей, перебираем их, переключаем класс в зависимости от наличия внутри элемента, где случился клик:

document.addEventListener('click', ({ target: t }) => t
  .closest(itemSelector)
  ?.closest(containerSelector)
  .querySelectorAll(itemSelector)
  .forEach(n => n.classList.toggle(activeClass, n.contains(t)))
);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы