JavaScript calculation returns NaN - javascript

I want to find total sum of passing the field values in array. If the field is for discount then perform minus else plus. For some reason I'm getting nan.
Here is my script code
<script>
var partial_cost = $('#bill_amount:disabled').val();
var fine = +$('#fine').val();
var discount = +$('#discount').val();
var other_cost = +$('#other_cost').val();
var total_cost = +$('#total').val();
var chargeAble = [
partial_cost,
fine,
discount,
other_cost
];
$.each(chargeAble, function (chargeIndex, charge) {
charge.blur(function () {
var amount = 0;
for(charge in chargeAble)
if(chargeAble[charge].attr('id') == 'discount')
amount -= (chargeAble[charge].val());
else
amount += (chargeAble[charge].val());
total_cost.val(amount);
});
});
</script>

The code is using a combination of .each() AND a for-in loop... and strangely the callback from a blur() function? It can be simplified like this:
var amount = 0;
$('#bill_amount:disabled, #fine, #discount, #other_cost')
.blur()
.each(function() {
var sign = this.id === 'discount' ? -1 : 1;
amount += parseFloat($(this).val()) * sign;
});
$('#total').val(amount);
Update:
Oh, you want the total to update on blur... try this code:
var $values = $('#bill_amount:disabled, #fine, #discount, #other_cost');
$values.on('blur', function() {
var amount = 0;
$values.each(function(){
var sign = this.id === 'discount' ? -1 : 1;
amount += parseFloat($(this).val()) * sign;
});
$('#total').val(amount);
});

I can see stuff like this all around:
var fine = +$('#fine');
The jQuery() method returns jQuery objects, not numbers or even strings. Forcing a number cast will thus return NaN.
You need to first grab the text inside and than parse numbers of out it. How to do it depends on how your HTML is structured but in general:
In form fields you can normally use .val()
In most other tags you can use .text()

Make sure that all values are interpreted as numbers by JavaScript. Otherwise it will try to calculate some odd result from a string, which might get interpreted as something else than the a decimal number (hex, octa, ...).

You array holds numbers and you act like they are strings
var chargeAble = [ //this holds values
partial_cost,
fine,
discount,
other_cost
];
and in the loop you are using it for an id???
chargeAble[charge].attr('id')

Related

Adding the sum of checkboxes appending instead of adding

What i am trying to do in my form is, when a user clicks on certain checkboxes, the value (in float form) is added up to a sum, but the way my code is now it appends instead of adds.
This is my code:
<script>
$(document).ready(function() {
function updateSum() {
var total = "0.00";
$(".sum:checked").each(function(i, n) { total += parseFloat($(n).val()).toFixed(2); })
$("#total").val(total);
}
// run the update on every checkbox change and on startup
$("input.sum").change(updateSum);
updateSum();
})
</script>
When i check multiple boxes i get: 1.002.003.00 instead of: 6.00
my code looks right i cannot see what i have missed. Any advice on the issue would be appreciated.
Let's see a quick example how toFixed() behaves and how should you add floats in JavaScript if you have the original value as a string:
(function() {
var total = '0.00';
for (var i = 0; i < 5; i++) {
total = (parseFloat(total) + parseFloat(4.3)).toFixed(2);
}
console.log('total', {
total: total,
typeOfTotal: typeof(total)
});
})();
Based on the below example you can see that toFixed() returns a string so I suggest to modify to your code to the following in order to add numbers properly:
$(document).ready(function() {
function updateSum() {
var total = "0.00";
$(".sum:checked").each(function(i, n) {
let sum = parseFloat(total) + parseFloat($(n).val());
total = sum.toFixed(2);
});
$("#total").val(total);
}
// run the update on every checkbox change and on startup
$("input.sum").change(updateSum);
updateSum();
});
You can read further about Number.prototype.toFixed() and parseFloat() here.
Change your total= '0.00' to number( total = 0.00 ) instead of string.
toFixed returns string not numbers
let x = 1.22
console.log(typeof (1.22).toFixed(2))

