Skip to content
Advertisement

Get summary number from only visible table rows

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 class="row">
  <div class="col-md-3">
    <h4>Date from</h4>
    <input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
    <h4>Date to</h4>
    <input type="date" class="form-control" id="datefilterto" data-date-split-input="true">
  </div>
</div>

<span id="val"></span>

<table id="table" class="sortable">
  <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)

enter image description here

I think there need to be some condition added here

sumVal = sumVal + parseInt(table.rows[i].cells[2].innerHTML);

Advertisement

Answer

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 class="row">
  <div class="col-md-3">
    <h4>Date from</h4>
    <input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
    <h4>Date to</h4>
    <input type="date" class="form-control" id="datefilterto" data-date-split-input="true">
  </div>
</div>

<span id="val"></span>

<table id="table" class="sortable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Date</th>
      <th>Price</th>
    </tr>
    <thead>
      <tbody>
        <tr>
          <td>Name</td>
          <td class="date">20.10.2020</td>
          <td class="price">20</td>
        </tr>
        <tr>
          <td>Name</td>
          <td class="date">21.10.2020</td>
          <td class="price">25</td>
        </tr>
        <tr>
          <td>Name</td>
          <td class="date">22.10.2020</td>
          <td class="price">30</td>
        </tr>
        <tbody>
</table>
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement