Table of Contents

10.6 Listener Events

Conceptually, listener events are similar to event handler properties. Like event handler properties, listener events are handled with a specially named object method (i.e., a property containing a callback function) that is invoked when a given event occurs. However, listener events add two important event handling features:

For example, suppose we want to center a text field, title_txt, in a movie by setting its position each time the movie changes size. Consulting the Language Reference, we determine that when a movie changes size the Stage.onResize( ) listener event is triggered. Our text field is not an instance of Stage, yet we want it to respond to Stage.onResize( ). This is no problem. Because State.onResize( ) is a listener event, it will let title_txt (and any other object) sign up to be notified when onResize( ) occurs.

Here's how it works. First, we create our onResize( ) method directly on title_txt, just as we created our earlier event handler properties:

title_txt.onResize = function ( ) {
  // Center the text field.
  // Stage.width and Stage.height always store the current movie dimensions.
  // In the callback function body we refer to title_txt as this.
  this._x = Stage.width/2 - this._width/2;
  this._y = Stage.height/2 - this._height/2;
}

Next, we must tell the Stage object that we want it to execute title_txt's onResize( ) method when the onResize( ) event occurs. This step is known as "adding a listener." The so-called listener is the object (in our case, title_txt) that wishes to receive event notifications from the event source or, synonymously, the event broadcaster (in our case, Stage). All listener event sources provide a special method, addListener( ), that is used to register new listeners. For example, here's how we add title_txt as a Stage listener:

Stage.addListener(title_txt);

Henceforth, when the Stage.onResize( ) event occurs, title_txt.onResize( ) is invoked. In fact, as a Stage listener, title_txt will receive event notices for all of Stage's listener events (though in Stage's case, it defines only one listener event). Some event sources define both event handler properties and listener events. In such a case, a listening object will receive notifications for the listener events only, not the event handler properties. Each object's supported listener events and event handler properties are listed in the ActionScript Language Reference.

Generally, an event is implemented as a handler property when it is of interest only to the object that generates it. Listener events are more common when many different kinds of objects have interest in a single event (for example, a movie clip, a button, and a text field may all want to know when a movie is resized, so Stage.onResize( ) is a listener event).

Here is the general syntax for creating an event listener (an object that defines a method that handles a listener event):

listenerObject.eventName = function ( ) {
  statements
}
eventSource.addListener(listenerObject);

The listenerObject can be any object. The eventName is the name of the predefined event to listen for (e.g., onResize in title_txt.onResize( )). The eventSource is the object that notifies listenerObject when eventName occurs. Therefore, unless eventName is one of the events broadcast by eventSource, the event listener method will never be executed. For details on specific event sources see the Key, Mouse, Selection, TextField, and Stage objects in the Language Reference.

Getting back to our example, suppose we want to center a second text field, subtitle_txt, underneath title_txt. We follow the same process we did with title_txt. First, we create our onResize( ) method directly on subtitle_txt:

subtitle_txt.onResize = function ( ) {
  this._x = Stage.width/2 - this._width/2;
  this._y = (Stage.height/2) + (title_txt._height/2) + 10;
}

Then, we register subtitle_txt as a Stage listener:

Stage.addListener(subtitle_txt);

Note that the onResize( ) methods must be written appropriately for each object that we wish to reposition. In this case, we reposition title_txt based on the height and width of the Stage and the text object itself. We offset subtitle_txt vertically, relative to the center of the Stage and title_txt's height.

In order to function properly, the Stage.onResize( ) event requires Stage.scaleMode and Stage.align to be set, as shown in Example 10-1.

Adding a listener to an event source is sometimes referred to as subscribing the listener. We now have two text fields�each with their own independent onResize( ) method�that respond to a single event, Stage.onResize( ). We can also register movie clips, buttons, or any other objects as Stage listeners, allowing for a entire movie's layout to adjust dynamically when the movie is resized. When multiple listeners are registered to a single event source, their methods are executed in the order the listeners were added.

To remove (or unsubscribe) any listener from an event source, use the removeListener( ) method. For example, the following code causes subtitle_txt to stop receiving onResize events, so it won't reposition itself when the movie is resized:

Stage.removeListener(subtitle_txt);

The general form to remove a listener is:

eventSource.removeListener(listenerObject);

Example 10-1 shows our text field centering code in its entirety. To test it, attach the code to the first frame of the main timeline in a new movie; then export the movie and try resizing the movie's window. For complete information on building resizable interfaces, see the Stage object in the ActionScript Language Reference.

Example 10-1. Keeping two text fields centered in a movie
// Set the scaling behavior of the movie
Stage.scaleMode = "noScale";
Stage.align = "LT";
   
// Create the first text field
this.createTextField("title_txt", 1, 0, 0, 180, 20);
title_txt.text = "Welcome to my website.";
title_txt.border = true;
   
// Assign its listener callback function
title_txt.onResize = function ( ) {
  this._x = Stage.width/2 - this._width/2;
  this._y = Stage.height/2 - this._height/2;
}
   
// Create the second text field
this.createTextField("subtitle_txt", 2, 0, 0, 180, 20);
subtitle_txt.text = "Thanks for visiting.";
subtitle_txt.border = true;
   
// Assign its listener callback function
subtitle_txt.onResize = function ( ) {
  this._x = Stage.width/2 - this._width/2;
  this._y = (Stage.height/2) + (title_txt._height/2) + 10;
}
   
// Register the text fields as Stage listeners
Stage.addListener(subtitle_txt);
Stage.addListener(title_txt);

Table of Contents