Как сделать, чтобы скрипт срабатывал для нескольких элементов с одинаковым классом не одновременно

Рейтинг: 1Ответов: 1Опубликовано: 22.03.2023

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

function calcAndShow() {
  let val = $("select.control").val();
  let num = parseInt($("input.control").val() || 0);
  let sum = val * num;
  if (!isNaN(sum) && sum > 0) {
    $(".text.big").removeClass("zero");
    let res = $(".text.big").text().replace(/\D+/g, "");
    res = parseInt(res);
    if (isNaN(res)) res = 0;
    let dif = Math.abs(sum - res);
    $(".text.big").text(sum).each(function() {
      $(this).prop("Counter", res).animate({
          Counter: parseInt($(this).text())
        }, {
          duration: 400,
          easing: "linear",
          step: function(now) { $(this).text(Math.ceil(now).toLocaleString("ru")); }
        });
    });
  } else { $(".text.big").addClass("zero").text(""); }
}
$(".maincalcs").on("input", calcAndShow).trigger("input");
@import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");

body { background-color: #eceff1; }

.maincalcs {
  margin: auto;
  display: flex;
  flex-direction: column;
  max-width: 820px;
  font: 400 16px/1em Montserrat, Arial, sans-serif;
  background-color: #fff;
}

.values, .numbers {
  margin: auto;
  display: flex;
  flex-direction: column;
  gap: 1em;
  max-width: 820px;
  padding: 1.25em 1.5em 1.5em;
  background-color: #fff;
}

b { font-size: 1.15em; color: #37474f; }
b::after { content: " *"; color: #f00; }

.control {
  border-radius: 0.4em;
  border: 2px solid #eceff1;
  font: inherit;
  color: #37474f;
  background-color: #eceff1;
}
select.control { padding: 0.5em 2em 0.5em 0.6em; }
select.control option { background: #fff; color: #37474f; }
input.control { padding: 0.5em 0.6em; }

.result {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 1em;
  padding: 1.5em;
  color: #fff;
  background-color: #2196f3;
}

.big { font-weight: 300; font-size: 2.25em; }
.big::after { content: ' руб.'; }
.big.zero::after { content: 'Нет данных'; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="maincalcs">
  <div class="controls">
    <div class="values">
      <b>Выберите значение:</b>
      <select class="control">
        <option disabled selected>Выберите пункт...</option>
        <option value="10">10</option>
        <option value="255">255</option>
        <option value="3704">3704</option>
        <option value="0">0</option>
      </select>
    </div>
    <div class="numbers">
      <b>Укажите количество:</b>
      <input class="control" type="number" min="0" step="1">
    </div>
  </div>
  <div class="result">
    <div class="text">Итого</div>
    <div class="text big zero"></div>
  </div>
</form>
<form class="maincalcs">
  <div class="controls">
    <div class="values">
      <b>Выберите значение:</b>
      <select class="control">
        <option disabled selected>Выберите пункт...</option>
        <option value="15">15</option>
        <option value="20">20</option>
        <option value="0">0</option>
        <option value="355">355</option>
      </select>
    </div>
    <div class="numbers">
      <b>Укажите количество:</b>
      <input class="control" type="number" min="0" step="1">
    </div>
  </div>
  <div class="result">
    <div class="text">Итого</div>
    <div class="text big zero"></div>
  </div>
</form>

Ответы

▲ 2Принят

Чтобы функция работала только для активного блока, необходимо при выборе (поиске) элемента указать контекст (область поиска) вторым параметром.

То есть, было:

$("select.control")

Стало:

$("select.control", this)

Таким образом, this будет указывать на ту форму, в которой происходят события.

Кроме того, чтобы каждый раз не искать один и тот же элемент, ...

$(".text.big")

... сохраним ссылку на него в переменной...

let textBig = $(".text.big", this);

... и далее, подставляем уже её в качестве селектора:

$(textBig)

function calcAndShow() {
  let textBig = $(".text.big", this);
  let val = $("select.control", this).val();
  let num = parseInt($("input.control", this).val() || 0);
  let sum = val * num;
  if (!isNaN(sum) && sum > 0) {
    $(textBig).removeClass("zero");
    let res = $(textBig).text().replace(/\D+/g, "");
    res = parseInt(res);
    if (isNaN(res)) res = 0;
    let dif = Math.abs(sum - res);
    $(textBig).text(sum).each(function() {
      $(this).prop("Counter", res).animate({
          Counter: parseInt($(this).text())
        }, {
          duration: 400,
          easing: "linear",
          step: function(now) { $(this).text(Math.ceil(now).toLocaleString("ru")); }
        });
    });
  } else { $(textBig).addClass("zero").text(""); }
}
$(".maincalcs").on("input", calcAndShow).trigger("input");
@import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");

body { background-color: #eceff1; }

.maincalcs {
  margin: auto;
  display: flex;
  flex-direction: column;
  max-width: 820px;
  font: 400 16px/1em Montserrat, Arial, sans-serif;
  background-color: #fff;
}

.values, .numbers {
  margin: auto;
  display: flex;
  flex-direction: column;
  gap: 1em;
  max-width: 820px;
  padding: 1.25em 1.5em 1.5em;
  background-color: #fff;
}

b { font-size: 1.15em; color: #37474f; }
b::after { content: " *"; color: #f00; }

.control {
  border-radius: 0.4em;
  border: 2px solid #eceff1;
  font: inherit;
  color: #37474f;
  background-color: #eceff1;
}
select.control { padding: 0.5em 2em 0.5em 0.6em; }
select.control option { background: #fff; color: #37474f; }
input.control { padding: 0.5em 0.6em; }

.result {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 1em;
  padding: 1.5em;
  color: #fff;
  background-color: #2196f3;
}

.big { font-weight: 300; font-size: 2.25em; }
.big::after { content: ' руб.'; }
.big.zero::after { content: 'Нет данных'; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="maincalcs">
  <div class="controls">
    <div class="values">
      <b>Выберите значение:</b>
      <select class="control">
        <option disabled selected>Выберите пункт...</option>
        <option value="10">10</option>
        <option value="255">255</option>
        <option value="3704">3704</option>
        <option value="0">0</option>
      </select>
    </div>
    <div class="numbers">
      <b>Укажите количество:</b>
      <input class="control" type="number" min="0" step="1">
    </div>
  </div>
  <div class="result">
    <div class="text">Итого</div>
    <div class="text big zero"></div>
  </div>
</form>
<form class="maincalcs">
  <div class="controls">
    <div class="values">
      <b>Выберите значение:</b>
      <select class="control">
        <option disabled selected>Выберите пункт...</option>
        <option value="15">15</option>
        <option value="20">20</option>
        <option value="0">0</option>
        <option value="355">355</option>
      </select>
    </div>
    <div class="numbers">
      <b>Укажите количество:</b>
      <input class="control" type="number" min="0" step="1">
    </div>
  </div>
  <div class="result">
    <div class="text">Итого</div>
    <div class="text big zero"></div>
  </div>
</form>