Hi everyone..I have a problem..

I want to make an auto calculation on each row..the things is, I only can do it on the first row..but for the second row, nothing happened..
here is my code:

<script>
function compute() {
    var inputObj = document.getElementById('k8goodsQty');
    var otherObj = document.getElementById('valuePerUnit');
    var diffObj = document.getElementById('valueTotal');

    var v1=inputObj.value;
    var v2=otherObj.value;

    var val1 = v1==="" ? 0 : parseFloat(v1); // convert string to float
    var val2 = v2==="" ? 0 : parseFloat(v2);

    diffObj.value = val1 * val2;        

}
</script>

and here is my table:

<?php
    $defaultrow = 3;
?>
<table>
<thead>  
    <th>No</th>
    <th>Goods<span class="red">*</span></th>
    <th>Quantity<span class="red">*</span></th>
    <th>Value per unit<span class="red">*</span></th>
    <th>Total<span class="red">*</span></th>
</thead>

<?php for ( $i=1; $i<=$defaultrow; $i++ ) { ?>
    <tr>
    <td class="labelcell"><?php echo $i; ?></td>
    <td class="datacell"><input type="text" id="goodsDesc" name="goodsDesc[<?php echo $i; ?>]"  maxlength="200" /></td>
    <td class="datacell"><input type="text" id="k8goodsQty" name="k8goodsQty[<?php echo $i; ?>]"  maxlength="200" onKeyUp="compute()"/></td>
    <td class="datacell"><input type="text" id="valuePerUnit" name="valuePerUnit[<?php echo $i; ?>]"  maxlength="200" onKeyUp="compute()"/></td>
    <td class="datacell"><input type="text" id="valueTotal" name="valueTotal[<?php echo $i; ?>]" maxlength="200" onKeyUp="compute()"/></td>
    </tr>
<?php }  ?>
</table>

So, how do I do with code to make it auto calculate for each row..?

Recommended Answers

All 21 Replies

The reason it is only working on the first row is because you are using ID. The JS goes through the DOM and finds the first ID that matches and stops there instead of continuing. You really should have more than one ID on a page at any one time anyways. What you will need to do is use a class name or another identifier.

I haven't done it in forever with plain JS, but I can say that it would probably be easier to do in jQuery and would be a lot less code.

@pixelsoul

ooh really.Then can you guide me how to do it with jQuery.?

If you are going to have multiple rows and one function, you have to somehow figure out what row you are on when within the function. This way you can correctly get/set the values for the other input elements in that row.

Here is an example...

<?php
        $defaultrow = 3;
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    <script>
        var x = 0;
        var y = 0;
        var z = 0;
        function compute(obj) {
            var e = obj.id.toString().substring(0, 3);
            var n = obj.id.toString().substring(4);
            if (e == 'qty') {
                x = Number(obj.value);
                y = Number(document.getElementById('uni-' + n).value);
            } else {
                x = Number(document.getElementById('qty-' + n).value);
                y = Number(obj.value);
            }
            z = x * y;
            document.getElementById('tot-' + n).value = z;

        }
    </script>

    </head>
    <body>

    <table>
    <thead>
     <tr>  
      <th>No</th>
      <th>Goods<span class="red">*</span></th>
      <th>Quantity<span class="red">*</span></th>
      <th>Value per unit<span class="red">*</span></th>
      <th>Total<span class="red">*</span></th>
     </tr> 
    </thead>

    <?php for ( $i=1; $i<=$defaultrow; $i++ ) { ?>

      <tr>
       <td class="labelcell"><?php echo $i; ?></td>
       <td class="datacell">
        <input type="text" id="des-<?php echo $i; ?>" name="goodsDesc[<?php echo $i; ?>]"/>
       </td>
       <td class="datacell">
        <input type="text" id="qty-<?php echo $i; ?>" name="k8goodsQty[<?php echo $i; ?>]" onblur="compute(this)" value="0"/>
       </td>
       <td class="datacell">
        <input type="text" id="uni-<?php echo $i; ?>" name="valuePerUnit[<?php echo $i; ?>]" onblur="compute(this)" value="0"/>
       </td>
       <td class="datacell">
        <input type="text" id="tot-<?php echo $i; ?>" name="valueTotal[<?php echo $i; ?>]" value="0" />
       </td> 
      </tr>

    <?php }  ?>

    </table>

    </body>
    </html>

