Chapter 13. Working with Events

<feature><title>In This Chapter</title> </feature>

Events drive applications. Nearly everything that happens in an ActionScript 3.0 application is triggered by events. There are two basic types of events: user and system. When a user clicks a button or types on the keyboard events are fired. These are examples of user events.System events are those which occur because of something based on time or asynchronous operations. For example, loading an external resource might trigger a load complete or a load error event.

In this chapter, we’ll look at what events are, what design problems they solve, how they related to known design patterns, and how they are used in ActionScript 3.0.

Understanding Events

Traditional, non-event-driven applications are susceptible to problems that give rise to the motivation for events and a unified event model. There are two primary problems with the traditional approach:

  • Tight coupling: In a traditional approach, the object that initiates something and the object that responds are tightly coupled, typically in a one-to-one relationship. For example, in the traditional approach, when a user clicks a button, the button might trigger the invocation of a callback method. Although this technique might work, it has significant shortcomings. What happens when you want several objects to respond to a button click rather than just one? What happens if you accidentally override the callback method? These problems highlight some of the reasons we strive for loosely coupled objects when designing applications.

  • Inconsistent manner of responding to operations: In a traditional approach to application design, synchronous and asynchronous operations require different ways of handling results. It’s far more advantageous to use a single consistent way to handle results. Events provide that.

Earlier versions of ActionScript use many different ways of responding to occurrences within the application. However, ActionScript 3.0 has one unified event model used across the board. At the core of this event model is the flash.events package of classes—namely the Event class and the EventDispatcher class.

The EventDispatcher class provides all the functionality to allow objects to register for event notifications. When an object registers with an event dispatcher for notifications for a particular event, the event dispatcher adds that object to a queue. When the event occurs, the event dispatcher notifies all the objects in the queue. The objects in the queue are called listeners, and in ActionScript 3.0 all listeners are functions/methods. When a listener is notified, it gets called and passed a parameter of type Event (or a subtype specific to the type of event). The event parameter provides the context for the event, including the type of event and the object that dispatched the event. This arrangement allows for the event dispatcher and the listener to know virtually nothing about one another at compile time, but at runtime, the listener can obtain a reference back to the dispatcher using the event parameter. This powerful design means that the dispatchers and listeners are loosely coupled. It also means that many listeners can register for notifications when an event occurs for just one dispatcher. Figure 13.1 illustrates this concept.

An event is handled.

Figure 13.1. An event is handled.

In ActionScript 3.0, the event model is closely related to a well-known design pattern called the Observer pattern. Although the Observer pattern is an important pattern, we don’t discuss it in any detail in this book because the built-in event model in ActionScript 3.0 already solves all the design patterns the Observer pattern is intended to solve.

Using Events

If you’re reading this book, we assume that you already know the basics of working with events because they are so fundamental to ActionScript. However, developers often know how to work with events without really understanding how they work at a basic level. In this section, we’ll look at the mechanics of events in ActionScript 3.0.

Understanding Event Elements

There are at least three elements required when working with events: event objects, event dispatchers, and event listeners. We’ve already talked about each of these briefly, but here we’ll discuss the mechanics of each.

All event objects are of type flash.events.Event or a subtype. Event subtypes are simply types that are specific to a particular sort of behavior. For example, events raised by mouse behavior are of type MouseEvent while events that occur because of a timer are of type TimerEvent. Usually subtypes define additional properties that provide information about the type of event. For example, MouseEvent defines a property called buttonDown, which indicates whether or not the mouse button is down at the time the event occurs. This is information that is important for events related to mouse behavior, but it wouldn’t be important for an event that occurs when data loads. Yet all event objects always have type and target properties that tell the listener what type of event it is and what object dispatched the event.

The second element that is always required is an event dispatcher. An event dispatcher is sometimes called a subject and sometimes called a target. The event dispatcher is the object that broadcasts an event. In ActionScript 3.0, all event dispatchers are instances of EventDispatcher, the built-in Flash Player class. Event dispatchers must allow listeners to register for notifications for events. The EventDispatcher API allows listeners to register. We’ll discuss this in more detail in the next section.

Event listeners in ActionScript 3.0 are always functions. You must register a listener with an event dispatcher for a specific event. When that event occurs, the dispatcher notifies the listener, and the listener gets called with an event parameter.

Registering Listeners

