How to calculate in this JQuery - javascript

I have a problem in jQuery in html. Just need some changes in calculation, below are my codes All result will be calculated in one field as I did
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1"></script>
<script>
$(document).on('keyup','input.expenses','input.deductions',function(){
$expenses = $(this).parents('tr').find('.expenses');
$deductions = $(this).parents('tr').find('.deductions');
$expenseTotal = $(this).parents('tr').find('#total');
$expenseTotal.val('0');
$.each($expenses,function(index,object){
if($(object).val()!='')
{
$expenseTotal.val(parseInt($expenseTotal.val())+parseInt($(object).val()));
}
})
});
</script>
</pre>
< <tbody>';
foreach($data as $d)
{
print '<tr>
<td>'.$d["staff_name"].'</td>
<td><input type="hidden" name="txtid[]" value="'.$d["id"].'">
<input type="text" name="txtbasic[]" class="form-control expenses">
</td>
<td><input type="text" name="txtallowance[]" class="form-control expenses"></td>
<td><input type="text" name="txtsocso[]" class="form-control deductions"></td>
<td><input type="text" name="txtkwsp[]" class="form-control deductions"></td>
<td><input type="text" id="total" name="txttotal[]" class="form-control"></td>
</tr>';
}
print '</tbody>
Existing result
txttotal = txtbasic + txtallowance
The result i need is
txttotal = txtbasic + txtallowance - txtsocso - txtkwsp
Then display the result on key up, Please anyone can help me

