【问题标题】:How to sum table columns using javascrip/jQuery?如何使用 javascript/jQuery 对表列求和?
【发布时间】:2020-08-08 09:06:01
【问题描述】:

我有一个简单的表格,我想对两个列求和。不仅是在选中相关复选框时。

桌子是这样的

<table id="Zinzino" style="border-collapse: collapse; width: 100%;" border="1">
<tbody>
<tr>
<th><strong>Název</strong></th>
<th class="sum"><strong>První balíček</strong></th>
<th class="sum"><strong>Měsíčně</strong></th>
<th> </th>
</tr>
<tr>
<td>BalanceOil <input type="checkbox" id="BalanceOil" name="BalanceOil" class="beru"></td>
<td>149 EUR</td>
<td>30 EUR</td>
<td> </td>
</tr>
<tr>
<td>Extend (2x)<input type="checkbox" </td>
<td>44 EUR</td>
<td>22 EUR</td>
<td> </td>
</tr>
<tr>
<td>Zinobiotic (3x)<input type="checkbox" </td>
<td>64 EUR</td>
<td>23 EUR</td>
<td> </td>
</tr>
<tr>
<td><strong>Celkem</strong></td>
<td class="celkem"> </td>
<td class="celkem"> </td>
<td> </td>
</tr>
</tbody>
</table>

如果需要,我可以修改 hmtl。我有一个工作的fiddle solution 因为我没有发现任何开箱即用的东西,所以我编写了这个。我相信有人可以为我们提供更优雅的东西。甚至是correct我的代码。