Listener objects register with the dispatcher object by calling the dispatcher’s addEventListener() method. At a minimum, the addEventListener() method requires two parameters: the name of the event and the listener.

dispatcher.addEventListener(eventName, listener);

ActionScript 3.0 implements proper method closure, which means that functions and methods always maintain their original scope. This is a significant change from previous versions of ActionScript which required workarounds to ensure that a listener would be called within the proper scope.

The following example creates a rectangular sprite, and it uses an event listener to move the rectangle to a random location each time the user clicks on it.

package {
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.display.StageScaleMode;
   import flash.display.StageAlign;

   public class Test extends Sprite {

      private var _rectangle:Sprite;

      public function Test() {

         stage.scaleMode = StageScaleMode.NO_SCALE;
         stage.align = StageAlign.TOP_LEFT;

         _rectangle = new Sprite();
         _rectangle.graphics.lineStyle(0, 0, 0);
         _rectangle.graphics.beginFill(0xFFFFFF, 1);
         _rectangle.graphics.drawRect(0, 0, 100, 50);
         _rectangle.graphics.endFill();
         addChild(_rectangle);

         _rectangle.addEventListener(MouseEvent.CLICK, onClick);
      }

      public function onClick(event:MouseEvent):void {
         event.target.x = Math.random() * 400;
         event.target.y = Math.random() * 400;
      }
   }
}

Because the event listener moves the event target to a random location, you can also use that same listener for a different target. In this next example, two event dispatchers use the same event listener. In this case, both the rectangle and the circle move to random locations when clicked.

package {
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.display.StageScaleMode;
   import flash.display.StageAlign;

   public class Test extends Sprite {

      private var _rectangle:Sprite;
      private var _circle:Sprite;

      public function Test() {

         stage.scaleMode = StageScaleMode.NO_SCALE;
         stage.align = StageAlign.TOP_LEFT;

         _rectangle = new Sprite();
         _rectangle.graphics.lineStyle(0, 0, 0);
         _rectangle.graphics.beginFill(0xFFFFFF, 1);
         _rectangle.graphics.drawRect(0, 0, 100, 50)
         _rectangle.graphics.endFill(); 
         addChild(_rectangle);

         _circle = new Sprite();
         _circle.graphics.lineStyle(0, 0, 0);
         _circle.graphics.beginFill(0xFFFFFF, 1);
         _circle.graphics.drawCircle(0, 0, 50);
         _circle.graphics.endFill();
         _circle.x = 100;
         _circle.y = 100;
         addChild(_circle);

         _rectangle.addEventListener(MouseEvent.CLICK, onClick);
         _circle.addEventListener(MouseEvent.CLICK, onClick);
      }

      public function onClick(event:MouseEvent):void {
         event.target.x = Math.random() * 400;
         event.target.y = Math.random() * 400;
      }
   }
}

Removing Event Listeners

On the flip side of adding event listeners is removing event listeners. Generally it’s advisable to remove event listeners whenever you no longer need to listen for a particular event. You can achieve this by using the removeEventListener() method. The removeEventListener() method accepts two parameters: the event name and the listener, and it removes the listener for the particular event for the dispatcher from which you call the method. The following code removes onClick() as an event listener for the click event.

_circle.removeEventListener(MouseEvent.CLICK, onClick);

Understanding Event Phases

There are two types of event dispatches: display objects on the display list and all other types. When an object that is not on the display list dispatches an event, it notifies only those listeners that are registered directly with the dispatcher. For example, when a URLLoader object dispatches a complete event, the only listeners that receive the notification are those registered directly with the URLLoader. However, when a display object on the display list dispatches events, the event flow is triggered. The event flow consists of three phases: capture, target, and bubble. We’ll talk about each of these phases next.

The Capture Phase

The first phase of the event flow is called the capture phase. In this phase, Flash Player is looking for the object that trigged the event. In doing so, it starts at the root display object and uses a drill-down approach through the hierarchy of the display list until it finds the event’s target, meaning the object that actually dispatched the event.

By default, event listeners do not receive notifications during the capture phase. Instead, if you want to register a listener for the capture phase, you must pass a value of true for the third parameter of the addEventListener() method. Otherwise, if the parameter is omitted or false, the listener only receives notifications during the target and bubble phases. Here is an example that registers a listener for the capture phase:

object.addEventListener(MouseEvent.CLICK, onClick, true);

