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".
Related
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());
})
I have 2 div's.
One is SHIPPING and another is TOTAL PRICE.
<div id="tt_shipping_rate_basket">$0.00</div> = SHIPPING
<div class="op_col5_3" align="right" id="tt_total_basket">$897.00</div> = TOTAL PRICE
Also there are 4 inputs for SHIPPING, each adds it's own price in the shipping div..
for example:
input 1 = 10$
input 2 = 20$
so when choosing an input the value in the #tt_shipping_rate_basket is changing ajax to the value of the input... this works great...
The problem is, I do not want 2 divs (one for shipping and one for total price)...
I just want ONE div, called Total Price, and when I choose an input, the value should ADD&CHANGE to the #tt_total_basket instead of tt_shipping_rate_basket...
What I'm trying to do is, GET the value of SHIPPING field (which is ajax populated), GET the value of TOTAL PRICE field, then just ADD shipping to Total Price...
here is what I tried to write but it doesn't seem to work, sorry I'm not to good at programming..
function plus() {
var spTotal = document.getElementById("tt_total_basket");
var spShip = document.getElementById("tt_shipping_rate_basket");
spTotal = spTotal.innerHTML = +spShip;
}
spTotal is the TOTAL PRICE
spShip is the Shipping Price
The result should be (spTotal = spTotal.value + spShip.value)..
Can somebody please help?
Untested, but you get the idea:
var spTotal = document.getElementById("tt_total_basket").innerHTML.replace('$', '');
var spShip = document.getElementById("tt_shipping_rate_basket").innerHTML.replace('$', '');
spTotal = parseFloat(spTotal) + parseFloat(spShip);
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 );
});
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));
}
I'm having an issue trying to get an accurate running total for my calculations. When you enter numbers into the input field I get an accurate total for that line item, but the grand total comes out to a higher number. Note that this is a dynamic form and that the id's will change depending on how many form fields I have added to the form. Also, I have it set to make the calculations onKeyUp for each input field instead of a calculate button.
The code that calculates a single item is this:
function calcLineItem(id) {
var id = $(id).attr("id");
var Item1 = $("#Item1" + id).val();
var Item2 = $("#Item2" + id).val();
var Item3 = $("#Item3" + id).val();
function calcTotal(Item1, Item2, Item3){
var total;
total = Math.round((Item1 * Item2) * Item3);
return total;
}
$("#total" + id).text(calcTotal(Item1, Item2, Item3));
calcAllFields();
}
This will give me the total of this particular input field. The function at the end, calcAllFields(), is supposed to do the calculations for all items in my form to give me the grand total of all input fields:
function calcAllFields(id) {
var id = $(id).attr("id");
$('#target1').text($("#total" + id).map(function() {
var currentValue = parseFloat(document.getElementById("currentTotal").value);
var newValue = parseFloat($("#total" + id).text());
var newTotal = currentValue + newValue;
document.getElementById("currentTotal").value = newTotal;
return newTotal;
}).get().join());
}
The variable currentTotal is getting its value from a hidden field on my form:
<input type="hidden" id="currentTotal" value="0">
As I enter numbers a field the calculation for that line will be accurate, but the grand total will be inaccurate because the value for currentTotal will continue to increment with every key stroke I make in the input field. Any ideas on how to avoid this from happening?
UPDATE: An example of what the form input fields would look like:
<tr id="row1">
<td><input type="text" id="field_1 onKeyUp="calcLineItem("#row1")></td>
<td><input type="text" id="field_2 onKeyUp="calcLineItem("#row1")></td>
</tr>
I hope this helps.
It appears that you are never removing the previous total when you calculate the grand total. For instance,
I start out with a grand total of 0. I change ID1 and get a total of 700. Now my grand total is 700. However, with your code, if I change ID1 again and set to 680, my grand total will be 1380 (700 + 680).
You should probably start with 0 and loop through all the totals again on calcGrandTotal() in order to pick up all client changes or track the previous total before you calculate the new line item total so that you can properly deduct it from the grand total. Also, if you have a lot of line items adding up to your grand total, you may consider only calling the calcGrandTotal() when on of your textboxes loses focus, else you could have a lot of JS calculations going on in the background which will interfere with animations and overall responsiveness of your site.
How's this?
function calcAllFields(id) {
var id = $(id).attr("id");
document.getElementById("currentTotal").value = 0; //reset the total as it will be caluclated next
$('#target1').text($("#total" + id).map(function() {
var currentValue = parseFloat(document.getElementById("currentTotal").value);
var newValue = parseFloat($("#total" + id).text());
var newTotal = currentValue + newValue;
document.getElementById("currentTotal").value = newTotal;
return newTotal;
}).get().join());
}
I would go about it slightly differently. You will need a function that returns the total for a row (Looks like calcLineItem pretty much does it, just remove the calcAlffields call. Add a class like calcrow to each row that needs to be totaled. Than just do something like this
function updateTotal () {
total = 0;
$.each($(".calcrow"), function(index, value) {
total += calcRow($(value).attr("id"));
});
$("#currentTotal").value(total);
}
Another if you don't want to calc each line again (it looked like you were storing a row total somewhere) have the row update function update the row total and than call this updateTotal.
function updateTotal () {
total = 0;
$.each($(".rowtotal"), function(index, value) {
total += $(value).attr("id");
});
$("#currentTotal").value(total);
}