There are a few logic/structure issues with your code so I'll first explain each of them, then at the bottom you can find the resulting code
KeyUp event wrong syntax
To be sure you listed to the keyup even on all fields, you need to separate with the comma within the same parameter, so instead of being
on('keyup','input.expenses','input.deductions',function()
It must be
on('keyup','input.expenses, input.deductions',function()
Using ID in loop
You're using a foreach loop to generate your table rows. So you'll have a lot of rows with the same content, which is fine. However, for the last cell of your row, you're using id="total" which is wrong because in any HTML page there can only be 1 element with a unique id. With your code, you will have all rows having the same ID for the last td.
So you need to remove the ID and use a class instead.
From
input type="text" id="total" name="txttotal[]" class="form-control"
You go to
input type="text" name="txttotal[]" class="form-control total"
Correctly loop the elements
Currently your code only loops the .expenses so the txtbasic and txtallowance values. You also need to loop the deductions to obtain txtsocso and txtkwsp
Final Code
Javascript
<script>
$(document).on('keyup', 'input.expenses, input.deductions', function () {
var total = 0;
// Adding txtbasic and txtallowance
$expenses = $(this).parents('tr').find('.expenses');
$.each($expenses, function (index, object) {
var val = parseInt($(object).val())
if(!isNaN(val) && val) {
total += parseInt($(object).val());
}
});
// Adding txtsocso and txtkwsp
$deductions = $(this).parents('tr').find('.deductions');
$.each($deductions, function (index, object) {
var val = parseInt($(object).val())
if(!isNaN(val) && val) {
total -= parseInt($(object).val());
}
});
// Updating the Total
$expenseTotal = $(this).parents('tr').find('.total');
$expenseTotal.val(total)
});
</script>
HTML TR Code
<tr>
<td>'.$d["staff_name"].'</td>
<td><input type="hidden" name="txtid[]" value="'.$d["id"].'">
<input type="text" name="txtbasic[]" class="form-control expenses">
</td>
<td><input type="text" name="txtallowance[]" class="form-control expenses"></td>
<td><input type="text" name="txtsocso[]" class="form-control deductions"></td>
<td><input type="text" name="txtkwsp[]" class="form-control deductions"></td>
<td><input type="text" name="txttotal[]" class="form-control total"></td>
</tr>
</tbody>
</table>
``

Related

Java Script Function Not working in second loop

When the page load the loop start and the java script function also work in the first row of loop but in the second loop it not working the multiplication does not work you can see in the pic ( unit rate * quantity = total price)
foreach($db->getRecordSet($sqlTrRecord) as $row){$counter += 1; ?>
<tr id="temTr" class="banktblhd">
<td width="5"> <?php echo($counter); ?> </td>
<td class="w10"> <input type="text" name="item_code" id="item_code" class="form-control" value="<?php echo($row['item_code']); ?>" readonly /></td>
<td class="w20"><input type="text" class="form-control" name="item_name" id="item_name" value="<?php echo($row['item_name']); ?>" readonly /> </td>
<td class="w10"><input type="text" class="form-control" name="description" id="description" value="<?php echo($row['description']); ?>" readonly /></td>
<td class="w10"><input type="text" class="form-control" name="availableQty" id="availableQty" value="<?php echo($row['quantity']); ?>" readonly /></td>
<td class="w10"><input type="text" class="form-control" name="unit_rate" id="unit_rate" onKeyUp="total()" value="<?php echo($row['unit_rate']); ?>" readonly /></td>
<td class="w10">
<input type="number" class="form-control" name="quantity" id="quantity" onKeyUp="total()" autocomplete="off" /> </td>
<td class="w10"><input type="text" class="form-control" name="total_price" id="total_price" value="" />
</td>
</tr>
--------------------------
function total(){
var unitRate= document.getElementById("unit_rate");
var qty = document.getElementById("quantity");
var total = unitRate.value * qty.value;
document.getElementById("total_price").value = total;
}
You cannot give the same ID to more than one element. It's invalid HTML. If you do, getElementById will typically return the first (but it could do anything, including returning none, since again it's invalid).
In your case, the minimal changes necessary to make this work are:
Remove all those ids in the rows, you don't need them. Keep the names on the inputs.
Pass this into total everywhere you call it so it knows what element the keyup occurred on, e.g.:
<input type="number" class="form-control" name="quantity" onKeyUp="total(this)" autocomplete="off" />
<!-- --------------------------------------------------------------------^^^^ -->
Update total to receive that as a parameter, and to find the various inputs in the same row by traversing the DOM:
function total(element) {
var row = element.closest("tr");
var unitRate = row.querySelector("input[name=unit_rate]");
var qty = row.querySelector("input[name=quantity]");
// (Note you're relying on implicit coercion from string to number here)
var total = unitRate.value * qty.value;
row.querySelector("input[name=total_price]").value = total;
}
That works by finding the row containing the element the event occurred on, and then using Element#querySelector with CSS selectors to find the various inputs within that row.
Note that that uses Element#closest, which is fairly new. To avoid using it, you could replace
var row = element.closest("tr");
with
var row = element;
while (row && row.tagName !== "TR") {
row = row.parentNode;
}
A couple of side notes:
keyup isn't a reliable event to use to update the total field, because it doesn't fire if the user updates the field via the mouse (for instance, right-clicking and choosing paste from the context menu). I'd suggest using the input event.
Using onxyz-attribute-style event handlers is not best practice, not least because they can only call global functions (or methods on the element, containing form if any, etc.). Instead, you could use an event handler registered on the table and use the target of the event object to know which element the event targeted (and thus what row to work in). That's possible because input and keyup both bubble.

Append a new table row with JavaScript

Following is the code to generate a table with input fields and buttons.
<table id="myTable">
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td class="up"><button type="button" class="append_up">Up</button></td>
<td class="down"><button type="button" class="append_down">Down</button></td>
</tr>
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td class="up"><button type="button" class="append_up">Up</button></td>
<td class="down"><button type="button" class="append_down">Down</button></td>
</tr>
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td class="up"><button type="button" class="append_up">Up</button></td>
<td class="down"><button type="button" class="append_down">Down</button></td>
</tr>
</table>
I want to be able to append a similar row anywhere in the table using JavaScript. If I click the Up button I want a similar row to be appended just above that row, and if clicked down, just below that row. And finally I want to be able to get all the data from the table in the order as created by clicking the buttons. Please help.
After receiving few answers this is what i did.
$(document).ready(function(){
var html = '<tr><td><input type="text" class="text1"></td><td><input type="text" class="text2"></td><td><input type="text" class="text3"></td><td><button type="button" class="append_up">Up</button></td><td><button type="button" class="append_down">Down</button></td></tr>';
$('.append_up').click(function(e) {
e.preventDefault();
$(this).closest('tr').before(html);
});
$('.append_down').click(function(e) {
e.preventDefault();
$(this).closest('tr').after(html);
});
});
I was able to append rows but clicking on the button from the new row does nothing.
As I failed to find a duplicate containing an answer to my liking (as in... works even in IE6... and doesn't need a trunk-load of work-arounds like copying events etc..) I'll post mine in pure javascript here (explained in comments):
<table id="tst_table"><tbody>
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td><button type="button" class="append_up">Up</button></td>
<td><button type="button" class="append_down">Down</button></td>
</tr>
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td><button type="button" class="append_up">Up</button></td>
<td><button type="button" class="append_down">Down</button></td>
</tr>
<tr>
<td><input type="text" class="text1"></td>
<td><input type="text" class="text2"></td>
<td><input type="text" class="text3"></td>
<td><button type="button" class="append_up">Up</button></td>
<td><button type="button" class="append_down">Down</button></td>
</tr>
</tbody></table>
<script> //hook it any way you like, this is just for focussing on the example..
document.getElementById('tst_table').onclick=(function(){
function _addRow(trg, dir){ //private function to add row in any direction
var row= trg.parentNode.parentNode //get correct row
, clone= row.cloneNode(true) //deep-clone that row
, inpts= clone.getElementsByTagName('input') //get inputs in clone
, L= inpts.length //total no of inputs in clone
; //end var
for(;L--; inpts[L].value=inpts[L].defaultValue); //reset inputs to defaultValue
row.parentNode.insertBefore(clone, dir ? row.nextSibling : row); //add row
row=clone=inpts=L=null; //cleanup
}
return function(e){ //return uniform click-handler for the whole table
var trg=e ? e.target : window.event.srcElement; // get source element
if(trg.nodeType === 3) trg = trg.parentNode; // fix Safari bug
var clsnam=' '+trg.className+' '; // get className, allow multiple classnames
if(~clsnam.indexOf( ' append_up ' )) return _addRow(trg, 0);
if(~clsnam.indexOf(' append_down ')) return _addRow(trg, 1);
};
})();
</script>
One of the nice things is that this sets just one eventhandler for the table instead of a (new) function for every button.
In the table's onclick-handler (the returned function) you can handle any click-event that originated in the table: in this example it handles buttons whose class contains 'append_up' or 'append_down' (so you can also set other styling classes like <button class="red_rounded_button append_up">).
In some way's this is simpler/unobtrusive because it deep-copies a row (instead of needing some html-string, which (without jQuery) has some problems with tables in older browsers, notably IE).
Also note that this technique does not touch javascript's global name-space.
EDIT: improved class-name cache so we don't get a misfire on (for example): alt_append_up and added early return.
Finally, to answer your last request: since this uses proper DOM-methods, every time you get the table's rows (and containing elements like inputs) you'll get them in order they are in the DOM (just what you wanted). Nice!
$('.append_up').click(function(){
var str='<tr><td><input type="text" class="text1" value="vikram"></td><td><input type="text" class="text2"></td><td><input type="text" class="text3"></td><td><button type="button" class="append_up">Up</button></td><td><button type="button" class="append_down">Down</button></td></tr>';
$(this).parent().parent().before(str);
});
$('.append_down').click(function(){
var str='<tr><td><input type="text" class="text1" value="sharma"></td><td><input type="text" class="text2"></td><td><input type="text" class="text3"></td><td><button type="button" class="append_up">Up</button></td><td><button type="button" class="append_down">Down</button></td></tr>';
$(this).parent().parent().after(str);
});
var html = '<tr><td><input type="text" class="text1"></td><td><input type="text" class="text2"></td><td><input type="text" class="text3"></td><td><button type="button" class="append_up">Up</button></td><td><button type="button" class="append_down">Down</button></td></tr>';
$(document).ready(function(){
$(document.body).on('click','.append_up',addAbove);
$(document.body).on('click','.append_down',addBelow);
});
function addAbove()
{
$(this).closest('tr').before(html);
}
function addBelow()
{
$(this).closest('tr').after(html);
}
you are dynamically appending the elements and hence you should use and on method to bind the click. hope this helps.
Try something like this:
$(document).ready(function(){
var html = '<tr><td><input type="text" class="text1"></td><td><input type="text" class="text2"></td><td><input type="text" class="text3"></td><td><button type="button" class="append_up">Up</button></td><td><button type="button" class="append_down">Down</button></td></tr>';
$('.append_up').click(function(e) {
e.preventDefault();
$(this).closest('tr').before(html);
});
$('.append_down').click(function(e) {
e.preventDefault();
$(this).closest('tr').after(html);
});
});
There is a fiddle here: http://jsfiddle.net/vyfhrfvf/

how to multiply 2 text box values with javascript and ouput the answer to a 3rd textbox that is a ko.observable

I have a webpage that has multiple textboxes inside of a table. I need to take a value from one textbox and multiply it with another textbox then display that answer to a third text box that is a ko.observable. I have written the below javascript and I cannot get it to work at all. Absolutely nothing happens.
<script type="text/javascript">
function calculateLineTotal(numunit, rate, total) {
var rate = document.getElementById(rate).value;
var numunit = document.getElementById(numunit).value;
var sum = numunit * rate;
document.getElementById(total).value = sum;
}
and the corresponding HTML:
<td><input class="text" type="number" name="NumUnit1" id="NumUnit1" value="0.00" onchange="calculateLineTotal('NumUnit1','Rate1','Total1')"/></td>
<td><input class="text" type="number" name="Rate1" id="Rate1" value="0.00" onchange="calculateLineTotal('NumUnit1','Rate1','Total1')"/></td>
<td><input data-bind="value: total1" type="number" class="text" name="Total1" id="Total1" value="0.00"/></td>
I have tried single just simplifying the function to just throw an alert when the first textbox value is changed and nothing even happens then. Again I am a javascript newb so please be kind. Thank you in advance.
You say that the text box is bound to a ko.observable, i.e. you are using KnockoutJS. So a much cleaner way to do this would be:
<table>
<tr>
<td><input class="text" type="number" data-bind="value: numUnit1" /></td>
<td><input class="text" type="number" data-bind="value: rate1" /></td>
<td><input class="text" type="number" data-bind="value: total1" /></td>
</tr>
</table>
Then as the corresponding view model:
var ViewModel = function() {
var self = this;
self.numUnit1 = ko.observable('0.00');
self.rate1 = ko.observable('0.00');
self.total1 = ko.computed(function() {
var total = parseFloat(self.numUnit1()) * parseFloat(self.rate1());
return total.toFixed(2); // assuming you want to show to 2 decimal places
});
};
ko.applyBindings(new ViewModel());
JSFiddle: http://jsfiddle.net/mZk42/3/
See fiddle
Add class to select on using querySelectAll called "changes"
<td><input class="changes text" type="number" name="NumUnit1" id="NumUnit1" value="0.00" /></td>
<td><input class="changes text" type="number" name="Rate1" id="Rate1" value="0.00" /></td>
<td><input data-bind="value: total1" type="number" class="text" name="Total1" id="Total1" value="0.00"/></td>
Use addEventListener to bind changes. Run a forloop to add the callback, notice that the function bindCalculateTotal returns another function.
var inputs = document.querySelectorAll("input.changes");
var bindCalculateTotal = function (numunitId, rateId, totalId) {
return function(event) {
console.log(numunitId, rateId, totalId);
console.log( document.getElementById(totalId).value);
var rate = document.getElementById(rateId).value;
var numunit = document.getElementById(numunitId).value;
var total = document.getElementById(totalId).value;
var sum = numunit * rate;
document.getElementById(totalId).value = sum;
};
};
for (var ii = 0; ii < inputs.length; ii++) {
inputs[ii].addEventListener(
'change',
bindCalculateTotal("NumUnit1", "Rate1", "Total1"));
}
Also notice how we use "*Id" names to store the value. That fixes this line
document.getElementById(total).value = sum; // error: total is number, not the id
Use parseFloat(...), i.e.
var rate = parseFloat(document.getElementById(rate).value);
var numunit = parseFloat(document.getElementById(numunit).value));
var sum = numunit * rate;
Also there is a typo in one call to your function, i.e. "caclulateLineTotal" instead of "calculateLineTotal"
Also, don't set the total variable again, i.e. don't do
var total = parseFloat(document.getElementById(total).value);
Also, note that your second call to calculateLineTotal, i.e. for element Rate1 is missing a closing ' after Rate1
should be
<input class="text" type="number" name="Rate1" id="Rate1" value="0.00" onchange="calculateLineTotal('NumUnit1','Rate1','Total1');"/>

HTML array multiply javascript

HTML code
<input name="itemCode[]" value="" class="tInput" id="itemCode" tabindex="1"/> </td>
<input name="itemDesc[]" value="" class="tInput" id="itemDesc" readonly="readonly" /></td>
<input name="itemQty[]" value="" class="tInput" id="itemQty" tabindex="2" onchange="multiply(this)"/></td>
<input name="itemPrice[]" value="" class="tInput" id="itemPrice" readonly="readonly" /> </td>
Javascript code
function multiply(el) {
var i= el.value * document.getElementById('itemPrice').value;
document.getElementById('itemPrice').value =i;
}
Problem is this:
the first row in the table multiplies correctly but the second row doesn't work....please help
Problem is that you cannot identify the row correctly with itemXxxxx alone.
It's better to use some id to identify the "row" you are referring to.
For example something like (for every row, in this case row/item no. 23):
<input id="price23" .....>
<input id="qty23" ......>
<input id="total23" onchange="calc(23);" ...>
function calc(id) is:
function calc(id)
{
var p = document.getElementById("price"+id).value;
var q = document.getElementById("qty"+id).value;
document.getElementById("total"+id).value = p * q;
}
It is easy to inject row number from some serverside code.
Edit: Another option would be using JQuery with some DOM traversals between parents and siblings to get the desired values.

Subtotal of Values in HTML Table

I have a table laid out like so:
<table border="0">
<tr>
<td>10: <input type="text" size="1" autocomplete="off" name="10"/> </td>
<td>12: <input type="text" size="1" autocomplete="off" name="12"/> </td>
<td>14: <input type="text" size="1" autocomplete="off" name="14"/> </td>
<td>16: <input type="text" size="1" autocomplete="off" name="16"/> </td>
<td>18: <input type="text" size="1" autocomplete="off" name="18"/> </td>
<td>20: <input type="text" size="1" autocomplete="off" name="20"/> </td>
<td>22: <input type="text" size="1" autocomplete="off" name="22"/> </td>
</tr>
</table>
I need to multiply the value that is inputted in the input box by 65 and generate a subtotal in dollars in real time. I've looked around and I'm not too proficient in javascript or jquery so I was wondering if such a solution already existed, or if someone could point me in the right direction in creating one.
using .on and .val() you can get all the values of input . Then you can do what ever operations you want
http://api.jquery.com/on/
http://api.jquery.com/val/
You need to handle the change() event on each input:
$('input').change(function () {
var that = $(this);
that.siblings('div').text(parseInt(that.val(), 10) * 65);
});
http://jsfiddle.net/XZNfS/
Add this to the bottom of your HTML: Subtotal: <span id="subtotal"></span>
Make sure jQuery is loaded, and then toss this JavaScript below the HTML:
<script type="text/javascript">
function compute_subtotal() {
var total = 0;
$("input[type=text]").each( function(i,e) {
var value = $(e).val();
if( parseInt(value) > 0 ) total += (65 * parseInt(value));
});
$("#subtotal").html( total );
}
jQuery(document).ready( function() {
$("input[type=text]").change( function() { compute_subtotal(); } );
$("input[type=text]").keyup( function() { compute_subtotal(); } );
});
</script>

Categories

Resources