【问题讨论】:

    标签: javascript html jquery html-table


    【解决方案1】:

    应该这样做。有不明白的地方欢迎追问。

    $("input[type='checkbox']").on('change', function() {
      updateTotals();
    });
    
    function updateTotals() {
      
      // loop cells with class 'celkem'
      $('.total').each(function(){
        
        // for each total, get the column
        const column = $(this).index();
        let total = 0;
        
        // loop trough all table rows, except the header and the row of totals
        $(this).closest('table').find('tr:not(:first, :last)').each(function(){
          if($(this).find('input').is(':checked')) {
          
            // if the input is checked, add the numeric part to the total
            const str = $(this).find(`td:eq(${column})`).text().replace(/\D/g, "");
            if(str) {
              total += Number(str);
            }
          }
        });
        
        if(!total) {
          // if the total is zero, clear the cell
          $(this).text("");
        } else {
          // otherwise, print the total for this column in the cell
          $(this).text(total + " EUR");
        }
      });
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <table border="1" width="100%">
      <tr>
        <th>Col 1</th>
        <th><strong>Col 2</strong></th>
        <th><strong>Col 3</strong></th>
      </tr>
      <tr>
        <td><input type="checkbox"></td>
        <td>149 EUR</td>
        <td>30 EUR</td>
      </tr>
      <tr>
        <td><input type="checkbox"></td>
        <td>44 EUR</td>
        <td>22 EUR</td>
      </tr>
      <tr>
        <td><input type="checkbox"></td>
        <td>64 EUR</td>
        <td>23 EUR</td>
      </tr>
      <tr>
        <td><strong>Totals</strong></td>
        <td class="total"> </td>
        <td class="total"> </td>
      </tr>
    </table>

    【讨论】:

    • 再次感谢您。我读的越多,你的回答就越喜欢。我想知道你是否可以帮助我处理css。该复选框隐藏在我的网站上。从我得到的问题stackoverflow.com/questions/63310473/… 的答案中,我可以看到它,但我想让它垂直居中。有什么想法吗?
    • 我冒昧地让这段代码更通用,以防其他人发现它有用。要在 td 内垂直居中,您只需添加 td { vertical-align: middle; }
    • 是的,我注意到了。您甚至只使用英语;-) 垂直对齐不起作用。我已经在复选框本身上尝试过。但这对TD也无济于事。 zz.zustatzdravy.cz/kalkulator
    • alotropico,您将如何更新另一行总计?假设我想插入新行作为第二行的总数。
    【解决方案2】:

    好的,我完成了我的解决方案,它可以被视为 Vanilla JavaScript 中的“几乎单行”。由于其简洁性,它的可准备性略有受损。

    在第二行中,数组trs 填充了所有带有复选框的表格行(trs)。仅当检查了某些内容(即 trs.length 是“真实的”)时,才会在以下几行中开始计算总和,否则将 sums 设置为 false。 “计算”包括一个两阶段的.map()-过程(产生一个包含所有单独价格的二维数组)和一个随后的.reduce() 调用以对每一列进行求和。此处内部使用.forEach() 对每个相关列(不是第一列和最后一列)进行求和。

    在最后两行中,结果被写回到表中(最后一个表记录)。这里三元运算符( ? : ) 在尝试连接sums[j]+" EUR" 之前仔细检查sums 是否“真实”。

    document.getElementById("Zinzino").addEventListener('change',function(ev){
      const trs=[...document.querySelectorAll("tbody tr")].filter(tr=>tr.querySelector(':checked'));
      const sums=trs.length                        // calculate only when boxes were checked ...
       ? trs.map(tr=>[...tr.children].slice(1,-1)  // NOT first and last columns
             .map(td=>parseInt(td.textContent)))   // 2D array of prices
         .reduce((a,c)=>(a.forEach((dum,j)=>a[j]+=c[j]),a) ) // summation for each column
       : false;  // -> no calculation 
      // put results into last table row: 
      [...document.querySelectorAll("tbody tr:last-child td")].slice(1,-1)
         .forEach((td,j)=>td.textContent=sums ? sums[j]+" EUR" :'' );
    })
    <table id="Zinzino" style="border-collapse: collapse; width: 100%;" border="1">
    <thead><tr>
    <th><strong>Název</strong></th>
    <th class="sum"><strong>První balíček</strong></th>
    <th class="sum"><strong>Měsíčně</strong></th>
    <th> </th>
    </tr></thead>
    <tbody>
    <tr>
    <td>BalanceOil <input type="checkbox" id="BalanceOil" name="BalanceOil" class="beru"></td>
    <td>149 EUR</td>
    <td>30 EUR</td>
    <td> </td>
    </tr>
    <tr>
    <td>Extend (2x)<input type="checkbox"></td>
    <td>44 EUR</td>
    <td>22 EUR</td>
    <td> </td>
    </tr>
    <tr>
    <td>Zinobiotic (3x)<input type="checkbox"></td>
    <td>64 EUR</td>
    <td>23 EUR</td>
    <td> </td>
    </tr>
    <tr>
    <td><strong>Celkem</strong></td>
    <td class="celkem"> </td>
    <td class="celkem"> </td>
    <td> </td>
    </tr>
    </tbody>
    </table>

    【讨论】:

    • 哇。那很好。太......让我说复杂。我喜欢它,但我不完全理解代码。您不必解释,这将需要很长时间。感谢您的宝贵时间。
    • 感谢您给我反馈。我也很喜欢接受的答案,因为它很容易理解!而且,因为您已经在使用 jQuery,所以使用它是有意义的! My.solution 只是在 Vanilla JS 中做的一个练习。
    • 如果我喜欢更好的东西,我可能会更改已接受的解决方案。我很高兴可能 100% 了解@alotropico 解决方案。谢谢你的。它几乎看起来像 ruby​​ 中的 oneliner....
    • :D 是的,它离单线不远。但有时以“可读”的方式编写代码更为重要。所以,坚持你接受的答案!
    • 我喜欢我的 :-) 在小提琴中,但我会用你的,伙计们……当我以前在 IT 部门工作时,我曾向我的老板展示过。我们得到了一些我们无法解决的问题......发布在 SO 上并在 5 分钟内得到了有效的解决方案
    猜你喜欢
    • 1970-01-01
    • 2012-10-01
    • 2017-05-01
    • 1970-01-01
    • 2015-10-16
    • 2012-04-05
    • 2016-10-23
    • 1970-01-01
    • 2019-07-12
    相关资源
    最近更新 更多