How to deal with "undefined" and "NaN" in simple javascript calculations? - javascript

So two dropdowns and a few javascript functions to choose a price and set a country (which comes with a tax rate). Then display the price + tax rate = total to the user on the payment form.
If a price and a country(tax rate) are selected, the javascript and the sums work, thusly:
£49.99 + 10% VAT = £54.99
If a price but no country(tax rate) are selected, this happens:
Total: £49.99 + undefined% VAT = £NaN
And if neither a price or a country(tax rate) are selected, then we get:
£undefined + undefined% VAT = £NaN
So the question is: how do we deal with those ugly errors from javascript? What's the javascript way to deal with if/else for undefined and NaN?
Thanks.
UPDATE 2: the NaN check works, but where do I put the undefined check. Have added the TaxPrice function so you can see where it is coming from.
// First grab the tax rate from a drop down
function TaxPrice()
{
var taxprice=0;
var theForm = document.forms["payment-form"];
var selectedrate = theForm.elements["country_vat"];
taxprice = tax_rates[selectedrate.value];
return taxprice;
}
// Then calculate the total, including the NaN checks
function calculateTotal()
{
var TaxRate = TaxPrice() / 100;
var TotalPrice = PlanPrice() + (TaxRate * PlanPrice());
var TotalTax = (TaxRate * PlanPrice())
if(isNaN(TotalPrice)) {
// check NaN
TotalPrice = 0
}
if(isNaN(TotalTax)) {
// check NaN
TotalTax = 0
}
//display the price
var divobj = document.getElementById('p');
divobj.innerHTML = "£" + PlanPrice();
//display the tax rate
var divobj = document.getElementById('r');
divobj.innerHTML = "£" + TotalTax.toFixed(2) + " (" + TaxPrice() + "% VAT)";
//display the total
var divobj = document.getElementById('t');
divobj.innerHTML = "£" + TotalPrice.toFixed(2);
}

Check specifically for undefined with
if(typeof price === "undefined"){}
Check specifically for NaN with
if(isNaN(price)){}
Generally you can also simply do
if(price){}
Where the inside of the if statement will return false if price is NaN, undefined or null, but also when it is 0 or empty string, which you may not want so you'd need to specify it in the condition.
Specifically in your case, it would be good not to perform the calculations when either of its parts is not defined as the result will only create undefined or NaN values anyway:
function calculateTotal(){
//first check all you need for the calculation is defined
if (typeof TaxPrice() != 'undefined' && typeof PlanPrice() != 'undefined'){
//perform the calculation and output the result
}else{
//output an error message or a default ouput
}
}
Then you don't have to check for NaN's because those were caused by making arithmetics with undefined's.

Please covert value to a finite number, for example:
function toNumber(value) {
if(typeof value !== 'number') {
// covert type to number
// void 0, null, true, false, 'abc', [], {} => NaN
// [0] => 0
value = parseFloat(value)
}
if(isNaN(value)) {
// check NaN
value = 0
}
if(!isFinite(value)) {
// check Infinity and -Infinity
value = Number.MAX_SAFE_INTEGER * Math.sign(value)
}
return value
}

make a function similar to this
function get_value(input, default_value) {
return input === undefined || isNaN(input) ? default_value : input;
}
and then use it whenever you need to do calculations with a possible undefined value. Eg
var a = 10;
var sum = a + get_value(b, 0); // b is undefined and get_Value returns 0, sum is 10
var prod = a * get_value(b, 1); // b is undefined and get_Value returns 1, prod is 10

Use the isNaN() function to check if a variable is NaN.
e.g. see here: http://www.w3schools.com/jsref/jsref_isnan.asp
You could also track which vars were set in additional vars. ;)

If you want calculation to be done only when both of them are selected, then simply check for these errors in front of your code by:
if(typeof (your_price_variable) !== undefined && typeof (your_country_variable) !== undefined)
and make the function only run when this condition is met. Then the output won't be "NaN."

Related

Why does my JavaScript function work but displays "undefined" right after?