The capture phase may seem strange at first. And, in fact, it is not often used. However, it’s an important part of the event flow because it allows the application to trap events before they reach child targets. When you want to trap events and stop them from propagating to child elements, you must call the stopImmediatePropagation() method of the event object in the event handler. Here’s an example that adds to the previous examples by trapping click events so that they are never handled by the listeners for child elements:

package {
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.display.StageScaleMode;
   import flash.display.StageAlign;

   public class Test extends Sprite {

      private var _rectangle:Sprite;
      private var _circle:Sprite;
      private var _loader:Loader;

      public function Test() {

         stage.scaleMode = StageScaleMode.NO_SCALE;
         stage.align = StageAlign.TOP_LEFT;

         _rectangle = new Sprite();
         _rectangle.graphics.lineStyle(0, 0, 0);
         _rectangle.graphics.beginFill(0xFFFFFF, 1);
         _rectangle.graphics.drawRect(0, 0, 100, 50);
         _rectangle.graphics.endFill(); 
         addChild(_rectangle);

         _circle = new Sprite();
         _circle.graphics.lineStyle(0, 0, 0);
         _circle.graphics.beginFill(0xFFFFFF, 1);
         _circle.graphics.drawCircle(0, 0, 50);
         _circle.graphics.endFill(); 
         _circle.x = 100;
         _circle.y = 100;
         addChild(_circle);

         addEventListener(MouseEvent.CLICK, onStageClick, true);

         _rectangle.addEventListener(MouseEvent.CLICK, onClick);
         _circle.addEventListener(MouseEvent.CLICK, onClick);

      }

      public function onClick(event:MouseEvent):void {
         event.target.x = Math.random() * 400;
         event.target.y = Math.random() * 400;
      }

      public function onStageClick(event:MouseEvent):void {
         event.stopImmediatePropagation();
      }
   }
}

The Target Phase

After the capture phase is the target phase. The target phase occurs when the event target (the event dispatcher responsible for the event) is reached in the event flow. This is probably the most commonly used phase of the event flow because it is the phase during which listeners that are registered directly with an event dispatcher are notified. This is the phase illustrated by most of the examples throughout this chapter and this book.

The Bubble Phase

The last phase of the event flow is the bubble phase. It allows for events to bubble up the display list. The bubble phase occurs in the reverse order of the capture phase: starting from the target and moving upward to parent containers until the root is reached.

You don’t need to do anything different for event bubbling to work. You can simply register a listener to a container for any event that any child can dispatch, and the event listener will receive the notification during the bubble phase. For example, the following code achieves the same effect as an earlier example, but it registers the listener with the container rather than with the children:

package {
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.display.StageScaleMode;
   import flash.display.StageAlign;

   public class Test extends Sprite {

      private var _rectangle:Sprite;
      private var _circle:Sprite;
      public function Test() {

         stage.scaleMode = StageScaleMode.NO_SCALE;
         stage.align = StageAlign.TOP_LEFT;

         _rectangle = new Sprite();
         _rectangle.graphics.lineStyle(0, 0, 0);
         _rectangle.graphics.beginFill(0xFFFFFF, 1);
         _rectangle.graphics.drawRect(0, 0, 100, 50);
         _rectangle.graphics.endFill(); 
         addChild(_rectangle);

         _circle = new Sprite();
         _circle.graphics.lineStyle(0, 0, 0);
         _circle.graphics.beginFill(0xFFFFFF, 1);
         _circle.graphics.drawCircle(0, 0, 50);
         _circle.graphics.endFill(); 
         _circle.x = 100;
         _circle.y = 100;
         addChild(_circle);

         addEventListener(MouseEvent.CLICK, onClick);

      }

      public function onClick(event:MouseEvent):void {
         event.target.x = Math.random() * 400;
         event.target.y = Math.random() * 400;
      }
   }
}

Notice in this example that the event object parameter’s target property still references the actual target of the event (the circle or rectangle in this example) rather than the object for which the listener is registered (the container). If you want to retrieve a reference to the object to which the listener is registered, you can use the currentTarget property.

It’s also important to note that not all event types can bubble. Only those events for which the bubbles property is set to true can bubble.

Note

When you create a custom event, you can specify whether the event will bubble. The default is true.

Event Priority

Event priority is a little-used concept, but it is important to understand what it can do. When you add an event, you have the ability to set your listener’s priority. The higher the priority setting, the sooner your listener will get called. You can set the priority for a listener using the fourth parameter of the addEventListener() method.