In this example, i am using the onblur event rather than keyup or keypress. The function is called when the input element looses focus. What you are sending the function is the input object itself. At that point, you need to figure out what is it you sent the function. One approach that I used, was to get the ID and break it up into two parts so you can figure out if you are working with the quantity or unit input. You also need to know which row number you are on.

Once you figure that out, its a matter of extracting the value of the other input element in the same row and then just multiple the two values (the one you just set and the one you get from the other element in the same row).

Hope that helps.. by the way, here is a working demo to look at: http://itg.somee.com/dw/dw-467834/

commented: Looks good +8

I like the solution JorgeM gave because it keeps it all standard JavaScript like you had originally. I might put together a quick jQuery example if I get the time, just for proof of concept, but I have been busy at work.

thanks JorgeM, it works. But, if I add another row, it is not working.
for the add row, I use javascript.

feb156c706d1e9738bb6ed7baedab804

how can I make it works..?

But, if I add another row, it is not working.

I'm not sure what you mean by adding another row. Based on my example and yours, the way that you control the number of rows is by modifying the value in the PHP block (line 2 in my example above). If you want 5 rows, then change this block to read as <?php $defaultrow = 5; ?>.

I've tested the code several times, I cant find any problems with it, at least with regards to how it is designed to work.

emm..If the user need to add lots of goods instead of only 3 goods, they can click the "add row" button, then, a new row will appear below the existing table.
So, for that new row, the auto calculate is not working..
Sorry if I'm confusing you.

I'm only confused because no where in your original post or the second post did you mention or provide code related to providing the ability to add additional rows. I missed that detail in your third post. I didnt understand what you were referring to.

In that case, you need to ensure that when you add rows clientside, you follow the same format as in the example i provided above in the PHP code. It will work the same way.

I would have to see your "addRow" javascript function to see if I can help you further.

So, I had some time and interest. Take a look at the updated demo. I included an "add row" feature. You can look at the jQuery function that was added to add rows to the table.

What I did was also add a hidden input element that stores the value of the default number of rows. I used that input element as a starting value for the current number of rows. I incremented the value for the new row, and so on...

http://itg.somee.com/dw/dw-467834/

here is my code for addRow :

<script language="javascript">
function addRow(tableID_k8)
{  
   var tbody_k8 = document.getElementById(tableID_k8).getElementsByTagName("tbody")[0];
   var rowCount = tbody_k8.rows.length +1;

   var row = document.createElement("tr"); 

   var cell1 = document.createElement("td");
   cell1.className = 'labelCell1';
   var x = document.createTextNode(rowCount);
    cell1.appendChild(x);
   row.appendChild(cell1);


    <!--add row for goodsDesc -->
   var cell2 = document.createElement("td");
   cell2.className = 'dataCell1'; 
   var goodsDesc = document.createElement('input');
   goodsDesc.setAttribute('name', 'goodsDesc['+rowCount+']'); 
   goodsDesc.setAttribute('maxlength', '50'); 
   cell2.appendChild(goodsDesc);
   row.appendChild(cell2);


    <!--add row for k8goodsQty -->
   var cell3 = document.createElement("td");
   cell3.className = 'dataCell1';
   var k8goodsQty = document.createElement('input');
   k8goodsQty.setAttribute('name', 'k8goodsQty['+rowCount+']'); 
   k8goodsQty.setAttribute('maxlength', '50'); 
    cell3.appendChild(k8goodsQty);
   row.appendChild(cell3);


   <!--add row for valuePerUnit -->
   var cell4 = document.createElement("td");
   cell4.className = 'dataCell1';
   var valuePerUnit = document.createElement('input');
   valuePerUnit.setAttribute('name', 'valuePerUnit['+rowCount+']'); 
   valuePerUnit.setAttribute('maxlength', '50'); 
   cell4.appendChild(valuePerUnit);
   row.appendChild(cell4);


   <!--add row for valueTotal -->
   var cell5 = document.createElement("td");
   cell5.className = 'dataCell1';
   var valueTotal = document.createElement('input');
   valueTotal.setAttribute('name', 'valueTotal['+rowCount+']'); 
   valueTotal.setAttribute('maxlength', '50'); 
    cell5.appendChild(valueTotal);
   row.appendChild(cell5);

   tbody_k8.appendChild(row);
   document.k8form.count.value = rowCount;

}

