@boga-net

Почему не работает калькулятор стоимости?

Пишу калькулятор расчёта стоимости. Вот одна часть:

<div class="input-box" id="valve">
    <div class="input">
      <div class="value-btn value-btn-minus">-</div>
      <div class="value-text"></div>
      <div class="value-btn value-btn-plus">+</div>
    </div>
    <div class="label">
      <h3>Вентиль</h3>
    </div>
  </div>
  <div class="input-box" id="harness">
    <div class="input">
      <div class="value-btn value-btn-minus">-</div>
      <div class="value-text"></div>
      <div class="value-btn value-btn-plus">+</div>
    </div>
    <div class="label">
      <h3>Жгут</h3>
    </div>
  </div>
  <div class="input-box" id="package">
    <div class="input">
      <div class="value-btn value-btn-minus">-</div>
      <div class="value-text"></div>
      <div class="value-btn value-btn-plus">+</div>
    </div>
    <div class="label">
      <h3>Пакет</h3>
    </div>
  </div>

Теперь сам скрипт. Кнопки - и + - меняют кол-во штук каждого предмета на 1 единицу.
Вот так всё работает, но приходится писать для каждого элемента повторяющиеся части кода. Я решил вынести повтор в отдельную функцию и всё сломалось.

var valveCalc = function() {
    var text  = $('#valve').find('.value-text'),
         plus  = $('#valve').find('.value-btn-plus'),
         minus = $('#valve').find('.value-btn-minus'),
         val   = 0;

    minus.on('click', function() {
      if (val <= 0) {
      }
      else {
        val--;
      }
      
      text.text(val);
    });
    
    plus.on('click', function() {
      val++;
      text.text(val);
    });

    text.text(val);

  }
  valveCalc();

Решил сделать вот так:

$(function() {
    $('#valve').on('click', function() {
      valveCalc($(this));
    });
    $('#harness').on('click', function() {
      valveCalc($(this));
    });
    $('#package').on('click', function() {
      valveCalc($(this));
    });

  }());

// Здесь при клике на элемент в функцию valveCalc() будет передаваться текущий ID.

  function valveCalc(thisID) {

  var text     = thisID.find('.value-text'),
        plus     = thisID.find('.value-btn-plus'),
        minus  = thisID.find('.value-btn-minus'),
        val       = 0;

    plus.on('click', function() {
      val += 1;
      text.text(val);
    });

    minus.on('click', function() {
      if (val <= 0) {
      }
      else {
        val -= 1;
      }
      
      text.text(val);
    });

    text.text(val);

  };

Вот так уже не работает... При клике на кнопки в первый раз ничего не происходит. Во второй - добавляется или отнимается единица. Всё.
Как я понимаю, при клике я каждый раз вызываю функцию и переменная val опять принимает значение равное нулю? Не пойму, куда её надо поместить, чтобы для каждого элемента она возвращалась в виде готового числа (которое я потом буду выводить в таблицу и прибавлять это значение к общей сумме).
Ещё не пойму, почему при первом клике ничего не происходит.
  • Вопрос задан
  • 104 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Как я понимаю, при клике я каждый раз вызываю функцию и переменная val опять принимает значение равное нулю?

Не совсем так. При каждом клике создаётся ещё один экземпляр val, подключаются ещё по одному обработчику клика к .value-btn-plus и .value-btn-minus, сами обработчики срабатывают в порядке подключения, поэтому в value-text последним будет записано значение val, к которому имеет доступ последний же подключенный обработчик - т.е. 0, или что там у вас.

Очевидно, стоит отказаться от подключения дополнительных обработчиков. Можно вообще ограничиться одним обработчиком клика для всех кнопок, а какая именно была нажата - узнавать, проверяя наличие соответствующих классов. Как-то так:

$(document).on('click', '.value-btn-plus, .value-btn-minus', function() {
  const $this = $(this);
  const change = $this.hasClass('value-btn-plus') ? 1 : -1;

  $this
    .closest('.input-box')
    .find('.value-text')
    .text((i, text) => Math.max(0, +text + change));
});

Или, к чёрту jquery:

document.addEventListener('click', ({ target: t }) => {
  const change =
    t.classList.contains('value-btn-plus')  ?  1 :
    t.classList.contains('value-btn-minus') ? -1 :
                                               0;
  if (change) {
    const valueEl = t.closest('.input-box').querySelector('.value-text');
    valueEl.innerText = Math.max(0, +valueEl.innerText + change);
  }
});
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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