Beginner coder here.
I am currently developing a website for calculating various equations, but I need help with user input.
On the HTML, I currently wrote up the following code.
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td>later</td>
<td> <input type="number" id="fahrenheit"/> </td>
<td>later</td>
</tr>
</table>
</section>
How would I go about changing the second and third row to change along with what the user inputs without having them have to press a submit button? How would I access the input that the user has given me in order to manipulate it into an output in the corresponding spot in the table?
This is what you're after I suspect :)
HTML
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td id="celc2">-</td>
<td> <input type="number" id="fahrenheit" /> </td>
<td id="kelv2">-</td>
</tr>
</table>
</section>
JQuery
//Hook into an event where if an input of type number changes
$('input[type=number]').change(function() {
//If the name of the input that has changed is celsius
if($(this).attr('id') == 'celsius'){
//Call a function to get the current value using $(this).val()
//Update the text inside the relevant td's by calling a function
$('#fahr1').text(celsiusToFahrenheit($(this).val()));
$('#kelv1').text(celsiusToKelvin($(this).val()));
}
//If the name of the input that has changed is fahrenheit
else if($(this).attr('id') == 'fahrenheit'){
//Call a function to get the current value using $(this).val()
//Update the text inside the relevant td's by calling a function
$('#celc2').text(fahrenheitToCelsius($(this).val()));
$('#kelv2').text(fahrenheitToKelvin($(this).val()));
}
});
function celsiusToFahrenheit(c) {
var f = parseInt(c);
f = f * (9/5) + 32;
return f;
}
function celsiusToKelvin(c) {
var k = parseInt(c);
k = k + 273.15;
return k;
}
function fahrenheitToCelsius(f) {
var c = parseInt(f);
c = (c - 32) * (5/9);
return c;
}
function fahrenheitToKelvin(f) {
var k = parseInt(f);
k = (k + 459.67) * (5/9);
return k;
}
Please note! You should put this in a <script></script> section in the top of your HTML. An example can be seen here: W3 Schools Script example
Similarly don't forget to reference JQuery in your <head></head> section. An example can be seen here: W3 Schools Reference JQuery
See it working live here: https://jsfiddle.net/cwr1hm9v/1/
EDIT
As per request, here is the Javascript equivalent
HTML
<section>
<!--- Celsius, Fahrenheit, Kelvin -->
<table>
<tr>
<td>°C</td>
<td>°F</td>
<td>°K</td>
</tr>
<tr>
<td> <input type="number" id="celsius"/> </td>
<td id="fahr1"></td>
<td id="kelv1"></td>
</tr>
<tr>
<td id="celc2">-</td>
<td> <input type="number" id="fahrenheit" /> </td>
<td id="kelv2">-</td>
</tr>
</table>
</section>
JavaScript
const celsius = document.getElementById('celsius');
const fahrenheit = document.getElementById('fahrenheit');
celsius.addEventListener('change', (event) => {
convertFromCelsius();
});
fahrenheit.addEventListener('change', (event) => {
convertFromFahrenheit();
});
function convertFromCelsius() {
var fahr1 = document.getElementById("fahr1");
var kelv1 = document.getElementById("kelv1");
fahr1.textContent = parseInt(celsius.value) * (9/5) + 32;
kelv1.textContent = parseInt(celsius.value) + 273.15;
}
function convertFromFahrenheit() {
var celc2 = document.getElementById("celc2");
var kelv2 = document.getElementById("kelv2");
celc2.textContent = (parseInt(fahrenheit.value) - 32) * (5/9);
kelv2.textContent = (parseInt(fahrenheit.value) + 459.67) * (5/9);
}
See it working live here: https://jsfiddle.net/0Luvq4nx/1/
Please mark this as accepted if this solves your issue.
Related
I'm very new to JS and I'm trying to learn for loops and in this case, I want to turn this into a for loop if possible. I want to calculate a static number string in cell 3, times the input number in cell 4, and output the result to a new cell 5 that has been created in the loop. Any help is much appreciated
var table = document.getElementById("table");
var Row1 = table.rows[1],
cell1 = Row1.insertCell(5);
var Row2 = table.rows[2],
cell2 = Row2.insertCell(5);
var Row3 = table.rows[3],
cell3 = Row3.insertCell(5);
var Row4 = table.rows[4],
cell4 = Row4.insertCell(5);
var Row5 = table.rows[5],
cell5 = Row5.insertCell(5);
var Row6 = table.rows[6],
cell6 = Row6.insertCell(5);
var x1 = table.rows[1].cells[4].getElementsByTagName('input')[0].value;
var y1 = table.rows[1].cells[3].innerHTML;
cell1.innerHTML = y1 * x1;
var x2 = table.rows[2].cells[4].getElementsByTagName('input')[0].value;
var y2 = table.rows[2].cells[3].innerHTML;
cell2.innerHTML = y2 * x2;
var x3 = table.rows[3].cells[4].getElementsByTagName('input')[0].value;
var y3 = table.rows[3].cells[3].innerHTML;
cell3.innerHTML = y3 * x3;
var x4 = table.rows[4].cells[4].getElementsByTagName('input')[0].value;
var y4 = table.rows[4].cells[3].innerHTML;
cell4.innerHTML = y4 * x4;
var x5 = table.rows[5].cells[4].getElementsByTagName('input')[0].value;
var y5 = table.rows[5].cells[3].innerHTML;
cell5.innerHTML = y5 * x5;
var x6 = table.rows[6].cells[4].getElementsByTagName('input')[0].value;
var y6 = table.rows[6].cells[3].innerHTML;
cell6.innerHTML = y6 * x6;
These don't need to be in functions but just to make it easier to read
function createCells() {
cells = []
for (let i = 1; i < 7; i++) {
var cells[i] = table.rows[i].insertCell(5)
}
}
function calculate() {
for
let (i = 1; i < 7; i++) {
var x = table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y = table.rows[i].cells[3].innerHTML;
cells[i].innerHTML = (y * x);
}
}
A short answer using a simple for-loop is this:
Loop through every row
For each row, multiply quantity with price
Output total in same row
Since we basically always want to have a "total"-field in every row, we can add it in the HTML directly.
And since we know the position of the price-element and quantity-element, we can access them using fixed values as indices.
var rows = document.querySelectorAll("#pricetable tbody tr");
for (var i = 0; i < rows.length; ++i) {
var price = rows[i].children[3].innerHTML;
var quantity = rows[i].children[4].children[0].value;
var total = price * quantity; // Implicit type-casting to numbers
rows[i].children[5].innerHTML = total;
}
<table id="pricetable">
<thead>
<tr>
<th>Number</th>
<th>Product</th>
<th>Brand</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>23456789</td>
<td>Phone</td>
<td>Apple</td>
<td>6500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>22256289</td>
<td>Phone</td>
<td>Samsung</td>
<td>6200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>24444343</td>
<td>Phone</td>
<td>Huawei</td>
<td>4200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>19856639</td>
<td>Tablet</td>
<td>Apple</td>
<td>4000</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>39856639</td>
<td>Tablet</td>
<td>Samsung</td>
<td>2800</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>12349862</td>
<td>Tablet</td>
<td>Huawei</td>
<td>3500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
</tbody>
</table>
Note: When changing the position of those elements (e.g. by add a new column infront of them), their index would shift. That would make you have to update the indices in the JS-file manually.
You can make this easier for yourself by using this simple "trick":
Add specific classes to the elements (e.g. .price, .quantity, .total), allowing you to easily find them using Element.querySelector().
Note: The script only runs once, the first time the page is loaded. That means, inputting a different quantity won't update the "total"-field. For that, we need an EventListener.
Another approach
By observing the for-loop, we can see:
We access only one row for each iteration
The order in which we access each row is irrelevant
Since both these points are checked, we can use a for...of-loop (also called foreach-loop or enhanced for-loop). A for...of-loop is (in my opinion) easier to read, and tells what we checked using the list above by itself.
Note: Be wary of the difference of the for...of-loop and the for...in-loop.
Now, we could calculate the total right then and there in the loop, but thinking ahead, we want to perform the same calculation again when inputting a new quantity-value. We can reduce the duplicate code by making the calculation a Function updateRowTotal(), making the code easier to debug and understand.
To actually update the total when entering a new quantity-value, we can use an EventListener that calls a function automatically when a new value is entered into the <input>-field (by calling updateRowTotal(evt.target.closest("tr"))).
function clamp(min, value, max) {
return Math.max(min, Math.min(value, max));
}
for (let row of document.querySelectorAll("#pricetable tbody tr")) {
updateRowTotal(row);
row.querySelector("input.quantity").addEventListener("input", evt => {
// Add '/*' before this comment to "remove" this extra part
// The 5 lines below are to clamp 'value' between 'min' and 'max'
let min = parseInt(evt.target.getAttribute("min"));
let max = parseInt(evt.target.getAttribute("max"));
if (isNaN(min)) min = Number.MIN_SAFE_INTEGER;
if (isNaN(max)) max = Number.MAX_SAFE_INTEGER;
evt.target.value = clamp(min, evt.target.value, max);
// */
updateRowTotal(evt.target.closest("tr"));
});
}
function updateRowTotal(row) {
row.querySelector(".total").innerHTML = row.querySelector(".price").innerHTML * row.querySelector(".quantity").value;
}
<table id="pricetable">
<thead>
<tr>
<th>Price</th>
<th>Quantity</th>
<th>Row-Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="price">6500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">6200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4000</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">2800</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">3500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
</tbody>
</table>
Sidenote
Making the <input>-field of type="number" prevents any non-numeric character to be entered.
And since the min- and max-attributes only prevent form-submission, we have to code the value-clamping ourselves. This is easily done by reading the values of the attributes and clamping the value to their defined range. Note that we have added default values for both min and max, being the lower-most and upper-most safe integer-value.
You can use for-loops like the one given below. Looks like you are operating on numbers, so I have added a + in front of x1's and y1's assignment to implicitly type-cast them to numbers.
for(var i = 1; i <= 6; i++) {
var firstRow = table.rows[i], cell = firstRow.insertCell(5);
var x1 = +table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y1 = +table.rows[i].cells[3].innerHTML;
cell.innerHTML = y1 * x1;
}
I'm trying to sum the values of one specific column but honestly I dont know how to it, also I want to refresh that total value when I add or remove some row, what can I do to make this? I'm triying with the anwsers of similar question here on SO but they sum values from all columns and I only want to do that for an specific column! Here is what I have:
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
$('#xd').click(function() {
var lines = "";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
$('#TableBody').append(lines);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td>15</td>
<td>170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
In the above code I added the Total columns (Price, Quantity) manually, I want to update total result when user add/remove a row.
Your approach is a bit brittle for long term use, but as a proof of concept this may help.
The key technique for summing up an array of numbers is to use Array.reduce, which works like this:
var array = [1, 2, 6, 1, 5];
var total = array.reduce(function(total, number) {
return total + number;
}, 0);
document.write('<h1>Total: <code>' + total + '</code></h1>');
Given an array of numbers, iterate over each of them and add number to total, with total starting at 0.
Array.reduce takes two arguments: a function to execute over each item, and a starting value. The iterator function will receive two arguments, in your case the running total and the next number.
See the MDN documentation on Array.reduce for more details.
Some Tips
Break things down into smaller functions whenever possible.
Limit use of global variables, but when you do need them, be clean and consistent about it
Limit storing data on the DOM (I'm violating this slightly, but this is just sketch code)
Try and write code in a way that's reusable
The benefits of this approach are it makes it a bit easier to add new features/change what you built. For example, if we write a generic function getColumnTotal(selector), which would let you specify a jQuery selector for a column's cells (ex: .priceCell), then you can reuse that for other columns like quantity.
I assume you were working towards a grand total cell, that displays the total of all individual orders/rows. To do that, all we'd need to do is calculate the subtotal for each row, add a new column for that, then re-use that getColumnTotal function to sum up all the sub-totals. Voila, grand total.
Note that my code doesn't account for errors, so you may need to handle situations where invalid quantity or price data is input.
var $tableBody = $('#TableBody');
var $totalQuantityCell = $('#totalQuantityCell');
var $totalPriceCell = $('#totalPriceCell');
var $totalGrandCell = $('#grandTotalCell');
// Add a row with random values on "Add Row" button click
$('#xd').click(addRandomRow);
function addRandomRow(event) {
var randomCode = Math.round(Math.random() * 4);
var randomClient = Math.round(Math.random() * 15);
var randomCharge = ( Math.round(Math.random()) ? 'Debit' : 'Credit' );
var randomQuantity = Math.ceil(Math.random() * 5);
var randomPrice = Math.ceil(Math.random() * 100).toFixed(2);
addRow(randomCode, randomClient, randomCharge, randomQuantity, randomPrice);
};
// Add some rows to start
addRandomRow();
addRandomRow();
// Listen for clicks on ".deleteRowButton" within the table
$tableBody.on('click', '.deleteRowButton', function(event) {
deleteRow( $(event.target).data('row') );
updateTotals();
});
// --------------------------
function addRow(code, client, chargeType, quantity, price) {
// Create a new row element
var idNum = ( $tableBody.find('tr').length + 1 );
var rowId = 'row-' + idNum;
var $row = $('<tr id="' + rowId + '"></tr>');
// Add the table cells
$row.append('<td class="idCell">' + idNum + '</td>');
$row.append('<td class="codeCell">' + code + '</td>');
$row.append('<td class="clientCell">' + client + '</td>');
$row.append('<td class="chargeTypeCell">' + chargeType + '</td>');
$row.append('<td class="quantityCell">' + quantity + '</td>');
$row.append('<td class="priceCell">' + price + '</td>');
$row.append('<td class="orderTotalCell">' + getSubtotal(quantity, price) + '</td>');
$row.append('<td><input type="button" value="Delete" class="deleteRowButton" data-row="#' + rowId + '" /></td>');
// Append the row to the table body
$tableBody.append($row);
updateTotals();
}
function deleteRow(rowId) {
$(rowId).remove();
}
function updateTotals() {
var totalQuantity = getColumnTotal('.quantityCell');
var totalPrice = getColumnTotal('.priceCell');
var totalOrder = getColumnTotal('.orderTotalCell');
$totalQuantityCell.text( totalQuantity );
$totalPriceCell.text( toMoney(totalPrice) );
$totalGrandCell.text( toMoney(totalOrder) );
}
/**
A standard function to calaculate the subtotal of a row, this is
where you could apply tax or other data transformations if need be.
*/
function getSubtotal(quantity, price) {
return (quantity * price).toFixed(2);
}
/**
Takes a jQuery selector, finds all matching elements for it, and totals up their contents.
It works by converting the elements list to an Array and then using Array.reduce.
#see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
*/
function getColumnTotal(selector) {
return Array.from( $(selector) ).reduce(sumReducer, 0);
}
/**
The reducer function that adds up a running total. This function parses the innerHTML content
of an element and converts it to a number so math works on it.
*/
function sumReducer(total, cell) {
return total += parseInt(cell.innerHTML, 10);
}
function toMoney(number) {
return '$' + number.toFixed(2);
}
#TableHead td {
border-bottom: 1px #000 solid;
}
.orderTotalCell,
#grandTotalCell,
#totalPriceCell {
text-align: right;
}
#TableFooter tr:first-child td {
border-top: 1px #000 solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead id="TableHead">
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Order Total</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Sub-Total</td>
<td id="totalQuantityCell">–</td>
<td id="totalPriceCell">–</td>
<td id="grandTotalCell">–</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
wow lots of answers but here is a somewhat of a more object oriented approach.
function row(Id, Code, Client, DebitCredit, Quantity, Price) {
this.Id = Id;
this.Code = Code;
this.Client = Client;
this.DebitCredit = DebitCredit;
this.Quantity = Quantity;
this.Price = Price;
}
function model() {
this.rows = [];
}
var mymodel = new model();
$(document).ready(function() {
mymodel.rows.push(new row(1, 1, 3, 'Debit', 10, 12))
mymodel.rows.push(new row(2, 2, 12, 'Debit', 5, 10))
draw();
$("body").on("click", ".delete", function() {
var id = $(this).data('id');
for (i = 0; i < mymodel.rows.length; i++) {
console.log(mymodel.rows[i].Id);
if (mymodel.rows[i].Id == id) {
mymodel.rows.splice(i, 1);
}
}
draw();
});
$('#add').click(function() {
mymodel.rows.push(new row(
$('#Id').val(),
$('#Code').val(),
$('#Client').val(),
'Debit',
Number($('#Quantity').val()),
Number($('#Price').val())
))
draw();
});
})
function draw() {
$('tbody').empty();
var totalQuantity = 0;
var totalPrice = 0;
$.each(mymodel.rows, function(i, row) {
totalQuantity += row.Quantity;
totalPrice += row.Price;
var myrow = '<tr>'
$.each(row, function(key, value) {
myrow += '<td>' + value + '</td>'
});
myrow += '<td><input type="button" class="btn btn-danger delete" data-id="' + row.Id + '" value="X"/></td>'
myrow += '<tr>'
$('tbody').append(myrow);
});
$('#totalQuantity').text(totalQuantity)
$('#totalPrice').text(totalPrice)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<table class="table table-condensed">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan=7>Total Quantity:
<span id="totalQuantity"></span> Total Price:
<span id="totalPrice"></span>
</td>
</tr>
</tfoot>
</table>
<form class="form-inline">
<div class="form-group">
<label for="id">Id:</label>
<input type="number" class="form-control" id="Id">
</div>
<div class="form-group">
<label for="Code">Code:</label>
<input type="number" class="form-control" id="Code">
</div>
<div class="form-group">
<label for="Client">Client:</label>
<input type="number" class="form-control" id="Client">
</div>
<div class="form-group">
<label for="Quantity">Quantity:</label>
<input type="number" class="form-control" id="Quantity">
</div>
<div class="form-group">
<label for="Price">Price:</label>
<input type="number" class="form-control" id="Price">
</div>
<input type="button" class="btn btn-info" value="add" id="add" />
</form>
You are missing:
<tr> </tr>
Tags when you add a new row. Also, just add a class that will add up "Quantities" and "Prices". Here's a working solution. Hope it helps!
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
sumOfColumns();
}
function sumOfColumns(){
var totalQuantity = 0;
var totalPrice = 0;
$(".someClass").each(function(){
totalQuantity += parseInt($(this).html());
$(".someTotalClass").html(totalQuantity);
});
$(".classPrice").each(function(){
totalPrice += parseInt($(this).html());
$(".someTotalPrice").html(totalPrice);
});
}
$(document).ready(function () {
$('#xd').click(function() {
var lines = "";
lines += '<tr>';
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class = "someClass">1</td>';
lines += '<td class = "classPrice">100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
lines += '</tr>';
$('#TableBody').append(lines);
sumOfColumns();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class = "someClass">10</td>
<td class = "classPrice">12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class = "someClass">5</td>
<td class = "classPrice">10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class = "someTotalClass">15</td>
<td class = "someTotalPrice"">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
You can create a function to calculate total and call it after you add each line and on page load if you have some initial value.
function setTotal()
{
var totalPrice=0;
var totalQty=0;
$('#TableBody').find('tr').each(
function(){
totalQty +=parseFloat($(this).find('td').eq(4).text());
totalPrice +=parseFloat($(this).find('td').eq(5).text());
//console.log(totalPrice);
});
$('#TableFooter').find('tr td').eq(1).text(totalQty);
$('#TableFooter').find('tr td').eq(2).text(totalPrice);
}
$(function(){
setTotal();
})
$('#ID').find('tr') will find all the rows of table with id 'ID'. then you iterate through each tr using each function. Then in each row you find all the td similarly and get to specific td using eq function. eq takes index of the element.
Here is running fiddler : https://jsfiddle.net/8a4umvdr/
There are several flaws within your script, which I will want to walk you through so that you can better understand the process:
Avoid using inline JS. If you want to bind events dynamically, you can use .on() instead. Since the table is present on DOM ready, you can use $('#Table').on(...) to listen to click events on the delete button
Modularise sum computation into a single function. You can create a function, say computeSum(), which will be called every time you modify the table: be it when a table row is added, or a table row is deleted. You can also call this function at runtime, so that you do not have to use server-side languages to precompute the starting sums.
In my example below, I will fetch the text node in the 5th and 6th columns (which is 4 and 5 by zero-based index), and convert them to float by appending + in front of them
I have also used the .toFixed(2) function when printing the sums, so that its nicely showing two decimal places.
Fix your HTML injection. Remember that for <td> elements to be valid, they have to be nested in <tr>. You seem to have left that out by accident.
So here is a completely functional example of your code snippet:
$(function() {
// Function to compute sum
var computeSum = function() {
// Get the total quantity and price by column index
var quantity = 0,
price = 0;
// Iterate through each row
$('#TableBody tr').each(function() {
quantity += +$(this).find('td').eq(4).text();
price += (+$(this).find('td').eq(5).text() * +$(this).find('td').eq(4).text());
});
// Update sum
$('#TableFooter td.total.quantity').text(quantity.toFixed(2));
$('#TableFooter td.total.price').text(price.toFixed(2));
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Recompute sum
computeSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Recompute sum
computeSum();
});
// Compute sum when starting up
computeSum();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
Further improvements
There are some minor improvements that you can make to my code above, but they are considered non-mission critical and hence I did not include them in my original answer.
Extensibility. If you want to compute additional columns, it would be difficult to rewrite the same lines over and over again. Instead, I recommend you store the sums in an object instead.
Value fetching. We are retrieving values based on the text node in the column. Sometimes, you do not want that—say you want to include currencies, or other texts in the quantity and/or price column. In that sense, you might want to store such data in a custom HTML5 data- attribute instead.
$(function() {
// Function to compute sum
var computeSum = function() {
// Get the total quantity and price by column index
var sums = { quantity: 0, price: 0 };
// Iterate through each table cell
$('#TableBody tr').each(function() {
sums.quantity += +$(this).find('td').eq(4).data('value');
sums.price += (+$(this).find('td').eq(4).data('value')*+$(this).find('td').eq(5).data('value'));
});
// Update sum
$.each(sums, function(key, value) {
$('#TableFooter td.total.'+key).text(value.toFixed(2));
});
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Recompute sum
computeSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class="quantity" data-value="1">1</td>';
lines += '<td class="price" data-value="100.00">100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Recompute sum
computeSum();
});
// Compute sum when starting up
computeSum();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class="quantity" data-value="10">10</td>
<td class="price" data-value="12.00">12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class="quantity" data-value="5">5</td>
<td class="price" data-value="10.00">10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
I make a code , that randomly display an 6-item array in a div.
i want to read the array and pass it to function to calculate the mean of it?
HTML
what i must do , how can i store the data of div(id="numbers" )
and push it in array ?
<pre>
<div >
<form action="" method="post" name="meanForm" onsubmit='return false' id="formmine">
<table width="100%" border="0"
<tr>
<td colspan="3" style="background-color:#06F ;color:#FFF">Answer this problem</td>
</tr>
<tr>
<td style="color:green; font-size:20px">What is the mean of these numbers </td>
<td colspan="2" ><div id="numbers"></div>
</td>
</tr>
<tr>
<td colspan="3"> </td>
</tr>
<tr id="answerANDpic">
<td height="62" colspan="3" align="center" > <input name="" type="text" size="15" maxlength="100" height="50" style=" border: solid #0C0 ; border-width:thin" id="answer" onkeydown="searchm(this)"/> </td>
</tr>
<tr>
<td colspan="3" ><div id ="explain" ></div></td>
</tr>
<tr>
<td> </td>
<td><input name="" type="button" id="newEx" style="background-color:green ; color:white" align ="left" value="New Problem" class="send_feed" onclick="randomArray(6,0,99)" /></td>
<td><input name="" type="button" id="solution" style="background-color:#606 ; color:#FFF " align="left" class="send_feed" value="Solution" onclick="solution()"/></td>
</tr>
</table>
</form>
</div>
in JS
var myNumArray = randomArray(6,0,99);
function random_number(min,max) {
return (Math.round((max-min) * Math.random() + min));
}
function randomArray(num_elements,min,max) {
var nums = new Array;
for (var element=0; element<num_elements; element++) {
nums[element] = random_number(min,max);
}
document.getElementById("numbers").innerHTML=nums;
calcMean(nums);
}
function calcMean(nums) {
var num=0;
for (var i=0;i<nums.length;i++) {
num += parseFloat( nums[i], 6 );
}
var divide=num/nums.length;
var mean=(parseInt(divide,10));
var maxi = Math.max.apply(Math,nums);
var mini = Math.min.apply(Math,nums);
return mean,maxi,mini;
}
function searchm(ele) {
if(event.keyCode == 13) {
// alert(ele.value); // i get the value and put it on alert
var inans= ele.value;
return inans;
}
}
function soltuion(){
//read array saved in div id="numbers"
// call calcMean()
//get the mean and max min values
}
See comments in code below. Your code is not far off working.
function calcMean(nums){
var num=0;
for (var i=0;i<nums.length;i++){
// parseFloat only has one argument
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat
num += parseFloat( nums[i])
// If the numbers in the nums array
// are already floats, you don't need parseFloat
// So maybe you can do... ?
// num += nums[i]
}
// The line below might divide by zero, so check
if (nums.length == 0) {
return 0;
}
var divide=num/nums.length;
// No need to reparse a number.
mean=divide
// This code suggests that nums is already filled with numbers
// See comment in for-loop above
var maxi = Math.max.apply(Math,nums);
var mini = Math.min.apply(Math,nums);
// This returns all 3 numbers
return [mean,mini,maxi];
// If you want just the mean,
// return mean;
}
I've looked around on the web for an answer to my question. Found lots of scripts that I've copied and messed around with but can't get it working properly.
When I run it, my script below initially works but then displays 'NaN'.
I'm trying to create a simple order form that uses JavaScript to dynamically update and display the order total.
Each item for sale has an input (type=number) tag that contains the item's price in a 'data-price' attribute.
What I'm trying to do is grab the price out of the data-price attribute and use it in a JS script to display a total.
Users can enter a quantity into text field and the TOTAL text field should automatically update with correct 'running total'.
Would appreciate any advice as to where I'm going wrong. I've used JavaScript (as opposed to jQuery) because I'm more familiar with the syntax.
<script>
function calculateTotal(frm) {
var order_total = 0
for (var i=0; i < frm.elements.length; ++i) {
form_field = frm.elements[i];
item_price = form_field.dataset.pric);
item_quantity = form_field.value;
if (item_quantity >= 0) {
order_total += item_quantity * item_price;
}
}
frm.total.value = round_decimals(order_total, 2);
}
function round_decimals(original_number, decimals) {
var result1 = original_number * Math.pow(10, decimals);
var result2 = Math.round(result1);
var result3 = result2 / Math.pow(10, decimals);
return result3.toFixed(2);
}
</script>
</head>
<body>
<form id="order-form">
<table cellpadding="8" align="center">
<tr>
<td align="left" width="150">Image</td>
<td align="left">Description</td>
<td align="left">Price</td>
<td align="left">Quantity</td>
</tr>
<tr>
<td align="left"><img src="http://placehold.it/150x200"></td>
<td align="left">Poster</td>
<td align="left">$24.00</td>
<td align="left"><input type="number" data-price="24" min="0" max="50" step="1" value="0" onChange="calculateTotal(this.form)"></td>
</tr>
<tr>
<td align="left"><img src="http://placehold.it/150x200"></td>
<td align="left"> T-shirt</td>
<td align="left">$66.00</td>
<td align="left"><input type="number" data-price="65" min="0" max="50" step="1" value="0" onChange="calculateTotal(this.form)"></td>
</tr>
<tr>
<td align="left"><img src="http://placehold.it/150x200"></td>
<td align="left"> Bag</td>
<td align="left">$120.00</td>
<td align="left"><input type="number" data-price="120" min="0" max="50" step="1" value="0" onChange="calculateTotal(this.form)"></td>
</tr>
<tr>
<td></td>
<td></td>
<td>TOTAL:</td>
<td align="right"><input type="text" name="total" size="6" onFocus="this.form.elements[0].focus()"></td>
</tr>
</table>
</form>
</div>
You have a typo in the sample code.
item_price = form_field.dataset.pric);
should probably be
item_price = form_field.dataset.price;
Apart from that, NaN is caused by the fact that you're also taking into account the value of the 'total' field when you run the function calculateTotal(). But that field does not have a data-price attribute so you're multiplying undefined with a number, resulting in NaN.
You need to add an extra check if there is a 'data-price' attribute:
function calculateTotal(frm) {
var order_total = 0;
for (var i=0; i < frm.elements.length; ++i) {
form_field = frm.elements[i];
if(typeof(form_field.dataset.price) != 'undefined') {
item_price = form_field.dataset.price;
item_quantity = form_field.value;
if (item_quantity >= 0) {
order_total += item_quantity * item_price;
}
}
}
frm.total.value = round_decimals(order_total, 2);
}
I could really your help! I need to sum a dynamic amount of textboxes but my JavaScript knowledge is way to week to accomplish this. Anyone could help me out? I want the function to print the sum in the p-tag named inptSum.
Here's a function and the html code:
function InputSum() {
...
}
<table id="tbl">
<tbody>
<tr>
<td align="right">
<span>June</span>
</td>
<td>
<input name="month_0" type="text" value="0" id="month_0" onchange="InputSum()" />
</td>
</tr>
<tr>
<td align="right">
<span>July</span>
</td>
<td>
<input name="month_1" type="text" value="0" id="month_1" onchange="InputSum()" />
</td>
</tr>
<tr>
<td align="right">
<span>August</span>
</td>
<td>
<input name="month_2" type="text" value="0" id="month_2" onchange="InputSum()" />
</td>
</tr>
<tr>
<td align="right">
<span>September</span>
</td>
<td>
<input name="month_3" type="text" value="0" id="month_3" onchange="InputSum()" />
</td>
</tr>
</tbody>
</table>
<p id="inputSum"></p>
function InputSum() {
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
if(inputs[i].id.indexOf("month_") == 0)
alert(inputs[i].value);
}
}
With a little jQuery, you could do it quite easily, using the attribute starts with selector. We then loop over them, parses their values into integers and sum them up. Something like this:
function InputSum() {
var sum = 0;
$('input[id^="month_"]').each(function () {
sum += parseInt($(this).val(), 10);
});
$("#inputSum").text(sum);
}
You could even get rid of the onchange attributes on each input if you modify the code to something like this:
$(function () {
var elms = $('input[id^="month_"]');
elms.change(function() {
var sum = 0;
elms.each(function () {
sum += parseInt($(this).val(), 10);
});
$("#inputSum").text(sum);
});
});
function InputSum() {
var month_0=document.getElementById("month_0").value;// get value from textbox
var month_1=document.getElementById("month_1").value;
var month_2=document.getElementById("month_2").value;
var month_3=document.getElementById("month_3").value;
// check number Can be omitted the
alert(month_0+month_1+month_2+month_3);//show result
}