1

I am trying to make a time sheet which can have multiple entries, so I have the following table set up, however, I am unsure how I would go about running the same function for every "total" element.

<table width="100%" id="table" border="0">
  <tr id="headers">
    <td width="15%">Name</td>
    <td width="15%">Info</td>
    <td width="10%">Monday</td>
    <td width="10%">Tuesday</td>
    <td width="10%">Wednesday</td>
    <td width="10%">Thursday</td>
    <td width="10%">Friday</td>
    <td width="10%">Total</td>
  </tr>
  <tr id="1">
    <td width="15%">
      <input name="name1" id="name1">
    </td>
    <td width="15%">
      <input name="info1" id="info1">
    </td>
    <td width="10%">
      <input name="mo1" id="mon1">
    </td>
    <td width="10%">
      <input name="tue1" id="tue1">
    </td>
    <td width="10%">
      <input name="wed1" id="wed1">
    </td>
    <td width="10%">
      <input name="thu1" id="thu1">
    </td>
    <td width="10%">
      <input name="fri1" id="fri1">
    </td>
    <td width="10%" id="total1"></td>
  </tr>
  <tr id="2">
    <td width="15%">
      <input name="name2" id="name2">
    </td>
    <td width="15%">
      <input name="info2" id="info2">
    </td>
    <td width="10%">
      <input name="mon2" id="mon2">
    </td>
    <td width="10%">
      <input name="tues2" id="tue2">
    </td>
    <td width="10%">
      <input name="wed2" id="wed2">
    </td>
    <td width="10%">
      <input name="thu2" id="thu2">
    </td>
    <td width="10%">
      <input name="fri2" id="fri2">
    </td>
    <td width="10%" id="total2"></td>
  </tr>
  <!-- More here -->
</table>

So, what will happen is people will put the information in the input fields, and then the id="total[i]" will calculate the total for the week. However, without doing a separate function for 1, 2, 3, etc. I have no idea how I'd be able to do a for loop for them.

empiric
  • 7,825
  • 7
  • 37
  • 48
jordsta95
  • 47
  • 5

5 Answers5

1

If your total column is always the last column, you can use this selector:

tr td:last-child

Otherwise I would recommend to add a class like .total to all those elements and iterate through them using this selector:

.total

Given the selector you can use this code in order to apply something to each elements.

$(selector).each(function(){
    // here 'this' represents current being iterated matching element
});
frogatto
  • 28,539
  • 11
  • 83
  • 129
1

I would suggest that you amend your HTML code so that each tr is identical. This makes it much easier to write DRY code which works on any instance of the tr within your table, and also makes future maintenance much easier. To achieve this you can use classes to identify your td and input elements within the table, something like this:

$('.day').change(calcRowTotals).change();

