Summing up input values - javascript

I am trying to use jquery to iterate through all '.invoice-lines' and generate a total by summing up all values in the '.amount-input' div.
AJAX dynamically generates the default values in '.amount-input' which can be manually changed by the user. I have been trying to create a function so that every time new data comes in using AJAX, a call will be made to the function updateTotal(), which iterates through all the non-empty 'amount-input' values and recalculates the total. I have been having a really tough time accomplishing this, and I would greatly appreciate any help.
JQuery - This is my jquery so far (pseudo code)
function updateTotal(){
var total=0;
for(i=0; i < $('.invoice-line').length; i++){
if($('.amount-input').eq(i).val() != empty)){
total += $('.amount-input').eq(i).val();
}
}
$('.total').val("$" + total);
}
Markup
<?
for(i=0; i < 25; i++){
echo' <div class="invoice-line">
<div class="prod-id-cell"><input type="text" class="prod-id-input"></div>
<div class="amount-cell"><input class="amount-input" type="text" /></div>
</div>';
}
?>
<div class="total">$0.00</div>

Make sure you cache the jQuery selection, otherwise you are doing 50 DOM traversals instead of 1:
var total=0, amounts = $('.amount-input'), len = amounts.length;
for(var i=0; i < len; i++){
total += +amounts[i].value;
}
Use the unary plus operator to convert the cell value from a string to a number. +"" will give you zero, so you don't need to check if the cell is empty, though you may want to check isNaN when validating the input.
Also, use val for input elements, but text for divs or spans.
$('.total').text("$" + total);

The basic syntax in pure JS is as follows:
var inputs = document.getElementsByClassName("amount-input");
var total = 0;
inputs.forEach(function (input) {
total += value;
});
The idea is that you get a collection of all the inputs in which you are interested, and then sum up the values using an external variable. If you wanted to expand this to include other inputs then you could use document.querySelectorAll("") with a CSS query selector to get the collection. (This is the same as the jQuery $("") selection syntax.)

Something like this should work:
function updateTotal() {
var total = 0;
$('.invoice-line').each(function (i, elem) {
total += parseFloat($(elem).find('.amount-input').val(), 10) || 0;
});
$('.total').val("$" + total);
}

You can use the change event to update the total amount everytime an input element is individually updated. Below is a simple example:
HTML:
<input class="invoice" type="text" value="0" />
<input class="invoice" type="text" value="0" />
<input class="invoice" type="text" value="0" />
<div id="total">0</div>
Javascript:
$('.invoice').change(function() {
var total = 0;
$('.invoice').each(function() {
total += parseFloat($(this).val());
});
$('#total').text(total);
});
You can see it working in this jsfiddle.

Shortly after posting, I was able to come up with my own solution as follows:
function updateTotal(){
var total=0;
for(i=0; i < $('.invoice-line').size(); i++){
currentAmount = Number($('.amount-input').eq(i).val().replace(/[^0-9\.]+/g,""));
total += currentAmount;
}
$('.total-number').text("$" + total.toFixed(2));
}

Related

How to sum input numbers and database values in javascript

