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);
}
Related
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".
Here is my code:
function credit() {
//storing value of grandTotal in txtGrandTotal.
var txtGrandTotal = $("#txtGraTot").val();
//here resetting value of grandTotal to 0.00
var txtGraTotal = document.getElementById('txtGraTot').value = '0.00';
//entering deduction amount
var txtCredit = document.getElementById('txtCreditAmt').value;
//subtracting values
var lclRes = (parseFloat(txtGrandTotal) - parseFloat(txtCredit)).toFixed(2);
//again storing values to Textbox GrandTotal
$("#txtGraTot").val(lclRes);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="txtCreditAmt" oninput="credit();">
<input type="text" id="txtGraTot">
The result is not as I expected. If I enter 3 in txtCredit input box then value deducting from the Grand Total is 100 - 3 = 97. But if I enter the dot(.) again the result is 97 - . = 94. Why it is happening?
The problem is that you are not storing the original value of grand total in a separate variable. So, when the input event fires, it updates the grand total every time. Here's what is going on:
Grand total Credit
Original state: 100 ___
Press 3 : 97 3 oninput invoked, grand total = (100 - 3)
Press . : 94 3. oninput invoked, grand total = (97 - 3.)
The quick and easy (but not the ideal) solution is to store the original value of grand total in a separate variable, and use that every time input event fires. My solution is to store that value in a data-total attribute ($("#txtGraTot").data("total")) but you can have something else there. Just make sure that you are subtracting from original value, and not from the current value in the text box.
// Save the original value of grand total in an attribute for future use.
if ($("#txtGraTot").data("total") === undefined) {
$("#txtGraTot").data("total", txtGrandTotal);
} else {
// else, get the original grand total value.
txtGrandTotal = $("#txtGraTot").data("total");
}
function credit(){
//storing value of grandTotal in txtGrandTotal.
var txtGrandTotal = $("#txtGraTot").val();
// Save the original value of grand total in an attribute for future use.
if ($("#txtGraTot").data("total") === undefined) {
$("#txtGraTot").data("total", txtGrandTotal);
} else {
// else, get the original grand total value.
txtGrandTotal = $("#txtGraTot").data("total");
}
//here resetting value of grandTotal to 0.00
var txtGraTotal = document.getElementById('txtGraTot').value = '0.00';
//entering deduction amount
var txtCredit = document.getElementById('txtCreditAmt').value;
//subtracting values
var lclRes = (parseFloat(txtGrandTotal) - parseFloat(txtCredit)).toFixed(2);
//again storing values to Textbox GrandTotal
$("#txtGraTot").val(lclRes);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="text" id="txtCreditAmt" oninput="credit();">
<br>
<input type="text" id="txtGraTot">
I'm not sure if this is what you want, but that should make sense.
Edited
Add the feature that after you press the enter button, calculate and reset txtCreditAmt.
function credit(){
//subtracting values
var lclRes = (parseFloat($("#txtGraTot").val()) - parseFloat($("#txtCreditAmt").val())).toFixed(2);
//again storing values to Textbox GrandTotal
$("#txtGraTot").val(lclRes);
}
$('#txtCreditAmt').keypress(function(e){
if (e.keyCode == 13) {
credit();
$("#txtCreditAmt").val('');
return false;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="txtCreditAmt" onblur="credit();">
<input type="text" id="txtGraTot" value="100">
The Discount field does not register
(discount is supposed to subtract from Grand Total)(check discount sample)
check the the jsfiddle click here
I want it to act like this picture. (with the discount being manually inputed) http://i.dailymail.co.uk/i/pix/2013/02/07/article-2275089-17694138000005DC-460_634x497.jpg
Javascript
function recordToFilename() {
var input = document.getElementById('discountvalue'),
discount12 = input.value;
Change your button to
<input type="button" onclick="recordToFilename();" value="Submit Discount" />
And function
function recordToFilename() {
var input = document.getElementById('discount'),
discount12 = input.value;
alert (discount12);
}
you have 2 id="discount". Change one of the id and the there is no problem to register the input value to discount12.
Put this line document.getElementById('discounts').innerHTML = "<strong>Discount </strong>: $" + (salesTotal * 0.14 + salesTotal - discount12).toFixed(2);
in your recordToFilename() method and make sure your variable is chage to discount12 not discount
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'm trying to have a label which contains a balance change when a person enters a charge amount. So assume something like...
<table>
<tr>
<td class="remainingBudget"></td>
.
.
.
...and then....
<form>
<table>
<tr>
<td><input class="percentCommitment"></td>
<td><input class="totalAmount"></td>
.
.
.
The user will never touch the totalAmount form input, only percentCommitment, which will calculate totalAmount based on another value, which we don't need to worry about. I have the totalAmount input populating automatically on the keydown event of percentCommitment with something like this...
$(".percentCommitment").keyup(function() {
var commit = caluculatePercentCommitment() || 0;
var salary = getSalary();
var amount;
if (commit > 0 && salary > 0) {
ttl = (salary * commit) / 100;
} else {
amount = 0.00;
}
$(this).parent().find('.amountCommitment').val(amount);
});
This part is working fine and the total amount calculates correctly in real time as the person changes the percentCommitment value. This works because the value I multiply the percent commitment by, the person's annual salary, is static. It doesn't change. So if the person enters 1, 1% of salary is calculated and displayed. If the user then tacks on a 2, 12% is calculated from the same original salary, and this is exactly what I want to happen.
The problem comes with calculating the remaining budget in real time. Subtracting totalAmount from remainingBudget poses a problem, because if the user does the same thing, enters 1, then my jQuery does newRemainingBudget = remainingBudget - (0.01 * salary), which is fine, but then if they tack on a 2 I'm doing newNewRemainingBudget = newRemainingBudget - (0.12 * salary), which isn't what I want. I want all changes to be computed from the original remaining budget.
I was trying to do something like this...
$(".totalAmount").change(function (event) {
var remain = $(".remainingBudget").text();
remain = formatDecimalInput(remain);
var enter = $(".totalAmount).val();
enter = formatDecimalInput(enter);
if (enter <= remain) {
$(".remainingBudget")text((remain-enter).formatCurrency());
}
else {
// Do nothing
event.preventDefault();
}
});
You have to have a place on the screen that holds the total budget amount and calculate remaining amount using it plus the other fields. Don't use a field in this way when you are replacing.
remainingBudget = totalBudget - (0.01 * salary)
Note: You can have a hidden form field to hold the total if you want.