Expected / pseudo example:
stage.addEventListener(MouseEvent.CLICK, onClick.someWayToPassParameters(true, 123, 4.56, "string"));
function onClick(e:
I would modify Creynders example slightly:
protected function createHandler(handler:Function, ...args):Function
{
var h:Function = function(e:Event = null):void
{
trace(args);
if (handler != null)
handler(e);
}
return h;
}
sm.addEventListener(StyleEvent.STYLE_CHANGE,
createHandler(updateStyle, 1,true,"Lorem",["a","b","c"]),
false, 0, true);
this way you can use original event handlers and inject the "arguments" to it,
also you could have your handlers to have following signature:
protected function myHandler(e:Event, ...args):void;
then you could pass arguments directly to the target handler:
protected function createHandler(handler:Function, ...args):Function
{
var h:Function = function(e:Event = null):void
{
//trace(args);
if (handler != null)
{
args.unshift(e);
handler.apply(this, args);
}
}
return h;
}
best regards
Passing a parameter directly to the event handler is not possible.
The best approximation is by using a function factory method, IMO
//--EDITED: I created a separate class to maintain parameterized handlers, see https://gist.github.com/4124722
usage is simple:
public class Usage extends Sprite{
private var _handlers : ParameterizedHandlerContainer;
public function ParameterizedEvents()
{
_handlers = new ParameterizedHandlerContainer();
_handlers.registerHandler( this, Event.ADDED_TO_STAGE, someMethod, 3000 );
}
private function someMethod( event : Event, amount : uint ):void
{
trace( this, 'someMethod', amount );
_handlers.destroyHandler( arguments.callee, event );
}
}
Now you can register parameterized handlers with ParameterizedHandlerContainer#registerHandler
and destroy them with ParameterizedHandlerContainer#destroyHandler
.
You can pass in any amount of parameters you want, but the first parameter of the callback method must be of type Event or a descendant.
var s1:Boolean = true;
station1.addEventListener(MouseEvent.ROLL_OVER, function(e:MouseEvent) : void { spread(e, s1) });
station1.addEventListener(MouseEvent.ROLL_OUT, function(e:MouseEvent) : void { collapse(e, s1) });
function spread(event:MouseEvent ,bb:Boolean):void {
if(bb != true) event.currentTarget.gotoAndPlay(2);
}
function collapse(event:MouseEvent,bb:Boolean ):void {
if(bb != true) event.currentTarget.gotoAndPlay(18);
}
Why not use AS3-Signals? Passing a parameter then is as simple as:
import org.osflash.signals.Signal;
public class AlarmClock
{
public var alarm:Signal;
public function AlarmClock()
{
alarm = new Signal(String);
}
public function ring():void
{
alarm.dispatch("9 AM");
}
}
Out of the box: it only takes 2 extra lines of elegant code to solve this ancient puzzle.
stage.addEventListener(MouseEvent.CLICK, onClick(true, 123, 4.56, "string"));
function onClick(b:Boolean, i:int, n:Number, s:String):Function {
return function(e:MouseEvent):void {
trace("Received " + b + ", " + i + ", " + n + " and " + s + ".");
};
}
But most importantly, you will very likely need to remove the listener later to free resources, so +1 line to store it in a variable:
var functionOnClick:Function = onClick(true, 123, 4.56, "string");
stage.addEventListener(MouseEvent.CLICK, functionOnClick);
function onClick(b:Boolean, i:int, n:Number, s:String):Function {
return function(e:MouseEvent):void {
trace("Received " + b + ", " + i + ", " + n + " and " + s + ".");
};
}
And you'll be able to remove it normally:
trace("Before: " + stage.hasEventListener(MouseEvent.CLICK));
stage.removeEventListener(MouseEvent.CLICK, functionOnClick);
trace("After: " + stage.hasEventListener(MouseEvent.CLICK));
Here's a more elaborated, dynamic example to prove its use:
function onClick(s:String):Function {
return function(e:MouseEvent):void {
trace("The square " + s + " at x = " + e.currentTarget.x + "px was clicked");
};
}
var myFunctions:Array = new Array();
for (var i:int = 0; i < 10; i++) {
myFunctions.push(onClick("#" + (i+1)));
}
for (i = 0; i < myFunctions.length; i++) {
var square:Sprite = new Sprite();
square.name = "sqr" + i;
square.addChild(new Bitmap(new BitmapData(20, 20, false, 0)));
square.x = 5 + 25 * i;
square.addEventListener(MouseEvent.CLICK, myFunctions[i]);
stage.addChild(square);
}
No properties through dynamic objects, no custom class, no loose functions, no scope overlap. Just what logic expects it to be: you're simply passing arguments to it.
And to remove every listener properly, you can do it like this later:
for (i = 0; i < myFunctions.length; i++) {
square = stage.getChildByName("sqr" + i) as Sprite;
trace("Before (#" + (i+1) + "): " + square.hasEventListener(MouseEvent.CLICK));
square.removeEventListener(MouseEvent.CLICK, myFunctions[i]);
trace("After (#" + (i+1) + "): " + square.hasEventListener(MouseEvent.CLICK));
stage.removeChild(square);
}
IMHO this is the simplest yet most solid way to do it.