Two listeners with the same priority level are called in the order they were added. It’s important to note that priorities are relevant only within a phase (capture, target, or bubble). The order of the phases of the event flow supersedes the priority level.

Weak References

The concept of weak references is particularly useful when adding listeners to objects. To understand why weak references are so good, you first need to understand a little about garbage collection. Garbage collection is how Flash Player cleans up memory that isn’t needed anymore; it’s important because otherwise applications would use more and more RAM until they required the system to restart. Flash Player 9 uses two systems called reference counting and mark and sweep.

Reference counting is not new to Flash Player. It is the traditional way in which Flash Player has run garbage collection. When you create an object in ActionScript, that object exists in memory. However, the object is useful only as long as there are references (such as variables) to that object. When no more references exist, it is safe to assume that the object is no longer used and can be garbage collected. Although this system is efficient, it is not accurate because it is possible, through circular references, to have references still in existence even though none of the references is actually accessible. For example, two objects can have references to one another. If the references to those objects are deleted, we would expect that the objects themselves would be garbage collected. However, because they have references to one another, they remain in memory.

The mark-and-sweep garbage collection system solves the circular reference problem by traversing all active (accessible) nodes within an application. Any objects that exist outside of the active nodes can be assumed to be no longer in use, and they can be garbage collected.

Although the two garbage collection systems work in conjunction to efficiently and effectively manage memory usage, they do not compensate for incorrect programming. It’s important that you always remove event listeners when you no longer need to use them. If you register an event listener using normal references, it will not get garbage collected even if you delete the listener or the object containing the listener because the event dispatcher will still have a reference to it. Removing the event listener using removeEventListener() ensures that the event target no longer has a reference to the listener, and that action will allow it to be properly garbage collected after you’ve deleted the listener.

However, sometimes we can’t remove the listeners because our object is deleted elsewhere. This is where weak references come in handy. They allow for normal event listening functionality, but when the listener object is removed, the listener is removed from memory properly because the reference is weak and not counted by the reference counting function of the garbage collector.

You can specify that a listener should use a weak reference by registering it using a value of true for the fifth parameter to the addEventListener() method.

target.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);

Creating Event Dispatchers

Dispatchers (also known as subjects or targets) are the source of events. These are the objects that fire events. Earlier in this chapter, you saw how to listen for events. Many classes are already capable of dispatching events. However, now we’ll look at how to create custom classes that dispatch events.

Understanding Event Objects

All events use event objects. In the following sections, we’ll look at how to dispatch events, but first we need to look at how to create an event object.

All event objects must be instances of the flash.events.Event class (or one of its subclasses). Event objects have properties that store information about the event and methods for manipulating the event.

The simplest way to create an event object is to use the constructor of the Event class or one of its subclasses in a new statement. The constructor requires that you pass it a string indicating the event type. The following example creates a new event object for a change event:

var event:Event = new Event(Event.CHANGE);

Often it is easiest and most effective to use an existing event type (Event, MouseEvent, and so on) when possible. However, when that’s not possible, you can create a custom event type by subclassing Event. The following is an example of a custom event that extends the Event class:

package {

   import flash.events.Event;

   public class CustomEvent extends Event {

      private var _customData:Object;

      public function customData(value:Object):void {
         _customData = value;
      } 

      public function get customData():Object {
         return _customData;
      }

      public function CustomEvent(type:String, bubbles:Boolean = false,
 cancelable:Boolean = false) {
         super(type, bubbles, cancelable); 
      }

   }

}

Understanding Event Target Properties

Events have both a target and a currentTarget property. This is relevant when an event is being dispatched into the event flow. It tells us the difference between the object we registered with and the object that dispatched the event. The target is the object that originates the event, while the currentTarget is the object with which you registered the listener. During the target phase, those two properties reference the same object. However, if you get an event during the capture or bubble phase, the two properties are different.

Default Behavior of Events

When most events are fired, the responses to those events are defined in the listeners. But in some cases, the responses are so common and predictable that there are default behaviors that occur inside Flash Player. A good example of this is the use case of a user typing in a text field. The default behavior is that the keystrokes fire events that populate the text field with the corresponding characters. However, there may be times when you don’t want this default behavior to happen. To stop the default behavior, you simply call the preventDefault() method of the event object. You can check the status of this behavior by calling the isDefaultPrevented() method. Only events with the cancelable property set to true can be canceled.

Stopping Propagation

