Счётчик кликов для разных блоков через делегирование JS

767
21 февраля 2017, 19:20

Есть код который название блока и считает клики по кнопке. Проблема в том что поле с количеством кликов меняется один раз. С 0 до 1 и все. Подскажите в чем проблема

(function () {
  var buttons = document.querySelector('#list');
  buttons.onclick = function (e) {
   var clicks = 0;
   clicks++;
   var target = e.target;
   if (target.tagName = 'BUTTON') {
  var counter = target.closest('li').querySelector('.product-item__counter');
  counter.innerHTML = clicks;
  var product = target.closest('li').querySelector('.product-item__title').innerHTML;
  alert(' You have bought a ' + product);
 }
 };
})();

Пример https://jsfiddle.net/dedn/60b6uL4c/

Answer 1

var clicks = 0; Здесь вы сбрасываете текущее значение счётчика и начинаете сначала.

Ну и, у каждого счётчика должно быть своё хранилище текущего значения.

if (target.tagName = 'BUTTON') { - Здесь вы ничего не проверяете, оператор присваивания возвращает truthy значение.

Можно выбрать все элементы(querySelectorAll) и навешать отдельный обработчик на каждый.
В качестве хранилища текущего значения счётчика можно использовать само отображаемое значение:

document.querySelectorAll('ul .btn') 
  .forEach(function(el){  
    el.onclick = function() { 
      let cnt = this.closest('li').querySelector('.cnt'); 
      cnt.innerText = parseInt(cnt.innerText, 10)+1; 
    }; 
  });
<ul> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
</ul>

Или с общим для всех обработчиком(по аналогии с вашим):

document.querySelector('ul').onclick = function(e) { 
  let target = e.target; 
  if (target.tagName != 'BUTTON') return; 
  let cnt = target.closest('li').querySelector('.cnt'); 
  cnt.innerText = parseInt(cnt.innerText, 10)+1; 
};
<ul> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
  <li> 
    <button class="btn">Button</button> 
    <span class="cnt">0</span> 
  </li> 
</ul>

Answer 2
buttons.onclick = function (e) {
    var clicks = 0;
    clicks++;

Все дело в том, что вы не сохраняете состояние. Каждый раз при нажатии на кнопку, у вас обнуляется счетчик и он же повышается на +1. Простой путь это проверить - поставить так var clicks = 0;debugger; и вы увидите, что после нажатия кнопки у вас clicks всегда равен 0.

Решение простое - вам нужно вынести объявление clicks вне функции нажатия. Однако у вас тогда будет один счетчик на все кнопки. Можно сохранить значение clicks для каждой кнопки отдельно в самом html например (не самый лучший вариант).

UPD

Посмотрел внимательней и обнаружил кое-что.

1) Смотрим тут по поводу querySelector, а именно на деталь, что он вернет только первый элемент.

2) Во вторых - почему у вас buttons это вдруг оказался <ul class="list" id="list"> ?? Это абсолютно неверно т.к. нажимая куда угодно мы получаем вызов функции ( не только на кнопку). Ваша переменная вводит в заблуждение. Если вы хотите обрабатывать кнопки, то повесьте на них класс и ищите с помощью селектора классов .someClass тык.

3) Вот накидал по шустрому (тапками не бить плз). Используя замыкание, мы получаем на каждой кнопке свой счетчик.

function makeCounter() { 
  var currentCount = 1; 
 
  return function() { 
    return currentCount++; 
  }; 
}; 
var buttons = document.getElementsByClassName('ss1'); 
var clicker = function(e) { 
  var value = this.counter(); 
  console.log(this.defaultValue + " - " + value); 
}; 
 
for (var i = 0; i < buttons.length; i++) { 
  buttons[i].counter = makeCounter(); 
  buttons[i].onclick = function(e) { 
    clicker.apply(this); 
  }; 
}
<div> <input type="button" id="1" class="ss1" text="s" value="haha"> </div> 
<div> <input type="button" id="2" class="ss1" value="haha1"> </div>

Answer 3

Можно использовать localStorage примерно так:

(function() { 
  var clicks = 0; 
  var buttons = document.querySelector('#list'); 
  buttons.onclick = function(e) { 
    clicks = clicks ? localStorage.getItem(e.target.id) : 0; 
    clicks++; 
    localStorage.setItem(e.target.id, clicks); 
    var target = e.target; 
    if (target.tagName = 'BUTTON') { 
 
      var counter = target.closest('li').querySelector('.list-item__counter'); 
      counter.innerHTML = clicks; 
 
      var product = target.closest('li').querySelector('.list-item__title').innerHTML; 
      alert(' You have bought a ' + product); 
    } 
  }; 
})();
<div class="container"> 
  <h1 class="title">List</h1> 
  <ul class="list" id="list"> 
    <li class="list-item"> 
      <h2 class="list-item__title">Title First</h2> 
      <p class="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam dolorum exercitationem harum ipsam modi nesciunt optio qui quia quidem reiciendis? Alias consectetur dolorem hic nobis optio quam quos sapiente veniam.</p> 
      <button id="bt1" class="list-item__click-btn">btn</button> 
      <span class="list-item__counter">0</span> 
    </li> 
    <li class="list-item"> 
      <h2 class="list-item__title">Title Second</h2> 
      <p class="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam dolorum exercitationem harum ipsam modi nesciunt optio qui quia quidem reiciendis? Alias consectetur dolorem hic nobis optio quam quos sapiente veniam.</p> 
      <button id="bt2" class="list-item__click-btn">Btn</button> 
      <span class="list-item__counter">0</span> 
    </li> 
    <li class="list-item"> 
      <h2 class="list-item__title">Title Third</h2> 
      <p class="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam dolorum exercitationem harum ipsam modi nesciunt optio qui quia quidem reiciendis? Alias consectetur dolorem hic nobis optio quam quos sapiente veniam.</p> 
      <button id="bt3" class="list-item__click-btn">btn</button> 
      <span class="list-item__counter">0</span> 
    </li> 
    <li class="list-item"> 
      <h2 class="list-item__title">Title Fourth</h2> 
      <p class="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam dolorum exercitationem harum ipsam modi nesciunt optio qui quia quidem reiciendis? Alias consectetur dolorem hic nobis optio quam quos sapiente veniam.</p> 
      <button id="bt4" class="list-item__click-btn">Btn</button> 
      <span class="list-item__counter">0</span> 
    </li> 
  </ul> 
</div>

READ ALSO
Запретить вызов stopNativeEvents в dojo/touch.js

Запретить вызов stopNativeEvents в dojo/touch.js

Проблема в том, что код ниже мешает корректно работать кликуПодскажите как мне пропустить вызов win

316
Сериализация React Bootstrap формы в объект

Сериализация React Bootstrap формы в объект

Есть форма, созданная с помощью React Bootstrap компонент:

382
Настройка плагина fileman

Настройка плагина fileman

Столкнулся с такой проблемой: На сайте использую редактор ckeditor, и подключил файл-менеджер filemanНастройки этого файл-менеджера лежат в файле...

270
Как идти по дереву js с помощью acorn?

Как идти по дереву js с помощью acorn?

Получил такое дерево из файла своего js с помощью парсераДля примера, что я получил идем сюда и вставляем код :

339