SPL
SPL

Reputation: 23

get sum of the column for each different table javascript

I have a page where several tables displayed with the data from the backend with php foreach functionality.
Each table has few rows with a column " m3 "

<td  class="p-0 singleUnitCubic-{{$container->id}}">
          {{$item->prettyDecimal('total_cubic')}}
</td>

rendered result is:

_______________________________________________________
<td class="p-0 singleUnitCubic-13">
                    12.600
</td>
<td class="p-0 singleUnitCubic-13">
                    4.000
</td>
_______________________________________________________
Total:  <span id="totalCubic-13">16.600</span>


_______________________________________________________
<td class="p-0 singleUnitCubic-69">
                    4.230
</td>
<td class="p-0 singleUnitCubic-69">
                    3.000
</td>
_______________________________________________________
Total:  <span id="totalCubic-69">7.230</span>

Now I can easily get the sum for one of the tables because I marked each class="singleUnitCubic" with corresponding table id number, in this case, it's class="singleUnitCubic-13" and my sum function is:

cubicOutput = document.getElementById('totalCubic-13');

var sumSingleUnits = 0;

$('.singleUnitCubic-13').each(function(){
    sumSingleUnits += parseFloat($(this).text());
    cubicOutput.innerText = SingleUnits.toFixed(3);
});

but how can I do the same dynamically for other tables where class="singleUnitCubic-69" and also display that sum under each corresponding table where <span id="totalCubic-69">?

Should it be something like finding what is the id number after singleUnitCubic- which I could do by:

 <td onload="getTableid(this.class)"  class="p-0 singleUnitCubic-{{$container->id}}">
                    {{$item->prettyDecimal('total_cubic')}}
 </td>

function getTableId(Id) {
           tableId = Id.split('-')[1];
           totalCubic = document.getElementById("totalCubic-".concat(tableId));

and then somehow injecting it to the sum function?

P.S. I can't do the sum in back-end which would be easy.

Upvotes: 2

Views: 257

Answers (2)

PeterKA
PeterKA

Reputation: 24638

First determine the tables that have the target columns, you can use :has() or other method. Then iterate through each table and find the total. Array#reduce comes in handy here:

  //capture the table that have target columns
  const tables = $('table:has(td[class*=singleUnitCubic])');
  //now process each table
  const totals = tables.each(function() {
      //determine the id of span to update
      const id = ['#totalCubic',$('td[class*=singleUnitCubic]',this).attr('class').split(' ')
      .filter(c => c.indexOf('singleUnitCubic') === 0)[0]
      .split('-')[1]].join('-');
      //get this total
      const total = $('td[class*=singleUnitCubic]', this)
      .map((i,td) => +td.textContent).get()
      .reduce((acc, cur) => acc += cur, 0);
      //now update the dom
      $(id).text( total.toFixed(3) );
  });

DEMO

$(function() {
  //capture the table that have target columns
  const tables = $('table:has(td[class*=singleUnitCubic])');
  //now process each table
  const totals = tables.each(function() {
      //determine the id of span to update
      const id = ['#totalCubic',$('td[class*=singleUnitCubic]',this).attr('class').split(' ')
      .filter(c => c.indexOf('singleUnitCubic') === 0)[0]
      .split('-')[1]].join('-');
      //get this total
      const total = $('td[class*=singleUnitCubic]', this)
      .map((i,td) => +td.textContent).get()
      .reduce((acc, cur) => acc += cur, 0);
      //now update the dom
      $(id).text( total.toFixed(3) );
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td class="p-0 singleUnitCubic-13">
                    12.600
</td>
</tr>
<tr>
<td class="p-0 singleUnitCubic-13">
                    4.000
</td>
</tr></tbody>
</table>
Total:  <span id="totalCubic-13"></span>


<table>
<tbody>
<tr>
<td class="p-0 singleUnitCubic-69">
                    4.230
</td>
</tr>
<tr>
<td class="p-0 singleUnitCubic-69">
                    3.000
</td>
</tr>
</tbody>
</table>
Total:  <span id="totalCubic-69"></span>

Determining the ID for the Total

//just a way to concatenate strings ['totalCubic', '69'].join('-')
//to give rise to 'totalCubic-69'
//for example

In this version of the demo I have broken down the line determining the total id into several lines just to make it simpler to follow what is being done:

  //get class(es) of first td of this table as an array
  const cl = $('td[class*=singleUnitCubic]',this).attr('class').split(' ');
  console.log( cl );
  //But we only need one 'singleUnitCubic-' ....
  const onecl = cl.filter(c => c.indexOf('singleUnitCubic') === 0)[0];
  console.log( onecl );
  //And we just want to numeric part at the end
  const thenumber = onecl.split('-')[1];
  //So now the id where the total will be put is
  const id = ['#totalCubic', thenumber].join('-');
  //or const id = `#totalCubic-${thenumber}`;

$(function() {
  //capture the table that have target columns
  const tables = $('table:has(td[class*=singleUnitCubic])');
  //now process each table
  const totals = tables.each(function() {
      //get class(es) of first td of this table as an array
      const cl = $('td[class*=singleUnitCubic]',this).attr('class').split(' ');
      console.log( cl );
      //But we only need one 'singleUnitCubic-' ....
      const onecl = cl.filter(c => c.indexOf('singleUnitCubic') === 0)[0];
      console.log( onecl );
      //And we just want to numeric part at the end
      const thenumber = onecl.split('-')[1];
      //So now the id where the total will be put is
      const id = ['#totalCubic', thenumber].join('-');
      //or const id = `#totalCubic-${thenumber}`;
      /*determine the id of span to update
      const id = ['#totalCubic',$('td[class*=singleUnitCubic]',this).attr('class').split(' ')
      .filter(c => c.indexOf('singleUnitCubic') === 0)[0]
      .split('-')[1]].join('-');*/
      //get this total
      const total = $('td[class*=singleUnitCubic]', this)
      .map((i,td) => +td.textContent).get()
      .reduce((acc, cur) => acc += cur, 0);
      //now update the dom
      $(id).text( total.toFixed(3) );
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td class="p-0 singleUnitCubic-13">
                    12.600
</td>
</tr>
<tr>
<td class="p-0 singleUnitCubic-13">
                    4.000
</td>
</tr></tbody>
</table>
Total:  <span id="totalCubic-13"></span>


<table>
<tbody>
<tr>
<td class="p-0 singleUnitCubic-69">
                    4.230
</td>
</tr>
<tr>
<td class="p-0 singleUnitCubic-69">
                    3.000
</td>
</tr>
</tbody>
</table>
Total:  <span id="totalCubic-69"></span>

Upvotes: 0

Y0ss-Please
Y0ss-Please

Reputation: 36

When making your td element you could take the id out of your classes and make it it's own attribute using data attributes.

Something like this:

<td  data-table-id={{$container->id}} class="p-0 singleUnitCubic">
  {{$item->prettyDecimal('total_cubic')}}
</td>

Then change your total to have the same attribute. Also change it's id to a class.

Total:  <span data-table-id={{$container->id}} class="totalCubic">16.600</span>

Then you can get a node list of of all your totalCubic elements. Loop over it and pass each singleUnitCubic with matching data-table-id attribute to your sum function. Then update totalCubic.

Here's a working JSFiddle Example.

Upvotes: 1

Related Questions