I have appended data and I print each data price in hidden input. Now I want to sum these prices with input numbers as quantity in order to get the total amount but nothing prints.
Code
javascript
success:function(data) {
//append data to my view
data.forEach(function(row) {
var $meto = '';
$meto += '<div class="col-md-3 mt-2">'+
'<div class="card">'+
'<div class="card-body">'+
'<img src="{{url("images")}}/'+row['photo']+'" class="menuimg img-fluid" alt="image">'+
'<p>'+row['name']+'</p>'+
'<input type="number" name="qty[]" class="qty form-control">'+
'<input type="hidden" class="price" value="'+row['price']+'" />'+
'</div>'+
'</div>'+
'</div>';
$('.here').append($meto);
//sum prices
$('.qty').on('keyup',function(){
var qty = $('.qty').val();
var price = $('.price').val();
$("#total").html(qty*price);
});
});
}
html
<div class="col-md-10">
<div class="row here"></div>
</div>
<p>Total: <span id="total"></span></p>
Explanation
I have filled 2 of my items with quantities 1 & 3 there is hidden input under each of them that holds their prices (as this sample they are 5000 & 16000)
Basically I should have something like this in my total div:
1*5000 = 5000
3*16000 = 48000
Total = 53000
However, it only gets my first input and ignores the rest. Any ideas?
You are not adding all items prices. You need to loop through all items and calculate total.
Note: keep this after your forEach statement.
Try this:
$('.qty').on('keyup',function() {
var quantities = $('.qty');
var prices = $('.price');
var total = 0;
$.each(quantities, (index, qty) => {
total += parseInt($(qty).val() || 0) * parseFloat($(prices[index]).val() || 0)
});
$("#total").html(total);
});
I think the problem is, that you cant get the value from multiple elements with the function ".val()". You only can get multiple values from one element.
You need another function to do want you want to achieve.
You should have a look here: Stackoverflow Question
Anway - you should not save prices into hidden html elements in production environments.
Iterate over the parent element to find the exact price and quantity for each element.
$('.qty').on('keyup',function(){
var total = 0;
$('.card-body').each(function(){
var qty = parseFloat($(this).find('.qty').val());
if (!qty) return;
var price = parseFloat($(this).find('.price').val());
total += (qty * price);
});
$("#total").html(total);
});
Attaching a Fiddle
I don't know jQuery, though I can help you with vanilla JS.
The problem here is:
$('.qty').on('keyup',function(){
var qty = $('.qty').val();
var price = $('.price').val();
$("#total").html(qty*price);
});
This is setting an event listener only for the first .qty, even though there are many of them. So, you should select and iterate over them all, just like you did with the data:
let qtyNodes = document.querySelectorAll('.qty');
let priceNodes = document.querySelectorAll('.price');
let outputNode = document.querySelector('#total');
let sum = 0;
qtyNodes.forEach(function(qtyNode) { // Set event listener to every single qty node
qtyNode.addEventListener('keyup', function() {
qtyNodes.forEach((qtyNode, index) => { // Calculate final price, using each meal price per quantity value.
sum = qtyNode.value * priceNodes[index].value;
})
});
})
outputNode.innerHTML = `${sum}`;
It is important that you keep the arrays-like (qtyNodes and priceNodes) outside the given loop, as it will be accessing the DOM at each iteration and will demand too much performance. Placing it outside, you will access the DOM only one time.
Also, note that: you should be using "input" event, as opposed to "keyup". Input events will fire as soon as the user insert any data, just like a combination of "keyup" and "keydown".

How to calculate the total value of a dynamic number of fields using javascript?

