1

I have an order form for products, that are available in different sizes. So for every product there is one input for each size with the sum at the end of the row. I reality I have about 500 rows.

<table>
  <tr>
    <th>Product</th>
    <th>Size 1</th>
    <th>Size 2</th>
    <th>Size 3</th>
    <th>TOTAL</th>
   </tr>
  <tr>
    <td>A</td>
    <td><input type="text" class="productA"></td>
    <td><input type="text" class="productA"></td>
    <td><input type="text" class="productA"></td>
    <td></td>
   </tr>
  <tr>
    <td>B</td>
    <td><input type="text" class="productB"></td>
    <td><input type="text" class="productB"></td>
    <td><input type="text" class="productB"></td>
    <td></td>
   </tr>
  <tr>
    <td>C</td>
    <td><input type="text" class="productC"></td>
    <td><input type="text" class="productC"></td>
    <td><input type="text" class="productC"></td>
    <td></td>
   </tr>
 </table>

I tried several ways but it never wanted to work. I only succeeded in calculating ALL inputs at once but not only for one single row separately.

I want to calculate the sum of each row in the last td everytime the input changes.

Has anyone an idea how I could solve this?

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
Joe_Pow
  • 23
  • 1
  • 3
  • 1
    We're not going to write it for you. Please post one of your several ways so we can help you understand where you went wrong. It seems like it should be a pretty straightforward `$("tr").each()` loop. – Barmar Jun 03 '16 at 14:38
  • Inside that you would use `$(this).find("input").each()`. – Barmar Jun 03 '16 at 14:39

3 Answers3

7

Bind input event handler to input and update column based on values.

$('table input').on('input', function() {
  var $tr = $(this).closest('tr'); // get tr which contains the input
  var tot = 0; // variable to sore sum
  $('input', $tr).each(function() { // iterate over inputs
    tot += Number($(this).val()) || 0; // parse and add value, if NaN then add 0
  });
  $('td:last', $tr).text(tot); // update last column value
}).trigger('input'); // trigger input to set initial value in column
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
  <tr>
    <th>Product</th>
    <th>Size 1</th>
    <th>Size 2</th>
    <th>Size 3</th>
    <th>TOTAL</th>
  </tr>
  <tr>
    <td>A</td>
    <td>
      <input type="text" class="productA">
    </td>
    <td>
      <input type="text" class="productA">
    </td>
    <td>
      <input type="text" class="productA">
    </td>
    <td></td>
  </tr>
  <tr>
    <td>B</td>
    <td>
      <input type="text" class="productB">
    </td>
    <td>
      <input type="text" class="productB">
    </td>
    <td>
      <input type="text" class="productB">
    </td>
    <td></td>
  </tr>
  <tr>
    <td>C</td>
    <td>
      <input type="text" class="productC">
    </td>
    <td>
      <input type="text" class="productC">
    </td>
    <td>
      <input type="text" class="productC">
    </td>
    <td></td>
  </tr>
</table>

In case if you want to put value in a readonly textbox.

$('table input').on('input', function() {
  var $tr = $(this).closest('tr'); // get tr which contains the input
  var tot = 0; // variable to sore sum
  $('input:not(:last)', $tr).each(function() { // iterate over inputs except last
    tot += Number($(this).val()) || 0; // parse and add value, if NaN then add 0
  });
  $('td:last input', $tr).val(tot); // update input in last column
}).trigger('input'); // trigger input to set initial value in column
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
  <tr>
    <th>Product</th>
    <th>Size 1</th>
    <th>Size 2</th>
    <th>Size 3</th>
    <th>TOTAL</th>
  </tr>
  <tr>
    <td>A</td>
    <td>
      <input type="text" class="productA">
    </td>
    <td>
      <input type="text" class="productA">
    </td>
    <td>
      <input type="text" class="productA">
    </td>
    <td>
      <input type="text" readonly>
    </td>
  </tr>
  <tr>
    <td>B</td>
    <td>
      <input type="text" class="productB">
    </td>
    <td>
      <input type="text" class="productB">
    </td>
    <td>
      <input type="text" class="productB">
    </td>
    <td>
      <input type="text" readonly>
    </td>
  </tr>
  <tr>
    <td>C</td>
    <td>
      <input type="text" class="productC">
    </td>
    <td>
      <input type="text" class="productC">
    </td>
    <td>
      <input type="text" class="productC">
    </td>
    <td>
      <input type="text" readonly>
    </td>
  </tr>
