sum of numbers not having desired effect jquery - javascript

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

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))

JavaScript calculation returns NaN

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')

Use the same function on multiple gridviews/tables

I have 6 asp gridviews that need the same calculations done on each of them. I could hard code the function 6 times over but looking for a more efficient way of doing it.
What I'm doing: There are 3 input boxes on each row, of each gv and I need to calculate the average and send it to a lbl in the last column.
Here is what I've done for the first gv:
function calculate() {
//********************
//Development Grid
//********************
//Find the number of rows in the grid
var rowCount = $('#devGV tr').length;
//Iterate through each row looking for the input boxes
for (var i = 0; i < rowCount; i++) {
//convert the total variable to an int
var total = 0;
parseInt(total);
//This variable is for tracking the number of actual fields that are populated.
//Not all the text fields will always be needed, so the average will not always be calculated by dividing by 3
var averNum = 0;
//Iterate through each text box
$("#devGV tr:eq(" + i + ")").find(":input[type=text]").each(function () {
//Convert the value to an int
var thisValue = parseInt($(this).val());
//In the value is blank, change it to 0 for calculation purposes
if (isNaN(thisValue) || thisValue == 0) {
thisValue = 0;
}
else {
averNum += 1;
}
total = (total + thisValue);
});
//Populate the totals label for each row
total = total / averNum;
total = total.toFixed(2);
//In the value is blank, change it to 0 for calculation purposes
if (isNaN(total)) {
total = 0;
}
$("#devGV tr:eq(" + i + ")").find("[class$='RowTotals']").text(total);
}
}
The above function is being trigger by 'onBlur' on each of the text fields. Is there a way I can make this block work for all the gridviews? I'm sure its just a matter of updating the selectors but I'm at a loss on how to do that.
Simplest is probably to pass a jquery object to calculate function:
function calculate(gv) {
Then use .find() in place of where you have the ID, for instance like this for the "find the number of rows in the grid":
var rowCount = gv.find('tr').length;
The reason I say it's easier to pass a jQuery object into the function (rather than the string ID of it, say) is that it lets you do something like this:
$('.some-gridview-css-class').each(function() {
calculate($(this));
});
Obviously replace that selector with whatever selector will identify your 6 gridviews for you.
EDIT: Oh I didn't read carefully enough. You want to do it onblur of a textbox. That means you want something like this:
$(document).ready(function() {
$(body).on('blur', 'input-fields-selector', function() {
calculate($(this).closest('gridview-selector'));
});
});
You have to replace input-fields-selector and gridview-selector with selectors to find the appropriate fields (which will depend on your HTML).

jQuery getting sum with keypress always one step behind

I am trying to create an calculator in which I want add/sum on every key press I make like this:
$('#padd').keypress(function() {
var ypoints = "200";
var points = parseInt( $(this).val() );
console.log( "Points: " + (points + parseInt(ypoints)) );
});
My issue is that it seems like "points" always is one step behind. Lets say that my "ypoints" is 200 and I type in first 1, the console.log says "NaN"? If I then type in a "10" the console.log says "201" while in fact it should say "210"?!? If I then add an "100" in the add field it says "210" but it should say "300". Always one keypress behind?!?
What am I missing here or is this not the correct way to do this?
Any help is appreciated and thanks in advance :-)
Try using the keyup function instead (although you might not want to listen for key* events at all, see below):
$('#padd').keyup(function(){
var ypoints = 200;
var points = parseInt($(this).val());
console.log("Points: "+(points+ypoints));
});
Instead of keyup, you should listen for the explicit input event:
$('#padd').on("input", function(){
var ypoints = 200;
var points = parseInt($(this).val());
console.log("Points: "+(points+ypoints));
});
An example when listening for the input event trumps using keyup is when using an input of type number. In a (not so) modern browser, this adds a stepper to the input field, which you can use to increment or decrement the inputs value by 1 using your mouse. This does not fire the keyup event (no keys are pressed) but nevertheless changes the value.
It is really a matter of when certain events are fired and the state of the input's value at that time. There is an explanation on quirksmode.org:
keyup
Fires when the user releases a key, after the default action of that key has been performed.
and more information on the input event on MDN:
The DOM input event is fired synchronously when the value of an or element is changed.
Try this, its a working code : Fiddle
$('#padd').keyup(function(){
var ypoints = "200";
var points = parseInt($(this).val());
alert("Points: "+(points+parseInt(ypoints)));
});
You can also code this way...
function GetTextboxAmount(obj) {
var retVal = 0;
try {
if (obj.val() == "") {
retVal = 0;
} else if (obj.val() == '') {
retVal = 0;
} else if (isNaN(parseFloat(obj.val()))) {
retVal = 0;
} else {
retVal = Math.round(parseFloat(obj.val()));
}
} catch (e) { retVal = 0; }
obj.val(retVal);
return retVal;
}
$('#padd').keyup(function(){
var ypoints = "200";
var points = GetTextboxAmount($(this));
console.log("Points: "+(points+parseInt(ypoints)));
});
Problem in ParseInt function.
try this Code:
$('#padd').keypress(function(){
var ypoints = "200";
var points = parseInt($(this).val());
console.log("Points: "+parseInt(ypoints+points));
});

JavaScript using isNaN to validate returns NaN