In some cases, you might want to stop the event flow dead in its tracks. To accomplish this, you use the stopPropagation() or stopImmediatePropogation() method of the event object. The methods are nearly identical and differ only in regards to when the stop is executed. If you call stopPropagation(), the event is not allowed to continue up the display list, but the currentTarget is allowed to finish dispatching the event to its listeners. The stopImmediatePropogation() method stops the event flow completely, and the currentTarget is not allowed to finish.

Dispatching Events Through Inheritance

The flash.events.EventDispatcher class is at the heart of the event model in ActionScript 3.0. All native Flash Player classes that dispatch events inherit from EventDispatcher. This is the simplest and most common way to add event dispatching functionality to a class. You can do this directly by creating a class that extends EventDispatcher. Optionally, because MovieClip, Sprite, and many other core classes already extend EventDispatcher, you can inherit the event functionality indirectly by extending those classes as well.

The EventDispatcher class defines the behavior that adds, queues, and removes event listeners. It also enables the dispatcher to actually dispatch the event to the listeners. We’ve already seen the behavior for adding and removing events using addEventListener() and removeEventListener(). Now we’ll look at how to actually dispatch events.

The dispatchEvent() method is a method of EventDispatcher, and it is what triggers an event to be broadcast. When you extend EventDispatcher, you can call dispatchEvent() within the class.

Caution

Although the dispatchEvent() method is public, it’s a good idea to leave event dispatching up to the subject objects. Objects triggering events to be dispatched from other subject objects can lead to un-maintainable code that is difficult for other developers to read. Subjects should always be responsible for dispatching their own events.

The only parameter you need to pass into the dispatchEvent() method is an Event object. We’ll talk more about Event objects and their behavior later in this chapter. However, here is a basic example:

dispatchEvent(new Event(Event.CHANGE));

This example dispatches a change event to all listeners that are currently registered to receive notifications for change events for instances of the class within which the dispatchEvent() method appears.

The IEventDispatcher Interface

ActionScript 3.0 supports only single inheritance. This means that if you’re already extending a class that doesn’t itself extend the EventDispatcher class, you must find another way to access the event dispatching functionality. For this reason, Flash Player includes an IEventDispatcher interface. By programming to this interface, you can get the EventDispatcher functionality into your class through composition instead of through inheritance. The following is an example of how you’d implement the IEventDispatcher interface:

package {

   import flash.events.Event;
   import flash.events.IEventDispatcher;
   import flash.events.EventDispatcher;

   public class Dispatcher implements IEventDispatcher {

      private var eventDispatcher:EventDispatcher;

      public function Dispatcher() {
         eventDispatcher = new EventDispatcher(this);
      }

      public function addEventListener(type:String, listener:Function,
 useCapture:Boolean=false, priority:int=0.0, useWeakReference:Boolean=false):void {
         eventDispatcher.addEventListener(type, listener, useCapture, priority, 
 useWeakReference);
      }

      public function dispatchEvent(event:Event):Boolean {
         return eventDispatcher.dispatchEvent(event);
      }

      public function hasEventListener(type:String):Boolean {
         return eventDispatcher.hasEventListener(type);
      }
      public function removeEventListener(type:String, listener:Function, useCapture:
Boolean=false):void {
         eventDispatcher.removeEventListener(type, listener, useCapture);
      }

      public function willTrigger(type:String):Boolean {
         return eventDispatcher.willTrigger(type);
      }

   }

}

Passing a target reference into the EventDispather constructor is necessary when using composition. The reference tells the EventDispatcher which object to use as the target for events dispatched by your class. This is not necessary for classes that extend EventDispatcher.

An Example Working with Events

In this example, we’re going to create and implement a custom icon button in order to better understand events. The button has three elements: an icon, a text field, and a background. Each of these elements triggers different events. We can examine these events to see exactly how the event flow works.

Creating the IconButton Class

The first thing we need to do is create our IconButton class. We will generate all the elements for this class inside its constructor. The background will be a Shape object. We’ll simply draw a gray rectangle on that shape. The next element is our icon. For our example, this icon is a simple square, so we’ll use a Sprite. Even though we’re still just drawing a shape, we want to use the Sprite class because it allows the icon to dispatch mouseOver and mouseOut events. The last element is the label, which is a text field that will hold the button label text.

We’ll also add a couple listeners to the icon Sprite so we can have a rollover on that item. When the user rolls over the icon, we’ll use a ColorTransform object to make the icon white. When the user rolls off the icon, it will go back to grey.

