Search code examples
actionscript-3flash

Flash AS3 AddEventListener with Parameter using loop


I have 34 buttons in my scene, if I click any of them a MovieClip will be visible and jump (gotoAndStop) to a frame based on which button I pressed.

import flash.events.Event;
import flash.events.MouseEvent;

stop();
MC.visible = false;

var btns:Array = new Array(
prov1, prov2, prov3, prov4, prov5, prov6, prov7, prov8, prov9, prov10,
prov11, prov12, prov13, prov14, prov15, prov16, prov17, prov18, prov19, prov20,
prov21, prov22, prov23, prov24, prov25, prov26, prov27, prov28, prov29, prov30,
prov31, prov32, prov33, prov34
);

for(var i:int = 0; i < 34; i++)
{
    btns[i].addEventListener(MouseEvent.CLICK, function(e:Event):void{OpenDetail(i+1)});
    trace(i);
}

function OpenDetail(frame:int)
{
    MC.visible = true;
    MC.gotoAndPlay(1);
    MC.MSC.gotoAndStop(frame);
}

In the code above it should be that if I click prov1 it will open MC.MSC and goto frame 1, if I click prov2 it will open MC.MSC goto frame 2, etc.

But what really happened is when I click any of my buttons above, MC.MSC is opened but goes to frame 34.

Where did I do wrong? Any help would be very appreciated. Thanks.


Solution

  • Your mistake is not understanding what closure (an unnamed unbound function) is and how it works. The thing is, your i iterator goes to 34 and all the closures you create read i value from variable reference rather than use i value of the moment they were created.

    Instead, you should do the following:

    for (var i:int = 0; i < 34; i++)
    {
        btns[i].addEventListener(MouseEvent.CLICK, onClick);
    }
    
    function onClick(e:MouseEvent):void
    {
        // Get reference to the clicked button.
        var aBut:DisplayObject = e.currentTarget as DisplayObject;
    
        // Option 1: figure its index within the list.
        var anIndex:int = btns.indexOf(aBut) + 1;
    
        // Option 2: figure its index from the button's name.
        var anIndex:int = int(aBut.name.substr(4));
    
        // Go to the relevant frame.
        OpenDetail(anIndex);
    }