Я хочу суммировать числа, когда флажок установлен в javascript

Я хочу суммировать числа и распечатать их в диапазоне, я пробовал с innerHTML, но поскольку это строка, я не могу, я пробовал parseInt, parseFloat, Number и ничего. Для всех отмеченных флажков я хочу, чтобы сумма его значений попадала в диапазон, а те, которые не отмечены, я не хочу, чтобы они получали сумму в диапазоне

(я сократил таблицу и много чисел, потому что это так долго, поэтому представьте, что я хочу суммировать много общих чисел)

const offersCheckbox = document.querySelectorAll("#checkbox-offers");
const recalculateText = document.querySelector(".recalculate-text");
const checkboxTotal = document.querySelectorAll("#checkbox-total");
let total = 0;

for (let i = 0; i < offersCheckbox.length; i++) {
  offersCheckbox[i].addEventListener("click", (e) => {
    if (offersCheckbox[i].checked === true) {
      recalculateText.innerHTML = "recalculate invoice total";
    } else {
      recalculateText.innerHTML = "";
    }
  });
}
<table>
  <tr>
    <tr>
      <td>
        <input type="checkbox" name="checkbox" id="checkbox-offers" value="2,434.38" />
        <td>
          <div class="price-container text-bold" id="checkbox-total">
            <b>$</b>2,434.38
          </div>
        </td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" name="checkbox" id="checkbox-offers" value="76.69" />
      </td>
      <td>
        <div class="price-container text-bold" id="checkbox-total">
          <b>$</b>76.69
        </div>
      </td>
    </tr>
</table>

<span class="recalculate-text text-right text-underline"></span>


person Simon    schedule 03.03.2021    source источник
comment
Что вы пробовали? SO не является бесплатной услугой по написанию или оценке кода, поделитесь своим достижением, и мы это исправим. Также сделайте минимальный воспроизводимый пример, нажав кнопку ‹› в редакторе и создав фрагмент, это значительно увеличит ваши шансы получение ответа. Также просто отметим, что ВСЕ, что вам нужно знать о том, как это сделать, уже даны ответы здесь или в Google. Поэтому приложите некоторые усилия, чтобы задать вопрос и попытаться решить эту проблему. Добро пожаловать в СО,   -  person ikiK    schedule 03.03.2021
comment
Идентификатор элемента HTML ДОЛЖЕН быть уникальным, вам необходимо изменить атрибуты id каждого поля ввода.   -  person AGE    schedule 04.03.2021
comment
я изменил идентификаторы для классов, но это не решает мою проблему, есть ли способ это сделать?   -  person Simon    schedule 04.03.2021
comment
это потому, что ваш селектор jquery неверен, уже есть несколько ответов, которые вы можете рассмотреть   -  person AGE    schedule 04.03.2021


Ответы (4)


Я не слишком сильно изменил ваш исходный код. Смотрите комментарии, чтобы понять изменения, которые я внес, и не стесняйтесь комментировать, если у вас есть дополнительные вопросы.

const recalculateText = document.querySelector(".recalculate-text");
const checkboxContainer = document.querySelector("#checkbox-container");
let total = 0;

// Create a number formatter to print out on the UI - this is a better approach than regex IMO.
const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

//Notice the use of event delegation here - meaning I only added 1 single event handler to a single DOM element
//Read this blog for more on event delegation and why it's useful: https://davidwalsh.name/event-delegate
checkboxContainer.addEventListener('change', e => {
  //Also notice that I am listening for the change event, instead of the click event.
  //See here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
  if (e.target.tagName == "INPUT") {
    const floatValue = parseFloat(e.target.value);
    if (e.target.checked) {
      total += floatValue;
    } else {
      total -= floatValue;
    }
  }

  recalculateText.innerHTML = formatter.format(total);
});
<!-- Notice I added a parent div to enable use to use event delegation technique -->
<!-- Also notice I removed element id attributes where they were not needed. Also be sure
to always use unique id values for every element - duplicate ids are not allowed, it will 
lead to bugs. If elements need to be considered part of the same "group" then you should use
the class attribute. -->
<div id="checkbox-container">
  <table>
    <tr>
      <tr>
        <td>
          <!-- Notice I removed the comma from the value attribute -->
          <input type="checkbox" name="checkbox" value="2434.38" />
          <td>
            <div class="price-container text-bold">
              <b>$</b>2,434.38
            </div>
          </td>
      </tr>

      <tr>
        <td>
          <input type="checkbox" name="checkbox" value="76.69" />
        </td>
        <td>
          <div class="price-container text-bold">
            <b>$</b>76.69
          </div>
        </td>
      </tr>
  </table>
</div>
<span class="recalculate-text text-right text-underline"></span>

person Tom O.    schedule 03.03.2021
comment
Я не слишком сильно изменил ваш исходный код. Ну, вы должны обратиться, если ничего другого не дублирует одинаковые идентификаторы ... В идентификаторе есть document.querySelectorAll("#checkbox-offers");, то есть дубликат ... И querySelectorAll, чтобы быть еще более точным. Таким образом, код, который он создал, неверен и требует исправления. - person ikiK; 04.03.2021
comment
Это сработало для меня, вместо использования этого средства форматирования я использовал split(),.join() и выполнял прослушиватель событий на входе, а не на контейнере div. Спасибо всем - person Simon; 04.03.2021

