How to calculate total table value with JavaScript?

7

Imagine that I have a table with a number of rows that varies dynamically (that is, the user can insert more rows), each row having two columns with two text fields: quantidade and valor .

What would be the most performative way to calculate the value of each of these lines and sum them to show the total value of my table?

Currently I'm using the following code:

$(document).on('keyup', '#calculaTotal tbody td input', function () {
    var total = 0;
    $('#calculaTotal tbody tr').each(function () {
        var td = $(this).children('td');
        total += td.eq(0).children('input').val() * td.eq(1).children('input').val();
    });
    $('.total').html(total);
});

What can be seen in this example: FIDDLE

The fact is that this table can have n lines and I believe there are faster ways to do this total calculation. Anyone have any idea how?

Some comments:

  • No end value processing is required, this will be dealt with later.
  • Any solution in both vanilla JavaScript and jQuery is welcome.
asked by anonymous 02.09.2014 / 23:07

2 answers

5

Assuming this micro-optimization is even necessary (eg, the table is gigantic), my suggestion would be to keep the total pre-calculated and update it whenever a row is edited - subtracting the old value and increasing the new value:

var total = 0;
var editando = 0;
var linha1;
var linha2;

$(document).on('focus', '#calculaTotal tbody td input', function () {
    var td = $(this).closest("tr").children('td');
    linha1 = td.eq(0).children('input')[0];
    linha2 = td.eq(1).children('input')[0];
    editando = parseInt(+linha1.value, 10) * parseInt(+linha2.value, 10);
});

$(document).on('keyup', '#calculaTotal tbody td input', function () {
    valor = parseInt(+linha1.value, 10) * parseInt(+linha2.value, 10);
    total = total - editando + valor;
    editando = valor;

    $('.total').html(total);
});

Example in jsFiddle .

Note: as pointed to Renan , query each key pressed can hurt performance, regardless of the size of the table. I updated my example to only do this during onfocus . It's still a micro-optimization, but it can affect the responsiveness of the application, so I think it might be a good idea to pay attention to that detail.

    
02.09.2014 / 23:26
1

Being pedantic: your code makes the queries $('#calculaTotal tbody tr') and $('.total') every time the user hits a key. Save this in variables that your code becomes more performative, because there you save the queries time.

Another thing, you're recalculating whenever the user hits a key, no matter where it is. Do this only when a value is updated;)

Create an input map and the total field reference:

var inputs = {}; // os inputs vão sendo colocados aqui a medida que forem criados.
var campoTotal = $('.total');

When you create an input, place it in the dictionary like this and initialize event like this:

inputs[idDoTeuInput] = $(novoInput);
novoInput.change(function () {
    var total = 0;
    for (var i in inputs) {
        total += Number(inputs[i].val());
    }
    campoTotal.html(total);
});

Do not forget to take an input from the map if the corresponding line is deleted.

The difference in runtime for small amounts of rows may be paltry. But if you're going to do a performance test with, say, ten thousand lines, you start to notice the difference.

    
02.09.2014 / 23:27