</script>

I dont see in your addRow function where you are assigning unique IDs to these input elements. Without the IDs following the naming standard i am using in my example, it is not going to work if you plan on using the function I provided you above.

I hope that you are not simply copying/pasting the code I am providing this in this thread. take some time to look at the sample code I provided and see if it makes sense to you. If it doesnt, there is no point in you using it as you will not be able to maintain, extend it, or explain how it works.

ok..I think I got it..one more question,
how do i fix the decimal places.?
lets say, 3 x 23.6, so the answer is 70.80000000000001.. I just want the answer be in 2 decimal places.
How can I do that.?

Just format the value using the number() and toFixed() methods. Refer to my sample code above or demo (updated). From example above, line 22, change to:

document.getElementById('tot-' + n).value = Number(z).toFixed(2);

Thanks a lot JorgeM...It's working greatly..
Thanks for your help.

Hi, I want to ask another question.
I want to add something to the code.
I have a table like this :

No| Goods|  OldQuantity|Out Quantity|valuePerUnit|  total|BalanceQuantity
---------------------------------------------------------------------------
1|  Valve|  20          |   5       |20.00      |   100.00| 15

I'm using the code given by you for auto calculate on "total" field and It's working greatly.
But then, I want on "BalanceQuantity" field to be auto substract:
oldQuantity - OutQuantity = BalanceQuantity
How Do I do it.? Can jorgeM help me?

i appologize, but a bit tied up at the moment... are you not able to use what has been given to you and simply extend it by adding in the additional fields?

The demo online is functional with all of the components up to this last post. http://itg.somee.com/dw/dw-467834/

is it correct if i do it like this.. :-

<script>
var x = 0;
var y = 0;
var z = 0;
var p = 0;
var q = 0;
var r = 0;
function compute(obj) {
var e = obj.id.toString().substring(0, 3);
var n = obj.id.toString().substring(4);
if (e == 'qty') {
x = Number(obj.value);
y = Number(document.getElementById('uni-' + n).value);
} else {
x = Number(document.getElementById('qty-' + n).value);
y = Number(obj.value);
}
z = x * y;
document.getElementById('tot-' + n).value=Number(z).toFixed(2);
} else
if (a == 'qty') {
p = Number(obj.value);
q = Number(document.getElementById('qtyO-' + n).value);
} else {
p = Number(document.getElementById('qty-' + n).value); 
q = Number(obj.value);
}
r = q - p;
document.getElementById('qtyB-' + n).value=z;
}
</script>

jorgeM please help me........

please understand that answering a question can take a few seconds, but looking at code and rewriting it takes much longer, at least for me. While I dont mind helping and providing guidance, the idea here is that you learn from the examples and build upon them. If you need someone to simply provide you with solutions, you may want to hire someone in the business exchange section. you will be likely to get quicker responses..

anyway, based on your previous description, you simply have to modify the javascript section to look at your column holding the "old quantity" then subtract the "out quantity", place that value in "Balance Quantity".

updated demo -- > http://itg.somee.com/dw/dw-467834/

<script>
    var x = 0;
    var y = 0;
    var z = 0;
    var b = 0;
    function compute(obj) {
        var e = obj.id.toString().substring(0, 3);
        var n = obj.id.toString().substring(4);
        var o = Number(document.getElementById('old-' + n).value);
        if (e == 'qty') {
            x = Number(obj.value);
            y = Number(document.getElementById('uni-' + n).value);
        } else {
            x = Number(document.getElementById('qty-' + n).value);
            y = Number(obj.value);
        }
        z = x * y;
        b = o - x;

        document.getElementById('tot-' + n).value = Number(z).toFixed(2);
        document.getElementById('bal-' + n).value = Number(b).toFixed(0);  
    }
</script>

then update the button related code to ensure the new columns are included. right click on the page to view source.

Thanks a lot jorgeM. Sorry to trouble you.

Dont be too concerend about the trouble... I'm here to volunteer and help. I hope that the help and guidance in this thread has helped you better understand how to address the problem you were encountering. Hopefully it can help others too.

If all that you (not saying this is your case) were able to get from this thread is just the answer to the problem, I failed at trying to help you. I hope that you got more than that out of this thread.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.