Can't determine reason for NaN output - javascript

first time asking a question, long-time lurker. Entry CS student here, first semester working with HTML and JS, and am working on a project that essentially checks the value of some checkboxes, radio buttons, and textboxes, formats some variables based on inputs and values, and outputs that information in a display section. The major issue being, my .js script is resulting in an output in NaN in places I would expect a number and I can't determine as to why. Below is the script, I can amend the html page as well if needed.
But Essentially, in the displayOutput function, the ranging from accessoriesOut to amountOut are giving me a display of NaN and I'm at a loss.
// Declares global variables and their default values.
const STEREO_COST=425.76;
const INTERIOR_COST=987.41;
const NAVIGATION_COST=1741.23;
const STANDARD_FINISH=0;
const PEARLIZED_FINISH=345.72;
const CUSTOM_FINISH =599.99;
const EXCELLENT_CONDITION=1.0;
const GOOD_CONDITION=0.9;
const FAIR_CONDITION=0.8;
const POOR_CONDITION=0.6;
const SALES_TAX_RATE=0.08;
const TRADE="trade";
const ACCESSORIES="accessories";
const SUBTOTAL="subtotal";
const TAX="tax";
const AMOUNT="amount";
const PRICE="price";
const NAME="name";
// Establishes pricing and condition values with the corresponding user inputs.
function pageLoad(){
document.getElementById("stereoDiv").innerHTML += FormatCurrencyText(STEREO_COST);
document.getElementById("interiorDiv").innerHTML += FormatCurrencyText(INTERIOR_COST);
document.getElementById("navigationDiv").innerHTML += FormatCurrencyText(NAVIGATION_COST);
document.getElementById("standardDiv").innerHTML += FormatCurrencyText(STANDARD_FINISH);
document.getElementById("pearlizedDiv").innerHTML += FormatCurrencyText(PEARLIZED_FINISH);
document.getElementById("customDiv").innerHTML += FormatCurrencyText(CUSTOM_FINISH);
document.getElementById("excellentDiv").innerHTML += FormatPercentText(EXCELLENT_CONDITION);
document.getElementById("goodDiv").innerHTML += FormatPercentText(GOOD_CONDITION);
document.getElementById("fairDiv").innerHTML += FormatPercentText(FAIR_CONDITION);
document.getElementById("poorDiv").innerHTML += FormatPercentText(POOR_CONDITION);
}
// Formats money value for output.
function FormatCurrency(amt){
return "$" + amt.toFixed(2); }
// Formats the output and text for currency.
function FormatCurrencyText(amt){
return " (" + FormatCurrency(amt) + ")"; }
// Formats the percent values for display.
function FormatPercentText(pct){
return " (" + (pct * 100).toFixed(2) +"%)"; }
// Determines which trade-in choice is made, and assigns it to and returns a variable.
function getConditionRate() {
var rate;
if (document.getElementById("excellent").checked==true){
rate=EXCELLENT_CONDITION; }
if (document.getElementById("good").checked==true){
rate=GOOD_CONDITION; }
if (document.getElementById("fair").checked==true){
rate=FAIR_CONDITION; }
if (document.getElementById("poor").checked==true){
rate=POOR_CONDITION; }
return rate; }
// Determines which accessories are selected, accumulates and returns a total.
function getAccessoriesTotal() {
var total;
if (document.getElementById("stereo").checked==true){
total += parseFloat(STEREO_COST); }
if (document.getElementById("interior").checked==true){
total += parseFloat(INTERIOR_COST); }
if (document.getElementById("navigation").checked==true){
total += parseFloat(NAVIGATION_COST); }
return total; }
// Determines which finish choice is made, assigns it to a variable for return.
function getFinishAmount(){
var amount;
if (document.getElementById("standard").checked==true){
amount = parseFloat(STANDARD_FINISH); }
if (document.getElementById("pearlized").checked==true){
amount = parseFloat(PEARLIZED_FINISH); }
if (document.getElementById("custom").checked==true){
amount = parseFloat(CUSTOM_FINISH); }
return amount; }
// Determines whether a trade-in was selected, enables/disables controls accordingly.
function EnableTradeIn(){
var isChecked = document.querySelector('[id="tradein"]:checked');
if (isChecked) {
document.getElementById("excellent").disabled=false;
document.getElementById("good").disabled=false;
document.getElementById("fair").disabled=false;
document.getElementById("poor").disabled=false;
document.getElementById("tradeinBox").disabled=false; }
else {
document.getElementById("excellent").disabled=true;
document.getElementById("good").disabled=true;
document.getElementById("fair").disabled=true;
document.getElementById("poor").disabled=true;
document.getElementById("tradeinBox").disabled=true;
document.getElementById("excellent").focus();
document.getElementById("tradeinBox").value=""; }
}
//
function DisplayOutput(accessoriesTotal, tradeinAllowance, subtotal, taxAmount, amountDue, price, name) {
document.getElementById("nameOut").innerHTML=name;
document.getElementById("priceOut").innerHTML=FormatCurrency(price);
document.getElementById("accessoriesOut").innerHTML=FormatCurrency(accessoriesTotal);
document.getElementById("tradeinOut").innerHTML=FormatCurrency(tradeinAllowance);
document.getElementById("subtotalOut").innerHTML=FormatCurrency(subtotal);
document.getElementById("salestaxOut").innerHTML=FormatCurrency(taxAmount);
document.getElementById("amountOut").innerHTML=FormatCurrency(amountDue);
}
function CalculateMain(){
var accessoriesTotal = 0;
var tradeinAllowance = 0;
var subtotal = 0;
var taxAmount = 0;
var amountDue = 0;
var isTradein;
var conditionRate = 0;
var tradeinAmount = 0;
var conditionRate = 0;
var price = document.getElementById("priceBox").value;
var name = document.getElementById("nameBox").value;
//Validate that name is entered
if (name == "" || document.getElementById("nameBox").value==undefined){
document.getElementById("nameError").style.border="1px solid red";
document.getElementById("nameError").innerHTML = "No name entered";
return; }
else{
document.getElementById("nameError").style.border="";
document.getElementById("nameError").innerHTML = ""; }
//Validate price
if (isNaN(price) || price == "" || price < 0){
document.getElementById("priceError").style.border="1px solid red";
document.getElementById("priceError").innerHTML = "Price is not valid";
return; }
else {
price = parseFloat(price);
document.getElementById("priceError").style.border="";
document.getElementById("priceError").innerHTML = "";
}
//Determine if there is a trade-in
isTradein = document.getElementById("tradein").checked;
if (isTradein) {
tradeinAmount = parseFloat(document.getElementById("tradeinBox").value);
conditionRate = getConditionRate(); }
//Validate trade in amount
if (isNaN(tradeinAmount) || tradeinAmount == "" || tradeinAmount < 0) {
document.getElementById("tradeinError").style.border = "1px solid red";
document.getElementById("tradeinError").innerHTML = "Tradein amount is not valid";
return; }
else {
document.getElementById("tradeinError").style.border = "";
document.getElementById("tradeinError").innerHTML = ""; }
//Calculate trade-in allowance (will be 0 if check box is not checked)
tradeinAllowance = parseFloat(tradeinAmount) * parseFloat(conditionRate);
//Validate trade in allowance is not greater than price
if (tradeinAllowance > price){
document.getElementById("tradeinError").style.border="1px solid red";
document.getElementById("tradeinError").innerHTML = "Trade in more than Price";
return; }
else {
document.getElementById("tradeinError").style.border="";
document.getElementById("tradeinError").innerHTML = "";
}
accessoriesTotal = getAccessoriesTotal() + getFinishAmount();
subtotal = price + accessoriesTotal - tradeinAllowance;
taxAmount = subtotal * SALES_TAX_RATE;
amountDue = subtotal + taxAmount;
//Call DisplayOutput
DisplayOutput(parseFloat(accessoriesTotal), parseFloat(tradeinAllowance), parseFloat(subtotal), parseFloat(taxAmount), parseFloat(amountDue), price, name);
}

