Как менять картинки при клике на кнопку?

Рейтинг: 0Ответов: 2Опубликовано: 19.04.2023

Нужно, при клике на цвет, менять картинку. Но проблема в том что таких блоков может быть на странице много, а все применяется только к первому. Подскажите пожалуйста, как сделать так что-бы у каждого блока менялась своя картинка?

document.body.addEventListener('click', e => {
  if (!e.target.matches('button')) return
  document.querySelector('.pic img').src = e.target.dataset.src
  
  document.querySelectorAll('button').forEach(btn => btn.classList.remove('active'))
  e.target.classList.add('active')
})
.pic {
  display: inline-block;
}

button {
  padding: 1em;
}

button.active {
  background: tomato;
}
<div class="content">
  <div class="pic">
    <img src="https://image.coolblue.nl/422x390/products/1216241">
  </div>

  <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active">
    Blue
  </button>

  <button data-src="https://image.coolblue.nl/422x390/products/1214824">
    Black
  </button>
  <div>

    <div class="content">
      <div class="pic">
        <img src="https://image.coolblue.nl/422x390/products/1216241">
      </div>

      <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active">
        Blue
      </button>

      <button data-src="https://image.coolblue.nl/422x390/products/1214824">
        Black
      </button>
      <div>

Ответы

▲ 1Принят

Я бы предложил такой вариант. В нем вы слушаем любые клики по document (в идеале, нужно повесить слушатель на контейнер, который оборачивает данные блоки), проверяем, что элемент на котором кликнули - кнопка и получаем нашу обертку в виде .content, изображение и активную кнопку. Убираем у активной кнопки класс active, даем его для нажатой кнопки и устанавливаем для image src из атрибута кнопки - data-src.

document.addEventListener("click", ({target}) =>
{
  if (target.tagName !== "BUTTON")
  {
    return;
  }
  
  const wrapper = target.closest(".content");
  if (wrapper === null)
  {
    return;
  }
  
  const image = wrapper.querySelector(".pic img");
  const activeButton = wrapper.querySelector("button.active");
  if (image === null || activeButton === null)
  {
    return;
  }
  
  activeButton.classList.remove("active");
  
  const button = target;
  button.classList.add("active");
  
  image.src = button.dataset.src; 
});
.pic {
  display: inline-block;
}

button {
  padding: 1em;
}

button.active {
  background: tomato;
}
<div class="content">
  <div class="pic">
    <img src="https://image.coolblue.nl/422x390/products/1216241">
  </div>

  <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active">
    Blue
  </button>

  <button data-src="https://image.coolblue.nl/422x390/products/1214824">
    Black
  </button>
</div>

<div class="content">
  <div class="pic">
    <img src="https://image.coolblue.nl/422x390/products/1216241">
  </div>

  <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active">
        Blue
  </button>

  <button data-src="https://image.coolblue.nl/422x390/products/1214824">
        Black
  </button>
</div>

▲ 1

На вскидку 2 варианта.

Первый - искать картинку не в document, а в родителе нашего target.

e.target.parentElement.querySelector('.pic img').src = e.target.dataset.src

Второй, на мой взгляд более универсальный, - добавить к блокам .content ID товара (типа id="item-1"), добавить в кнопики data-itemid, в котором будет содержаться ID товара, картинку которого нужно изменить. В таком случае смена картинки будет делаться как-то так:

let pic = document.querySelector('#' + e.target.dataset.itemid + ' .pic img')
pic.src = e.target.dataset.src

Второй вариант более универсальный, т.к. не так сильно привязан к структуре HTML. Поэтому рабочий пример ниже именно с ним.

PS. Не забывайте корректно закывать HTML блоки. В вашем примере в коце блоков .content у вместо закрывающего тега </div>, открывающий - <div>

document.body.addEventListener('click', e => {
  if (!e.target.matches('button')) return

  let pic = document.querySelector('#' + e.target.dataset.itemid + ' .pic img')
  pic.src = e.target.dataset.src


  document.querySelectorAll('#' + e.target.dataset.itemid + ' button').forEach(btn => btn.classList.remove('active'))
  e.target.classList.add('active')
})
.pic {
  display: inline-block;
}

button {
  padding: 1em;
}

button.active {
  background: tomato;
}
<div class="content" id="item-1">
  <div class="pic">
    <img src="https://image.coolblue.nl/422x390/products/1216241">
  </div>

  <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active" data-itemid="item-1">
    Blue
  </button>

  <button data-src="https://image.coolblue.nl/422x390/products/1214824" data-itemid="item-1">
    Black
  </button>
</div>

<div class="content" id="item-2">
  <div class="pic">
    <img src="https://image.coolblue.nl/422x390/products/1216241">
  </div>

  <button data-src="https://image.coolblue.nl/422x390/products/1216241" class="active" data-itemid="item-2">
        Blue
      </button>

  <button data-src="https://image.coolblue.nl/422x390/products/1214824" data-itemid="item-2">
        Black
      </button>
</div>