0

I'm trying to loop through my totals in order to get a grand total for my web app. So far the code I am working with is the following:

function calcAllFields() {
    var name = parseFloat($('div [name = total[]]').text());
    var totArray = $.makeArray(name);
    var total = 0;
        for (var i = 0; i < totArray.length; i++) {
                total += totArray[i];
                }
    $("#target1").text(total);
}

Instead of adding integers, something is being read as a string. Say I want to add 200 + 50, instead of 250 I get 20050. Could anyone please point out what I'm doing wrong? Thanks!

Ricket
  • 33,368
  • 30
  • 112
  • 143
rshivers
  • 147
  • 1
  • 1
  • 11

5 Answers5

6

Use parseInt to ensure you're not concatenating a string.

E.g.:

total += parseInt(totArray[i], 10);
Matt
  • 43,482
  • 6
  • 101
  • 102
2

You can cast to a number using +, or Number():

(+"200") + (+"50")              //-> 250
Number("200") + Number("50")    //-> 250

total += +totArray[i]; 

Personally, I prefer using + over parseInt/parseFloat in many situations because those functions will return a number as long as the string starts with a number, e.g. 1,000 would parse as 1. +"1,000" will return NaN, which is more desired IMO. You don't have to worry about the radix either, as +"010" will not be treated as an octal.

Community
  • 1
  • 1
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • Another option I like to use sometimes is `|0`. In a case like this, a non-number would throw no error, it would default to `0`, so in effect, nothing is added if the input isn't a number. – Matt May 28 '10 at 19:15
  • @Matt: Yes, that can be useful in certain situations, too. – Andy E May 28 '10 at 19:18
  • Careful with bitwise operations like `|`: they also clip the number to within the range of a 32-bit signed integer (potentially wrapping a large number into a negative number). – bobince May 28 '10 at 19:28
  • @bobince - thanks for the tip, you're right. I never knew that, but `'4294967297'|0` does return `1` as you warned. – Matt May 28 '10 at 19:33
2

div[name=total[]] probably contains multiple element's so that might cause some weird behaviour. Try this:

function calcAllFields() {
    var total = 0;
    $('div[name=total[]]').each(function() {
        total += parseFloat($(this).text());
    }
    $("#target1").text(total);
}
Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185
1

have you tried?

total+= parseInt(totArray[i]);
Andreas
  • 5,305
  • 4
  • 41
  • 60
  • He also remembered the radix, so his code will work with `09` and such. – Kobi May 28 '10 at 19:08
  • 1
    Also, to save you from future headaches, be sure to pass a `radix` a parameter to avoid unexpected results. For example, `parseInt('010')` will return `8`, but `parseInt('010', 10)` will return `10`, as expected. – Matt May 28 '10 at 19:08
0

I'm surprised you're getting as far as 20050. The code shouldn't really work at all.

$('div [name = total[]]')

Firstly, that's not a valid selector. You would have to escape or quote the attribute selector, otherwise the first ] in it closes the selector, leaving an invalid trailing second ].

It is only working at all because of a quirk (bug) in selector-parsing in jQuery/Sizzle. But because it's non-standard, (a) it might break in the future, and (b) it won't take advantage of the fast native querySelectorAll in modern browsers. Better:

$('div [name="total[]"]')

However you would need jQuery 1.4 for this because jQuery 1.3's attribute selector parsing was even more buggy and broke this case.

It might be better to avoid all these issues by just assigning a class to those elements and selecting on that instead.

$('div [name = total[]]').text()

What are the elements inside the div that have name="total[]"? I am supposing they are some sort of form controls otherwise the name attribute would be invalid. But text() is not the right way to read a form control. It gives you the textual content inside the element's tags, not the current value of the field.

<input>​s don't have textual content. <textarea> does have textual content, but it is not necessarily the same as the field's value. The textual content, like the value attribute of <input>, is the default-value of the field, not the current value. You should use val() to read the current value.

var totArray = $.makeArray(name);

That's no use. By calling text() on the selector wrapper object you have already thrown away the multiple elements you have in there to turn them into one text string. You can't get them back from a string. All makeArray does is give you an Array containing that single string as an item.

What you need to do is read the value of each input in turn, separately, in order to add them together.

var total= 0;
$('div [name="total[]"]').each(function() {
    total+= +$(this).val();
});
$("#target1").text(total);

(The + converts the value string into an integer, as per Andy's answer.)

bobince
  • 528,062
  • 107
  • 651
  • 834