Let me preface this by saying I'm a beginner in the world of programming so please excuse my ignorance.
I wrote a simple script for calculating discounts that work, however it displays "undefined" after I execute the code.
let price = prompt("What is the total cost? ");
function total() {
if (price > 250) {
var result = price * discount;
var cost = price - result;
console.log("your total cost will be " + cost);
} else {
console.log("your total cost will be " + price)
}
}
discount = 0.15
console.log(total());
However, when I switch the console.log statements to return statements the undefined message goes away.
let price = prompt("What is the total cost? ");
function total() {
if (price > 250) {
var result = price * discount;
var cost = price - result;
return ("your total cost will be " + cost);
} else {
return ("your total cost will be " + price)
}
}
discount = 0.15
console.log(total());
Why is this? It's confusing me and I don't understand why I'm getting the undefined message.
On the two lines marked "1" you are outputting strings to the console.
In the line marked "2" you are outputting the results of the function total() to the console. But, in your code there is no "result" because you didn't return a value. (Therefore, the value of total() was undefined).
However, when you replaced the lines marked "1" with return(..) in your second code, the total function returned a value (the string). So when you tried to console.log the value of the total() function, it worked.
To look at it another way... if you had a function like this:
function example(){
let value1 = 5+5;
let value2 = 1+1;
}
What would be the value of example()? Nothing -- or undefined. Because how would the function know if you wanted value1, value2 or some combination of the two?
You use the "return" statement to let the function know what is the final value.
function example(){
let value1 = 5+5;
let value2 = 1+1;
return value1*value2;
}
Now the function returns the value (in this case 20).

Javascript/Jquery: Compute the values based on the values or null values of input type

I am new to Javascript/Jquery. Below is my code that can compute an average (A) value as long as there are 3 present values in the input.
Here is the jquery code
$(".q-value, .e-value, .t-value").click(function(){
let currentRow = $(this).closest('tr');
let EValue = parseFloat(currentRow.find('.e-value').val());
let QValue = parseFloat(currentRow.find('.q-value').val());
let TValue = parseFloat(currentRow.find('.t-value').val());
currentRow.find('.a-value-core').val((EValue + QValue + TValue ) / 3);
currentRow.find('.a-value-support').val((EValue + QValue + TValue ) / 3);
currentRow.find('.a-value-research').val((EValue + QValue + TValue ) / 3);});
I would like to set an average value even if the Q or E or T input is null However, A value is not computing. when Q or E or T value is null.
For example.
Q = 5, E = null and T = null then A value should be 5
Q = 5, E = 2 and T = null then A value should be 3.5
Q = 5, E = 5 and T = 5 then A value should be 5
try
Number(currentRow.find('.*-value').val());
instead of
parseFloat(currentRow.find('.*-value').val());
as when no value is selected in the dropdown, .val() returns an empty string, not null, and parseFloat("") returns NaN. When you try to add NaN to any number answer returned is still a NaN and your result field stays empty.
Few more notes:
What type of elements are .a-value-**** ? They need to be textfields or such to use .val(). If not, use .text()
Your formula to calculate average of only available numbers will not work when you divide by 3, irrespective of the input. You need to change the logic there as well.
I would use .change instead of .click for a dropdown
PS: It's always a good idea to use console.log(variable) for quick debugging and look for error messages in the console inside the Devtools of the browser and share the same with your question
Hello #AlwaysaLearner noted on your notes. as for the computations, I have to change the logic for the computation by creating a counter for Q, E or T value !== 0 then counter + 1 inside an if else statement. below is the code
//COMPUTE THE AVERAGE PER ROW
$(".q-value, .e-value, .t-value").change(function(){
let currentRow = $(this).closest('tr');
let EValue = Number(currentRow.find('.e-value').val());
let QValue = Number(currentRow.find('.q-value').val());
let TValue = Number(currentRow.find('.t-value').val());
let counter = 0
if (QValue !== 0){
counter = counter + 1
}
if (EValue !== 0){
counter = counter + 1
}
if (TValue !== 0){
counter = counter + 1
}
currentRow.find('.clerical-value-core').val((EValue + QValue + TValue ) / Number(counter));
currentRow.find('.technical-value-core').val((EValue + QValue + TValue ) / Number(counter));
currentRow.find('.a-value-support').val((EValue + QValue + TValue ) / Number(counter)); });
and now It works perfectly. I also change the handler .change and also applied Number function for each field.

Price calculation based on dimensions in WooCommerce single product page

