How to sum table columns using javascrip/jQuery?

空扰寡人 提交于 2020-08-10 20:09:11

问题


I have a simple table and I want to sum two comlumns. On top of than only when a relevant checkbox is checked.

The table is like that

<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>

I can modify the hmtl if needed. I have a working fiddle solution Because I have not found anything working out of the box I coded this one. I am sure that someone could provide us with something more elegant. Or even correct my code.


回答1:


This should do it. Feel free to ask if some detail is not understood.

$("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>



回答2:


OK, I completed my solution which can be seen as an "almost One-Liner" in Vanilla JavaScript. Because of its brevity the readybility is slightly impaired.

In the second line the array trs is filled with all table rows (trs) with checked boxes. Only if something was checked (i.e. trs.length is "truthy") the calculation of sums is started in the following lines, otherwise sums is set to false. The "calculation" consists of a two-stage .map()-process (resulting in a 2D Array with all the individual prices) and a subsequent .reduce() call to do the summation for each column. A .forEach() is used internally here to do the summation for each of the relevant columns (not the first and the last ones).

In the last two lines the reults are written back to the table (last table record). Here the trenary operator ( ? : ) carefully checks whether sums is "truthy" before attemping the concatenation of sums[j]+" EUR".

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>


来源:https://stackoverflow.com/questions/63313608/how-to-sum-table-columns-using-javascrip-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!