</table>
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
  • 1
    Close enough to what I was going to propose to suffice – Mark Schultheiss Jun 03 '16 at 14:49
  • @MarkSchultheiss : :) – Pranav C Balan Jun 03 '16 at 14:51
  • It works fine, but my total text box gets lost. In this example, I understand the total is not getting displayed in a text box but in my case, i have a read-only text box where i want to display the total. Any idea? – 3AK Jun 04 '16 at 05:46
  • @PranavCBalan - awesome, perfect!! – 3AK Jun 04 '16 at 05:52
  • @Sizzler : glad to help you :) – Pranav C Balan Jun 04 '16 at 05:52
  • @PranavCBalan Thanks, So, will it work if there is no input box at the last? – 3AK Jun 04 '16 at 05:53
  • @Sizzler : nop..... for that you need to check it exist... if not generate and update else just update.. – Pranav C Balan Jun 04 '16 at 05:54
  • @PranavCBalan - ya i tested it, it is displaying the sum in the last input box. I believe, you can update the answer with your last js as well in case, some one is having the problem exactly asked in the question. thx again! – 3AK Jun 04 '16 at 05:56
  • @Sizzler : I don't think that he needs something like that – Pranav C Balan Jun 04 '16 at 06:00
  • Hi @PranavCBalan - How to display the sum of all totals in the last in another input box? I tried to do it via event listeners but looks like there is no clean way to listen to changes done via javascript to any input text. http://stackoverflow.com/a/1848414/1936319 Please correct me if i am wrong. Edit: It works well when i gave a try with click event. – 3AK Jun 04 '16 at 12:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113807/discussion-between-sizzler-and-pranav-c-balan). – 3AK Jun 04 '16 at 13:36
  • Hi @PranavCBalan, I got one new requirement that a new td should be added at the second column position. That Td will have an input box which can take number but we have to avoid the addition of that number in the total field. I tried this - $('input:not(:last :nth-child(2))', $tr).each(function() { // iterate over inputs except last tot += Number($(this).val()) || 0; // parse and add value, if NaN then add 0 }); But it is not working. Can you give any idea please? – 3AK Jun 21 '16 at 01:24
  • @Sizzler : the selector will not work `$('input:not(:last :nth-child(2))'`, instead use `$('input:not(:last,:nth-child(2))'` or `$('input:not(:nth-child(2))'` – Pranav C Balan Jun 21 '16 at 03:47
  • @PranavCBalan - Does not works. i tried in our last fiddle itself. Not working :( – 3AK Jun 21 '16 at 03:54
  • Thx! @PranavCBalan You gave a way ahead :) Please check my updated fiddle - https://jsfiddle.net/sizzler/xodzm0qw/2/ Now it excludes the size1 column which was my requirement. This is my change - 'td:not(:last,:nth-child(2)) input' – 3AK Jun 21 '16 at 04:14
  • @Sizzler : ok fine :) – Pranav C Balan Jun 21 '16 at 04:16
5

You do this with map and reduce

$('tr input').on('input', function() {
  //Select all inputs in row of input that is changed and self (this or changed input)
  var inputs = $(this).parent('td').siblings('td').andSelf().find('input');
  
  //Use map to return array of only values on inputs in row that is changed
  var values = inputs.map(function() { return Number($(this).val())}).get();
  
  //Use reduce to sum array of values 
  var sum = values.reduce((a, b) => { return a + b});
  
  //Find .result() cell in row that is changed
   var result = $(this).parent().siblings('.result');
  
  //Check if sum is number or not and append sum or text msg
  (isNaN(sum)) ? result.text('Numbers only') : result.text(sum);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr>
    <th>Product</th>
    <th>Size 1</th>
    <th>Size 2</th>
    <th>Size 3</th>
    <th>TOTAL</th>
   </tr>
  <tr>
    <td>A</td>
    <td><input type="text" class="productA"></td>
    <td><input type="text" class="productA"></td>
    <td><input type="text" class="productA"></td>
    <td class="result"></td>
   </tr>
  <tr>
    <td>B</td>
    <td><input type="text" class="productB"></td>
    <td><input type="text" class="productB"></td>
    <td><input type="text" class="productB"></td>
    <td class="result"></td>
   </tr>
  <tr>
    <td>C</td>
    <td><input type="text" class="productC"></td>
    <td><input type="text" class="productC"></td>
    <td><input type="text" class="productC"></td>
    <td class="result"></td>
   </tr>
 </table>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • In `keyUp` event it will not be triggered until we will not release that key. So it would be better to use `input` event – AsgarAli Jun 03 '16 at 15:04
0

$(document).on("input", "input:text", function () {
    var strClass = $(this).prop("class");
    var intTotal = 0;
    $.each($("input:text." + strClass), function () {
        var intInputValue = parseInt($(this).val());
        if (!isNaN(intInputValue))
        {
            intTotal = intTotal + intInputValue;
        }
    });
    $(this).parent("td").siblings("td:last").text(intTotal);
});
<table>
    <tr>
        <th>Product</th>
        <th>Size 1</th>
        <th>Size 2</th>
        <th>Size 3</th>
        <th>TOTAL</th>
    </tr>
    <tr>
        <td>A</td>
        <td><input type="text" class="productA"></td>
        <td><input type="text" class="productA"></td>
        <td><input type="text" class="productA"></td>
        <td></td>
    </tr>
    <tr>
        <td>B</td>
        <td><input type="text" class="productB"></td>
        <td><input type="text" class="productB"></td>
        <td><input type="text" class="productB"></td>
        <td></td>
    </tr>
    <tr>
        <td>C</td>
        <td><input type="text" class="productC"></td>
        <td><input type="text" class="productC"></td>
        <td><input type="text" class="productC"></td>
        <td></td>
    </tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
AsgarAli
  • 2,201
  • 1
  • 20
  • 32