How to create custom MouseEvent.CLICK event in AS3 (pass parameters to function)?

48,328

Solution 1

Without knowing more about your application, it seems more like you should use the target to pass parameters, or extend MouseEvent. The former would be more in line with common practice, though. So for example, if you exposed an integer public property on your "clip" object (whatever it is):

public class MyClip
{
   public var myPublicProperty:int;

   public function MyClip() { //... }
}

for (var i:int = 0; i < 10; i++)
{
   myClips[i].myPublicProperty = i;
   myClips[i].addEventListener(MouseEvent.CLICK, doSomething);
}

... and then, in your event listener, you could retrieve that property using either the target or currentTarget property of the event (probably currentTarget, in your case):

function doSomething(event:MouseEvent):void
{
   trace(event.currentTarget.myPublicProperty.toString());
}

That ought to do it! Good luck.

Solution 2

You really need to extend the event class to create your own event with extra parameters. Placing functions inside the addEventListener (anonymous functions) is a recipe for memory leaks, which is not good. Take a look at the following.

import flash.events.Event;

//custom event class to enable the passing of strings along with the actual event
public class TestEvent extends Event
{
    public static const TYPE1 :String = "type1";
    public static const TYPE2 :String = "type2";
    public static const TYPE3 :String = "type3";

    public var parameterText:String;

    public function TestEvent (type:String, searchText:String)
    {
        this.parameterText = searchText;
        super(type);
    }

}

when you create a new event such as

dispatchEvent(new TestEvent(TestEvent.TYPE1, 'thisIsTheParameterText'))" ;

you can then listen for that event like this

someComponent.addEventListener(TestEvent.TYPE1, listenerFunction, true , 0, true);

and inside the function 'listenerFunction' event.parameterText will contain your parameter.

so inside your myClips component you would fire off the custom event and listen for that event and not the Click event.

Solution 3

    private function myCallbackFunction(e:Event, parameter:String):void
    {
         //voila, here's your parameter
    }

    private function addArguments(method:Function, additionalArguments:Array):Function 
    {
         return function(event:Event):void {method.apply(null, [event].concat(additionalArguments));}
    }

    var parameter:String = "A sentence I want to pass along";
    movieClip.addEventListener(Event.COMPLETE, addArguments(myCallbackFunction, [parameter] ) );

Take advantage of the dynamic function construction in AS3.

Solution 4

You can accomplish this by getting your handler out of a function that gives the variable closure, like this:

for (var i=0; i<5; i++) {
    myClips[i].addEventListener( MouseEvent.CLICK, getHandler(i) );
}

function getHandler(i) {
    return function( e:MouseEvent ) {
        test(i);
    }
}

function test( j ) {
    trace("foo "+j);
}

Also, as for why this creates a new closure, you might want to check the explanation in the accepted answer to this similar question.

Solution 5

Thanks so much for this usefull tips, this technique is better to understand than classes explanation.

for me I just started new code algorithm using this technique to solve link relation between timers array and viewports array, and update status by change text inside them frequently, by passing ID's with timers events.

like this:

    var view:Object=[];

    for(var i:uint=0;i<Camera.names.length;i++){

    view[i]=getChildByName("Cam"+i);

    //_________ Add Text _________
    var tf:TextField = new TextField();
    tf.autoSize = TextFieldAutoSize.LEFT;
    tf.textColor=0xffffff;
    view[i].tf=view[i].addChild(tf);

    //_________ Add Timer _________
    var t:Timer = new Timer(1000);
    view[i].timer=t;
    view[i].timer.start();
    view[i].timer.addEventListener(TimerEvent.TIMER, addArg(i)); 
}

function addArg(adi:uint):Function {
    return function(event:TimerEvent):void {
        updatecamstatus(adi);
    }
}
function updatecamstatus(vH:uint):void {
   with (view[vH]){
    tf.text="Cam" + vH + "\n";
    tf.appendText("activityLevel: " + videosource.activityLevel + "\n"); 
    tf.appendText("motionLevel: " + videosource.motionLevel + "\n"); 
   }
}
Share:
48,328
lbrandao
Author by

lbrandao

Updated on December 05, 2020

Comments

  • lbrandao
    lbrandao over 3 years

    This question doesn't relate only to MouseEvent.CLICK event type but to all event types that already exist in AS3. I read a lot about custom events but until now I couldn't figure it out how to do what I want to do. I'm going to try to explain, I hope you understand:

    Here is a illustration of my situation:

    for(var i:Number; i < 10; i++){
        var someVar = i;
         myClips[i].addEventListener(MouseEvent.CLICK, doSomething);
    }
    
    function doSomething(e:MouseEvent){ /* */ }
    

    But I want to be able to pass someVar as a parameter to doSomething. So I tried this:

    for(var i:Number; i < 10; i++){
    
        var someVar = i;
        myClips[i].addEventListener(MouseEvent.CLICK, function(){
            doSomething(someVar);
        });
    }
    
    function doSomething(index){ trace(index); }
    

    This kind of works but not as I expect. Due to the function closures, when the MouseEvent.CLICK events are actually fired the for loop is already over and someVar is holding the last value, the number 9 in the example. So every click in each movie clip will call doSomething passing 9 as the parameter. And it's not what I want.

    I thought that creating a custom event should work, but then I couldn't find a way to fire a custom event when the MouseEvent.CLICK event is fired and pass the parameter to it. Now I don't know if it is the right answer.

    What should I do and how?

  • fenomas
    fenomas over 15 years
    Why would anonymous functions be a likely cause of memory leaks, exactly?
  • Hani
    Hani over 15 years
    you have no reference to the function, that combined with the weakReference in the eventListener defaulting to false can if you're not carefull lead to memory leaks. considered bad practise + any flashplayer 9.115 or below has a bug which causes a memory leak for anon funcs.
  • lbrandao
    lbrandao over 15 years
    This still doesn't explain how I would fire/dispatch this custom event when a MouseEvent.CLICK event occurs. Am I missing something?