My page shows some forms with content loaded from a database. Every row will get his own <input>. The ID of this input is equal for every row, except for the number that is attached to it, to make it unique. To make it more clear; this is how the form looks like when it loads 3 rows from the database:
<form>
<input id="Amount1" value="<?php echo $databaseValue; ?>" >
<input id="Amount2" value="<?php echo $databaseValue; ?>" >
<input id="Amount3" value="<?php echo $databaseValue; ?>" >
<input type="hidden" name="numberOfRows">
<input id="finalResult">
</form>
This is all done with the mysqli_array function. The value of numberOfRows is based on numRows function.
What I'd like to achieve is that javascript calculates the value of each existing input and put the result in finalResult, regardless the number of forms (because this may vary). If I make some changes to one of the values, the finalResult should update real-time.
What I've tried so far:
formnum contains the number of fields.
var a is created at the beginning, starting at 0. Inside it's function I create an ID, matching the fields on the page. All fields are named "Amount" + number. If this number equals the number of fields, the function will stop. This way the script won't be looking for fields that doesn't excist.
Then it gets the value of this field and adds the value to var b. var b is just created to store the value temporary, untill the function's over.
At the end the total is divided to 15. This is something extra I need. Nothing special on this line.
My code:
<script type='text/javascript'>
$(document).ready(function(){
var formnum = $("#numberOfRows").val();
var a;
var b = 0;
var formname = '#Amount';
for (a = 0; a < formnum; a++) {
var complete = formname.concat(a);
var completeContent = $(complete).val();
b = b + completeContent;
};
b = b.toFixed(2);
});
$(document).mousemove(function(event){
var formula_finalResult = b / 15;
var total_finalResult = Math.floor(formula_finalResult);
$("#finalResult").val(total_finalResult);
});
</script>
This doesn't do anything. It doesn't change the value. What's going wrong?
Make it simple:
$(function(){
var sum = 0;
// Selector to select all input whose id starts with Amount
$("input[id*='Amount']").each(function(){
sum += +$(this).val(); // Parsing as int and adding it to sum
});
$("#finalResult").val(Math.floor(sum/15)); // Storing the values
})
Assuming that all of the fields always have Amount at the beginning of their id attribute, you could use jQuery's ID selector to achieve this, without the need for any of the internal counters, etc.
I'm not entirely sure why you need to hook into the mousemove event, since the data should never change on the page (since it's being generated by PHP when the page is first loaded). The following code should achieve what you're looking for:
$(function() {
var total = 0;
$('input[id*="Amount"]').each(function() { total+= parseFloat( $(this).val() ); });
$('#finalResult').val( Math.floor( total / 15 ) );
});
Your code has an error Uncaught ReferenceError: b is not defined
see it in action here: http://jsfiddle.net/ca9vascj/
There's no reason to bring the mousemove event into this, I'm not even sure what that was needed for.
Like the above answers, here's a much simplified version. But instead of a partial ID selection, let's just give the form an ID, and then give all the needed elements inside that form a class that we can select by. We also no longer need to have the numberOfRows form element.
<form id="theForm">
<input class="formAmmount" value="5" />
<input class="formAmmount" value="10" />
<input class="formAmmount" value="27.5" />
<input class="formAmmount" value="4" />
<input class="formAmmount" value="9" />
<hr />
<input id="finalResult" />
</form>
And then our jQuery code can be reduced to this:
$(function(){
var total = 0;
$("#theForm .formAmmount").each(function(){
total += parseFloat(this.value, 10);
});
var final = Math.floor(total.toFixed(2) / 15);
$("#finalResult").val(final);
});
See it in action here: http://jsfiddle.net/ca9vascj/1/
You dont'need jQuery. The simplest way to do this is document.getElementsByTagName:
var inputs = document.getElementById('my-form').getElementsByTagName('input')
That's it. inputs.length will always get an actual count of inputs in your form. That's because getElementsByTagName() returns a NodeList object, containing a live view of the matching elements. This object is mutable; it will change in response to DOM mutations.
So if you need to get sum from all of the inputs:
function sum() {
var result = 0;
[].slice.call(inputs).forEach(function(input){
result += parseFloat(input.value)
});
return result;
}
If you are able to change the generated Html-Source I would suggest to give a new class to your InputElements.
<input id="Amount1" class="ElementToCount" value="<?php echo $databaseValue; ?>" >
Then you can calculate like that
var getSumOfElements = function() {
var Elements = $('.ElementToCount')
var sum=0
if (Elements && Elements.length>0) {
for (var i=0; i<Elements.length; i++) {
sum += Elements[i].val();
}
}
return sum
}
And to update the field you could register to the 'change'-Event
$('.ElementToCount).on('change', function() {
$('#finalResult').val(getSumOfElements());
})

Loop through each child in a div with data-attribute

I have multiple <div>s, based on a <select>, where each one contains multiple <input>s and sometimes a disabled <select> with a fixed value. Now I'm trying to loop through each of the divs and put all inputs and select values into an array and push that array into the "master" array.
However this seems not to work to well.
I feel like I'm already close but yet so far. :(
var dummy = [];
for(var i = 1; i <= toSend.count; i++){
var temp = [];
$("div[data-row="+i+"]").children('input, select').each(function(){
temp.push( $(this).val() );
});
dummy.push(temp);
};
console.log(dummy);
toSend.count is the counting of how many div's with data-row exist.
The HTML looks like this :
<div id="container">
<div data-row="1">
<input type="text"/>
<input type="text"/>
</div>
<div data-row="2">
<input type="text"/>
<input type="text"/>
</div>
</div>
Aaah, nevermind this was my own stupidity! I'm generating the div's via AJAX
and I copy pasted myself an error.
All div's had data-row=1, no wonder it packed all in one array >.<
(Edit: pays to read the code more completely)
Since the toSend variable is just the DIVs with a data-row attribute, no need to loop over toSend to find the DIVs:
var dummy = [];
$("#container div[data-row]").each(function() {
var temp = [];
$(this).children("input, select").each(function() {
temp.push(this.value);
});
dummy.push(temp);
});
After this, you might not even need the toSend variable at all.
Brief code for what you want to achieve.
$("div[data-row="+i+"]")each(function(){
$(this).children('input, select').each(function(){
console.log( $(this).val());
console.log("Child Change");
});
console.log("Div Change");
});
.each function from jquery is not syncrounious, use for instead.
var $tmp;
for(var i = 1; i <= toSend.count; i++)
{
$tmp = $("div[data-row="+i+"]").children('input, select');
for(var ii = 1,len = $tmp.length; ii <= len; ii++){
console.log( $tmp.eq(ii).val());
};
console.log("New line #" + i);
};

