Event-observation and scoping
you cannot really call it a scoping problem. it was just a basic structural understanding problem. the theory: inside a loop you cannot assign variables to anonymous functions for event-handling. even if they are in the same scope, because the events are "fired" later and have no more connection to the scope. let's assume we have the following construct:
for(var a=0;a<foo.length;a++) Event.observe(bar[a],'click',function() { alert(a); });
what happens now? this construct cannot work! why? it is simple. the event onclick is fired later. so how can the anonymous function know the value of the loop from the past? this one can do the job:
for(var a=0;a<foo.length;a++) eval("Event.observe(bar["+a+"],'click',function() { alert("+a+"); });");
honestly we have to say we do not like this construct. makes the code really unreadable.
handgestrickt wrote a function that solves this problem and additonally makes writing several event-handlers for one element a charm. this function requires Prototype.js.
var foo = {
observe: function(element,handlers,runtime_args) {
if(element && handlers && typeof(handlers) == 'object') for(var handler in handlers) {
var func = String(handlers[handler]);
if(runtime_args && typeof(runtime_args) == 'object') for(var arg in runtime_args)
eval('func = func.replace(/(\W)'+this.regexp_quote(arg)+'(\W)/g,"'+runtime_args[arg]+'");');
eval('func = '+func);
element.observe(handler,func);
}
},
regexp_quote: function(string) {
return string.replace(/(\|\/|\||\+|\*|\?|\(|\)|\[|\]|\{|\}|\^|\.|\"|\'|$|\r|\n|\t|\f|\@)/g,"\$1");
}
}
the usage is very simple:
for(var a=0;a<foo.length;a++) {
foo.observe(bar[a],{
click: function() { alert(will_be_replaced); },
mouseover: function() { alert(will_be_replaced); },
mouseout: function() { alert(will_be_replaced); }
},{
will_be_replaced: a
});
}
a little bit about the inside: the first argument is the element were to set the event-handlers on, the second argument is an associative array or hash of the event handlers and functions to assign. the third handler is the tricky one. here you assign values to variables inside the functions. the variables inside the functions are replaced with real values. nearly the same as the eval(), but more handy and elegant.