package {

   import flash.display.Shape;
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.geom.ColorTransform;
   import flash.text.TextField;
   import flash.text.TextFieldAutoSize;

   public class IconButton extends Sprite {
   public function IconButton(text:String) {

      // Create the button background, drawing a
      // rectangle.
      var background:Shape = new Shape();
      background.graphics.beginFill(0xEEEEEE, 1);
      background.graphics.drawRect(0, 0, 100, 20);
      background.graphics.endFill();
      addChild(background);

      // Create the icon, and also draw a rectangle 
      // within the icon.
      var icon:Sprite = new Sprite();
      icon.graphics.beginFill(0xAAAAAA, 1);
      icon.graphics.drawRect(4, 4, 12, 12);
      icon.graphics.endFill();

      // Listen for mouse events on the icon.
      icon.addEventListener(MouseEvent.MOUSE_OVER, onIconMouseOver, false, 0, true); 
      icon.addEventListener(MouseEvent.MOUSE_OUT, onIconMouseOut, false, 0, true);
      addChild(icon);

      // Create a text field to use as a label.
      var label:TextField = new TextField();
      label.height = 20;
      label.x = 22;
      label.text = text;
      label.selectable = false;
      label.autoSize = TextFieldAutoSize.LEFT; 
      addChild(label);
     }

     private function onIconMouseOver(event:MouseEvent):void {
       var colorTransform:ColorTransform = new ColorTransform();
       colorTransform.color = 0xFFFFFF;
       (event.target as Sprite).transform.colorTransform = colorTransform;
     }

     private function onIconMouseOut(event:MouseEvent):void {
       var colorTransform:ColorTransform = new ColorTransform();
       colorTransform.color = 0xAAAAAA;
        (event.target as Sprite).transform.colorTransform = colorTransform;
     }

   }

}

The preceding code is fairly basic. When the user moves the mouse over the icon, the icon changes color using events. Next we’ll look at how to use this button.

Creating the Main Class

Now that we have our IconButton class, we need to create a simple main class that uses the button We’ll do this with a ButtonExample class that will serve as the main class for this project. In the constructor, we create an instance of the IconButton class, add a couple event listeners, and add the IconButton instance to our display list. Notice that we add two listeners that are nearly the same. We’re doing this to illustrate the useCapture functionality. The second listener has the useCapture parameter set to true. Each of these listeners is treated separately, so our class should get the MOUSE_UP event twice: once during the capture phase and the second during either the target or bubble phase.

That last statement may seem a bit confusing. What determines whether the MOUSE_UP event will be dispatched to our ButtonImp class during the target phase versus the bubble phase? Well, it all comes down to which element inside our button is clicked on. If the user clicks on the icon Sprite, then the icon is going to be the target of the event. Because our ButtonImp class registered itself directly to the IconButton class, we wouldn’t get that event during the target phase. However, the MOUSE_OVER and MOUSE_OUT events inside the IconButton class would occur in the target phase because the IconButton registered itself directly to the icon Sprite. The same would be true if the user clicked on the TextField. Therefore, the ButtonImp gets those events through bubbling.

Recall that we also have a third element in our button: the background Shape. If the user clicks on it, the Shape does nothing because Shape doesn’t dispatch a MOUSE_UP event. Therefore, the IconButton would dispatch the event and our ButtonImp would get its event during the target phase.

The following code is our ButtonImp class. Notice the trace statements in the listener function. These trace statements allow you to see the event’s phase and the difference between the target and currentTarget properties for each event.

package {

   import flash.display.Sprite;
   import flash.events.MouseEvent;

   public class ButtonExample extends Sprite {

      public function ButtonExample() {
         var button:IconButton = new IconButton("Test");
         button.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, false, 0, true);
         button.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, true, 0, true);
         addChild(button);
      }

      private function onMouseUp(event:MouseEvent):void {
         trace("phase: " + event.eventPhase);
         trace("target: " + event.target);
         trace("currentTarget: " + event.currentTarget);
      }

   }

 }

Summary

The event framework in ActionScript 3.0 offers a solid and consistent way to handle events. It improves on earlier versions of Flash by unifying all events under one standardized system. The new event bubbling and weak reference features are also very valuable. Overall, the new event framework is a great addition to ActionScript 3.0 and will surely play a major part in all your ActionScript projects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.115.21