3

I have such situation: There is 8 div-blocks with ids like 'rateN_wrapper' where is 'N' is the number of div:

<div id="rate1_wrapper">
 <a href="#" id="0_1">...</a>
 <a href="#" id="0_2">...</a>
 <a href="#" id="0_3">...</a>
</div>
<div id="rate2_wrapper">
 <a href="#" id="1_1">...</a>
 <a href="#" id="1_2">...</a>
 <a href="#" id="1_3">...</a>
</div>
...
var ratings = new Array();
for (i=0; i < 8; i++)
{
 ratings[i] = -1; // Default is unrated
}
for (i=0; i < 8; i++)
{
 $('#rate' + i + '_wrapper a').click(function() {
 ratings[i] = parseInt( $(this).attr('id').split('_')[1] );
 console.debug(ratings);
 });
}

My work is to fill array in need place with clicked link's id (parsed). But it's always changes only latest element of array (8). Why?

asked May 19, 2010 at 20:13

2 Answers 2

2

That's a problem caused by the closure in the for loop. You could lookup the id by parsing the parent id:

for (i=0; i < 8; i++)
{ 
 $('#rate' + i + '_wrapper a').click(function() {
 var parentId = $(this).parent('div').attr('id');
 var index = /\d/.exec(parentId);
 ratings[index] = parseInt( $(this).attr('id').split('_')[1] );
 });
}
answered May 19, 2010 at 20:23
Sign up to request clarification or add additional context in comments.

Comments

1

Because the function you create is closing over the i variable. It sees a reference to i at its current value instead of the value when you created the function. After the for loop exits, i will be 8, so all your anonymous functions will update ratings[8]. I think this might fix it:

for (i=0; i < 8; i++)
{
 var idx = i;
 $('#rate' + idx + '_wrapper a').click(function() {
 ratings[idx] = parseInt( $(this).attr('id').split('_')[1] );
 console.debug(ratings);
 });
}

I'm not sure if declaring the var inside the loop body will rebind it for every iteration. If so, then the anonymous function will only see the value that idx had at the time the function was created. Here is a way that I know will work:

function CreateHandler(idx) {
 return function() {
 ratings[idx] = parseInt( $(this).attr('id').split('_')[1] );
 console.debug(ratings);
 }
}
for (i=0; i < 8; i++) {
 $('#rate' + idx + '_wrapper a').click(CreateHandler(i));
}

So you create a function that will create an anonymous function with the correct index. The returned anonymous function will see the value of idx at the time of its creation.

answered May 19, 2010 at 20:18

4 Comments

It would also be possible to avoid the for loop completely by using jquery .each() which might be more clear
Actually, come to think of it, the first example will work if you declare var idx = i inside the anonymous function body instead of the outer loop body...
@jarrett I can't use each() here, I haven't static name of object.
You don't need a static name to use each

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.