Java Script Function Not working in second loop - javascript

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.

Related

How to calculate in this JQuery

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>
``

HTML input multiplication using JS is having issue with multiple PHP sql query

I have a table in database with single row as some value in it.
I been trying to write a sql query in a way along with HTML 3 input boxes which one takes input number from user and multiplies it with other default number in input box 2 and prints it out in input box 3.
I wrote JS code for it and it works fine. now i added php to it, in a way it input box 1 takes value directly from php table row and multiplies it with user inserted value in box2
It still works fine, but when there are two rows i the given table, it does not work for second value. it doesn't multiplies while the first value gets multiplied.
My Php , Js, Html code goes as:
<?php
$sql2 = "SELECT * FROM table WHERE number = '$number'";
$result2 = $conn->query($sql2);
if ($result2->num_rows > 0) {
while($row2 = $result2->fetch_assoc()) {
?>
<input type="number" name="input1" id="input1" default value="<?php echo $row2['price']; ?>" readonly>
<input type="text" name="input2" id="input2" value="0">
<input type="text" name="output" id="output" value="">
<script>
$("#input2,#input1").keyup(function () {
$('#output').val($('#input1').val() * $('#input2').val());
});
</script>
As i mentioned it works perfectly fine with single row in table, but when i add another row with another value, it prints out another column with input 1 , 2,3 but doesn't work with multiplication,...
Any help is appreciated..
This is because you will be creating elements with duplicate id's, in the case there are several of the same id's on the page the id-selector will on get the first one in the DOM.
If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM.
One solution is to have each loop modify the id given to be unique for each iteration, such as changing id="input1" into id="input1_<?php echo index; ?>" where index would be from 0 to n-1. Or you could use the unique column or PK of the record: id="input1_<?php echo $row2['id'] ?>". You would need to modify the id-selector in all cases with this approach.
Another probably cleaner way to do this is have only a single script and use class (instead of id's) or name as the selectors and give each group a parent instead. Then you could modify the output item based on the shared parent node of the input1 and input2. Here is an example of that:
$(".input2,.input1").keyup(function () {
$output = $(this).parent().find(".output");
$input1 = $(this).parent().find(".input1");
$input2 = $(this).parent().find(".input2");
$output.val($input1.val() * $input2.val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> <!-- first record -->
<input type="number" name="input1" class="input1" value="0" />
<input type="text" name="input2" class="input2" value="0" />
<input type="text" name="output" class="output" value="" />
</div>
<div> <!-- second record -->
<input type="number" name="input1" class="input1" value="0" />
<input type="text" name="input2" class="input2" value="0" />
<input type="text" name="output" class="output" value="" />
</div>

Check Box Disablement On Page Reload Jscript

When I select the boxes, I want the text fields to become editable. At first it works but if I reload the page with the boxes checked, it will do the opposite of what it is supposed to do (i.e. after page is reloaded, when the boxes aren't checked, the text fields are editable; when checked, they become un-editable)
<table>
<tr>
<td>
<input type="checkbox" name="Download_Limit" value="download" class="checkme"/>Download Limit
<br/>
<input type="text" name="download" class="text required" id="Download_Input" size="3">
<label class="description" for="Expire">Downloads</label>
</td>
</tr>
<tr>
<td>
<input type="checkbox" name="Time_Limit" value="time" class="checkme"/>Time Limit
<br/>
<input type="text" name="time" class="text required" id="Time_Input" size="3">
<label class="description" for="Expire">Hours</label>
</td>
</tr>
My Javascript
$('.checkme').attr('checked', false);
$('.checkme').click(function(){
if($('input[name='+ $(this).attr('value')+']').attr('disabled') == false){
$('input[name='+ $(this).attr('value')+']').attr('disabled', true);
}else{
$('input[name='+ $(this).attr('value')+']').attr('disabled', false);
}
});
Here is what I would do. First, setup all the default values that you want:
// Set default page values on load...
$('.checkme').prop('checked', false);
$('input[type="text"]').prop('disabled', true).val('');
// Then setup events...
$('.checkme').on('click', function () {
var $this = $(this);
if($('input[name='+ $this.val() +']').prop('disabled')){
$('input[name='+ $this.val()+']').prop('disabled', false);
} else {
$('input[name='+ $this.val()+']').prop('disabled', true);
}
});
We've changed a few things up here. Let me explain.
First, we've changed .attr('checked'...) and .attr('disabled'...) to use .prop() instead. checked and disabled are properties not attributes.
We're now attaching the event using .on(). This is just the method I prefer, however simply doing .click() will work as well.
We're saving off the element into a local variable $this first thing. This keeps jQuery from having to re-traverse the DOM multiple times within the same function.
I've simplified .attr('value') to the shorthand .val().
Lastly, we've simplified your if statement by removing the negative condition and allowing JavaScript to use the truthy/falsy conditionals.
Fiddle
A Few Other Notes:
I know it is a traditional method of page layout, but I highly discourage using tables to position elements. It is not the appropriate use of tables and results in a page layout that is not semantically correct. Check out the <div> and <span> elements to layout your code and try styling it to appear the way you want with CSS.
Also, it appears you are formatting your HTML in the XHTML syntax. That is perfectly fine, however I recommend that you be consistent when closing tags. Two of your <input /> element tags are not closed properly.
// This...
<input type="text" name="download" class="text required" id="Download_Input" size="3">
// Should be this...
<input type="text" name="download" class="text required" id="Download_Input" size="3" />
// And this...
<input type="text" name="time" class="text required" id="Time_Input" size="3">
// Should be this...
<input type="text" name="time" class="text required" id="Time_Input" size="3" />
Make sure you are consistent in your methods of markup. Inconsistencies such as this will result in an invalid markup.
Finally, I do not believe that you can have <tr> elements nested directly inside of a <table> element. I believe they have to be inside of a <thead>, <tbody> or <tfoot> element. Again, leaving out elements such as these results in invalid markup.
Try this DEMO . I think it's more elegant.
$('.checkme').click(function() {
var input = $(this).closest('td').find('input[type="text"]');
if (input.is(':disabled')){
input.attr('disabled', false);
}else{
input.attr('disabled', true);
}
});
Also, your input type="text" mark up should be disabled as follows:
<input type="text" disabled="disabled" name="time" class="text required" id="Time_Input" size="3" />

Function named "clear" is not being called. Trying to call "clear()" with inline js

I can't find out why my function isn't being called. I put the alert("test") in there just to test if the function was being called at all, and it isn't.
HTML:
<input type="button" onclick="clear(price,quantity)" value="Clear">
JS:
function clear(price,quantity){
alert("test");
i=0;
if(i<5){
price[i].value = "";
quantity[i].value = "";
i++;
}
}
EDIT: Here's all of the code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Amount Owed</title>
<script type = "text/javascript">
function amount(price, quantity){
sum1 = price[0].value * quantity[0].value;
sum2 = price[1].value * quantity[1].value;
sum3 = price[2].value * quantity[2].value;
sum4 = price[3].value * quantity[3].value;
return sum1 + sum2 + sum3 + sum4;
}
function clear(price,quantity){
alert("test");
i=0;
if(i<5){
price[0].value = "";
quantity[0].value = "";
i++;
}
}
</script>
</head>
<body>
<h1>Amount Owed</h1>
<p>Enter price for first amount and quantity for each item</p>
<form>
<table>
<tr>
<td>PRICE</td>
<td>QUANTITY</td>
</tr>
<tr>
<td><input type="text" name="price" size="6"></td>
<td><input type="text" name="quantity" size="6"></td>
</tr>
<tr>
<td><input type="text" name="price" size="6"></td>
<td><input type="text" name="quantity" size="6"></td>
</tr>
<tr>
<td><input type="text" name="price" size="6"></td>
<td><input type="text" name="quantity" size="6"></td>
</tr>
<tr>
<td><input type="text" name="price" size="6"></td>
<td><input type="text" name="quantity" size="6"></td>
</tr>
</table>
<input type="button" onclick="pay.value = amount(price,quantity)" value="Total">
<input type="button" onclick="clear(price,quantity)" value="Clear">
<p>The total is: <input type="text" id="pay" name="pay"></p>
</form>
</body>
</html>
Probably because clear(price,quantity) in your html is invalid. I bet if you check your console, it is saying that "price" doesn't exist.
Just to verify, I created a demo here (click) and it shows this error in the console (f12)
Uncaught ReferenceError: price is not defined
The problem is with the name "clear" being used in inline js!
This is because "clear" is referring to document.clear and that's not at all what you intend. This is another argument for not using inline js. Read here: Is "clear" a reserved word in Javascript? and here: https://www.google.com/search?q=Why+is+inline+js+bad%3F
In this function — onclick="clear(price,quantity)" — price and quantity are variables that haven't been defined, so you will get a reference error before clear is called.
You can define them with either window.price = 1; or (in the same or wider scope) var price = 1. The latter is usually the better choice.
It looks like you want to pass NodeLists of the input elements you have. You can't just reference them as globals, you have to access them through the DOM.
Since you are dealing with a click event hander on a form control, you can access the form control via this. Form control element objects have a form property which references their associated form. Forms element objects have an elements collection. The elements collection allows you to access form controls by name. If there are multiple controls with the same name, you get a NodeList rather then the node itself.
onclick="clear(this.form.elements.price,this.form.elements.quantity)"

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.

Categories

Resources