В соответствии с исправлением кода, который у вас уже есть:

  1. идентификаторы уникальны, поэтому используйте checkbox-offers как класс и querySelectorAll, поскольку у вас уже есть цикл для него.
  2. В числах Js нет ,, поэтому вам нужно очистить их, чтобы получить число, способное выполнять математические функции.
  3. в вашем цикле у вас есть (e) ведьма, указывающая событие, поэтому используйте e.target, чтобы нацелить это event и зарегистрировать и взять его value.
  4. с offersCheckbox[i] вы просто addEventListener и с этого момента вы используете e.target
  5. вам нужно преобразовать значение в число с помощью parseFloat(num)
  6. При вставке значения нужно учитывать уже добавленное значение, если оно есть, если не разобрать как 0, если есть какое-то разобрать его как число и добавить к нему дополнение:
  7. если вы хотите добавить обратно в качестве тысячного разделителя к результату, у которого есть много ответов здесь, на SO, просто найдите их.

recalculateText.innerHTML = (parseFloat(recalculateText.innerHTML || 0) + num2)

const offersCheckbox = document.querySelectorAll(".checkbox-offers");
const recalculateText = document.querySelector(".recalculate-text");

let total = 0;

for (let i = 0; i < offersCheckbox.length; i++) {
  offersCheckbox[i].addEventListener("click", (e) => {
   
    let num = e.target.value.split(",").join("")
    let num2 = parseFloat(num)

    if (e.target.checked === true) {
      recalculateText.innerHTML = (parseFloat(recalculateText.innerHTML || 0) + num2)
    } else {
      recalculateText.innerHTML = "";
    }
  });
}
<table>
  <tr>
    <tr>
      <td>
        <input type="checkbox" class="checkbox-offers" name="checkbox" value="2,434.38" />
        <td>
          <div class="price-container text-bold" id="checkbox-total">
            <b>$</b>2,434.38
          </div>
        </td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" class="checkbox-offers" name="checkbox" value="76.69" />
      </td>
      <td>
        <div class="price-container text-bold" id="checkbox-total">
          <b>$</b>76.69
        </div>
      </td>
    </tr>
</table>

<span class="recalculate-text text-right text-underline"></span>

Полезные ссылки:

Что возвращают методы querySelectorAll и getElementsBy*?

Как напечатать число с запятыми как разделители тысяч в JavaScript

Какие свойства можно использовать с event.target?

Как преобразовать строку в целое число в JavaScript?< /а>

person ikiK    schedule 03.03.2021

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

Я записал нормализатор валюты в число через регулярное выражение, однако я не записал число в средство форматирования валюты, чтобы переформатировать общую сумму обратно в валюту. Вам нужно будет справиться с этим самостоятельно.

let sum = 0;

let addPrice = (elem) => {
  let value = parseFloat(elem.value.replace(/\$|,/g, ''), 2);
  
  elem.checked ? (sum += value) : (sum -= value);

  document.getElementById('result').innerHTML = sum;
};
<table>
  <tr>
    <tr>
      <td>
        <input type="checkbox" name="price" value="2,434.38" onchange="addPrice(this)" />
        <td>
          <div class="price-container text-bold">
            <b>$</b>2,434.38
          </div>
        </td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" name="price" value="76.69" onchange="addPrice(this)" />
      </td>
      <td>
        <div class="price-container text-bold">
          <b>$</b>76.69
        </div>
      </td>
    </tr>
</table>

<div class="recalculate-text text-right text-underline">Total: <span id="result">0</span></div>

person AGE    schedule 03.03.2021
comment
зачем, ради бога, вы добавили jquery во сниппет только для этой последней вставки?!? И jquery нигде не упоминался;) - person ikiK; 04.03.2021
comment
@ikiK хм, строку jQuery можно легко изменить на document.getElementById, обновление сделано для согласованности - person AGE; 04.03.2021
comment
конечно можно, и так и должно быть :) Думаю, это было просто смешно. После всего, что в vanilla js, вставлять с помощью jquery смысла нет. - person ikiK; 04.03.2021
comment
Я понял тебя, в любом случае хорошая мысль - person AGE; 04.03.2021
comment
Спасибо, кстати, мне нравится ваш подход к использованию регулярных выражений для этого, но вы никогда не увидите, чтобы я делал это для таких простых вещей, как эта. Split.join — мой путь. Тем не менее хороший пример. есть также replaceAll. Чтобы сделать его еще более избыточным - person ikiK; 04.03.2021
comment
Я понимаю вашу точку зрения. Средство форматирования валюты является еще одним препятствием реализации для человека, который задал вопрос, который нужно решить, я могу дать очень хороший ответ на него, поскольку я сам создал много, но ограничения здесь обычно гораздо более строгие (отсюда прямое регулярное выражение). Здесь важна проблема с самим вопросом. - person AGE; 04.03.2021
comment
Конечно, это были всего лишь мои 2 цента, ура. - person ikiK; 04.03.2021

person    schedule
comment
Хотя подобные ответы могут решить проблему, которую они не приветствуют на SO, они нуждаются в объяснении, чтобы OP-актуальность узнала от них что-то для следующего раза. - person ikiK; 04.03.2021