0

I have a table like this in my page:

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<input type="text" id="myInput"  placeholder="Search for anything.." title="Type in a name" ></input>
<table  class="table table-bordered table-striped"  >
<tbody id="myTable">
<td>
<?php echo  $product_name ?>
</td>
<td>

<?php echo  $gender ?>
</td>
<td>
<?php echo  $date ?>
</td>

</td>
<td>
<?php echo  $quantity ?>
</td>
<td>
<?php echo  $shopname ?>
</td>
<td class="valor text-right">
<?php echo  $price ?>
</td>
</tbody>
<tfoot>
        <tr class="info">
            <td colspan="2" class="text-right">TOTAL:</td>
            <td class="total text-right"></td>
        </tr>
   </tfoot>
</table>

The idea here is to calculate the total for the column with class valor and it's shown on foot of the table at the colmn with class total.

And also the idea is that the user can filter rows typing anything on the input text named myInput and therefore the total should be recalculated.

By this time I'm able to filter rows with the jQuery code below:

$(document).ready(function () {

    var $rows = $(".table tbody tr");
    var total = 0;


$rows.each(function () {
    total += parseFloat($(this).find(".valor").text().replace(/\./g, "").replace(",", "."));
});
     $("#myInput").keyup(function () {
    var filtertext = $(this).val();
    var regex = new RegExp(filtertext, 'i');
    $rows.hide().filter(function () {
        return regex.test($(this).text());
    }).show();

    $(".table tbody tr:visible").each(function () {
        total += parseFloat($(this).find(".valor").text().replace(/\./g, "").replace(",", "."));
    });
    $(".total").html(formataTotal(total.toFixed(2)));

});

$(".total").html(formataTotal(total.toFixed(2)));
});

function formatTotal(num) {
var parts = num.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return parts.join(",");
}

By using the above code m successfully filtering the rows but i am not getting any sum of the column after being filtered rows nor the total sum of that column valor

1 Answers1

0

A couple things to address to get the script functioning

  1. You have defined formatTotal but you are calling formataTotal. With that adjustment you should start seeing a total output.
  2. You'll see a total but you now have a running total since you have the variable total was defined in the global scope of the script. This will persist until you refresh the browser. Reset your total when your keyup function begins. $("#myInput").keyup(function () { total = 0; ...

I would recommend to also break some of your code into smaller, reuseable functions. For example, when setting your total value create a function as such

function displayTotal(total) {
    $(".total").html(formatTotal(total.toFixed(2)));
}

You can take that one step further and note that you use the same class consistently to output the total so you might want to offload that a global.

$totalElement = $(".total");
function displayTotal(total) {
    $totalElement.html(formatTotal(total.toFixed(2)));
}

You should consider handling your total value consistently and with some precaution so you do not end up with a 'NaN' value. Again you can break the task of checking a row for a price with a function.

function getPriceForRow(row) {
   $valor = $(row).find(".valor");
   if($valor.length) {
     return parseFloat($valor.text().replace(/\./g, "").replace(",", "."));
   }
   return parseFloat(0);
}

With a couple small adjustments your script may look as such. There are other improvements that can be made and things that you should ideally do in this case, but hopefully I gave a sense for what you can accomplish just with breaking your code down into solid functions.

$(document).ready(function () {

    var $rows = $(".table tbody tr");
    var $totalElement = $(".total");
    var total = 0;

    $rows.each(function () {
        total += getPriceForRow(this);
    });
    displayTotal(total);

    $("#myInput").keyup(function () {
        total = 0;
        var filtertext = $(this).val();
        var regex = new RegExp(filtertext, 'i');
        $rows.hide().filter(function () {
            return regex.test($(this).text());
        }).show();
        $(".table tbody tr:visible").each(function () {
            total += getPriceForRow(this);
        });
        displayTotal(total);

    });

    function getPriceForRow(row) {
        $valor = $(row).find(".valor");
        if ($valor.length) {
            return parseFloat($valor.text().replace(/\./g, "").replace(",", "."));
        }
        return parseFloat(0);
    }

    function formatTotal(num) {
        var parts = num.toString().split(".");
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
        return parts.join(",");
    }

    function displayTotal(total) {
        $totalElement.html(formatTotal(total.toFixed(2)));
    }
});

Ideally you can avoid your globals in this case. You may want to read into closures here on MDN . It is how you can simulate private scope to an extent in your script. More or less, wrapping up and protecting the values in the contexts they are needed (simplification, I know).

Global scope variables are often troublesome for a number of reasons. You can do some reading on this here

Here is a good library for formatting currency as well, accounting.js

erpfast
  • 36
  • 3