问题
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 (tr
s) 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