I have this html table:
<table id='table1'>
<tr>
<td>String</td>
<td><input type='text' id='first-input-01'></input></td>
<td><input type='text' id='second-input-01'></input></td>
</tr>
<tr>
<td>String</td>
<td><input type='text' id='first-input-02'></input></td>
<td><input type='text' id='second-input-02'></input></td>
</tr>
<tr>
<td>Total:</td>
<td> </td>
<td>(total goes here)</td>
</tr>
</table>
and using jQuery, I want to find the value of #first-input-xx and multiply it by #second-input-xx for each table row, adding up each row to an overall total. However, I'm finding it difficult to select each input for each table row. I'm trying:
var total = 0;
$("#table1 tr").each(function() {
var amount1 = $(this).children("td:nth-last-child(2) input").val();
var amount2 = $(this).children("td:last input").val();
total = total + (parseFloat(amount1) * parseFloat(amount2));
});
Appreciative of any help.
You cannot use .children() as you are trying to find the input element, instead use .find()
var total = 0;
$("#table1 tr").each(function () {
var amount1 = $(this).find("td:eq(-2) input").val();
var amount2 = $(this).find("td:last input").val();
total += (parseFloat(amount1) * parseFloat(amount2)) || 0;
});
alert(total)
$('button').click(function() {
var total = 0;
$("#table1 tr").each(function() {
var amount1 = $(this).find("td:eq(-2) input").val();
var amount2 = $(this).find("td:last input").val();
total += (parseFloat(amount1) * parseFloat(amount2)) || 0;
});
alert(total)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='table1'>
<tr>
<td>String</td>
<td>
<input type='text' id='first-input-01'></input>
</td>
<td>
<input type='text' id='second-input-01'></input>
</td>
</tr>
<tr>
<td>String</td>
<td>
<input type='text' id='first-input-02'></input>
</td>
<td>
<input type='text' id='second-input-02'></input>
</td>
</tr>
</table>
<button>Test</button>
Try this: use eq()
var total = 0;
$("#table1 tr").each(function () {
var input = $(this).find('input');
if (input.length == 2) {
total += input.eq(0).val() * input.eq(1).val();
}
console.log(total)
});
DEMO
$("#table1 tr").each(function() {
var amount1 = $(this).find("td:nth-child(2)").val();
var amount2 = $(this).find("td:nth-child(3)").val();
total = total + (parseFloat(amount1) * parseFloat(amount2));
});
Here i have added few codes. please check it out.
$("#calculate_btn").click(function(){
var total=0;
var row_mux=1;
$("#table1 tr").each(function(key,val){
$(val).find("input").each(function(k,v){
row_mux*=parseFloat($(v).val());
});
total=row_mux++;
});
alert(total);
$("#table1 tr:last").find("td:last").html(total);
});
demo
Related
I have a table with three columns: item, price and a checkbox. I want to calculate the subtotal but only include the prices with a checked checkbox. The code I have so far is a mix of various bits that work on its own; however right now I get the error message "TypeError: Cannot read properties of undefined (reading 'innerHTML')". What am I doing wrong?
function calculate() {
const ele = document.getElementsByTagName('input');
let table = document.getElementById("myTable");
let tr = table.getElementsByTagName("tr");
let subTotal = 0;
for (var i = 0; i < ele.length; i++) {
let td = tr[i].getElementsByTagName("td")[1];
let price = td[i].innerHTML;
if (ele[i].type == 'checkbox' && ele[i].checked == true)
subTotal += price;
}
document.getElementById("val").innerHTML = "The subtotal is " + subTotal;
}
<!DOCTYPE html>
<html>
<body>
<table id="myTable">
<tr>
<td>T-Shirt</td>
<td>9.99</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td>Pants</td>
<td>49.99</td>
<td><input type="checkbox"></td>
</tr>
</table>
<span id="val">The subtotal is 0</span>
<button onclick="calculate()">Calculate subtotal</button>
</html>
You have to change the line td[i] because it's not defined as the error suggests. So, consider using bare td and accessing its innerText. It'll return a string with the value, which you have to convert to a float number with parseFloat. Finally, you must set the precision you want to subTotal so that it will print with the number of decimals you want.
function calculate() {
const ele = document.getElementsByTagName('input');
let table = document.getElementById("myTable");
let tr = table.getElementsByTagName("tr");
let subTotal = 0;
for (var i = 0; i < ele.length; i++) {
let td = tr[i].getElementsByTagName("td")[1];
let price = parseFloat(td.innerText); // change here
if (ele[i].type == 'checkbox' && ele[i].checked == true)
subTotal += price;
}
document.getElementById("val").innerHTML = "The subtotal is " + subTotal.toFixed(2); // and set precision here
}
<!DOCTYPE html>
<html>
<body>
<table id="myTable">
<tr>
<td>T-Shirt</td>
<td>9.99</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td>Pants</td>
<td>49.99</td>
<td><input type="checkbox"></td>
</tr>
</table>
<span id="val">The subtotal is: </span>
<button onclick="calculate()">Calculate subtotal</button>
</html>
Problem with your code is simple. You referenced the td and than you try to reference it again.
let td = tr[i].getElementsByTagName("td")[1];
let price = td[i].innerHTML;
Should be
const td = tr[i].getElementsByTagName("td")[1];
const price = td.innerHTML;
If you use a value on the checkbox, you can just loop over the checked inputs and calculate the total using the values. No need to look up cell contents.
function calculate() {
const checkedInputs = document.querySelectorAll("#myTable input:checked");
const total = Array.from(checkedInputs).reduce(function(total, cb) {
return total + +cb.value;
}, 0);
document.querySelector("#val").textContent = "The subtotal is " + total.toFixed(2);
}
<table id="myTable">
<tr>
<td>T-Shirt</td>
<td>9.99</td>
<td><input type="checkbox" value="9.99"></td>
</tr>
<tr>
<td>Pants</td>
<td>49.99</td>
<td><input type="checkbox" value="49.99"></td>
</tr>
</table>
<span id="val">The subtotal is 0</span>
<button onclick="calculate()">Calculate subtotal</button>
You can iterate trhough checkbox and going up until the previous td
function calculate() {
let chckboxes = document.querySelectorAll('#myTable input:checked');
let sum = 0;
chckboxes.forEach((itm) => {
let val = parseFloat(itm.parentElement.previousElementSibling.innerHTML)
sum += val;
});
document.getElementById("val").innerHTML = "The subtotal is " + sum;
}
<!DOCTYPE html>
<html>
<body>
<table id="myTable">
<tr>
<td>T-Shirt</td>
<td>9.99</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td>Pants</td>
<td>49.99</td>
<td><input type="checkbox"></td>
</tr>
</table>
<span id="val">The subtotal is 0</span>
<button onclick="javascript:calculate()">Calculate subtotal</button>
</html>
HTML:
<table id="tbl" border="1">
<tr>
<th>Name</th>
<th>Mark1</th>
<th>Mark2</th>
<th>Total</th>
</tr>
<tr>
<td><input type="text"></td>
<td><input type="text" class="cell"></td>
<td><input type="text" class="cell"></td>
<td><b><span id="total_sum_value"></span></b></td>
<td><b><span id="total_sum_value1"></span></b></td>
<th><input class="add-row" data-id="1" type="button" value="+"></th>
</tr>
</table>
JavaScript:
$(document).ready(function(){
var i = $(".add-row").data("id");
$(".add-row").click(function(){
$('#tbl').append('<tr><td><input type="text"></td><td><input type="text"></td><td><input type="text"></td></tr>');
var two = $("input").addClass("cell"+i);
$("#tbl").on('input','.cell'+i,function(){
var sum1 = 0;
$(".cell"+i).each(function() {
var get_val = $(this).val();
sum1 += parseFloat(get_val);
});
$("#total_sum_value1").html(sum1);
});
i++;
});
$("#tbl").on('input','.cell',function(){
var sum = 0;
$('.cell').each(function(){
var get_val = $(this).val();
sum += parseFloat(get_val);
});
$("#total_sum_value").html(sum);
});
});
When you click on the plus sign button, it generates three textboxes. I want to calculate the sum of those textboxes and print it in a span.
Here is a CodePen of my code: https://codepen.io/anon/pen/XBqKVZ?editors=1010
can you try like this:
$('.cell').on('change', function(){
var sum = 0;
var data ={
}
$('.cell').each(function(index, item){
var val = $(item).val();
var get_val = $(this).val();
sum += Number(get_val);
console.log(sum);
});
$("#total_sum_value").html(sum);
});
URL: Jsfiddle
I have a table where the user can decide how many rows they wish to add. I've found a script that copy and pastes both columns and rows from excel. It works perfectly from the first 2 existing row's but the function doesn't work properly in any of the cloned rows that get added.
So if you use the function on the first two row's it will split the paste into each row and column (inluding the cloned rows) but if i try paste into a newly added row the function just doesn't work,
function cloneRow() {
var rowAmmount = document.getElementById("rowAmmount").value;
var getTotalRows = $('table > tbody').children().length;
for (var i = -1; i < rowAmmount-1;i++) {
var row = document.getElementById("row"); // find row to copy
var table = document.getElementById("table"); // find table to append to
var clone = row.cloneNode(true); // copy children too
clone.id = "newRow" + (getTotalRows + i); // change id or other attributes/contents
clone.classList.remove('hidden');
table.appendChild(clone); // add new row to end of table
$('#newRow' + (getTotalRows + i)).children().each(function() {
$(this).children().attr('id', $(this).children().attr('id') + (getTotalRows + i));
});
}}
$('input').on('paste', function(e){
var $this = $(this);
$.each(e.originalEvent.clipboardData.items, function(i, v){
if (v.type === 'text/plain'){
v.getAsString(function(text){
var x = $this.closest('td').index(),
y = $this.closest('tr').index()+1,
obj = {};
text = text.trim('\r\n');
$.each(text.split('\r\n'), function(i2, v2){
$.each(v2.split('\t'), function(i3, v3){
var row = y+i2, col = x+i3;
obj['cell-'+row+'-'+col] = v3;
$this.closest('table').find('tr:eq('+row+') td:eq('+col+') input').val(v3);
});
});
});
}
});
return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="rowAmmount"/>
<button id="add" onclick="cloneRow()">New Row</button>
<button type="button" onclick="submit()">Submit</button>
<table>
<thead>
<tr>
<th>Product Code</th>
<th>Item Name</th>
<th>Long Description></th>
<th>Material</th>
<th>Style</th>
</tr>
</thead>
<tbody id="table">
<tr id="row">
<td><input id="productId"></td>
<td><input id="itemname"></td>
<td><input id="long"></td>
<td><input id="fabric"></td>
<td><input id="style"></td>
</tr>
<tr id= "newRow0">
<td><input id="productId0"></td>
<td><input id="itemname0"></td>
<td><input id="long0"></td>
<td><input id="fabric0"></td>
<td><input id="style0"></td>
</tr>
</tbody>
</table>
You attach the change event handler before you insert the new inputs.
What you need is delegated event handling $('table').on('paste', 'input', function(e){
function cloneRow() {
var rowAmmount = document.getElementById("rowAmmount").value;
var getTotalRows = $('table > tbody').children().length;
for (var i = -1; i < rowAmmount-1;i++) {
var row = document.getElementById("row"); // find row to copy
var table = document.getElementById("table"); // find table to append to
var clone = row.cloneNode(true); // copy children too
clone.id = "newRow" + (getTotalRows + i); // change id or other attributes/contents
clone.classList.remove('hidden');
table.appendChild(clone); // add new row to end of table
$('#newRow' + (getTotalRows + i)).children().each(function() {
$(this).children().attr('id', $(this).children().attr('id') + (getTotalRows + i));
});
}}
$('table').on('paste', 'input', function(e){
var $this = $(this);
$.each(e.originalEvent.clipboardData.items, function(i, v){
if (v.type === 'text/plain'){
v.getAsString(function(text){
var x = $this.closest('td').index(),
y = $this.closest('tr').index()+1,
obj = {};
text = text.trim('\r\n');
$.each(text.split('\r\n'), function(i2, v2){
$.each(v2.split('\t'), function(i3, v3){
var row = y+i2, col = x+i3;
obj['cell-'+row+'-'+col] = v3;
$this.closest('table').find('tr:eq('+row+') td:eq('+col+') input').val(v3);
});
});
});
}
});
return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="rowAmmount"/>
<button id="add" onclick="cloneRow()">New Row</button>
<button type="button" onclick="submit()">Submit</button>
<table>
<thead>
<tr>
<th>Product Code</th>
<th>Item Name</th>
<th>Long Description></th>
<th>Material</th>
<th>Style</th>
</tr>
</thead>
<tbody id="table">
<tr id="row">
<td><input id="productId"></td>
<td><input id="itemname"></td>
<td><input id="long"></td>
<td><input id="fabric"></td>
<td><input id="style"></td>
</tr>
<tr id= "newRow0">
<td><input id="productId0"></td>
<td><input id="itemname0"></td>
<td><input id="long0"></td>
<td><input id="fabric0"></td>
<td><input id="style0"></td>
</tr>
</tbody>
</table>
I am trying to calculate the sum of text fields from a row which are checked.
My code works fine, but the problem which I am facing is my only calculate the value of first row only and it to previous result every time instead of adding current text field value.
Here is working fiddle:
https://jsfiddle.net/infohassan/27L6wvgw/
Here is my JS code:
$(document).ready(function(){
var $checkboxes = $('input[name^="txtChecked"]');
$checkboxes.change(function() {
$('input[name^="txtChecked"]').each(function() {
var countCheckedCheckboxes = $checkboxes.filter(':checked').length;
calculateTotal();
});
});
});
function calculateTotal() {
var total = 0;
$('input[name^="txtChecked"]:checked').each(function(){
var val = parseFloat($('input[name^="txtCostAmount"]').val());
total += val;
});
$('input[name="txtNetAmount"]').val(total);
}
I cleaned your event handler...
And I made the .each() loop look for the text input which is on the same tr as the checkbox...
UpdatedFiddle
$(document).ready(function(){
var $checkboxes = $('input[name^="txtChecked"]');
$checkboxes.change(function() {
//$('input[name^="txtChecked"]').each(function() {
//var countCheckedCheckboxes = $checkboxes.filter(':checked').length;
calculateTotal();
//});
});
});
function calculateTotal() {
var total = 0;
$('input[name^="txtChecked"]:checked').each(function(){
var val = parseFloat($(this).parents("tr").find('input[name^="txtCostAmount"]').val());
total += val;
});
$('input[name="txtNetAmount"]').val(total);
}
$(document).ready(function(){
var $checkboxes = $('input[name^="txtChecked"]');
$checkboxes.change(function() {
// var countCheckedCheckboxes = $checkboxes.find(':checked').length;
calculateTotal();
});
});
function calculateTotal() {
var total = 0;
$('input[name^="txtChecked"]:checked').each(function(index, item){
var parent = $(item).closest('tr');
var val = parseFloat(parent.find('input[name^="txtCostAmount"]').val());
total += val;
});
$('input[name="txtNetAmount"]').val(total);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th></th>
<th>Items</th>
<th>Cost</th>
</thead>
<tbody>
</tbody>
<tr>
<td><input name="txtChecked0" type="checkbox"></td>
<td>Item Name 1</td>
<td><input class="form-control input-sm" name="txtCostAmount0" value="3500" type="text"></td>
</tr>
<tr>
<td><input name="txtChecked1" type="checkbox"></td>
<td>Item Name 2</td>
<td><input class="form-control input-sm" name="txtCostAmount1" value="4500" type="text"></td>
</tr>
<tr>
<td><input name="txtChecked2" type="checkbox"></td>
<td>Item Name 3</td>
<td><input class="form-control input-sm" name="txtCostAmount2" value="4500" type="text"></td>
</tr>
</table>
<p>NetAmount <input class="form-control" name="txtNetAmount" value="0.00" readonly="" type="text"></p>
This question already has answers here:
Event handler not working on dynamic content [duplicate]
(2 answers)
Closed 9 years ago.
I have a table to allow user to do multiple stock entry
<table class="table1" id="table1">
<thread>
<tr>
<th scope="col">Item Name</th>
<th scope="col">Qty</th>
<th scope="col">Rate</th>
<th scope="col">Amount</th>
</tr>
</thread>
<tbody>
<tr>
<td><input type="text"/></td>
<td><input type="text" class="num" id="qty"/></td>
<td><input type="text" class="num" id="rate"/></td>
<td><input type="text" class="num" id="amt"/></td>
</tr>
</tbody>
</table>
<a id="add"><button>Add</button></a>
And this code is to add a new row:
<script type="text/javascript">
$(document).ready(function() {
$("#add").click(function() {
var newrow = $("<tr><td><input type="text"/></td><td><input type=\"text\" id=\"qty\"/></td><td><input type="\text\" id="\rate\"/></td><td><input type="\text\" id="\amt\"/></td></tr>");
newrow.insertAfter('#table1 tbody>tr:last');
return false;
});
$(".num").keyup(function() {
var id = $(this).attr('id');
if (id == 'qty') {
var i = parseFloat($("#rate").val())
if (!isNaN(i)) {
var t = ($(this).val()*$("#rate").val());
$("#amt").val(t.toFixed(2));
} else {
$("#amt").val('');
}
} else if (id == 'rate') {
var i = parseFloat($("#qty").val())
if (!isNaN(i)) {
var t = ($(this).val()*$("#qty").val());
$("#amt").val(t.toFixed(2));
} else {
$("#amt").val('');
}
}
});
});
The calculation is working perfect on the first row of table, but when I am adding a second row the calculation is not working. Where I am wrong?
Use event delegation:
$('body').on('keyup', ".num", function() {
// your code
});
Also you must add class .num to your created elements,
and you can't have the same ID for multiple elements, instead
use another attribute (like data-id, it doesn't matter),
var newrow = $('<tr><td><input type="text" /></td><td><input type="text" class="num" data-id="qty"/></td><td><input type="text" data-id="rate"/></td><td><input type="text" class="num" data-id="amt" /></td></tr>');
And in your function get them with this attribute:
$('body').on('keyup', ".num", function() {
var $row = $(this).closest('tr');
var $amt = $row.find('[data-id="amt"]');
var $qty = $row.find('[data-id="qty"]');
var $rate = $row.find('[data-id="rate"]');
var id = $(this).attr('data-id');
if (id == 'qty') {
// now using `$rate` instead of $('#rate')
var i = parseFloat($rate.val())
// other code
}
// other code
});
Give the new rows the num class (your new inputs don't have it), and use .on:
$(document).on('keyup', '.num', function() {
});
This is required if you want to add an event listener to elements that are not yet in the DOM.
Also, element IDs should be unique. Your new inputs are getting the same ID as the previous row.
try this
<table class="table1" id="table1">
<thread>
<tr>
<th scope="col">Item Name</th>
<th scope="col">Qty</th>
<th scope="col">Rate</th>
<th scope="col">Amount</th>
</tr>
</thread>
<tbody>
<tr>
<td>
<input type="text" />
</td>
<td>
<input type="text" class="num" name="qty" id="qty" />
</td>
<td>
<input type="text" class="num" id="rate" name="rate" />
</td>
<td>
<input type="text" class="num" id="amt" name="amt" />
</td>
</tr>
</tbody>
</table>
<a id="add">
<button>
Add</button></a>
<script type="text/javascript">
$(document).ready(function () {
$("#add").click(function () {
var newrow = $('<tr><td><input type="text"></td><td><input type="text" id="qty" name="qty" class="num"></td><td><input type="text" id="rate" name="rate" class="num"></td><td><input type="text" id="amt" name="amt" class="num"></td></tr>');
newrow.insertAfter('#table1 tbody>tr:last');
$('#table1 tbody>tr:last').find('[name="qty"]').keyup(function () {
var this_tr = $(this).closest('tr');
;
var i = parseFloat(this_tr.find('[name="rate"]').val())
if (!isNaN(i)) {
var t = ($(this).val() * this_tr.find('[name="rate"]').val());
this_tr.find('[name="amt"]').val(t.toFixed(2));
} else {
this_tr.find('[name="amt"]').val('');
}
});
$('#table1 tbody>tr:last').find('[name="rate"]').keyup(function () {
var this_tr = $(this).closest('tr');
;
var i = parseFloat(this_tr.find('[name="qty"]').val())
if (!isNaN(i)) {
var t = ($(this).val() * this_tr.find('[name="qty"]').val());
this_tr.find('[name="amt"]').val(t.toFixed(2));
} else {
this_tr.find('[name="amt"]').val('');
}
});
return false;
});
$('[name="qty"]').keyup(function () {
var this_tr = $(this).closest('tr');
;
var i = parseFloat(this_tr.find('[name="rate"]').val())
if (!isNaN(i)) {
var t = ($(this).val() * this_tr.find('[name="rate"]').val());
this_tr.find('[name="amt"]').val(t.toFixed(2));
} else {
this_tr.find('[name="amt"]').val('');
}
});
$('[name="rate"]').keyup(function () {
var this_tr = $(this).closest('tr');
;
var i = parseFloat(this_tr.find('[name="qty"]').val())
if (!isNaN(i)) {
var t = ($(this).val() * this_tr.find('[name="qty"]').val());
this_tr.find('[name="amt"]').val(t.toFixed(2));
} else {
this_tr.find('[name="amt"]').val('');
}
});
});
</script>
This issue can be solved via event delegation to the existing closet parent like in your case is $('#table1') or $(document) which is the parent of all the elements on a page, so you need to change this:
$(".num").keyup(function() {
to this:
$("#table").on('keyup', '.num', function() {
I just seen your additions you are adding same ids when clicked to add, so that results in a invalid html markup due to ids should be unique in the same page (same ids for multiple elems is invalid).
var newrow = $("<tr><td><input type='text'/></td>"+
"<td><input type='text' id='qty'/></td>"+
"<td><input type='text' id='rate'/></td>"+
"<td><input type='text' id='amt'/></td></tr>");
The above one everytime adds same id for multiple elements when added to the dom. you can try to do this way:
$("#add").click(function () {
var i = $("#table1 tbody>tr:last").index();
var newrow = $("<tr><td><input type='text'/></td>" +
"<td><input type='text' class='num' id='qty" + (i) + "'/></td>" +
"<td><input type='text' class='num' id='rate" + (i) + "'/></td>" +
"<td><input type='text' class='num' id='amt" + (i) + "'/></td>");
newrow.insertAfter('#table1 tbody>tr:last');
return false;
});