function calcRowTotals() {
  $('table tr:gt(0)').each(function() {
    var $row = $(this), total = 0;
    $row.find('.day').each(function() {
      total += parseInt($(this).val(), 10) || 0;
    });
    $row.find('.total').text(total);
  });
}
html {
  padding: 50px 0 0;
}
input {
  width: 90%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table width="100%" id="table" border="0">
  <tr id="headers">
    <td width="15%">Name</td>
    <td width="15%">Info</td>
    <td width="10%">Monday</td>
    <td width="10%">Tuesday</td>
    <td width="10%">Wednesday</td>
    <td width="10%">Thursday</td>
    <td width="10%">Friday</td>
    <td width="10%">Total</td>
  </tr>
  <tr>
    <td>
      <input name="name1" class="name">
    </td>
    <td>
      <input name="info1" class="info">
    </td>
    <td>
      <input name="mo1" class="mon day" value="1">
    </td>
    <td>
      <input name="tue1" class="tue day" value="2">
    </td>
    <td>
      <input name="wed1" class="wed day" value="3">
    </td>
    <td>
      <input name="thu1" class="thu day" value="4">
    </td>
    <td>
      <input name="fri1" class="fri day" value="5">
    </td>
    <td class="total"></td>
  </tr>
  <tr>
    <td>
      <input name="name2" class="name">
    </td>
    <td>
      <input name="info2" class="info">
    </td>
    <td>
      <input name="mon2" class="mon day" value="6">
    </td>
    <td>
      <input name="tues2" class="tue day" value="7">
    </td>
    <td>
      <input name="wed2" class="wed day" value="8">
    </td>
    <td>
      <input name="thu2" class="thu day" value="9">
    </td>
    <td>
      <input name="fri2" class="fri day" value="10">
    </td>
    <td class="total"></td>
  </tr>
  <!-- More here -->
</table>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • After fiddling with this for a few minutes, I can seem to get it to work. I have tried it on document ready, set timeout (to run every few seconds), and onclick of a button, and even tried the script in the head, and at the bottom of the page. All of which don't change the value from 0, and Google Dev. tools don't output any errors. [Edit] Forgot to change from ID to class. All works great, thanks :D – jordsta95 Apr 11 '16 at 10:25
  • No problem, glad to help – Rory McCrossan Apr 11 '16 at 10:29
0

There's sufficient structure in your table to be able to perform the math without resorting to row and/or column IDs at all. However the addition of a class attribute on the cells that contain the numbers you want to add up would simplify it somewhat whilst making the code more resilient to any future changes to your DOM.

In the code below, I've assumed that each input contains a class="count" attribute and that the final cell has a class="total" attribute.

$('#table .total').each(function(_, $total) {

    // find desired input cells
    var $counts = $total.closest('tr').find('.count');

    // extract an array of their values
    var count = $counts.map(function(_, el) {
        return +el.value;
    }).get();

    // add their values
    var total = count.reduce(function(a, b) {
        return a + b;
    }, 0);

    // store result
    $total.text(total);    
});

(Simpler summation methods exist, but I like the functional style of the .map / .reduce calls)

Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

Taking Ali Rezas advice, you should add a 'total' class to all your total elements.

Then, you would do something like this:

$('.total').each(function(){
    // first, find the containing 'tr' element
    var parentRow = $(this).closest('tr');

    var total = 0;

    // then iterate over all inputs (you may want to give these all a class as well)
    parentRow.find('input.class').each(function(){
        total += $(this).val();
    })
})
TKoL
  • 13,158
  • 3
  • 39
  • 73
0

Here is a function called calculateRow to use on each row providing a prefix letter.

It is important to nothe that an id that start with a number is not valid as HTML selector so I changed a little your ids an the because of this, the function look for a letter. More info about this here

function calculateRow(letter) {
  var inputs = document.querySelectorAll('#' + letter + ' [id$="'+ letter + '"]');
  var total = [].reduce.call(inputs, function(acc, next) {
    if (next.nodeName == 'INPUT' && next.value !== '') {
       return acc + parseInt(next.value)
    } else {
      return acc;
    }
  }, 0);

  return total;
}

document.querySelector('#getTotal-a').addEventListener('click', 
  function() {
    document.querySelector('#total-a').innerHTML = calculateRow('a');
}, false)
<table width="100%" id="table" border="0">
  <tr id="headers">
    <td width="15%">Name</td>
    <td width="15%">Info</td>
    <td width="10%">Monday</td>
    <td width="10%">Tuesday</td>
    <td width="10%">Wednesday</td>
    <td width="10%">Thursday</td>
    <td width="10%">Friday</td>
    <td width="10%">get Total</td>
    <td width="10%">Total</td>
  </tr>
  <tr id="a">
    <td width="15%">
      <input name="name1" id="name-a" value='1'>
    </td>
    <td width="15%">
      <input name="info1" id="info-a">
    </td>
    <td width="10%">
      <input name="mo1" id="mon-a">
    </td>
    <td width="10%">
      <input name="tue1" id="tue-a">
    </td>
    <td width="10%">
      <input name="wed1" id="wed-a">
    </td>
    <td width="10%">
      <input name="thu1" id="thu-a">
    </td>
    <td width="10%">
      <input name="fri1" id="fri-a">
    </td>
    <td width="10%">
      <button id=getTotal-a>tot</button>
    </td>
    <td width="10%" id="total-a">
    </td>
  </tr>
  </table>
Community
  • 1
  • 1
Lionel T
  • 1,559
  • 1
  • 13
  • 30