I have some code here that will make validations of whether or not the input from a text box is NOT an empty string and isNaN. When i do these validations on amounts entered, i would like it to add them up.. however when a user does not enter anything in one or more amount fields the program should just add entered fields. But instead i get NaN showing in the total field.
link to full code: http://jsfiddle.net/KxNqQ/
var $ = function (id) {
return document.getElementById(id);
}
var calculateBills = function () {
var myErrorFlag = "N";
for (i = 1; i <= 4; i++) {
AmountNumber = 'amount' + i;
AmountValue = $(AmountNumber).value;
if (AmountValue != "" && isNaN(AmountValue)) {
$(AmountNumber).style.color = "red";
myErrorFlag = "Y";
} else {
$(AmountNumber).style.color = "black";
myErrorFlag = "N";
}
}
if (myErrorFlag != "Y") {
var Amount = 0;
for (i = 1; i <= 4; i++) {
Amount += parseInt($('amount' + i).value,10);
}
$('total').value = Amount;
}
}
var clearFields = function () {
for (i = 1; i <= 4; i++) {
itemName = 'item' + i;
$(itemName).value = "";
}
for (i = 1; i <= 4; i++) {
amountName = 'amount' + i;
$(amountName).value = "";
}
$('total').value = "";
}
window.onload = function () {
$("clearfields").onclick = clearFields;
$("addbills").onclick = calculateBills;
}
I think you've got your requirements a little bit confused, or at the very least I was confused by them. So in order to answer your question, I'm going to rephrase the requirements so I understand them better. This is a useful exercise that I try to do when I'm not 100% sure of the requirements; if I can't get the requirements right, what's to say I'll get the code right?
So the requirements – as I understand them – are:
Given each amount input
When the input has a value
And that value is a number
Then add the value to the total
And make the input color black
But if the input does not have a value
Or that value is not a number
Then make the input color red
Going through your code, I can see a number of problems with it. First, I noticed that both AmountNumber and AmountValue are global variables, because they were not declared local with the var keyword. So before fixing our code, let's change that. Let's also change the variable names to something that more accurately describe what they are, hopefully making the code easier to understand:
var input = $('amount' + i);
var value = input.value;
Now, note that I chose to store the element in the input variable. This is so we don't have to look it up multiple times within the loop. Looking things up in the DOM can be expensive so we'll want to keep it to a minimum. There are other was to look up elements as well, such as getElementsByClassName, querySelector and querySelectorAll; those are left as an exercise for the reader to research and evaluate.
Next, in each iteration of the loop, you check that AmountValue is not a string and simultaneously is not a number:
if (AmountValue != "" && isNaN(AmountValue)) {
This will be true so long as AmountValue is truthy (which is the case for non-empty strings) and so long as isNaN thinks it's a number (which is the case for strings that contain numbers.) It really is rather confusing; if I understand your code correctly this clause is there to check for invalid input and if it is true should mark the input field red and set a flag. I.e. this is the but clause in the aforementioned requirements.
Let's rewrite this to be the when clause instead, we'll take care of the but later. Before we do that, let's look at the myErrorFlag. It's used – I think – to see whether all input is well formed and in that case, add it all up. Well, validation and summation can be done in one fell swoop, so let's get rid of the flag and sum the values while validating them. So we replace myErrorFlag with a total variable:
var total = 0;
Now, let's get back to our clause. The requirements say:
When the input has a value
And that value is a number
Then add the value to the total
In code, that should look something like this:
if (value && !isNaN(value)) {
total += parseInt(value, 10);
input.style.color = 'black';
}
There are a couple of things going on here. For one, the if statement has been turned on its head a bit from what it was. It first checks to see that value is truthy, then that it is a number. The second check can be a bit tricky to read, because it is essentially a double negation; in english it reads "is not not a number", i.e. "is a number". I'll leave it as an exercise for the reader to figure out whether there's a more easily understood way of writing this check.
Now what about the but clause in our requirements?
But if the input does not have a value
Or that value is not a number
Then make the input color red
Well, it's essentially the inverse of our previous statement, so let's simply add an else clause:
else {
input.style.color = 'red';
}
Because the requirements doesn't mention the total variable in this clause, it is simply ignored and doesn't show up in the end result.
Adding it all up (no pun intended) the code – with comments – looks like this:
var calculateBills = function () {
var total = 0;
for (i = 1; i <= 4; i++) {
// Given each amount input
var input = $('amount' + i);
var value = input.value;
if (value && !isNaN(value)) {
// When the input has a value
// And that value is a number
// Then add the value to the total
total += parseInt(value, 10);
// And make the input color black
input.style.color = 'black';
} else {
// But if the input does not have a value
// Or that value is not a number
// Then make the input color red
input.style.color = 'red';
}
}
$('total').value = total;
};
There are more things that could be learned from this to make for better code. For instance, this code will break if the number of inputs change, or if their id names change. This is because they are selected specifically by their IDs and as such, if those change then this code will no longer function.
Another potential issue is that we're setting inline styles on the inputs as we loop over them. This means that in order to keep this code up to date with the styling of the site, it'll have to change. Generally, mixing styling and functionality like this is not a good idea and should be avoided. One way of doing so is to use class names instead, and toggle these on and off. Incidentally, this could also help the previous problem I mentioned.
There are other problems as well, but we'll leave those for another day. Hope this helps!
Try this
var calculateBills = function () {
var Amount = 0;
for (i = 1; i <= 4; i++) {
var AmountElement = $('amount' + i),
AmountValue = AmountElement.value;
if (AmountValue != "" && !isNaN(AmountValue)) {
AmountElement.style.color = "red";
Amount += parseInt(AmountValue,10);
} else {
AmountElement.style.color = "";
}
}
$('total').value = Amount;
};
Demo
Anyway, instead of using elements with id like id="amount1", id="amount2", id="amount3", etc., you could use classes (e.g class="amount") and get them with .getElementsByClassName

Categories

Resources