How to calculate total table value with Javascript?

Asked

Viewed 3,994 times

7

Imagine that I have a table with a number of rows that varies dynamically (that is, the user can insert more rows) and each row has 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 add them together to show the total value of my table?

Currently I am 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);
});

That can be seen in this example: FIDDLE

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

Some remarks:

  • No final value treatment is required, this will be dealt with later.
  • Any solution, both in vanilla Javascript how much with jQuery is welcome.

2 answers

5


Assuming that this micro-optimization is really necessary (e.g., the table is gigantic), my suggestion would be to keep the pre-calculated total and update it whenever a line is edited - subtracting the old value and adding 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 out by Renan, to query each key pressed can impair performance, regardless of table size. I updated my example to only do this during the 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 this detail.

1

Being very pedantic: your code makes the queries $('#calculaTotal tbody tr') and $('.total') every time the user hits a key. Keep it in variables that your code becomes more performatic, because then you save the time of queries.

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

Create a map of inputs and the reference of the total field:

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

When creating an input, put 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 running time, for small amounts of lines, can be derisory. But if you’re going to do a performance test with, say, ten thousand lines, you begin to realize the difference.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.