Javascript: Add or Subtract to running total

I am very new to Javascript, only a few weeks, and am stuck on something I assume to be simple. I have searched for hours, but cant find an example to point me in the right direction. Im basically wanting to create a simple "Running Balance" calculator. One textbox has the input (added by using add button) and the other textbox has the output. The output should change depending on what I put into the input textbox and keep adding to the value in the output textbox.
Here is my code in Javascript:
var accountBalance = 0;
function addBalance()
{
var inPrice = document.getElementById("inAmt").value
total = parseInt(inPrice += accountBalance);
document.getElementById("outBalance").value = total;
}
and the HTML:
<form id="form2" name="form2" method="post" action="">
<p>
Enter an amount:
<input type="text" name="inAmt" id="inAmt" />
</p>
<p>
Display Balance::
<input type="text" name="outBalance" id="outBalance" />
</p>
</form>
<p><input type="button" id="addBal" value="Add the amount to the balance" onclick="addBalance()"/></p>
I have a feeling my total variable in my function is what I am screwing up. Thanks in advance for the help!!
This part doesn’t really make sense:
total = parseInt(inPrice += accountBalance);
It takes accountBalance (0), appends it to inPrice (since inPrice is a string), stores the value back in inPrice, parses the result as an integer, and sets total to that integer. What you seem to need is pretty much the reverse, that is:
Parse inPrice so that it’s a number instead of a string
Add it to accountBalance and store the result in accountBalance
Put the new accountBalance in total (or just use accountBalance in the first place)
Or, in JavaScript:
var accountBalance = 0;
function addBalance() {
var inPrice = parseInt(document.getElementById("inAmt").value, 10);
accountBalance += inPrice;
document.getElementById("outBalance").value = accountBalance;
}
You've confused a few variables - the problem was you were never reading the current balance and you were resetting the total variable every time (aside from mixing ints and strings). Here is a version without the total variable:
function addBalance()
{
var inPrice = document.getElementById("inAmt").value
accountBalance += parseInt(inPrice, 10);
document.getElementById("outBalance").value = accountBalance;
}
See it here: http://jsfiddle.net/fdureo1s/

Using JavaScript to show total of an order

I have a table of items available for purchases which I am displaying on the site. I am using mysql to fetch all the items and display them in a table. Among others, the table contains this:
<input type="hidden" name="price" id="price'.$id.'"> //id is one part of MySQL query results
<input type="text" name="count_'.$id.'">
All this is displayed for around 200 items with ID being not completely in sequence (I found some JavaScript code that used for (i = 0; i < rows.length; i++) {}, however, with my IDs not being in a sequence, this is not a good option for me).
I would like to display a total of an order using JavaScript and I am not experienced when it comes to JS. I would be very thankful for your advices.
You coul duse jQuery:
function orderTotal()
{
var total=0;
$('input[name="price"]').each(function(){
var price = parseFloat($(this).val());
var amount = parseFloat($('input[name="count_'+$(this).attr('name').substring(5)+'"]').val());
total += price+amount;
});
return total;
}
Consider adding a class to each element that you want to count and see the answer below on stackoverflow. You should be able to have a counter for each occurrence of the class and show this variable in the html
How to getElementByClass instead of GetElementById with Javascript?
<div class="item"> ... <your inputs> ... </div>
I suggest you wrap them in another element, lets use div. Add a class to that, lets say moneyline
<div class="moneyline">
<input class="price" type="hidden" name="price" id="price'.$id.'"> //id is one part of MySQL query results
<input class="quantity" type="text" name="count_'.$id.'">
</div>
Im going to give the example with jQuery, and some button to trigger it:
$('#someButton').on('click', function(){
var total = 0;
$('.moneyline').each(function(){
var price = parseInt($(this).find('.price'), 10);
var quantity = parseInt($(this).find('.quantity'), 10);
total+= quantity*price;
});
alert( total );
});

Categories