views:

63

answers:

5

I'm trying to increase a number on each iteration of a for loop, in jQuery (1.4.2), by the width of the previous element.

I've tried the following:

var
$lis = $('#bookmarks > li'),
liHeight = parseInt($lis.height()),
numLis = $lis.length;
console.log(numLis);

var totalLeft = '0';
console.log(totalLeft);

for (i=1; i<numLis; i++) {
    var leftOffset = $lis.eq(i-1).width();
    var leftTotal = leftOffset + leftTotal;


    console.log(leftOffset +"/"+ leftTotal);
}

The output from this section is:

11 (the length of the array)
0 (the initial value of 'totalLeft')
97/97
117/214
90/
115/NaN
101/NaN
138/NaN
93/NaN
96/NaN
102/NaN
80/NaN

I've tried using parseInt() around one, and both, variables in the var leftTotal = leftOffset + leftTotal; variable assignment, to no avail. I've also tried using jQuery's each(), with the exact same result. Which is unsurprising, since I assigned the values in almost exactly the same way...

There are two questions here:

  1. Why is leftTotal not-a-number (NaN)?
  2. How can I add the new value of leftOffset to the previous-iteration's value of leftOffset?

The console log should read something like:

11
0
97/97
117/214
90/304
115/419
101/520
138/658
93/751
96/847
102/949
80/1029


Edited in response to @KennyTM:

Console.log output is now (more promising):

11
0
97 "/" "970"
117 "/" "117970"
90 "/" "90117970"
115 "/" "11590117970"
101 "/" "10111590117970"
138 "/" "13810111590117970"
93 "/" "9313810111590117970"
96 "/" "969313810111590117970"
102 "/" "102969313810111590117970"
80 "/" "80102969313810111590117970"

With regards to @Tomalak: yeah, it was a typo. Sadly it was a typo in both my code here and in the real darn script. ...sigh... Thanks for the catch, though, that seems to have done a lot to help out.

...how embarrassing. =)

+1  A: 

Hi,

It seems you are not keeping the last value for the next iteration. i.e - put " var leftTotal" out of the loop, so it will keep the value for the next iteration and you'll add to it.

Hope I got you right :)

Roman
I created the variable outside of the loop, but called it `totalLeft`. And then, for some reason, inside the loop called it `leftTotal`. It seems that was the crux of the problem. But +1 for the suggestion.
David Thomas
+3  A: 

i'd try somethin like this:

var leftTotal = 0
$('#bookmarks > li').each( function(){ 
    leftTotal += parseInt(this.width());  // just to be sure its an int :) 
    console.log(this.width(); +"/"+ leftTotal);
});
someGuy
You can (should) use `this.width` instead of `$(this).width()`.
Tomalak
oh thanx :) i'm new to jq myself :)
someGuy
@Tomalak: No, there is no `width` attribute for an `li` element.
Guffa
@Guffa: You are right, I've just noticed myself.
Tomalak
@someGuy, I'm assuming that the first semi-colon in the `console.log...` line is a typo, or am I just not getting it?
David Thomas
errr jep, it's a typo.. :)
someGuy
A: 
var totalLeft = 0;
console.log(totalLeft);

for (i=1; i<numLis; i++) {
    var leftOffset = $lis.eq(i-1).width();
    var leftTotal = parseInt(leftOffset,10) + totalLeft;


    console.log(leftOffset +"/"+ leftTotal);
}
Praveen Prasad
A: 

The solution was, apparently, to pay a little more attention to variable names, and use a parseInt:

var
$lis = $('#bookmarks > li'),
liHeight = parseInt($lis.height()),
numLis = $lis.length;
console.log(numLis);

var leftTotal = '0';    // somehow, between creating this var and the loop I started calling it something else 'totalLeft', for no known reason.
console.log(leftTotal);

for (i=1; i<numLis; i++) {
    var leftOffset = $lis.eq(i-1).width();
    var leftTotal = leftOffset + parseInt(leftTotal);   // added the parseInt here to force it to be a number.      

    console.log(leftOffset, "/" , leftTotal);
}

Thanks to @Tomalak who caught my clinical blindness... =)

David Thomas
Why are you treating `leftTotal` as a string at all? Just initialise it to integer zero and you can drop the weird `parseInt`. `height()` and `width()` return plain integers, you should not need to parse anything. (Otherwise, always use `parseInt(..., 10)` to ensure you are not caught out by the infamous leading-zero-means-octal trap.)
bobince
someguy's solution is clearer than this. If it is also correct, you should op for that instead of this. Also you are missing `var` in `for (i=1...)` and you should move the declaration `var leftTotal` outside of the loop for clarity
Justin Johnson
@Justin, done. @Bob...honestly? I don't know, I think, at one point, `console.log(variable)` returned `38px`, and I assumed that the 'px' portion would require the parseInt()...I think I just got ridiculously confused somewhere.
David Thomas
@David: The return value of `width()` always is an int. The value of the CSS property might contain `px`, but you're not using that here. Then again, the value of the CSS property might also contain `em` or `%`, so that you would not get away with a ``parseInt()` anyway.
Tomalak
Yeah, it's `css('width')` that returns a width in CSS `length` format, with potentially a trailing unit like `px`. `width()` is always integer screen-pixels.
bobince
+1  A: 

It appears that you are not assigning to totalLeft in your code.

Also, I think your code is way to complicated and has subtle errors. Here is a more compact and jQuery-style version.

var totalLeft = 0;

$('#bookmarks > li:gt(0)').prev().each(function () {
    totalLeft += $(this).width();
});

At least, this generates the same number as the code in your own answer.

Tomalak
Oh, I agree with the over-complicated code. I'm pretty good with (x)html and css, but I have little-to-no concept of good js/jQuery. I've never actually *seen* people cry while looking at it, but I harbour suspicions of such. +1, and sorry for the non-accept, but @someGuy's answer was recommended by @Justin Johnson, and seemed worth. I'm curious as to your opinion of why it can't possibly work, though? =(
David Thomas