In the getAccessoriesTotal function, you don't have total defined before trying to add to it. I assume you'd want to default it to 0. (Note: I'd also recommend defaulting amount in getFinishAmount to something).
function getAccessoriesTotal() {
var total = 0;
if (document.getElementById("stereo").checked==true){
total += parseFloat(STEREO_COST); }
if (document.getElementById("interior").checked==true){
total += parseFloat(INTERIOR_COST); }
if (document.getElementById("navigation").checked==true){
total += parseFloat(NAVIGATION_COST); }
return total;
}

Related

Counter App: Button function to trigger various if else messages

I'm building a passenger counter application for buses with vanilla javascript and I'm trying to wrap my head around how, when clicking a HTML DOM Object button, will alter the messages I want to output based on where the count is.
I have an increase and decrease button that increase or decrease the count by 1. Each bus has different passenger capacities, so I've placed each three busses in the navbar (dds, ddsb, mci). When clicking "dds" for example, I want specific messages to be called relative to where the count is. Likewise for other bus models.
let messageEl = document.getElementById("message-el")
let countEl = document.getElementById("count-el")
let ddsNavEl = document.getElementById("dds-nav-el")
let ddsbNavEl = document.getElementById("ddsb-nav-el")
let mciNavEl = document.getElementById("mci-nav-el")
let increaseEl = document.getElementById("increase-btn")
let decreaseEl = document.getElementById("decrease-btn")
let increaseFiveEl = document.getElementById("increaseFive-btn")
let decreaseFiveEl = document.getElementById("decreaseFive-btn")
var count = 0
/* BASIC COUNTER FUNCTIONALITY WITH NO SEATING LIMIT WARNINGS */
function increase() {
count++
countEl.textContent = count
}
function decrease() {
count--
countEl.textContent = count
}
function increaseFive() {
count += 5
countEl.textContent = count
}
function decreaseFive() {
count -= 5
countEl.textContent = count
}
function reset() {
messageEl.textContent = "";
countEl.textContent = 0
count = 0
ddsNavEl.style.fontWeight = "normal";
ddsbNavEl.style.fontWeight = "normal";
mciNavEl.style.fontWeight = "normal";
}
/* COUNTER WITH SEATING AND STANDING LIMIT WARNINGS */
function ddsSelect() {
if (count === 15) {
message = "you are at full seating capacity"
} else if (count > 16) {
message = "you are over capacity"
} else {
message = ""
}
messageEl.textContent = message
ddsNavEl.style.fontWeight = "bold";
ddsbNavEl.style.fontWeight = "normal";
mciNavEl.style.fontWeight = "normal";
}
function ddsbSelect() {
if (count === 12) {
message = "you are at full seating capacity"
} else if (count > 13) {
message = "you are over capacity"
} else {
message = ""
}
messageEl.textContent = message
ddsbNavEl.style.fontWeight = "bold";
ddsNavEl.style.fontWeight = "normal";
mciNavEl.style.fontWeight = "normal";
}
function mciSelect() {
if (count === 10) {
message = "you are at full seating capacity"
} else if (count > 11) {
message = "you are over capacity"
} else {
message = ""
}
messageEl.textContent = message
mciNavEl.style.fontWeight = "bold";
ddsNavEl.style.fontWeight = "normal";
ddsbNavEl.style.fontWeight = "normal";
}
I didn't include all of your functions in this example, but essentially I think the best way to do this would be to create an object and instantiate it per bus, either based on its type or id of some kind. You mentioned in your example that there were three types of bus... "dds, ddsb, and mci" but essentially by using this technique you could simply instantiate more instances of the object if you needed to setup another bus at some point in the future.
Example below, all of these functions could be setup to accept html elements to update various interface elements. None of that is included because none of it was provided.
let bus = {
passengers: 0,
increase: function() {
this.passengers++;
console.log(this.passengers);
},
decrease: function() {
this.passengers--;
console.log(this.passengers);
},
increaseFive: function() {
this.passengers += 5;
console.log(this.passengers);
},
decreaseFive: function() {
this.passengers -= 5;
console.log(this.passengers);
}
};
// bus types dds, ddsb, mci
let ddsBus = Object.create(bus);
ddsBus.increase();
ddsBus.increaseFive();
let ddsbBus = Object.create(bus);
ddsbBus.increase();
ddsbBus.increaseFive();
ddsbBus.increase();
let mciBus = Object.create(bus);
mciBus.increase();
mciBus.increaseFive();
mciBus.increase();
mciBus.increase();
console.log("dds : " + ddsBus.passengers); //expected value: 6
console.log("ddsb : " + ddsbBus.passengers); //expected value: 7
console.log("mci : " + mciBus.passengers); //expected value: 8

Javascript to calculate and display odds as their simplest fraction

I'm writing a bit of script for the WooCommerce product page that takes the quantity entered in the qty input field and displays some text based on that qty:
function reduce(numerator,denominator){
var gcd = function gcd(a,b){
return b ? gcd(b, a%b) : a;
};
gcd = gcd(numerator,denominator);
return [numerator/gcd,denominator/gcd];
}
jQuery('.qty').on('change', function() {
showOdds();
});
function showOdds() {
var qty = 1; // hard coded for testing
var min = 200; // hard coded for testing
var sofar = 40; // hard coded for testing
var plural = '';
var total = 0;
var odds = '';
if (qty > 1){
plural = 'tickets';
}
else{
plural = 'ticket';
}
if (qty > 0){
if ((qty + sofar) > min){
total = qty + sofar;
odds = reduce(qty, total);
}
else {
odds = reduce(qty, min);
}
var text = document.createElement('p');
text.className = 'product-odds';
text.innerHTML = 'Max odds of ' + qty + ' ' + plural + ' winning is ' + odds + '.';
var theDiv = document.getElementById('odds');
theDiv.appendChild(text);
}
}
jQuery(document).ready(function loadPage() {
showOdds();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='odds'></div>
The current output:
Max odds of 1 ticket winning is 1,200
How can I make the odds display in their simplest fraction form? For example if there are 200 tickets available and '1' is entered, it should show '1/200' but if someone enters '20' it should show '1/10'. The 'total' figure will eventually be picked up from the page rather than a fixed value too.
I can use the gcd as posted here but how can I get the two numbers from the array and display them as a fraction (with the /) in the required div?
You can return the desired string instead of array. Check the snippet below.
I've changed return [numerator/gcd,denominator/gcd]; to return numerator/gcd+'/'+denominator/gcd;
function reduce(numerator,denominator){
var gcd = function gcd(a,b){
return b ? gcd(b, a%b) : a;
};
gcd = gcd(numerator,denominator);
return numerator/gcd+'/'+denominator/gcd;
}
jQuery('.qty').on('change', function() {
showOdds();
});
function showOdds() {
var qty = 1; // hard coded for testing
var min = 200; // hard coded for testing
var sofar = 40; // hard coded for testing
var plural = '';
var total = 0;
var odds = '';
if (qty > 1){
plural = 'tickets';
}
else{
plural = 'ticket';
}
if (qty > 0){
if ((qty + sofar) > min){
total = qty + sofar;
odds = reduce(qty, total);
}
else {
odds = reduce(qty, min);
}
var text = document.createElement('p');
text.className = 'product-odds';
text.innerHTML = 'Max odds of ' + qty + ' ' + plural + ' winning is ' + odds + '.';
var theDiv = document.getElementById('odds');
theDiv.appendChild(text);
}
}
jQuery(document).ready(function loadPage() {
showOdds();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='odds'></div>

Recalculating price in JS after redeeming 20% voucher

Trying to recalculate the final price in JS after applying a discount, but doesn’t seem to work. Total Cart and Redeem Coupon function just fine, but I can’t get the final price.
// TOTAL CART
obj.totalCart = function () {
var totalCart = 0;
for (var item in cart) {
totalCart += cart[item].price * cart[item].count;
} return Number(totalCart.toFixed(2));
}
// REDEEM COUPON
function validate(discount) {
var disc = "WE56DQ1";
var coupon = disc.trim();
var input = document.getElementById('discount').value;
if (input.toUpperCase() == coupon.toUpperCase()) {
document.getElementById('message').innerHTML = "Discount applied!";
document.getElementById('err').innerHTML = "";
return true;
} else {
document.getElementById('err').innerHTML = "Invalid discount";
document.getElementById('message').innerHTML = "";
return false;
}
}
// FINAL PRICE AFTER COUPON
obj.totalPrice = function () {
var discount = 20;
return totalPrice = totalCart - (totalCart * discount / 100);
}
To do this you could simply try:
newprice = Math.floor((oldprice/10)*80)
or
newprice = Math.floor((oldprice/100)*(100-discount))
Thanks for taking the time to make a post.
However, if you are planning to make this into a shop, it would be best to do all of the calculations on the server unless the js is server-side.

Solve mathematical function in javascript

I have created this function for a shopping basket. To be simple, i have x products with (2 checkbox + quantity input) for each.
The first checkbox add +3, second +8, to the product price. It's like (3+8+price)*quantity. At the end of the page, i have the total result (like product1 + product2...Etc)
The problem is: If i'm posting the form with new quantities, and going back to the page, i have the default result (total price) (of course, checkbox are checked + new quantity with PHP).
Here is my function:
$(function(){
var item_prices = 0;
var total_item_prices = 0;
var total_unique_item_prices = 0;
var total_price = 0;
$.each($('*[data-item-price]'), function(index, element) {
var item_price = $(element).data("item-price");
total_unique_item_prices = parseInt($('[data-total]').html()) + item_price;
total_price = total_unique_item_prices;
$('[data-total]').html(total_unique_item_prices);
})
$.each($('*[data-item-price]'), function(index, element) {
var item_price = $(element).data("item-price");
var price_of_options = 0;
var quantity = parseInt($(element).find('input[data-quantity]').val());
$.each($(element).children().find("[data-price]"), function(index, element2) {
$(element2).click(function(){
var actual_price = parseInt($('[data-total]').html());
var actual_item_price = parseInt($(element).find('[data-item-total]').html());
var price = $(element2).data("price");
if ($(element2).is(':checkbox') && $(element2).is(':checked')) {
price_of_options += price;
$(element).find('[data-item-total]').html(actual_item_price + (price * quantity));
$('[data-total]').html(actual_price + (price * quantity));
}
else {
price_of_options -= price;
$(element).find('[data-item-total]').html(actual_item_price - (price));
$('[data-total]').html(actual_price - (price * quantity));
}
})
})
$(element).find('input[data-quantity]').bind('keyup mouseup', function () {
var new_quantity = parseInt($(element).find('input[data-quantity]').val());
var quantity_dif = new_quantity - quantity;
var actual_price = parseInt($('[data-total]').html());
if (quantity_dif > 0) {
quantity_dif = new_quantity - quantity;
$(element).find('[data-item-total]').html((item_price + price_of_options) * new_quantity);
$('[data-total]').html(actual_price + ((item_price + price_of_options) * quantity_dif));
}
else {
quantity_dif *= -1;
quantity = parseInt($(element).find('[data-quantity]').val());
$(element).find('[data-item-total]').html((item_price + price_of_options) * new_quantity);
$('[data-total]').html(actual_price - ((item_price + price_of_options) * quantity_dif));
}
quantity = parseInt($(element).find('[data-quantity]').val());
})
})
})
As I said, code is working: https://jsfiddle.net/redbean/4dy38ye4/1/ Just not when i'm reloading the webpage.
I'm not english, be kind about this. I'm trying to do the best to be clear!

JavaScript - How to make 6 individual order total functions into one

I should be using a single function for this. When the button is clicked, simply multiply each quantity by its respective price and add them together.
I'm not sure how to create a single function. I've added comments to each section to to help understand, I'm creating a basic ordering page. I have set values of cost for 5 items, the quantity is a number text field the user will enter in any whole interger.
Here's my code:
/*Array to hold QTY wanted from user*/
var dvdQTY = [0, 0, 0, 0, 0];
var movieName = new Array(5);
movieName[0] = "Star Wars";
movieName[1] = "The Empire Strikes Back";
movieName[2] = "Return of the Jedi";
movieName[3] = "The Force Awakens";
movieName[4] = "Rogue One";
/*variables to store the values entered.*/
var ep4Cost = 0;
var ep5Cost = 0;
var ep6Cost = 0;
var ep7Cost = 0;
var rogueCost = 0;
var totalEstimate = 0;
/* Array of the price variables*/
var moviePrice = new Array(5);
moviePrice[0] = 65; //Price of EP4
moviePrice[1] = 55; //Price of EP5
moviePrice[2] = 45; //Price of EP6
moviePrice[3] = 35; //Price of EP7
moviePrice[4] = 25; //Price of Rouge One
/*Function to calculate the totalEstiamte of entered values by the user at a price of $65 dollars each.*/
function calcEP4() {
totalEstimate -= ep4Cost;
dvdQTY[0] = document.movielist.dvdQTY[0].value;
ep4Cost = dvdQTY[0] * moviePrice[0];
totalEstimate += ep4Cost;
+totalEstimate;
console.log(dvdQTY);
}
/*Function to calculate the totalEstiamte of entered values by the user at a price of $55 dollars each.*/
function calcEP5() {
totalEstimate -= ep5Cost;
dvdQTY[1] = document.movielist.dvdQTY[1].value;
ep5Cost = dvdQTY[1] * moviePrice[1];
totalEstimate += ep5Cost;
+totalEstimate;
}
/*Function to calculate the totalEstiamte of entered values by the user at a price of $45 dollars each.*/
function calcEP6() {
totalEstimate -= ep6Cost;
dvdQTY[2] = document.movielist.dvdQTY[2].value;
ep6Cost = dvdQTY[2] * moviePrice[2];
totalEstimate += ep6Cost;
+totalEstimate;
}
/*Function to calculate the totalEstiamte of entered values by the user at a price of $35 dollars each.*/
function calcEP7() {
totalEstimate -= ep7Cost;
dvdQTY[3] = document.movielist.dvdQTY[3].value;
ep7Cost = dvdQTY[3] * moviePrice[3];
totalEstimate += ep7Cost;
+totalEstimate;
}
/*Function to calculate the totalEstiamte of entered values by the user at a price of $25 dollars each.*/
function calcRogue() {
totalEstimate -= rogueCost;
dvdQTY[4] = document.movielist.dvdQTY[4].value;
rogueCost = dvdQTY[4] * moviePrice[4];
totalEstimate += rogueCost;
+totalEstimate;
}
/*Function to calculate the totalEstiamte and show the results to the button "total" on click.*/`enter code here`
function myTotal()
{
var newTotal = "$" + totalEstimate;
document.getElementById("total").innerHTML = "$" + totalEstimate;
console.log(newTotal)
}
You take what varies from function to function and pass those values into a single function that uses them:
function calc(epCost, dvd, moviePrice) {
totalEstimate -= epCost;
dvd = document.movielist.dvd.value;
epCost = dvd * moviePrice;
totalEstimate += epCost;
+totalEstimate;
}
And you pass those values when you need to call the function:
calc(ep6Cost, dvdQTY[2], moviePrice[2]);

Categories