Andreas, thanks twice : not only I understand but it works !

On 23 Mar 2009, at 19:42, Andreas Junghans wrote:

> Hi JB,
>
> Am 23.03.2009 um 17:36 schrieb Jean-Baptiste BRIAUD -- Novlog:
>
>> I come into a tricky javascript issue with a listener.
>> The idea is to have a description of several buttons like this :
>>
>> [{lbl:"OK", cde:okFunction, ctx:this}, {lbl:"Cancel",
>> cde:cancelFunction, ctx:this}]
>>
>> Then, a static function is called to build the panel and listeners
>> like that :
>>
>> f : function(currentDesc) {
>>            var buttonPane = new qx.ui.container.Composite(new
>> qx.ui.layout.HBox(5, "right"));
>>            for (var i = 0, buttonDescLength = buttonDesc.length; i <
>> buttonDescLength; i++) {
>>                var button = new qx.ui.form.Button(buttonDesc[i]
>> ['lbl']);
>>                    var currentDesc = buttonDesc[i];
>>                    var listenerCode = function() {
>>                        button.debug("Button " + currentDesc['lbl'] +
>> " CLICK ! code " + currentDesc['cde']);
>>                        if (currentDesc['cde'] != null &&
>> currentDesc['ctx'] != null) {
>>
>> currentDesc['cde'].call(currentDesc['ctx']);
>>                        }
>>                    };
>>                    button.addListener("execute", listenerCode,
>> button); // I try here with and without context as I think it doesn't
>> matter in this case because of the use of call.
>>                buttonPane.add(button);
>>            }
>> }
>>
>> Whatever I try, it is always the cancel button code that is launched
>> in the listener.
>> I guess it is linked to some closure and variable that are not stored
>> in the closure's context : currentDesc['cde'] doesn't "stick" to the
>> okFunction during the loop ??
>>
>> Could it be the static ? Only the factory is static, so the  
>> definition
>> line is just pass as a parameter to the static function.
>> Like that : blabla.f([{lbl:"OK", cde:okFunction, ctx:this},
>> {lbl:"Cancel", cde:cancelFunction, ctx:this}]); // So here, ctx:this
>> make sense.
>>
>> Any idea ?
>
> The problem is the way you're defining the closure:
>
> for (var i = ...) {
>   var x = someArray[i];
>   var listenerCode = function(...) {
>     // do something with x
>   }
>   // add the listener to the button
> }
>
> Because of JavaScript scoping rules (all local variables are visible
> in the whole function), the pseudo-code above is equivalent to this:
>
> var x;
> for (var i = ...) {
>   x = someArray[i];
>   var listenerCode = function(...) {
>     // do something with x
>   }
>   // add the listener to the button
> }
>
> When you instantiate the function, it is bound to the current variable
> context (i.e. it receives an invisible reference to the current set of
> local variables). The problem is that the variables are bound by
> reference, not by value. So every function instance references the
> same variable x with the same value (the last one that the variable
> receives inside the loop).
>
> The solution (or at least one solution) is to use a generator  
> function:
>
> var generateListener = function(x) {
>   var listenerCode = function() {
>     // do something with x here
>   };
>   return listenerCode;
> }
>
> for (var i = ...) {
>   var listenerCode = generateListener(someArray[i]);
>   // add the listener to the button
> }
>
> This way, the array value is passed _by value_ to the generator
> function. The generated code then references the local variables
> inside the generator _by reference_ (including the function
> parameters). However, this doesn't matter as a new local variable set
> is created for each invocation of the generator.
>
> I hope this explanation is understandable :-)  Of course, it also
> works for more than one parameter - just make the generator receive as
> many parameters as you need.
>
> Regards,
>
>   Andreas
>
>
> ------------------------------------------------------------------------------
> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM)  
> are
> powering Web 2.0 with engaging, cross-platform capabilities. Quickly  
> and
> easily build your RIAs with Flex Builder, the Eclipse(TM)based  
> development
> software that enables intelligent coding and step-through debugging.
> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
> _______________________________________________
> qooxdoo-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>


------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
qooxdoo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel

Reply via email to