Squaring each number in an array with dynamically added inputs

I'm trying to calculate the standard deviation of a set of data entered by a user into a form with dynamically added inputs. Thus far I have been able to calculate the sum of the elements in the array, but I cannot figure out how to square each element of the array. I have searched this forum, but trying suggestions from the only applicable result (Square each number in an array in javascript) did not seem to work. Here is a snippet of my code:
$(".calcSD").click(function() {
$("input[type=text]").each(function() {
arr.push($(this).val().trim() || 0);
sum += parseInt($(this).val().trim() || 0);
});
Where .calcSD is the button the user clicks to perform the calculation. Moreover, the length of the array is given by var number = arr.sort().filter(Boolean).length; as the script is intended to filter out any inputs that are left blank.
Also, if it make a difference, inputs are dynamically added to the array via:
$('.multi-field-wrapper').each(function() {
var $wrapper = $('.multi-fields', this);
$(".add-field", $(this)).unbind('click').click(function(e) {
$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
});
So I ask: how would go about determining the square of each element in the resulting array?
The pow() method returns the value of x to the power of y (x^y)
|| in parseInt will use base as 0 if it returns falsey value
$(".calcSD").click(function() {
var sum = 0;
var arr=[];
$("input[type=text]").each(function() {
var squared = Math.pow(parseInt(this.value)||0, 2);
arr.push(squared);
sum += squared;
});
alert(sum);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<input type="text">
<input type="text">
<button class="calcSD">Calculate</button>
I might not have followed you correctly, but couldn't you just multiply the value by itself as it's pushed to the array?
$(".calcSD").click(function() {
$("input[type=text]").each(function() {
arr.push(($(this).val()*$(this).val()).trim() || 0);
sum += parseInt($(this).val().trim() || 0);
});
Ultimately I wanted to be able to sum the squares of the elements in the array (as it is a part of calculating the SD) so I did this and it works:
var sumXsq = 0;
for(var i = 0 ; i <= number ; i++) {
sumXsq += parseInt(arr[i]*arr[i]);
}
but not quite as good as Rayon's answer.

sum of numbers not having desired effect jquery

I'm relatively new to javascript/jQuery and I'm having trouble getting my expected outcome. I would like the total to be shown even if only one input has a value, otherwise I want 0 to be shown. However right now it requires all 3 values to be input before it will show the sum. It will not simply add the next input onto the total as I type into an input. I can imagine a series of lengthy conditional statements that would cross check each input for .length and return the total based on each input. Surely there has to be an easier/cleaner way. If this were java I would use total += (variable) and it would total them as I went. That doesn't seem to work here.
$('#invoice_labor, #invoice_materials, #invoice_other').keyup(function() {
if ($('#invoice_labor').length || $('#invoice_materials').length || $('#invoice_other').length ) {
updateTotal();
} else {
$('#invoice_total').html(0);
}
});
var updateTotal = function () {
var input1 = parseFloat($('#invoice_labor').val(), 2);
var input2 = parseFloat($('#invoice_materials').val(), 2);
var input3 = parseFloat($('#invoice_other').val(), 2);
var total = input1 + input2 + input3;
$('#invoice_total').html(total);
$("#invoice_total").html(parseFloat($("#invoice_total").html()).toFixed(2));
};
and here is the fiddle I was tinkering with.
So I want the total to change regardless of which field I type a number into. If it's only one, total that add that to the total variable and return it. If it's any combination of two then combine them and add them to the total. Thanks for the help.
Try
$('#invoice_labor, #invoice_materials, #invoice_other').keyup(function() {
updateTotal();
});
var updateTotal = function () {
var input1 = parseFloat($('#invoice_labor').val()) || 0;
var input2 = parseFloat($('#invoice_materials').val()) || 0;
var input3 = parseFloat($('#invoice_other').val()) || 0;
var total = input1 + input2 + input3;
$("#invoice_total").html(total.toFixed(2));
};
Demo: Fiddle
Your fiddle has few problesm
You were registering the input keyup event, in the body keyup handler which was wrong - it will cause the first keystroke not to be recognised and will fire multiple updatetotal calls in subsequent calls
If a field is empty parseFloat will return NaN which when added will result in NaN as the result
parseFloat takes only one argument

Using a variable to search an array instead of a static string

Okay, so what I have is basically three dynamic drop down boxes and a 2D array. I have each box adding their values together, and then I want the sum of the values to be searched for through the array to pull out the fifth value on whatever the row the value was on.
var shape = document.getElementById("shape").value;
var dimension_one = document.getElementById("dimension_One").value;
var x = 'x';
var dimension_two = document.getElementById("dimension_Two").value;
var selected_beam = shape + dimension_one + x + dimension_two; // combine all values from text boxes
alert(selected_beam);
for (i = 0; i < array_shapes.length; i++)
{
if (array_shapes[i][2] == selected_beam) {
alert('Area=' + array_shapes[i][5]);
//Area= array_shapes[i][5]);
}
}
I know that selected _beam is giving me the value I want, and I also know that the array loop returns what I want out of the array but only if I replace
if (array_shapes[i][2] == selected_beam)
with
if (array_shapes[i][2] == "value I want to search for")
So what I really need to know is - why will it only accept it as a string and not as my selected_beam variable.
Based on your array values, it looks like you need var x to be uppercase like:
var x = 'X';
If I am reading your array correctly, it also looks like the beam size is in element 0 and 1 of the array not 1 and 2, so you may need to not look for array_shapes[i][2], but rather array_shapes[i][0] or array_shapes[i][1]
The first item in the array is at index value = 0.
You need to do some debugging.
To start off, you need to know why selected_beam !== "your value".
I suggest you use this function to compare the strings:
function compare( s1, s2 ){
alert("s1: " + s1.toString());
alert("s2: " + s2.toString());
if (s1.toString() == s2.toString())
return alert("true");
return alert("false");
}
>>> compare(selected_beam,"your value");
The problem might be as simple as having unnecessary characters in your selected_beam.
So where you have alert(selected_beam), try to compare the strings and see if it returns true or false.
You are concatenating values that you're parsing from a text box. The result will be a string
Try doing:
var selected_beam = parseInt(shape) + parseInt(dimension_one) + parseInt(x) + parseInt(dimension_two);

Javascript: Math.floor(Math.random()*array.length) not producing a random number?

This on e is a doozey.
I have while loop to generate a random number that is not the same as any other random number produced before. The random number is used to select a text value from an object.
for example:
quoteArray[1] = "some text"
quoteArray[2] = "some different text"
quoteArray[3] = "text again"
quoteArray[4] = "completely different text"
quoteArray[5] = "ham sandwich"
This is part of a larger function and after that function has cycled through = quoteArray.length it resets and starts the cycle over again. The issue I am hitting is that the following code is SOMETIMES producing an infinite loop:
//Note: at this point in the function I have generated a random number once already and stored it in 'randomnumber'
//I use this while statement to evaluate 'randomnumber' until the condition of it NOT being a number that has already been used and NOT being the last number is met.
while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
randomnumber = Math.floor(Math.random() * (quoteArray.length));
}
When I console.log(randomnumber) - when I am stuck in the loop - I am just getting '0' as a result. When stuck in the loop it doesn't appear as though Math.floor(Math.random() * (quoteArray.length)) is producing a random number but rather just '0' infinitely.
can anyone tell me why I am running into this problem?
EDIT: Here is the complete pertinent code with function + variable declarations
// Function to initialize the quoteObj
function quoteObj(text,cname,ccompany,url,height) {
this.text=text;
this.cname=cname;
this.ccompany=ccompany;
this.url=url;
this.height=height;
}
// Populate my quotes Object with the quotation information from the XML sheet.
var qObj = new quoteObj('','','','');
var quoteArray = new Array();
var counter = 0;
//cycles through each XML item and loads the data into an object which is then stored in an array
$.ajax({
type: "GET",
url: "quotes.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('quote').each(function(){
quoteArray[counter] = new quoteObj('','','','');
console.log(quoteArray[counter]);
quoteArray[counter].text = $(this).find('text').text();
quoteArray[counter].cname = $(this).find('customer_name').text();
quoteArray[counter].ccompany = $(this).find('customer_company').text();
quoteArray[counter].url = $(this).find('project').text();
++counter;
});
}
});
// This is the setion that is generating my infinite loop issue.
// I've included all of the other code in case people are wondering specific things about how an item was initialized, etc.
// Generate a random first quote then randomly progress through the entire set and start all over.
var randomnumber = Math.floor(Math.random() * (quoteArray.length));
var rotationArray = new Array(quoteArray.length);
var v = 0;
var lastnumber = -1;
bHeight = $('#rightbox').height() + 50;
var cHeight = 0;
var divtoanim = $('#customerquotes').parent();
//NOT RELATED//
// Give the innershadow a height so that overflow hidden works with the quotations.
$(divtoanim).css({'height' : bHeight});
// Rotate the Quotations Randomly function.
setInterval(function(){
randomnumber = Math.floor(Math.random() * (quoteArray.length));
//checks to see if the function loop needs to start at the beginning.
if(v == (quoteArray.length)){
rotationArray.length = 0;
v = 0;
}
//determines if the random number is both different than any other random number generated before and that is is not the same as the last random number
while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
randomnumber = Math.floor(Math.random() * (quoteArray.length));
}
lastnumber = randomnumber;
rotationArray[randomnumber] = randomnumber;
++v;
//NOT RELATED//
//animation sequence
$('#ctext, #cname').animate({'opacity':'0'},2000, function(){
$('#ctext').html(quoteArray[randomnumber].text);
$('#cname').html('- ' + quoteArray[randomnumber].cname);
cHeight = $('#customerquotes').height() + 50;
adjustHeight(bHeight,cHeight,divtoanim);
$('#ctext').delay(500).animate({'opacity':'1'},500);
$('#cname').delay(1500).animate({'opacity':'1'},500);
});
},15000);
This is an asynchronous problem: the array quoteArray is empty when the code runs, because it fires off the ajax request, and moves on. Anything that depends on quoteArray should be inside the success function of $.ajax.
The array has a length when you type quoteArray.length in the console, only because by that time the Ajax request has completed.
have you tried something like
Math.floor(Math.random() * (5));
To make sure the array length is being found properly?
First, since you updated your question, be sure that you are handling asynchronous data properly. Since an ajax call is asynchronous, you will need to be sure to only run the randomizer once the call is successful and data has been returned.
Second, assuming you are handling the asyc data properly, the size of your result set is likely it is too small. Thus, you are probably randomly getting the same number too often. Then, you can't use this number because you have already done so.
What you need to do is pop off the parts that are already used from the results array each time. Recalculate the array length, then pull a random from that. However, the likelihood of this feeling random is very slim.
There is probably a more efficient way to do this, but here's my go:
var results = ['some text','some text2','some text3','some text4','some text5', /* ...etc */ ],
randomable = results;
function getRandomOffset( arr )
{
var offset,
len;
if( arr.length < 1 )
return false;
else if( arr.length > 1 )
offset = Math.floor(Math.random() * arr.length );
else
offset = 0;
arr.splice( offset, 1 );
return [
offset,
arr
];
}
while( res = getRandomOffset( randomable ) )
{
// Set the randomable for next time
randomable = res[1];
// Do something with your resulting index
results[ res[0] ];
}
The arrgument sent to the function should be the array that is returned form it (except the first time). Then call that function as you need until it returns false.

Categories

Resources