views:

65

answers:

4

In this code, the ident and data variables are correct in the callback, but I don't know how to pass in the right i for each loop iteration. I've tried reading up on functions and tried like 10 things, but alas, I must seek the wisdom of the stack.

function callback()
{
    $(ident).html( data.fields[i].value );
    $(ident).fadeTo('slow',1);
}

for(i=0;i<data.fields.length;i++)
{
    ident='#'+data.rID+'_'+data.fields[i].field;
    $(ident).fadeTo('slow',0,callback);
}
A: 

You can use an anonymous function instead of the pointer to callback, so that you can pass in i to callback.

function callback(i, elem)
{
    $(elem).html( data.fields[i].value );
    $(elem).fadeTo('slow',1);
}

for(i=0;i<data.fields.length;i++)
{
    var ident='#'+data.rID+'_'+data.fields[i].field;
    $(ident).fadeTo('slow',0,function() { callback(i, this); });
}

Rather than making ident a global variable, it would be best to declare it (making it constrained to the current function's scope), and then use this in the callback to reference that element.

If you're not using callback anywhere else, it may make sense to just put its implementation inside of the anonymous function, rather than defining it separately and calling out to it:

for(i=0;i<data.fields.length;i++)
{
    ident='#'+data.rID+'_'+data.fields[i].field;
    $(ident).fadeTo('slow',0,function() { 
        $(ident).html( data.fields[i].value );
        $(ident).fadeTo('slow',1);
    });
}

The above example with the inline anonymous function doesn't work, because the reference to i is shared between the callbacks.

bdukes
That will not work. Each instance of that function will end up referencing the same value of "i" (that being "data.fields.length").
Pointy
both examples are wrong.. first one because the callback still references the global `ident` variable and the parameter `i` will be the same. And the second both `i` and `ident` would be wrong in the callback..
Gaby
Thanks for the feedback. The inline example is definitely wrong (need to do like @Pointy and use a new function to give `i` a different scope). I've updated the other one so that `ident` isn't a global variable, changing it to use `this` from the callback, instead.
bdukes
A: 

One way would be to declare the callback function within the for loop.

Gintautas Miliauskas
+3  A: 

Change your "callback" function:

function callback(i) {
  return function() {
    $(ident).html( data.fields[i].value );
    $(ident).fadeTo('slow',1);
  };
}

Then in your loop:

$(ident).fadeTo('slow',0,callback(i));

This "callback" implementation returns the function that you'll pass to "fadeTo()".

Pointy
need to make the `ident` variable local in the loop as well, to maintain the correct reference.. or change it to `$(this)` in the callback
Gaby
I'm not sure what you mean Gaby, the solution worked great as written ^^
Matt
It seems from the posted code that "ident" is global, or at least relatively global. It could indeed be passed in to the function, of course, as could "data".
Pointy
I think the idea is that `ident` *is* global and uses the value of `i` in the for loop in its creation (of the selector string). As such, it is overwritten each time, and any reference to it in the `.callback()` will be to the version with the latest value of `i`.
patrick dw
A: 

My original answer was incorrect. Thanks to @Pointy for the heads-up.

This is similar to @Pointy's answer, but has different placement for the closure.

function callback(k) {
     $( this ).html( data.fields[k].value );
     $( this ).fadeTo('slow',1);
}

for(i=0;i<data.fields.length;i++) {
    (function(j) {
             ident='#'+data.rID+'_'+data.fields[j].field;
             $(ident).fadeTo('slow',0, function() { callback.call( this, j) });
    })(i);
}
patrick dw