Javascript addition giving me NaN - javascript

I have a Javascript code as written below. Everything is working fine except the fact the net value that is the grand total of addition of all the total values, is coming as NaN. I have used parseFloat() but still the result is NaN. But I am getting the all the total values.
Any help is welcome.
window.onkeyup=function() {
var items = document.querySelectorAll(".item");
var itemsArray = Array.prototype.slice.call(items,0);
var unit, rate, total, net, tax, margin, rateamount = 0;
itemsArray.forEach(function(el){
unit = el.querySelector('input[name="unit[]"]').value;
rate = el.querySelector('input[name="rate[]"]').value;
tax = el.querySelector('input[name="tax[]"]').value;
margin = el.querySelector('input[name="margin[]"]').value;
el.querySelector('input[id="marginrate[]"]').options[el.querySelector('input[id="marginrate[]"]').selectedIndex].text;
var rateMargin =el.querySelector('[name="marginrate[]"]').selectedIndex;
if (rateMargin==1) {rateamount=margin/100}
if (rateMargin==0) {rateamount=margin}
total = (parseFloat(unit * rate) + parseFloat(rateamount))-parseFloat(tax/100);
alert(total);
el.querySelector('input[name="total[]"]').value = total;
net+= parseFloat(total);
});
document.getElementById('net').value=net;
}

