Sasha
Sasha

Reputation: 6466

Summing a table column with javascript

I'm trying to use JS to sum up a column of already Javascript-generated values. I'm new to JS, so this may be way wrong. At any rate, I tried this:

NOTE -- FINAL CODE AT BOTTOM

 $(".js-package").change(function(){
        var parentTable = $(this).parents("table");
        var table_rows = parentTable.rows;
        var height = table_rows.length;
        var total = 0;
        for (var i = 0; i < height; i++) {
            var current_row = table_rows[i];
            total += current_row[5];
        }
        $(parentTable).find(".js-lb-total").html((total).toFixed(2));
 });

This applies to a bunch of html, but the relevant stuff is that I've got this line where things are supposed to total up:

<td class="js-lb-total">?</td>

And this further up:

 <td>
   <%= l.select :units, dropdown, {}, :class => "unit_select js-package" %>
 </td>

Importantly, the seemingly arbitrary number 5 refers to the column (assuming JS starts arrays at 0) that I'm trying to sum up.

Any idea what I'm doing wrong/how to fix it? I'll go ahead and look into opening a fiddle that I can link to with the more complete code. I'll add that link below.

Thanks!

EDIT -- Row totaling script below

 $(".js-package").change(function(){
        var numOfPackages = parseFloat($(this).val());
        var parentTr = $(this).parents("tr");
        var parentTable = $(this).parents("table");
        var weight = parseFloat($(parentTr).find(".js-weight").attr('data-weight'));
        var price = parseFloat($(parentTr).find(".js-lb-price").attr('data-lb-price'));
        $(parentTr).find(".js-price").html(((numOfPackages * weight * price).toFixed(2)));
        $(parentTr).find(".js-lbs").html((numOfPackages * weight).toFixed(2));
    });

EDIT 2 -- Basic fiddle link here Fiddle. None of the JS is working there, though, for some reason. (The first bunch works on my server). So it may not be particularly helpful.

EDIT 3 -- To be clear, I'm trying to sum a column whose values are all dynamically generated by another javascript action. They're not in the html. Could that be part of the problem?

FINAL EDIT -- After much tweaking and following of advice, I got this, which works great (and totals both price and poundage, after totaling each line).

$(".js-package").change(function(){
        var numOfPackages = parseFloat($(this).val());
        var parentTr = $(this).parents("tr");
        var parentTable = $(this).parents("table");
        var weight = parseFloat($(parentTr).find(".js-weight").attr('data-weight'));
        var price = parseFloat($(parentTr).find(".js-lb-price").attr('data-lb-price'));
        $(parentTr).find(".js-price").html(((numOfPackages * weight * price).toFixed(2)));
        $(parentTr).find(".js-lbs").html((numOfPackages * weight).toFixed(2));

    var table = document.getElementById('sumtable');
    var table_rows = table.rows;
    var height = parseInt(table_rows.length);
    var lb_total = 0;      
    var money_total = 0;
    var cell;   
    for (var i = 1, iLen = height - 1; i < iLen; i++) {
        cell = table_rows[i].cells[5];
        lb_total += Number(cell.textContent);
    }
    for (var j = 1, jLen = height - 1; j < jLen; j++) {
        cell = table_rows[j].cells[6];
        money_total += Number(cell.textContent);
    }

    $(parentTable).find(".js-lb-total").html(lb_total.toFixed(2));
    $(parentTable).find(".js-price-total").html(money_total.toFixed(2));
});

Upvotes: 1

Views: 6543

Answers (2)

RobG
RobG

Reputation: 147453

The example below might get you started. If the headers and footers are in a different table section, it will make life easier, I've put them all in the one tbody.

Things to note:

  1. Values read from cells will be strings, so you need to convert them to numbers
  2. Javascript is notoriously bad at decimal arithmetic, much better to do integer arithmetic and convert to decimal only at the very end for presentation
  3. Be careful of Math.toFixed, it has quirks, search the questions

Good luck. :-)

<script>
// column is the column with values in it to total (first column is zero)
// Assume values are floats.
function addRows(tableId, column, resultId) {

    var table = document.getElementById(tableId);
    var rows = table.rows;
    var total = 0;
    var cell;

    // Assume first row is headers, adjust as required
    // Assume last row is footer, addjust as required
    for (var i=1, iLen=rows.length - 1; i<iLen; i++) {
        cell = rows[i].cells[column];
        total += Number(cell.textContent || cell.innerText);
    }
    document.getElementById(resultId).innerHTML = total.toFixed(2);
}
</script>

<table id="productTable">
  <tr>
    <th>Item
    <th>value ($)
  <tr>
    <td>foo
    <td>23.33
  <tr>
    <td>bar
    <td>03.04
  <tr>
    <td>Total
    <td id="totalValue">
</table>
<button onclick="addRows('productTable', 1, 'totalValue')">Update total</button>

Upvotes: 4

Omar As&#39;hab
Omar As&#39;hab

Reputation: 138

try this:

total = parseInt(total)+ parseInt(current_row[5].childNodes[1].value);

if that doesn't work try getting the cell of the column you want:

total =parseInt(total)+ parseInt(current_row[5].cells[try numbers here].childNodes[1].value);

hope i helped.

Upvotes: 2

Related Questions