Based on "Get selected variation price in jQuery on Woocommerce Variable products" answer code, in my code bellow, I have a problem with the price calculation of a WooCommerce variable product.
The price gets multiplied with 10 or 1000, depending on the option selected on a dropdown, which is not supposed to happen and I don't know why it is happening.
Here is my code:
<script>
jQuery(function($) {
var jsonData = <?php echo json_encode($variations_data); ?>,
inputVID = 'input.variation_id';
$('input').change( function(){
if( '' != $(inputVID).val() ) {
var vid = $(inputVID).val(), // VARIATION ID
length = $('#cfwc-title-field').val(), // LENGTH
diameter = $('#diameter').val(), // DIAMETER
ene_enden = $('#id_dropdown_one_end').find('option:selected').attr("value_one_end"),
vprice = ''; // Initilizing
// Loop through variation IDs / Prices pairs
$.each( jsonData, function( index, price ) {
if( index == $(inputVID).val() ) {
vprice = price; // The right variation price
}
});
var rope_price = (length*vprice) + ene_enden;
if (rope_price != 0){
$('.price').html(rope_price+',-');
}
alert('variation Id: '+vid+' || Lengde: '+length+' || Diameter: '+diameter+' || Variantpris: '+vprice+ ' || Rope price: '+rope_price+' || ene_enden = '+ene_enden);
}
});
});
</script>
For some reason rope_price gets multiplied by 10 or concatenated with 0 when the option selected for 'I enden av tauet ' is 'Ingenting'(it's value is 0). When I change the option selected to any of the others rope_price gets multiplied with 1000 or concatenated with 00. I don't know why this is happening.
Any ideas?
Because you are concatenating strings. Is not the same 1 + 0 than "1" + "0", as you can check here:
console.log("1 + 0 =", 1 + 0);
console.log('"1" + "0" =', "1" + "0");
When you get a value from an HTML object, you receive it as a string. If you want to use it as a number you must convert it before. You can use either Number or parseFloat (even parseInt, but will remove decimals).
var oneNumber = 1;
var oneString = "1";
var oneConverted = Number(oneString);
console.log("typeof oneNumber:", typeof oneNumber);
console.log("typeof oneString:", typeof oneString);
console.log("typeof oneConverted:", typeof oneConverted);
console.log("oneNumber + oneNumber =", oneNumber + oneNumber);
console.log('oneString + oneString =', oneString + oneString);
console.log('oneConverted + oneConverted =', oneConverted + oneConverted);
The exact problem you are having is your ene_enden variable being a string in the line var rope_price = (length*vprice) + ene_enden;. When you multiply two strings, they are automatically converted to a number (your (length*vprice)), but when you concatenate that number to another string, they are converted automatically to a string again (your + ene_enden), so you must first convert ene_enden to a number, ot better convert all expected number variables to a number.

js function ignores Decimal Numbers

So i made a function that calculate the price by multiplication how many meters i put the problem is when ever i put decimal numbers it ignores it
heres my script
<script>
function getFillingPrice() {
cake_prices = document.getElementById('price').value;
filling_prices = document.getElementById('test2').value;
var t=parseInt(filling_prices);
var x=parseInt(cake_prices);
return t*x;
}
function calculateTotal() {
var total = getFillingPrice();
var totalEl = document.getElementById('totalPrice');
document.getElementById('test3').value =total + " دينار ";
totalEl.style.display = 'block';
}
</script>
You're converting the values to integers when you get them from the DOM.
Change this...
var t=parseInt(filling_prices);
var x=parseInt(cake_prices);
to this...
var t=parseFloat(filling_prices);
var x=parseFloat(cake_prices);
Beside the parsing problem, you could use
an unary plus + and
a default value for non parsable value, like letters or an empty string (falsy values) with a logical OR ||.
cake_price = +document.getElementById('price').value || 0
// ^ unary plus for converting to numbner
// ^^^ default value for falsy values
Together
function getFillingPrice() {
var cake_price = +document.getElementById('price').value || 0,
filling_price = +document.getElementById('test2').value || 0;
return cake_price * filling_price;
}

Why it is not entering in if condition

<script type="text/javascript">
//var EProductId = prompt('Please enter your product Id');
var EProductId = [];
EProductId[0] = prompt("New member name?");
//Product price, code, name, declare here
var ProductId = [];
ProductId[0] = 001;
var product = [];
product[0] = "tshirt";
var ProdPrice = [];
ProdPrice[0] = 299;
//Condition start here
if (ProductId[0] === EProductId[0]) {
// var EProductId2 = parseInt(prompt("Please enter a product", "")ProductId[0] + ' ' + product[0] + ' ' + ProdPrice[0]);
prompt(ProductId[0] + ' ' + product[0] + ' ' + ProdPrice[0]);
} else{
alert("You pressed Cancel or no value was entered!");
}
</script>
Why it is not entering in if condition. i am entering the value 001 after run a program but it alert the message is You pressed Cancel or no value was entered!
if (ProductId[0] == EProductId[0]) {}
Only use === when comparing types.
=== is only used for strict comparisons in javascript. For example: if('0' == 0) would return true as only values are compared here. However, === would check if they are of the same type (2 strings, 2 numbers, but not 1 of each). So, 0===0 returns true while 0==='0' returns false.
You should use == instead. Using == you can compare if values of different types are 'truthy' or 'falsy'. Example: 0 == 0 returns true as well as '0' == 0.
typeof(prompt()) returns string. You will have to convert it to an integer first using parseInt(string, radix). The 10 specifies base 10, the common numbering system used by people.
if (ProductId[0] === parseInt(EProductId[0],10))
I guess it returns "001" as a string, try this
if (ProductId[0] === +EProductId[0])

Categories