You never initialized net, so when you do net += parseFloat(total); you're adding a number to undefined, which results in NaN. You need to initialize it to 0.
You also should be calling parseFloat on the values that are read from the inputs, not on the results of arithmetic operations (they always return numbers, you don't need to parse them).
window.onkeyup = function() {
var items = document.querySelectorAll(".item");
var itemsArray = Array.prototype.slice.call(items, 0);
var unit, rate, total, net = 0, tax, margin, rateamount = 0;
itemsArray.forEach(function(el) {
unit = el.querySelector('input[name="unit[]"]').value;
rate = el.querySelector('input[name="rate[]"]').value;
tax = el.querySelector('input[name="tax[]"]').value;
margin = el.querySelector('input[name="margin[]"]').value;
el.querySelector('input[id="marginrate[]"]').options[el.querySelector('input[id="marginrate[]"]').selectedIndex].text;
var rateMargin = el.querySelector('[name="marginrate[]"]').selectedIndex;
if (rateMargin == 1) {
rateamount = margin / 100
} else if (rateMargin == 0) {
rateamount = margin
}
total = (parseFloat(unit) * parseFloat(rate) + parseFloat(rateamount)) - parseFloat(tax) / 100;
alert(total);
el.querySelector('input[name="total[]"]').value = total;
net += total;
});
document.getElementById('net').value = net;
}

Related

No clue what's wrong with my code [duplicate]

This question already has an answer here:
Javascript calculator keeps concatenating calculation results with first number entered for next calculation
(1 answer)
Closed 4 years ago.
I'm writing a program that takes two numbers, a subtotal and tax rate, and prints the sales tax and grand total. However, I've run into multiple problems writing it, so I've tried working backwards and dumbing it down to simply adding two numbers. Instead of adding the numbers, however, it is simply printing the two numbers side by side. Can anyone tell me what's wrong with my code?
https://codepen.io/anon/pen/jvNZox
HTML:
var subtotal = document.getElementById("subtotal");
var taxRate = document.getElementById("tax-rate");
var salesTax = document.getElementById("sales-tax");
var total = document.getElementById("total");
subtotal.addEventListener("input", calc);
taxRate.addEventListener("input", calc);
function calc()
{
var sub = (subtotal.value) || 0;
var tax = (taxRate.value) || 0;
total.innerHTML = sub + tax;
}
JS:
var subtotal = document.getElementById("subtotal");
var taxRate = document.getElementById("tax-rate");
var salesTax = document.getElementById("sales-tax");
var total = document.getElementById("total");
subtotal.addEventListener("input", calc);
taxRate.addEventListener("input", calc);
function calc()
{
var sub = (subtotal.value) || 0;
var tax = (taxRate.value) || 0;
total.innerHTML = sub + tax;
}
EDIT: My bad, forgot to add parseFloat before my value checks. Same problem still stands for when I go back to my original code:
var subtotal = document.getElementById("subtotal");
var taxRate = document.getElementById("tax-rate");
var salesTax = document.getElementById("sales-tax");
var total = document.getElementById("total");
subtotal.addEventListener("input", calc);
taxRate.addEventListener("input", calc);
function calc()
{
var sub = parseFloat(subtotal.value) || 0;
var tax = parseFloat(taxRate.value) || 0;
salesTax.innerHTML = sub * (tax /100);
total = sub + salesTax.innerHTML;
}
You're bumping into the fact that the values are strings, and you can use + to concatenate strings as well as add up numbers.
Parse the number strings into actual Numbers first:
function calc()
{
var sub = parseFloat(subtotal.value || 0);
var tax = parseFloat(taxRate.value || 0);
total.innerHTML = sub + tax;
}
You need to take the numerical value of the strings by using an unary plus +, for example.
This approach has the advantage, if a nonconvertable string is supplied, a NaN value is taken as falsy value and together with logical OR ||, you get zero as default value.
var sub = +subtotal.value || 0;
var tax = +taxRate.value || 0;
JavaScript considers the values as two strings and thus combines them.
Do something like this:
var subtotal = document.getElementById("subtotal");
var taxRate = document.getElementById("tax-rate");
var total = document.getElementById("total");
subtotal.addEventListener("input", calc);
taxRate.addEventListener("input", calc);
function calc() {
var sub = Number(subtotal.value) || 0;
var tax = Number(taxRate.value) || 0;
total.innerHTML = sub + tax;
}
<p> Subtotal: <input id = "subtotal"></p>
<p> Tax Rate: <input id = "tax-rate"></p>
<p id = "total"></p>
Change the logic for addition to below as previously it was considering it as a JavaScript string and instead of summing it was concatenating it. Explicitly converting it to an integer/double will prevent this. '||' handles non-numeric data in text field.
var subtotal = document.getElementById("subtotal");
var taxRate = document.getElementById("tax-rate");
var salesTax = document.getElementById("sales-tax");
var total = document.getElementById("total");
subtotal.addEventListener("input", calc);
taxRate.addEventListener("input", calc);
function calc()
{
var sub = parseFloat(subtotal.value) || 0;
var tax = parseFloat(taxRate.value) || 0;
salesTax.innerHTML = sub * (tax /100);
total.innerHTML = sub + parseFloat(salesTax.innerHTML|| 0);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p> Subtotal: <input id = "subtotal"></p>
<p> Tax Rate: <input id = "tax-rate"></p>
Total: <p id = "total"></p>
Sales tax: <p id = "sales-tax"></p>
</body>
</html>
You need to cast string value to integer type. To do it you could use parseInt function:
total.innerHTML = parseInt(sub) + parseInt(tax);

Setting up Javascript order price minimum

I am trying to set up a way so that if my total cart's price is under $125, it will charge $125. I have googled multiple ways of getting the order minimum added but nothing works with how this code was set up. Please view the code below:
function Recalculate() {
var total = 0;
$.each(cart, function(index, item) {
var options = {};
if (item.o) $.each(item.o, function(opt_ind, opt_item) {
options[opt_item.name] = opt_item.value;
options[opt_item.id] = opt_item.value;
});
var width_ft = parseInt(options.width_ft);
if (!width_ft || isNaN(width_ft)) width_ft = 0;
var width_in = parseInt(options.width_in);
if (!width_in || isNaN(width_in)) width_in = 0;
var width = width_ft + width_in / 12;
var length_ft = parseInt(options.length_ft);
if (!length_ft || isNaN(length_ft)) length_ft = 0;
var length_in = parseInt(options.length_in);
if (!length_in || isNaN(length_in)) length_in = 0;
var sq = width * length;
var inshop = options.type_of_cleaning == 'In_Shop_Cleaning';
var base_price = 0;
var base_min = 0;
switch (item.p) {
case 'livingroom':
base_price = LIVING_ROOM;
break;
case 'stair':
base_price = STAIR;
break;
}
var i_total = sq * base_price;
if (i_total < base_min) i_total = base_min;
$('span.isize').eq(index).html('$' + i_total.toFixed(2));
total += i_total;
if (options.SCOTCHGARD == 'on') total += Math.min(sq * SCOTCHGARD, 25.00);
if (options.DECON == 'on') total += Math.min(sq * DECON, 25.00);
if (options.DA == 'on') total += Math.min(sq * DA, 25.00);
if (options.clean_or_buy == 'buy') total += i_total * NEW_PAD_TAX / 100;
});
return [total];
}
If you want to charge a minimum of $125, the simplest thing you could do is simply set the total to that minimum just before you return it. e.g.
if (total < 125) { total = 125; }
return total;
(Note that this is returning total not [total], as it is not clear to me why you want an array of a single value returned.)
Your question includes the phrase "...getting the order minimum added". That doesn't make sense to me, i.e. if the real total is $100, I doubt that you want to add $125 (to make $225 total), but rather you simply want to set the total to the minimum. If that is correct, but you do want to keep track of the extra that you add, then perhaps you could do the following, again right before you return from the function:
var extraForMinimum = 0;
if (total < 125) { extraForMinimum = 125 - total; }
return {total: total, extraForMinimum: extraForMinimum };
In this case, the function is returning an object that contains both the actual total (which could still be less than $125) as well as the extra cost that is required to bring the charge up to the minimum. If you are doing this, however, you might want to change the variable name from total to, say, subtotal or something else similar.

Finding average from input array with Javascript - not calculating correctly

I am trying to calculate the average of 3 values (each numbered from 1-10) that are selected by the user and then pass the results to an text input (for display as a graph).
It should be updating the new average every time one of the values is changed, but the averaging is not working correctly at all. I think that the loop is not resetting the values every time it runs- it's adding up the sum each time it runs, but not sure how to fix it.
Here is my code:
var sliders = $("#health1,#health2,#health3");
var elmt = [];
$(sliders).each(function () {
elmt.push($(this).attr('value'));
$("#health1,#health2,#health3").change(function () {
var sum = 0;
averageRisk();
});
});
function averageRisk() {
var sum = 0;
for (var i = 0; i < elmt.length; i++) {
sum += parseInt(elmt[i], 10);
}
var avg = sum / elmt.length;
document.getElementById('healthLevel').value = +avg;
elmt.push($(sliders).attr('value'));
$('#healthLevel').val(avg).trigger('change');
console.log("Sum: " + sum);
console.log("Average: " + avg);
}
Here is an example:
http://jsfiddle.net/pixelmix/783cfmnv/
Not sure but seems like a lot of extra work going. Main issue was you were building array of initial values and not getting the values each time they changed. That first .each got all the slider values and added them to elmt and continued to push new values on to after every change instead of just getting the current values every time. Did you want to accumulate all values over time?
Fiddle: http://jsfiddle.net/AtheistP3ace/783cfmnv/6/
$("#health1,#health2,#health3").on('change', function () {
averageRisk();
});
function averageRisk() {
var sum = 0;
var elmt = $("#health1,#health2,#health3");
for (var i = 0; i < elmt.length; i++) {
sum += parseInt(elmt[i].value, 10); //don't forget to add the base
}
var avg = sum / elmt.length;
document.getElementById('healthLevel').value = +avg;
$('#healthLevel').val(avg).trigger('change');
console.log("Sum: " + sum);
console.log("Average: " + avg);
}
And as pointed out if you want to ignore updating things when the sum is NaN you can do this:
function averageRisk() {
var sum = 0;
var elmt = $("#health1,#health2,#health3");
for (var i = 0; i < elmt.length; i++) {
sum += parseInt(elmt[i].value, 10); //don't forget to add the base
}
if (isNaN(sum)) {
return false;
}
var avg = sum / elmt.length;
document.getElementById('healthLevel').value = +avg;
$('#healthLevel').val(avg).trigger('change');
console.log("Sum: " + sum);
console.log("Average: " + avg);
}
The problem is that you fill the elmt array at page loading.
When user changes the values, you do not refresh the elmt array. So the array used to compute the average is always the same, empty.
You have to recover the input values each time they are modified.
function averageRisk() {
var sum = 0;
// Re make the loop for getting all inputs values
$(sliders).each(function() {
var value = parseInt($(this).val(), 10);
sum += value;
});
var avg = sum/$(sliders).length;
$('#healthLevel').val(avg);
}
Working example : http://jsfiddle.net/783cfmnv/7/
PS : You can use the css class healthInput to select your inputs. If you add later other fields, you will not have to add the new input id to your jQuery selector.
I did this work, check it .
http://jsfiddle.net/783cfmnv/10/
$("#health1,#health2,#health3").change(function() {
var val1 = +slider1.val();
var val2 = +slider2.val();
var val3 = +slider3.val();
var avg = (val1 + val2 + val3) /3;
$("#healthLevel").val(avg);
});

jQuery Round up to nearest whole number

I am trying to round up the .qty field to the nearest whole number. I am really unsure where to place this in the below code snippet? I take it I should be using Math.ceil()?
function (){
var sm = parseFloat($(this).val());
var tsm = parseFloat($('.tsm', $(this).parent().parent()).val());
var calc = (sm*tsm); // total tiles needed
if($('.addwaste', $(this).parent().parent()).is(':checked')){
var onepercent = calc/100;
var sevenpercent = Math.ceil(onepercent*7);
calc+=sevenpercent;
}
$('.qty', $(this).parent().parent()).val(calc);
$('div.product form.cart .qty').val( calc );
var rawprice = parseFloat($('.rawprice', $(this).parent().parent()).val());
var total = (rawprice*calc).toFixed(2);
$('.total', $(this).parent().parent()).html(total);
$('div.product .price .amount').html( '£' + total );
}
this can be done by using basic javascript:
either use:
Math.floor(number here); <- this rounds it DOWN so 4.6 becomes 4
Math.round(number here); <- this rounds it UP so 4.6 becomes 5
its either floor and round OR Floor and Round.
so with your code it would be:
function (){
var sm = parseFloat($(this).val());
var tsm = parseFloat($('.tsm', $(this).parent().parent()).val());
var calc = (sm*tsm); // total tiles needed
if($('.addwaste', $(this).parent().parent()).is(':checked')){
var onepercent = calc/100;
var sevenpercent = Math.ceil(onepercent*7);
calc+=sevenpercent;
}
calc = Math.round(calc);
$('.qty', $(this).parent().parent()).val(calc);
$('div.product form.cart .qty').val( calc );
var rawprice = parseFloat($('.rawprice', $(this).parent().parent()).val());
var total = (rawprice*calc).toFixed(2);
$('.total', $(this).parent().parent()).html(total);
$('div.product .price .amount').html( '£' + total );
}

Javascript for total price of cart- good practice and adding a function

I am writing a simple cart that to handle user input before arriving at a sum that I pass off to my payment processor. I have code that works, but I'm not sure if it's the most efficient way of calculating the total. Secondly, I would like to add the possibility for a percentage discount when three of the categories are selected. I originally had a way that did a lot of checking through IF statements, but that was inefficient and there was also an unresolved issue with it. How would I go about applying a percentage discount to my preexisting code (if three of four of the item categories are >0)?
var subtotal = 0;
var veu4 = 0;
var veo4 = 0;
var vres = 0;
var vcvl = 0;
var vedb = 0;
function update_price(pin) {
quantity = parseFloat(pin.value);
var callname = pin.name;
if (callname == "item1"){
price = quantity * 50;
subtotal -= vcvl * 50;
vcvl = quantity;
}
else if (callname == "item2"){
price = quantity * 50;
subtotal -= vres * 50;
vres = quantity;
}
else if (callname == "item3"){
price = quantity * 99;
subtotal -= veu4 * 99;
veu4 = quantity;
}
else if (callname == "item4"){
price = quantity * 129;
subtotal -= veo4 * 129;
veo4 = quantity;
}
else{
//commented out irrelevant
}
subtotal += price;
passtotal = document.getElementById("ftotal");
total = document.getElementById("ptotal");
total.innerHTML = subtotal;
passtotal.value = subtotal;
passtotal.innerHTML = subtotal;
}
}
Your help is greatly appreciated!
Many ways to do this, but this would be a bit more DRY.
var items = {
item1: 50,
item2: 50,
item3: 99,
item4: 129
};
var cart = {};
function update_price(pin) {
quantity = parseFloat(pin.value);
var callname = pin.name;
// Get the total for this item with quantity
price = quantity * items[callname];
// Update quantity in cart
cart[callname] = {quantity: quantity, subtotal: price};
passtotal = document.getElementById("ftotal");
total = document.getElementById("ptotal");
total.innerHTML = price;
passtotal.value = price;
passtotal.innerHTML = price;
}
I think your concept of totals/subtotals is weird. It seems like your total/subtotal will always be equal to your last calculation of price * quantity. Maybe your code generated is wrong. As such mine will be slightly wrong too. To fix it, make the total equal to all of the subtotals in the cart.
As for passing this data to your server, you should pass the items that will be purchased and the quantity. On the server-sider, the subtotals and totals should be recalculated. I added your cart variable to help with this. Just serialize this data and send it over to your server processing. Do not take the value of ftotal or ptotal to be accurate when you actually charge the user.

Categories