I’m a bit stuck trying to loop through a table row, calculate the values (which are then output) then move onto the next row. Seems to work fine for the first row?
Here’s a code snippet and jsfiddle link:
var rows = $("#invoice_table tr:gt(0)"); // skip the header row
rows.each(function(index) {
rows.children("td").each(function() { // calculate amount, vat, subtotal for row
qty = $("td:nth-child(3) input").val();
rate = $("td:nth-child(4) input").val();
amount = qty * rate;
vat = amount / 100 * 20;
subtotal = amount;
subtotal += vat;
vat = vat.toFixed(2); // limit to two decimal places
amount = amount.toFixed(2);
subtotal = subtotal.toFixed(2);
$("td:nth-child(5) input").val(amount); // output the values
$("td:nth-child(6) input").val(vat);
$("td:nth-child(7) input").val(subtotal);
});
});
Thanks!
EDIT:
Okay so being the stubborn man I am, I forged ahead with my own ideas. This is the code I ended up with. Totals the rows, then adds up the columns.
$("#invoice_table").live({ // invoice calculations
blur: function() {
var qty = '0.0';
var rate = '0.0';
var amount = '0.0';
var amttotal = '0.0';
var vat = '0.0';
var vattotal = '0.0';
var subtotal = '0.0';
var total = '0.0';
var num_tr = $('#invoice_table tr').length;
num_tr = num_tr-2; // skip totals row
amount = amount * 1; // force js to handle the var as a number
qty = qty * 1;
rate = rate * 1;
vat = vat * 1;
amttotal = amttotal * 1;
vattotal = vattotal * 1;
total = total * 1;
for(var i = 1;i < num_tr;i++) {
var row = $('#invoice_table tr:nth-child('+i+')'); // skip the header row
row.children("td").each(function() { // calculate amount, vat, subtotal for row
qty = $('tr:nth-child('+i+') td:nth-child(3) input').val();
rate = $('tr:nth-child('+i+') td:nth-child(4) input').val();
amount = qty * rate;
vat = amount / 100 * 20;
subtotal = amount;
subtotal += vat;
vat = vat.toFixed(2); // limit to two decimal places
amount = amount.toFixed(2);
subtotal = subtotal.toFixed(2);
$('tr:nth-child('+i+') td:nth-child(5) input').val(amount); // output the values
$('tr:nth-child('+i+') td:nth-child(6) input').val(vat);
$('tr:nth-child('+i+') td:nth-child(7) input').val(subtotal);
});
}
for(var i = 2;i < num_tr;i++) {
var rows = $('#invoice_table tr:nth-child('+i+')'); // skip the header row
amttotal += parseFloat($('tr:nth-child('+i+') td:nth-child(5) input').val());
vattotal += parseFloat($('tr:nth-child('+i+') td:nth-child(6) input').val());
total += parseFloat($('tr:nth-child('+i+') td:nth-child(7) input').val());
}
amttotal = amttotal.toFixed(2); // limit to two decimal places
vattotal = vattotal.toFixed(2);
total = total.toFixed(2);
$("#total_amount input").val(amttotal);
$("#total_vat input").val(vattotal);
$("#grand_total input").val(total);
}
});
First up I can see a problem, in your first
rows.eachyou are then looping through all td that are children ofrows. Instead usethisto limit it to the current row that you are looping through. Also, you don’t have any scope for yourqtyandrateparts, you are looking at alltds as well.You may need to adjust the selectors as stuff for the outputs as I don’t actually know your layout or where you are trying to display the outputs.
Potentially though, you could bind to the change events for each input field and only do the calculations then. If you can edit your source to add some more classes you could do something like:
Not sure if it’d be faster or easier though.