Brian
Brian

Reputation: 39

Javascript sum table conditional

I need to sum values in a two column table, where for each row if col2 is not blank, add it to the total, else instead add col1. Then publish the total to a div

Below is what I've tried but it outputs blank.

var table = document.getElementById("PLTable");
    var cost_est = document.getElementsByClassName("cost_estimate");
    var act_cost = document.getElementsByClassName("act_cost");
    var sum2 = 0;
    for (var i = 0, row; row = table.rows[i]; i++) {
       if (act_cost[i].innerText>0) {
         sum2 += act_cost[i].innerText;
       }
       else {
         sum2 += cost_est[i].innerText;
       }
    }
    document.getElementById("cost_projected_total").innerHTML = sum2
<!--HTML data looks like this:-->

    <table id="PLTable">
      <thead>
        <tr>
          <th>cost estimate</th>
          <th>cost actual</th>
        </tr>
      </thead>
        <tr>
          <td class = "cost_estimate">100</td>
          <td class = "act_cost"></td>
        </tr>
        <tr>
          <td class = "cost_estimate">100</td>
          <td class = "act_cost">50</td>
        </tr>
    </table>
    
    <div id="cost_projected_total">
    </div>

Correct output should be sum2 = 150 & that result should be output inside the div.

Any ideas?

Upvotes: 1

Views: 629

Answers (2)

ThS
ThS

Reputation: 4783

Loop through act_cost and check if the text in each cell is a valid and > 0 number then add it to sum2 otherwise add the cost_est at that index to sum2.

const table = document.getElementById("PLTable"),
      cost_est = document.querySelectorAll(".cost_estimate"),
      act_cost = document.querySelectorAll(".act_cost"),
      total = document.getElementById("cost_projected_total");

let sum2 = 0;

/** loop through the "act_cost" (2nd column) **/
/**
* el: current td from "act_cost".
* i: its index in "act_cost"
**/
act_cost.forEach((el, i) => sum2 += +el.textContent > 0 ? +el.textContent:+cost_est[i].textContent); 

/** "+" transforms the text into a number if possible **/

total.textContent = 'Total: ' + sum2;
<table id="PLTable">
  <thead>
    <tr>
      <th>cost estimate</th>
      <th>cost actual</th>
    </tr>
  </thead>
  <tr>
    <td class="cost_estimate">100</td>
    <td class="act_cost"></td>
  </tr>
  <tr>
    <td class="cost_estimate">100</td>
    <td class="act_cost">50</td>
  </tr>
</table>
<div id="cost_projected_total"></div>

Upvotes: 1

briosheje
briosheje

Reputation: 7446

There are some points to address in your code.

I will try to summarize what was wrong and how it should be change:

  • table.rows actually loops the head as well, so your index would go out of bounds.
  • innerText returns a text, so you first need to conver that value to a Number first, otherwise it will concatenate the strings.

So, basically, what I did to keep your code as it currently was is:

  • added a tbody
  • changed table.rows to the count of the tbody rows.
  • Acquired both numeric values of the looped items.

Below is the working code with the mentioned changes and fixes, it could've been way shorted, I just want to keep the code as close to your so that you can understand where and what was wrong, without necessarely relying on an optimal solution.

var table = document.getElementById("PLTable");
var tbody = table.getElementsByTagName('tbody')[0];
var cost_est = document.getElementsByClassName("cost_estimate");
var act_cost = document.getElementsByClassName("act_cost");
var sum2 = 0;

for (var i = 0; i < tbody.getElementsByTagName('tr').length; i++) {
   var row_act_cost = Number(act_cost[i].innerText);
   var row_cost_est = Number(cost_est[i].innerText);
   if (row_act_cost > 0) {
     sum2 += row_act_cost;
   }
   else {
     sum2 += row_cost_est;
   }

}
document.getElementById("cost_projected_total").innerHTML = sum2;
<table id="PLTable">
  <thead>
    <tr>
      <th>cost estimate</th>
      <th>cost actual</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class = "cost_estimate">100</td>
      <td class = "act_cost"></td>
    </tr>
    <tr>
      <td class = "cost_estimate">100</td>
      <td class = "act_cost">50</td>
    </tr>
   </tbody>
</table>

<div id="cost_projected_total">
</div>

Upvotes: 1

Related Questions