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>
Related
How do I do that JavaScript will print in my HTML page a table via the value the user will choose?
That the JS script:
let numCol = document.getElementById('txtColumns').value;
let numRow = document.getElementById('txtRows').value;
let go = document.getElementById('btn');
let table = document.getElementById('table');
let td = "<td></td>" * numCol;
let tr = ("<tr>" + td + "</tr>") * numRow;
go.addEventListener('click', function(){
table.innerHTML = tr;
})
That the HTML code:
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<table class="workTable">
<tr>
<td>
<input type="number" placeholder="Columns Number" id="txtColumns">
</td>
<td>
<input type="number" placeholder="Rows Number" id="txtRows">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="btn">
Print
</button>
</td>
</tr>
<div>
<table id="table">
<!--Here I want to print the table-->
</table>
</div>
</table>
<script src="script.js"></script>
</body>
</html>
At first I thought about that way with the script but its only appear as a NaN and not table...
The following syntax:
let td = "<td></td>" * numCol;
does not produce numCol cells, so the following syntax:
let tr = ("<tr>" + td + "</tr>") * numRow;
does not produce numRow rows also.
So, the whole source code should be:
let go = document.getElementById('btn');
let table = document.getElementById('table');
go.addEventListener('click', () => {
let numCol = document.getElementById('txtColumns').value; //Get the value of txtColumns at the button click moment.
let numRow = document.getElementById('txtRows').value;
let td = "",
tr = "";
for (let i = 0; i < numCol; i++) {
td = td + "<td></td>";
}
for (let i = 0; i < numRow; i++) {
tr = tr + "<tr>" + td + "</tr>";
}
table.innerHTML = tr;
})
<table class="workTable">
<tr>
<td>
<input type="number" placeholder="Columns Number" id="txtColumns">
</td>
<td>
<input type="number" placeholder="Rows Number" id="txtRows">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="btn">
Print
</button>
</td>
</tr>
<div>
<table id="table" border="1">
<!--Here I want to print the table-->
</table>
</div>
</table>
A billing form
I am trying to make a billing form where I need to automatically show amount generated after entering values for price and quantity columns. But with the following code I am only able to calculate it for one row. I want it to work for every row each time I entry values to it and at the end, it should display sum total of the amount column also.
function deleteRow(row)
{
var i=row.parentNode.parentNode.rowIndex;
document.getElementById('billingSheet').deleteRow(i);
}
function addRow(){
var x=document.getElementById('billingSheet');
// deep clone the targeted row
var new_row = x.rows[1].cloneNode(true);
// get the total number of rows
var len = x.rows.length;
// set the innerHTML of the first row
new_row.cells[0].innerHTML = len;
// grab the input from the first cell and update its ID and value
var inp1 = new_row.cells[1].getElementsByTagName('input')[0];
inp1.id += len;
inp1.value = '';
// grab the input from the second cell and update its ID and value
var inp2 = new_row.cells[2].getElementsByTagName('input')[0];
inp2.id += len;
inp2.value = '';
// grab the input from the third cell and update its ID and value
var inp3 = new_row.cells[3].getElementsByTagName('input')[0];
inp3.id += len;
inp3.value = '';
// append the new row to the table
x.appendChild( new_row );
}
function calc(){
$('#input1,#input2').keyup(function(){
var textValue1 =$('#input1').val();
var textValue2 = $('#input2').val();
$('#output').val(textValue1 * textValue2);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="billingSheet" border="1" width="65%">
<tr>
<th>Serial No</th>
<th>Enter item name</th>
<th> Price </th>
<th> Quantity </th>
<th> Amount</th>
<th>Add</th>
<th>Delete</th>
</tr>
<tr>
<td>1</td>
<td><input type="text"></td>
<td><input type="number" name="input1" id="input1" onkeyup="calc()"></td>
<td><input type="number" name="input2" id="input2" onkeyup="calc()"></td>
<td><input type="text" name="output" id="output" value=""></td>
<td><input type="button" id="add" value="Add Row" onClick="addRow()"/></td>
<td><input type="button" id="delete" value="Delete Row" onclick="deleteRow(this)"></td>
</tr>
</table>
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
document.getElementById('billingSheet').deleteRow(i);
}
var input1 = "";
function addRow() {
var x = document.getElementById('billingSheet');
// deep clone the targeted row
var new_row = x.rows[1].cloneNode(true);
// get the total number of rows
var len = x.rows.length;
// set the innerHTML of the first row
new_row.cells[0].innerHTML = len;
// grab the input from the first cell and update its ID and value
var inp1 = new_row.cells[1].getElementsByTagName('input')[0];
inp1.id += len;
inp1.value = '';
// grab the input from the second cell and update its ID and value
var inp2 = new_row.cells[2].getElementsByTagName('input')[0];
inp2.id += len;
inp2.name = len;
inp2.value = '';
// grab the input from the third cell and update its ID and value
var inp3 = new_row.cells[3].getElementsByTagName('input')[0];
inp3.id += len;
inp3.name = len;
inp3.value = '';
// grab the input from the third cell and update its ID and value
var inp4 = new_row.cells[4].getElementsByTagName('input')[0];
inp4.id = "output" + len;
inp4.value = '';
// append the new row to the table
x.appendChild(new_row);
}
function calc(input, name) {
if (!input.value || isNaN(input.value))
return;
var str = input.id.substr(6, input.id.length);
var textValue1 = $('#input1' + str).val();
var textValue2 = $('#input2' + str).val();
$('#output' + name).val(textValue1 * textValue2);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="billingSheet" border="1" width="65%">
<tr>
<th>Serial No</th>
<th>Enter item name</th>
<th> Price </th>
<th> Quantity </th>
<th> Amount</th>
<th>Add</th>
<th>Delete</th>
</tr>
<tr>
<td>1</td>
<td><input type="text"></td>
<td><input type="number" name ="1" id="input1" onkeyup="calc(this,name)"></td>
<td><input type="number" name ="1" id="input2" onkeyup="calc(this,name)"></td>
<td><input type="text" name="output1" id="output1" value=""></td>
<td><input type="button" id="add" value="Add Row" onClick="addRow()"/></td>
<td><input type="button" id="delete" value="Delete Row" onclick="deleteRow(this)"></td>
</tr>
</table>
</body>
<script src="js/index.js"></script>
</html>
I have number inputs
number around 30
I need to sum them all to one field
what I have is below
View:
<table>
<tbody>
<tr>
<td><input class="days_tpu" type="number" id="sth_1"></td>
</tr>
<tr>
<td><input class="days_tpu" type="number" id="sth_2"></td>
</tr>
<tr>
<td><input class="days_tpu" type="number" id="sth_3"></td>
</tr>
</tbody>
// field in which it will add up
<tfoot>
<th><input id="id_days_tpu" type="time" type="text"></th>
</tfoot>
</table>
I tried:
I try to take all inputs.
and count by length
and sum them
but, it doesn't work
Javascript:
const days_tpu_s = [...document.getElementsByClassName("days_tpu")];
//or
const table = document.querySelector('table');
table.sumInputs = function () {
var inputs = document.getElementsByClassName('days_tpu'),
result = document.getElementById('sum_id_days_tpu'),
sum = 0;
for (var i = 0; i < inputs.length; i++) {
var ip = inputs[i];
if (ip.name && ip.name.indexOf("total") < 0) {
sum += parseInt(ip.value) || 0;
}
}
result.value = sum;
}
sumInputs();
anyone have a good idea?
You can use Array.prototype.map() to get all the input value the use Array.prototype.reduce() to sum them.
Demo:
const days_tpu_s = [...document.getElementsByClassName("days_tpu")];
function sumInputs() {
var sum = days_tpu_s.map(i => Number(i.value)).reduce((a, c) => a + c, 0);
document.getElementById('id_days_tpu').value = sum;
}
days_tpu_s.forEach(function(el){
el.addEventListener('input', sumInputs);
});
<table>
<tbody>
<tr><td><input class="days_tpu" type="number" id="sth_1"></td></tr>
<tr><td><input class="days_tpu" type="number" id="sth_2"></td></tr>
<tr><td><input class="days_tpu" type="number" id="sth_3"></td></tr>
</tbody>
// field in which it will add up
<tfoot>
<th><input id="id_days_tpu" type="text"></th>
</tfoot>
</table>
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 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