jQuery汇总具有唯一ID元素的行

时间:2018-10-02 22:10:38

标签: javascript jquery

我正在寻找一种显示每行最后2个单元格中所有输入元素的总和(数量和数量)的方法。 该表中的每个元素都有唯一的ID。每个输入元素都有一个ID,该ID包含有关它出现在该行中的信息:

var trRows = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];

trRows.forEach(function(trRow) {

  var $sumQuantity = 0;
  var $sumAmount = 0;

  $(this).find('#tr' + trRow + 'input[id *= "qty"]').each(function() {

    $sumQuantity += +$(this).text() || 0;
  });

  $(this).find('#tr' + trRow + 'input[id *= "amount"]').each(function() {

    $sumAmount += +$(this).text() || 0;
  });

  $('#sumQtyTR' + trRows, this).html($sumQuantity);
  $('#sumAmountTR' + trRows, this).html($sumAmount);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>

  <tr id='tr2'>
    <td id='td2_65'><span id='span_i2qty_65'><input id='input_i2qty_65' class='editbox'></span>
    </td>
    <td id='td2_65'><span id='span_i2amount_65'><input id='input_i2amount_65' class='editbox'></span>
    </td>

    <td id='td2_66'><span id='span_i2qty_66'><input id='input_i2qty_66' class='editbox'></span>
    </td>
    <td id='td2_66'><span id='span_i2amount_66'><input id='input_i2amount_66' class='editbox'></span>
    </td>

    <td id='sumQtyTR2'></td>
    <td id='sumAmountTR2'></td>
  </tr>

  <tr id='tr3'>
    <td id='td3_65'><span id='span_i3qty_65'><input id='input_i3qty_65' class='editbox'></span>
    </td>
    <td id='td3_65'><span id='span_i3amount_65'><input id='input_i3amount_65' class='editbox'></span>
    </td>

    <td id='td3_66'><span id='span_i3qty_66'><input id='input_i3qty_66' class='editbox'></span>
    </td>
    <td id='td3_66'><span id='span_i3amount_66'><input id='input_i3amount_66' class='editbox'></span>
    </td>

    <td id='sumQtyTR3'></td>
    <td id='sumAmountTR3'></td>
  </tr>
  <!-- More rows -->

</table>

我不知道为什么不显示总和。选择器?谢谢

1 个答案:

答案 0 :(得分:-1)

建议

在您的代码中,有一些有趣的地方可能值得考虑,以减少混乱:

  1. ID旨在唯一。在HTML文档中不应该在多个地方使用ID。在您认为两个或多个元素可能共享一个id的地方,应该改用class
  2. 除非您在其他地方使用jQuery,否则您应该知道jQuery是不必要的。它确实具有几个优点(包括跨浏览器合规性),但是您应该考虑使用本机JavaScript和将添加必要的polyfills的打包器

示例

出于学习目的,以下示例旨在在结构/设计上与OP中的原始源代码非常接近;但是,应注意,有许多方法可以进行优化以提高性能和可读性。

逻辑流程值得一提。这些示例中的结构效率低下,因为每次更新输入时,它都会循环遍历并重新计算所有行的总和。可以通过仅计算和更新更改后的行的总和来改善这一点。此外,通过使用更多的语义HTML和使用类(如果需要选择),可以更好地改善包含感兴趣行(例如row_ids)的数组的功能。

下面的jQuery和ES6 +示例也进行了其他一些重大更改。最值得注意的是onChange事件处理程序。 OP中的代码会在页面加载后立即遍历每个ID,但是再也不会遍历。在修改输入框时,需要挂钩某个事件,该事件将被调用。因此onChange或onBlur事件对于重新计算值是必需的。

jQuery示例

鉴于这两项建议,我对您的HTML和JavaScript进行了一些实质性更改,包括但不限于:

  • 删除了不必要的ID,并添加了相应的类
  • 使用reduce进行总和计算

jQuery(document).ready(function($) {
  let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];

  function changeEventHandler() {
    $.each(row_ids, function(ndx, row_id) {

      const $row = $('#' + row_id)
      if (!$row.length)
        return;

      const quantity = $row.find('input.quantity').get().reduce(function(acc, input) {
        acc += parseFloat(input.value) || 0;
        return acc
      }, 0)
      const amount = $row.find('input.amount').get().reduce(function(acc, input) {
        acc += parseFloat(input.value) || 0;
        return acc
      }, 0)

      $row.find('.sum.quantity').text(quantity)
      $row.find('.sum.amount').text(amount)

    });
  }

  $(document).on('change', 'input', changeEventHandler)
})
.sum { background: #eee; }
th,td {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
table { width: 100%; }
input { width: 40%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Fill in each input with a number (watch sums auto-update):
<table>
  <thead>
    <tr>
      <th>QTY 1</th>
      <th>AMT 1</th>
      <th>QTY 2</th>
      <th>AMT 2</th>
      <th>SUM QTY</th>
      <th>SUM AMT</th>
    </tr>
  </thead>
  <tbody>
    <tr id='tr2'>
      <!-- td: use class and not id -->
      <!-- remove unnecessary classes -->
      <td class="item_65"><span><input class='quantity'></span></td>
      <td class="item_65"><span><input class='amount'></span></td>
      <td class="item_66"><span><input class='quantity'></span></td>
      <td class="item_66"><span><input class='amount'></span></td>

      <td class="sum quantity"></td>
      <td class="sum amount"></td>
    </tr>

    <tr id='tr3'>
      <td class="item_65"><span><input class='quantity'></span></td>
      <td class="item_65"><span><input class='amount'></span></td>
      <td class="item_66"><span><input class='quantity'></span></td>
      <td class="item_66"><span><input class='amount'></span></td>

      <td class="sum quantity"></td>
      <td class="sum amount"></td>
    </tr>
    <!-- More rows -->
  </tbody>
</table>


ES6 +示例

鉴于两项建议,我对您的HTML和JavaScript进行了一些实质性更改,包括但不限于:

  • 删除了不必要的ID,并添加了相应的类
  • 删除了不必要的jQuery代码(使用了本机事件处理)
  • 使用reduce进行总和计算
  • 使用箭头功能简化语法

注意:如前所述,该代码可能无法在所有浏览器(所有版本和变体)中运行,但应在大多数较新的浏览器中运行。由于该代码段配置为使用babel

,因此该代码段可在大多数(如果不是全部)范围内使用

function changeEventHandler() {
  let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
  // could iterate over the rows:
  //   document.querySelectorAll(selector) 
  //   where selector is 'tr' or '[id^="tr"]' 

  row_ids.forEach(row_id => {
    const row = document.querySelector(`#${row_id}`)
    if (row == null)
      return;

    const qty_el = row.querySelectorAll('input.quantity')
    const quantity = [...qty_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)
    const amt_el = row.querySelectorAll('input.amount')
    const amount = [...amt_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)

    row.querySelector('.sum.quantity').textContent = quantity
    row.querySelector('.sum.amount').textContent = amount

  });
}

window.setTimeout(function() {
  document.querySelectorAll('input').forEach(() => this.onchange = changeEventHandler)
},0);
.sum { background: #eee; }
th,td {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
table { width: 100%; }
input { width: 40%; }
Fill in each input with a number (watch sums auto-update):
<table>
  <thead>
    <tr>
      <th>QTY 1</th>
      <th>AMT 1</th>
      <th>QTY 2</th>
      <th>AMT 2</th>
      <th>SUM QTY</th>
      <th>SUM AMT</th>
    </tr>
  </thead>
  <tbody>
    <tr id='tr2'>
      <!-- td: use class and not id -->
      <!-- remove unnecessary classes -->
      <td class="item_65"><span><input class='quantity'></span></td>
      <td class="item_65"><span><input class='amount'></span></td>
      <td class="item_66"><span><input class='quantity'></span></td>
      <td class="item_66"><span><input class='amount'></span></td>

      <td class="sum quantity"></td>
      <td class="sum amount"></td>
    </tr>

    <tr id='tr3'>
      <td class="item_65"><span><input class='quantity'></span></td>
      <td class="item_65"><span><input class='amount'></span></td>
      <td class="item_66"><span><input class='quantity'></span></td>
      <td class="item_66"><span><input class='amount'></span></td>

      <td class="sum quantity"></td>
      <td class="sum amount"></td>
    </tr>
    <!-- More rows -->
  </tbody>
</table>