So I wonder if this is what I needed to do... (yes agreed it's academic, but fun to carry on)
for (var i=1; i<=5;i++){
var new_i = new Number(i);
Event.observe($('star'+new_i), 'click',
function(e){objRating.setRating(new_i)});
}
...or even...
for (var i=1; i<=5;i++){
var new_i = i.toString();
Event.observe($('star'+new_i), 'click',
function(e){objRating.setRating(new_i)});
}
Now I would really assume either of those should work to force a value copy to the new variable with each iteration. If not, I give up :-)
On 9/7/06, Chris Lear <[EMAIL PROTECTED]> wrote:
* Ryan Gahl wrote (07/09/06 15:42):
> What Eric was saying was not that they are all using the same callback,
> but that they are all referencing the same i variable at the same
> address in memory, which at the end of your loop holds the value 6. You
> would have been fine if you had created a locally scoped variable new_i
> within the loop and used that in the callback (of course Eric's
> alternative also works fine, but I'm just trying to clear this issue up
> a little in your mind so you know next time)
>
> This would have worked:
>
> for (var i=1; i<=5;i++){
> var new_i = i;
> Event.observe($('star'+new_i), 'click',
> function(e){ objRating.setRating(new_i)});
> }
I don't think even this works. new_i is in the same scope. When I tried
it, I got all 5s (rather than 6s), which would correspond to all the
closures using one value for new_i - the last one assigned.
Variable scoping in closures is hard (for me, anyway) to get to grips
with, so I don't think I'll try an explanation - probably Ryan could doo
better than me anyway.
These should both work, and are viable alternatives to Eric's solution:
// Solution One (simplest case of returning a closure from a function)
for (var i=1; i<=5;i++){
Event.observe($('star'+(x)), 'click', myfunc(i));
}
// Return the closure from a new function that uses a variable in local
// scope
function myfunc(x) {
return function(e){objRating.setRating(x)}
}
// Two
// Use the prototype bind function to bind the "this" variable
for (var i=1; i<=5;i++){
Event.observe(
$('star'+(x)),
'click',
function(e){objRating.setRating(this)}.bind(i)
);
}
Eric's solution does the same thing, but hides the detail behind more
prototype cleverness.
Apologies if I've transcribed these wrong. They worked in a test page I
made, but I just used alerts rather than objRating.setRating etc.
This is all a bit academic considering that the OP says he's happy now,
but I find closure code fascinating. I also find the bind() and
bindAsEventListener() methods to be some of the best things about prototype.
Chris
Athena Group, Inc.
Inquire: 1-888-919-8700 x2903
Blog: http://www.someElement.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs
-~----------~----~----~----~------~----~------~--~---
- [Rails-spinoffs] Re: Event.observe problems Eric Anderson
- [Rails-spinoffs] Re: Event.observe problems jumblesale
- [Rails-spinoffs] Re: Event.observe problems Ryan Gahl
- [Rails-spinoffs] Re: Event.observe problems Chris Lear
- [Rails-spinoffs] Re: Event.observe problems Ryan Gahl
- [Rails-spinoffs] Re: Event.observe pro... Matt Jones
- [Rails-spinoffs] Re: Event.observe... Ryan Gahl
- [Rails-spinoffs] Re: Event.obs... Matt Jones
- [Rails-spinoffs] Re: Event.observe problems Brandon Aaron
- [Rails-spinoffs] Re: Event.observe pro... Ryan Gahl
- [Rails-spinoffs] Re: Event.observe... Chris Lear
