I have a code which counts a total summary of all price table cells. This is not exactly what do I need. I need to count the summary from only visible rows. I use filtering by date range, once I change date it displays only dates from the selected date range, but the summary price is from the all rows. I need to implement the part of the code for visible table rows only and update the summary price in the span.
Any advice?
function filterRows() {
var from = jQuery("#datefilterfrom").val();
var to = jQuery("#datefilterto").val();
if (!from && !to) { // no value for from and to
return;
}
from = from || "1970-01-01"; // default from to a old date if it is not set
to = to || "2999-12-31";
var dateFrom = moment(from);
var dateTo = moment(to);
jQuery("#table tr").each(function(i, tr) {
var val = jQuery(tr).find("td:nth-child(2)").text();
var dateVal = moment(val, "DD.MM.YYYY");
var visible = (dateVal.isBetween(dateFrom, dateTo, null, [])) ? "" : "none"; // [] for inclusive
jQuery(tr).css("display", visible);
//summary start
var table = document.getElementById("table"),
sumVal = 0;
for (var i = 1; i < table.rows.length; i ) {
sumVal = sumVal parseInt(table.rows[i].cells[2].innerHTML);
}
document.getElementById("val").innerHTML = "Sum Value = " sumVal;
console.log(sumVal);
});
//summary end
}
jQuery("#datefilterfrom").on("change", filterRows);
jQuery("#datefilterto").on("change", filterRows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<div >
<div >
<h4>Date from</h4>
<input type="date" id="datefilterfrom" data-date-split-input="true">
<h4>Date to</h4>
<input type="date" id="datefilterto" data-date-split-input="true">
</div>
</div>
<span id="val"></span>
<table id="table" >
<tr>
<th>Name</th>
<th>Date</th>
<th>Price</th>
</tr>
<tr>
<td>Name</td>
<td>20.10.2020</td>
<td>20</td>
</tr>
<tr>
<td>Name</td>
<td>21.10.2020</td>
<td>25</td>
</tr>
<tr>
<td>Name</td>
<td>22.10.2020</td>
<td>30</td>
</tr>
</table>
This is how it looks like when I select date range in HTML (so I need to get summary from only this selected tr)
I think there need to be some condition added here
sumVal = sumVal parseInt(table.rows[i].cells[2].innerHTML);
CodePudding user response:
You don't need two loops. You're already looping through the rows with .each()
to make them visible or invisible, you can calculate the total in that same loop. After you determine if the row should be visible, use that variable in an if
statement to add to the total.
jQuery has a built-in function .toggle()
that will switch the visibility of an element. You can make visible
a boolean variable instead of a display
style value, then use that as the argument to .toggle()
. Then you can use this same value in the if
condition.
Make your access to columns less dependent on the table layout by using classes instead of column indexes. Use jQuery(tr).find(".price")
to access the price column, for instance.
Use <thead>
and <tbody>
to distinguish the headings from the table data, then use tbody
in the .each()
loop to only process data rows.
function filterRows() {
var from = jQuery("#datefilterfrom").val();
var to = jQuery("#datefilterto").val();
if (!from && !to) { // no value for from and to
return;
}
from = from || "1970-01-01"; // default from to a old date if it is not set
to = to || "2999-12-31";
var dateFrom = moment(from);
var dateTo = moment(to);
var sumVal = 0;
jQuery("#table tbody tr").each(function(i, tr) {
var val = jQuery(tr).find(".date").text();
var dateVal = moment(val, "DD.MM.YYYY");
var visible = (dateVal.isBetween(dateFrom, dateTo, null, []));
jQuery(tr).toggle(visible);
if (visible) {
sumVal = parseInt(jQuery(tr).find(".price").text());
}
$("#val").text("Sum Value = " sumVal);
});
}
jQuery("#datefilterfrom, #datefilterto").on("change", filterRows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<div >
<div >
<h4>Date from</h4>
<input type="date" id="datefilterfrom" data-date-split-input="true">
<h4>Date to</h4>
<input type="date" id="datefilterto" data-date-split-input="true">
</div>
</div>
<span id="val"></span>
<table id="table" >
<thead>
<tr>
<th>Name</th>
<th>Date</th>
<th>Price</th>
</tr>
<thead>
<tbody>
<tr>
<td>Name</td>
<td >20.10.2020</td>
<td >20</td>
</tr>
<tr>
<td>Name</td>
<td >21.10.2020</td>
<td >25</td>
</tr>
<tr>
<td>Name</td>
<td >22.10.2020</td>
<td >30</td>
</tr>
<tbody>
</table>