EventDispatcher is the base class for all objects that can be a target for events. Many native classes inherit from this class with their own appropriate events:
[code]
import flash.display.Sprite;
import flash.events.MouseEvent;
// this draws a button listening to a mouse event
var sprite:Sprite = new Sprite();
sprite.addEventListener(MouseEvent.CLICK, onClick);
import flash.utils.Timer;
import flash.events.TimerEvent;
// this creates a timer listening to a timer event
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER , onTimer);
timer.start();
[/code]
event.target is the object associated with the listening function, or its scope:
[code]
function onClick(event:MouseEvent):void {
trace(event.target); // Sprite
}
function onTimer(event:TimerEvent):void {
trace(event.target); // Timer
}
[/code]
The listener object, also known as the event handler, is called when the event happens (the onClick or onTimer functions in the preceding example). It takes a single event instance as a parameter.
The dispatcher, the mechanism that monitors the event, saves a reference of the listener to call back when an event occurs, and its target, in a queue.
You must use removeEventListener to remove these references from memory. Removing the target will not do it:
[code]
sprite.removeEventListener(MouseEvent.CLICK, onClick);
timer.removeEventListener(TimerEvent.TIMER , onTimer);
[/code]
Event Propagation
For display objects, an event starts from the root parent, travels down the tree to the object that is registered, and travels back up.
Event propagation has three phases. The capturing phase occurs when the propagated event, after being received by the system, starts its search from the root parent. The targeting phase occurs when the event reaches the object registered for it. The bubbling phase is the event following the path in reverse.
Note that the event only needs to traverse until it finds the object that is registered. Regardless, you can see how keeping your displayList shallow would have a significant impact on performance.
If you want to stop the event during its journey, you can use the following methods. The latter method prevents other remaining event listeners from executing. This is a good technique for optimizing your mobile application:
[code]
function eventVisiting(event:MouseEvent):void {
if (event.target) {
event.stopPropagation();
// OR
event.stopImmediatePropagation();
}
}
[/code]
To prevent objects from being targeted, you can use:
[code]
someObject.mouseEnabled = false;
someParent.mouseChildren = false;
[/code]
Events for objects that are not on the displayList flow directly to the target.
One Listener for Many Children
Let’s demonstrate the benefit of the event model. Imagine that you have many objects that need to transform in response to a mouse event. In this example, their scale changes upon a click.
Create the objects:
[code]
import flash.display.Sprite;
var sw:int = stage.stageWidth;
var sh:int = stage.stageHeight;
for (var i:int = 0; i < 20; i++) {
var temp:Sprite = createSprite();
}
function createSprite():Sprite {
var temp:Sprite = new Sprite();
var g:Graphics = temp.graphics;
g.beginFill(0x3399FF, 1);
g.drawRect(0, 0, 100, 75);
g.endFill();
temp.x = Math.random()*sw;
temp.y = Math.random()*sh;
}
[/code]
Put them in a container instead of adding them to the stage:
[code]
var container:Sprite = new Sprite;
addChild(container);
for (var i:int = 0; i < 20; i++) {
var temp:Sprite = createSprite();
addChild(temp);
}
[/code]
Add a single listener to the container instead of creating a listener for each object:
[code]
import flash.events.MouseEvent;
var objectClicked:Sprite;
container.addEventListener(MouseEvent.CLICK, onObjectClick, false);
function onObjectClick(event:MouseEvent):void {
event.stopPropagation();
objectClicked = event.target as Sprite;
objectClicked.scaleX = objectClicked.scaleY = Math.random();
}
[/code]
Generic and Custom Events
In some situations, you may need to send an event that is not built in. In such cases, make your class a subclass of the EventDispatcher or create a member variable as an EventDispatcher.
In this example, we load an external opening animation. When it reaches its last frame, we are notified so that we can unload it and continue with the application.
Add an EventListener and use dispatchEvent to trigger the event:
[code]
package {
public class myClass extends EventDispatcher {
public function myClass() {
loadOpening();
}
function loadOpening():void {
// load a swf with a timeline animation
background.addEventListener(“OpeningDone”, removeBackground);
}
function removeBackground(event:Event):void {
removeChild(background);
}
}
}
[/code]
The code on the last frame of the opening .swf is:
[code]
stop();
dispatchEvent(new Event(“OpeningDone”));
[/code]
In the current event model, the listener function only receives one parameter: the event. If you want to pass additional parameters, you need to write your own custom class that inherits from the Event class. In the following example, the CustomEvent class has an event of type CONNECTED. It passes a parameter called parameters of type Object:
[code]
package {
import flash.events.Event;
final public class CustomEvent extends Event {
public static const CONNECTED:String = “connected”;
public var parameters:Object;
public function CustomEvent(type:String, parameters:Object = null) {
// type, bubbles, cancelable
super(type, true, true);
this.parameters = parameters;
}
// this is needed if the event is re-dispatched
public override function clone():Event {
return new CustomEvent(this.type, this.parameters);
}
}
}
addEventListener(CustomEvent.CONNECTED, onConnected);
dispatchEvent(new CustomEvent(CustomEvent.CONNECTED, {name:”somebody”});
[/code]