Chapter 3. Properties, Methods, and Events

IN THIS CHAPTER

Jump Right In

Properties

Events

Methods

Event Propagation

Frame and Timer Events

Removing Event Listeners

What’s Next?

In addition to the core language fundamentals reviewed in the previous chapter, you will find that the majority of your scripts are written using properties, methods, and events. These are the basic building blocks of most scripted tasks and allow you to get and set characteristics of, issue instructions to, and react to input from, many assets.

This is what we’ll be covering in this chapter:

  • Jump Right In. Get your feet wet right away by starting the chapter with a simple practical example. Adapt the Hello World! example by conveying your greeting one character at a time.

  • Properties. Properties are somewhat akin to adjectives, in that they describe the object being modified or queried. For example, you can check or set the width of a button. Most properties are read-write, in that you can both get and set their values. Some properties, however, are read-only, which means you can ask for, but not change, their values.

  • Events. Events are the catalysts that trigger the actions you write, setting properties and calling methods. For instance, a user might click the mouse button, which would then result in a mouse event. If you write code to react when that event is detected, the event can then cause a function to execute performing the desired actions.

  • Methods. Methods are a bit like verbs. They tell objects to do something, such as play and stop. In some cases, methods can be used to simplify the setting of properties. You might use a method called setSize(), for example, to simultaneously set the width and height of something. Other methods are more unique, such as navigateToURL(), which instructs a browser to display a web page.

In this chapter, you will build a utility that will demonstrate each of these ActionScript structures. Using mouse and keyboard events, you will manipulate several properties, as well as execute a few methods. The majority of ActionScript objects—from visual assets like movie clips to code-only objects like timers—have properties, methods, and events.

For simplicity, we’ll focus primarily on the movie clip. Using the movie clip to centralize our discussion will make it easier for you to expand your examples on your own, as you look for other attributes to manipulate. Once you are comfortable with how properties, methods, and events work, it will be relatively easy to learn about other objects.

Jump Right In

This chapter’s first script again builds on the Hello World! theme, this time concentrating on properties, methods, and events. In this example, we’ll display our salutation one character at a time. As with prior chapters, we’ll explain this code briefly, and elaborate as the chapter continues. This script is found in the hello_world_prop_event.fla source file.

1    var txtFld:TextField = new TextField();
2    addChild(txtFld);
3
4    txtFld.textColor = 0xFF0000;
5
6    var str:String = "Hello World!";
7    var len:int = str.length;
8    var i:int = 0;
9
10    this.addEventListener(Event.ENTER_FRAME, onEnter, false, 0, true);
11    function onEnter(evt:Event):void {
12        txtFld.appendText(str.charAt(i));
13        i++;
14        if (i > len) {
15            removeEventListener(Event.ENTER_FRAME, onEnter);
16        }
17    }

Lines 1 and 2 again create a text field and add it to the display list so the user can see it. Line 4 sets textColor, a basic property of the text field, coloring the text red. This approach to text coloring is a quick solution, but it colors all text in the field. In Chapter 10, you’ll learn how to exercise more precise control over text, allowing you to color individual segments of text.

Note

ActionScript 3.0 uses hexadecimal notation to express colors as numbers. The format of a simple color is 0xRRGGBB. 0x tells the compiler the number is a hexadecimal value and replaces the # symbol used to express the same value as a string, as in HTML. The next three character pairs represent red, green, and blue and must represent values from 0 to 255. To do this, hexadecimal numbers use base16 (instead of base10 like a decimal number) and each character uses not only 0–9 but also A–F. 00 is no color and FF is all color, for each pair. 0x000000 is black (no colors), and 0xFFFFFF is white (all colors). The color used in this script is all red, no green, and no blue.

Lines 6 through 8 create and populate variables including a string, the number of characters in that string, and a counter’s initial value. The remainder of the script is an enter frame event listener to add the string text to the end of the field, character by character. Each time the event is received, line 12 uses the string method charAt() to determine the character at position i in the string, and the appendText() method to add that character to the field. The i counter is then incremented and, if it exceeds the number of characters in the field, the listener is removed, halting the process. The result is that “Hello World!” is added to the field, one character at a time.

Properties

If you think of properties as ways of describing an object, they become second nature. Asking where a movie clip is, for example, or setting its width, are both descriptive steps that use properties.

In Chapter 2, we briefly discussed the object model and dot syntax that bring order and structure to ActionScript as well as many other scripting and programming languages. The first step in using a property is to determine which object you want to manipulate. For example, you might want to affect a movie clip on the stage with an instance name of box. The instance name is important because there may be multiple movie clips on stage, but you may want to alter only one. So you need to be able to differentiate which clip to change.

It’s easy to give a movie clip on the stage an instance name. Select it and type the name in the upper portion of Flash Professional’s Properties panel, as seen in Figure 3-1. (You’ve also learned how to create objects, such as text fields, entirely from code, and you’ll be doing that more and more as the book progresses.)

Giving a movie clip an instance name in Flash Professional CS5’s Properties panel
Figure 3-1. Giving a movie clip an instance name in Flash Professional CS5’s Properties panel

The syntax for manipulating a property with ActionScript requires that you follow the instance name with a dot (period) and the property name. To get you started, we’ll show you the syntax for making several changes to movie clip properties in the following table. Then, when we demonstrate how to handle events in the next section, we’ll change these properties interactively. The following examples assume that a movie clip with an instance name of box is on the stage, and Figure 3-2 demonstrates the visual change made by each property. The light-colored square is the original state before the movie clip is affected. (The alpha property shows only the final state, and the dashed stroke for the visible property is only to show that the box is not visible.)

Changes to movie clip properties
Figure 3-2. Changes to movie clip properties

Table 3-1 shows nine movie clip properties with sample syntax and notes on each property’s unit of measure and possible sample range of values.

Table 3-1. Movie clip properties

Description

Property

Syntax for Setting Value

Units and/or Range

Location

x, y

box.x = 100;

box.y = 100;

Pixels

Scale

scaleX, scaleY

box.scaleX = 0.5;

box.scaleY = 0.5;

Percent / 0–1

Dimensions

width, height

box.width = 72;

box.height = 72;

Pixels

Rotation

rotation

box.rotation = 45;

Degrees / 0–360

Transparency

alpha

box.alpha = 0.5;

Percent / 0–1

Visibility

visible

box.visible = false;

Boolean

If you have experience with prior versions of ActionScript, you may notice a few changes in the property syntax. First, the properties do not begin with an underscore. This is a beneficial consistency introduced with ActionScript 3.0. Rather than varying property syntax, some with and some without leading underscores, in 3.0 no properties begin with the underscore character.

Second, some value ranges that used to be 0–100 are now 0–1. Examples include scaleX, scaleY, and alpha. Instead of using 50 to set a 50% value, specify 0.5.

Finally, the first scaling method uses properties scaleX and scaleY, rather than _xscale and _yscale, which are their ActionScript 1.0 and 2.0 equivalents. Typically, ActionScript 3.0 properties will cite the x and y version of a property as a suffix to make referencing the property easier.

Table 3-1 shows syntax only for setting properties for the box movie clip. Getting the value of a property is just as easy. For example, if you wanted to trace the movie clip’s alpha value, or store it in a variable, you could write either of the following, respectively:

trace(box.alpha);
var bAlpha:Number = box.alpha;

Note

In Chapter 2, you learned that ++ adds 1 and -- subtracts 1 from a variable. You can also use these operators with properties.

The following code uses += to change the rotation of the box movie clip. Rather than adding just 1 to the left side of the equation, += will add whatever value is on the right side of the equation. The operators -=, *=, and /= function similarly—subtracting, multiplying, or dividing the left side of an equation by the value on the right of the operator. These are called compound assignment operators because they simultaneously alter and assign values.

This code will add 20 degrees to the movie clip’s rotation:

box.rotation += 20;

This is equivalent to, but shorter than:

box.rotation = box.rotation + 20;

Events

Events make the Flash world go ’round. They are responsible for setting your scripts in motion, causing them to execute. A button can be triggered by a mouse event, text fields can react to keyboard events—even calling your own custom functions is a means of issuing a custom event.

Events come in many varieties. In addition to the obvious events like mouse and keyboard input, most ActionScript classes have their own events. For example, events are fired when watching a video, working with text, and resizing the stage. To take advantage of these events to drive your application, you need to be able to detect them.

In previous versions of ActionScript, there were a variety of ways to react to events. You could apply a script directly to a button, for example, and use the on(Release) approach. As the language matured, you could create event handlers and apply them remotely using instance names—for example, using myButton.onRelease. Finally, you could use event listeners, structures that listen for the occurrence of an event and execute a function, primarily with components or custom objects.

In the latest version of ActionScript, reacting to events is simplified by relying on one approach for all event handling. The ActionScript 3.0 event model uses event listeners regardless of the type of event or how it is used.

Using Event Listeners

The concept of event listeners is pretty simple. Essentially, you tell an object to listen for an event and react if that event occurs. Imagine that you’re sitting in a busy airport. Lots of things are going on around you, all of which can be thought of as events. If you had no particular reason to be at the airport, you might ignore all of these events. They would still occur, but you would not listen for them.

However, if you’re scheduled to depart on an upcoming flight, you might establish a few listeners. For example, you might listen for a loudspeaker announcement about your flight number but ignore everything else. Or, you might also listen for a loudspeaker announcement about your destination city. You might even plan to listen for a third event: the inclusion of your airline in an announcement.

In all cases, the reaction to these events would be to pay attention to the announcement hoping to learn more about your flight. Other events might still occur in the airport, including other announcements, but without listening for those events, they would wash over you without reaction.

ActionScript 3.0 event listeners work much the same way. Creating an event listener, in its most basic form, is fairly straightforward. The first item needed is the object that will listen for the event. A button is a good example to start with. The addEventListener() method is then used to assign a listener to that object. This method requires two arguments. The first argument is an event to listen for—one that is appropriate for your goal. For example, it makes sense for a button to listen for a mouse event, but less so to listen for the end of a video or a resizing of the stage. The second argument is a function to execute when the event is heard.

Here’s an example of code that uses a button with the instance name rotate_right_btn and a function called onRotateRight(). This can be found in the simple_event_listener.fla source file.

1    rotate_right_btn.addEventListener(MouseEvent.MOUSE_UP, onRotateRight);
2    function onRotateRight(evt:MouseEvent):void {
3        box.rotation += 20;
4    }

The event this code is listening for is a mouse up event—that is, when the mouse button is released while over the button. In ActionScript 3.0 syntax, events are typically grouped together in classes, and the event itself is usually defined as a constant—a variable that cannot be changed after it’s defined. Using constants, when you know a value will never change, reduces errors because the compiler will warn you if you try to change them. Constants are usually typed in all uppercase letters, with multiple words separated by underscores.

The MouseEvent class contains constants that refer to mouse events like MOUSE_UP and MOUSE_DOWN. Other examples of events are ENTER_FRAME, found in the Event class and used to react to playhead updates, and KEY_UP, found in the KeyboardEvent class, for reacting to user keyboard input. We’ll look at both of these events later on in this chapter.

Note

Separating mouse events into discrete up and down events allows you to react independently to each event. That is, you can assign one listener to the down event and another to the up event. This can be useful when creating draggable objects. You can start dragging on mouse down, and then stop dragging on mouse up, as you’ll see later in this chapter.

You can also use a simpler mouse event called CLICK, which requires both the down and up stages of the user’s click process to trigger a listener.

The second argument in the addEventListener() method, the function that is called when the event is received, is listed by name only, without the trailing parentheses. This is because you are referring to the function, not actually calling it. The listener will do that for you when the event is received. In this example, onRotateRight refers to the onRotateRight() function, defined in lines 2 through 4.

You will probably be familiar with the structure of this function from the discussion about functions in Chapter 2. To review the syntax, the braces define the function’s contents. In this case, line 3 adds 20 degrees to the current rotation value of the movie clip box. Also explained in Chapter 2, the void that follows the function name and parentheses indicates that no value is returned by the function.

However, new to our discussion of functions (see Chapter 2 if needed) is the fact that when functions are used in event listeners, the function requires a single parameter. This parameter receives information not from any ActionScript you write, but rather from the event. In this case, we arbitrarily named the parameter evt. (You may also see e or event used in other resources, but any valid parameter name will work.)

Without a parameter in place to receive that incoming data, you will get an error that says something like, “Argument count mismatch. Expected 0, got 1.” It will also tell you which function has the problem to make it easier to find. The error means that the function expected no arguments coming in, because no parameters were defined. Instead, one argument was received, resulting in a mismatch.

You’ll get used to this quickly, and reap the benefits. The data received usually contains useful information about the event and element that triggered the event. You can parse this information for use in the function. In keeping with good error reporting, the parameter should have a data type that matches the type of data being sent into the function. In this case, the event that triggered the listener was of type MouseEvent. Using this as the parameter data type will make sure that the listener receives only a MouseEvent, or the compiler will warn you to the contrary.

Note

It is also possible to type an event listener parameter with the more generic Event class, from which other built-in ActionScript 3.0 event classes are extended. This will allow more than one type of event to call the same function.

To illustrate the use of this argument data, let’s look at another mouse event example, found in the start_stop_drag.fla source file. This time, however, we’ll use two events, and use the incoming information to identify the target of the event—speaking generically, the object at which the event occurred. Specific to this case, the target is the object that was clicked.

1    myMovieClip.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
2    myMovieClip.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);
3    function onStartDrag(evt:MouseEvent):void {
4        evt.target.startDrag();
5    }
6    function onStopDrag(evt:MouseEvent):void {
7    stopDrag();
8    }

In this example, two event listeners are assigned to a movie clip in lines 1 and 2. One listens for a mouse down event, another listens for a mouse up event. They each invoke different functions. In the first function, the target property of the event, which is parsed from the function argument, is used to identify which object received the mouse event. This allows the onStartDrag() function in lines 3 through 5 to start dragging the movie clip that was clicked. The onStopDrag() function in lines 6 through 8 then stops all dragging when the movie clip receives a mouse up event.

The best thing about this example is that the target property identifies the movie clip without an instance name. This generic approach is very useful because it makes the function much more flexible. The function can act upon any appropriate object that is clicked and passed into its parameter. In other words, the same function could start and stop dragging any movie clip to which the same listener was added. The following additional lines, adding the same functionality to a second movie clip called myMovieClip2, demonstrate this:

9    myMovieClip2.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
10    myMovieClip2.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);

Note

A similar event property is currentTarget, which references the object to which the event listener is attached. When a listener is attached to a single movie clip (as in the cited example), target and currentTarget are the same because you click on the object with the listener. However, you’ll learn in the next chapter that events can pass from a parent clip down to any child clips within. When the listener is attached to the parent and you click on the child, target will still refer to the child, because that’s what you clicked. The currentTarget property, however, will refer to the parent movie clip because that’s the object to which the listener is attached. For more information, see “The Event Object,” an event-related post at http://www.LearningActionScript3.com.

Finally, this example’s last modification demonstrates that more than one object can also call the same listener function. It is possible, while dragging an object, to move your mouse so quickly that the mouse up event occurs outside the bounds of the object you’re dragging. If that occurs, the object would not receive the mouse up event, and the drag would not be stopped.

One way to get around this is to attach another listener to the stage, and set that listener to also call the onStopDrag() function. This way, whether your mouse up occurs over the movie clip or over the stage, the dragging will cease.

11    stage.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);

Using Mouse Events to Control Properties

Now we can combine the syntax we’ve covered in the Properties and Events sections to set up interactive control over properties. In the chapter03 directory of the accompanying source code for this book, you’ll find a file called props_events_methods_ui.fla. It contains nothing more than the example movie clip box and two buttons in the library that will be used repeatedly to change the five properties discussed earlier. The movie clip contains numbers to show which of its frames is visible, and the instance name of each copy of the button on the stage reflects its purpose. Included are move_up_btn, scale_down_btn, rotate_right_btn, fade_in_btn, and toggle_visibile_btn, among others. Figure 3-3 shows the layout of the file.

Layout of the props_events_ui.fla file
Figure 3-3. Layout of the props_events_ui.fla file

Starting with movement, we need to define one or more functions to update the location of the movie clip. There are two common approaches to this task. The first is to create one function in the keyframe in frame 1 for all movement that uses a conditional to decide how to react to each event. We’ll demonstrate that when we discuss keyboard events. For now, we’ll use the simpler direct approach of defining a separate basic function for each type of movement, as shown in the following script:

1    function onMoveLeft(evt:MouseEvent):void {
2        box.x -= 20;
3    }
4    function onMoveRight(evt:MouseEvent):void {
5        box.x += 20;
6    }
7    function onMoveUp(evt:MouseEvent):void {
8        box.y -= 20;
9    }
10    function onMoveDown(evt:MouseEvent):void {
11        box.y += 20;
12    }

Once the functions are defined, all you have to do is add the listeners to the appropriate buttons.

13    move_left_btn.addEventListener(MouseEvent.MOUSE_UP, onMoveLeft);
14    move_right_btn.addEventListener(MouseEvent.MOUSE_UP, onMoveRight);
15    move_up_btn.addEventListener(MouseEvent.MOUSE_UP, onMoveUp);
16    move_down_btn.addEventListener(MouseEvent.MOUSE_UP, onMoveDown);

This simple process is then repeated for each of the buttons on stage. The remaining script collects the aforementioned properties and event listeners to complete the demo pictured in Figure 3-3. The resulting file wires up one or more buttons for each property, all of which manipulate the movie clip in the center of the stage. The finished script can be found in the prop_events.fla source file.

17    scale_up_btn.addEventListener(MouseEvent.MOUSE_UP, onScaleUp);
18    scale_down_btn.addEventListener(MouseEvent.MOUSE_UP, onScaleDown);
19
20    rotate_left_btn.addEventListener(MouseEvent.MOUSE_UP, onRotateLeft);
21    rotate_right_btn.addEventListener(MouseEvent.MOUSE_UP,
22                                      onRotateRight);
23
24    fade_in_btn.addEventListener(MouseEvent.MOUSE_UP, onFadeIn);
25    fade_out_btn.addEventListener(MouseEvent.MOUSE_UP, onFadeOut);
26
27    toggle_visible_btn.addEventListener(MouseEvent.MOUSE_UP,
28                                        onToggleVisible);
29
30    function onScaleUp(evt:MouseEvent):void {
31        box.scaleX += 0.2;
32        box.scaleY += 0.2;
33    }
34    function onScaleDown(evt:MouseEvent):void {
35        box.scaleX -= 0.2;
36        box.scaleY -= 0.2;
37    }
38
39    function onRotateLeft(evt:MouseEvent):void {
40        box.rotation -= 20;
41    }
42    function onRotateRight(evt:MouseEvent):void {
43        box.rotation += 20;
44    }
45
46    function onFadeIn(evt:MouseEvent):void {
47        box.alpha += 0.2;
48    }
49    function onFadeOut(evt:MouseEvent):void {
50        box.alpha -= 0.2;
51    }
52
53    function onToggleVisible(evt:MouseEvent):void {
54        box.visible = !box.visible;
55    }

Methods

Methods, the verbs of the ActionScript language, instruct their respective objects to take action. For example, you can tell a movie clip to stop playing by using its stop() method. Like properties, methods appear consistently in the dot syntax that is the foundation of ActionScript, following the object calling the method. One way to tell methods apart from properties is that methods always end with parentheses—even when no values are required for the method to work. For example, if the movie clip box in the main timeline calls the stop() method, the syntax would be:

box.stop();

As they have properties, most ActionScript classes also have specific methods, and you can define your own methods by writing functions in your own custom classes. For the following demonstration, we’ll again focus on the movie clip from the prior example. This time, however, we’ll introduce another event class and show you how to control your movie clips with the keyboard.

Using Keyboard Events to Call Methods

Listening for keyboard events is very similar to listening for mouse events, with one significant exception: The target of the event listener is not always the object you wish to manipulate. When working with text, the text field may indeed serve well as the target of the keyboard events. When controlling movie clips, however, the stage itself is often a useful, centralized recipient of keyboard events.

Adding an event listener to the stage means that you can process all key events with a single listener, and then isolate only the desired key events with a conditional, issuing instructions accordingly. To simplify the syntax of this demonstration, we’ll use the switch form of conditional statements. The switch statement, discussed in Chapter 2, is simply a more easily readable if/else-if conditional structure.

This script in the following example can be seen in the methods_events.fla file in the accompanying source code. We’ll start by adding the listener to the stage. In this case, we’ll be looking for the key down event, which is specified using a constant like all predefined events, KEY_DOWN. This time, however, it’s part of the KeyboardEvent class. When the event is heard, our listener will call the onKeyPressed() function.

1    stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);

Next, we define the onKeyPressed() function, being sure to type the incoming argument value as KeyboardEvent. Finally, we parse the incoming event information for the keyCode property. The keyCode is a unique number assigned to each key and allows you to determine which key was pressed.

Note

One keyCode value is assigned to a key, so this value can’t be used directly for case-sensitive key checking—that is, uppercase “S” has the same keyCode as lowercase “s.” In case you need to analyze case sensitivity, the charCode property has a unique value for each character in each case. Finally, not all keys trigger keyboard events, as some keys are reserved for operating system use.

To specify each key in our script, we’ll use constants defined in the Keyboard class that each contain key codes. Using these constants, when they suit your purpose, is easier than having to know the keyCode value for each key. For example, you can reference the Enter/Return key as Keyboard.ENTER, the left arrow key as Keyboard.LEFT, and so on.

We’ll use five keys to execute five methods. When each desired key is pressed, it will execute the appropriate method, and then break out of the switch statement. We’ll also add a default state that will trace the keyCode of any other key pressed. The final script segment looks like this:

2    function onKeyPressed(evt:KeyboardEvent):void {
3        switch (evt.keyCode) {
4            case Keyboard.ENTER:
5                box.play();
6                break;
7            case Keyboard.BACKSPACE:
8                box.stop();
9                break;
10            case Keyboard.LEFT:
11                box.prevFrame();
12                break;
13            case Keyboard.RIGHT:
14                box.nextFrame();
15                break;
16            case Keyboard.SPACE:
17                box.gotoAndStop(3);
18                break;
19            default:
20                trace("keyCode:", evt.keyCode);
21        }
22    }

The first four methods are basic movie clip navigation options: playing, stopping, or sending the movie clip to the previous or next frame in its timeline. The last method sends the movie clip to a specific frame and then stops its playback. The methods are probably self-explanatory, with only the last method even using an argument—in this case, the frame number. If you do want additional information, however, we’ll put these and other navigation options to use in Chapter 5 when we discuss timeline control.

Note

Depending on your computer setup, some key events may not function properly in Flash Professional when using the Control ✓ Test Movie command. This is probably not an error but instead a result of Flash Player using keyboard shortcuts just like the Flash Professional application does. To test your key events, simply use the Control ✓ Disable Keyboard Shortcuts menu command to disable keyboard shortcuts in the Flash Professional integrated player (that is, after invoking Test Movie). Be sure to reenable the shortcuts, or you won’t be able to use Cmd+W (Mac) or Ctrl+W (Windows) to close the window, or use other familiar shortcuts.

Alternatively, you can test the movie in a browser using Cmd+F12 (Mac) or Ctrl+F12 (Windows). Also, the keyboard shortcut conflicts do not apply to the standalone Flash Player, in case you choose to use it for testing. Typically, double-clicking an SWF will open the SWF in the standalone player, but your system may be configured differently.

The combined source file, props_methods_events.fla, includes both the properties and methods examples in this chapter.

Event Propagation

So far in this book, we’ve been working primarily with movie clips, which are visual assets, or display objects. A display object is any ActionScript object that can be seen by the eye. That is, a movie clip is a display object, but a sound is not. For your audience to see a display object, it must be part of the display list—a list of everything a user can see at any given time. That is, you can create a display object (such as a text field), but not add it to the display list. This means the text field will exist, but the user won’t be able to see it.

The display list includes the stage, buttons, text fields, shapes, and bitmaps, as well as visual assets loaded at runtime like images and other SWFs—everything you can see, right down to the most deeply nested clip. We’ll explain the display list in greater detail in the next chapter, but we need a little background to get the most from our introduction to events. (It’s hard to talk about one without the other!)

One of the best things about ActionScript 3.0 is the way that events and the display list work together. This includes event propagation, in which events flow through objects in the display list, making it possible for multiple display objects to react to the same event. Certain events, such as mouse and key events, are not sent directly to the target of the event. That is, a button doesn’t immediately receive a mouse event when clicked. Instead, events are dispatched to the start of the display list, and the event propagates down to the event target, and then bubbles back up through the display list again. You can react to the event anywhere along this path.

Consider two movie clips (mc2 and mc3) within another movie clip (mc1) that is on the stage. Next, imagine that you click on the nested movie clip, mc2, making it the target of the event. When the event occurs, it is not dispatched directly to mc2, but rather to the display list. For a simple look at the route the event takes, the stage receives the event first, then the main timeline (also called the root), then the parent movie clip, mc1, and then the target of the event, mc2. After the target receives the event, it then propagates back up through the display list to mc1, the main timeline (root), and stage. Figure 3-4 depicts the journey of the event.

Not every display object is a part of this path, however—only those in the hierarchical line of the event flow. For example, mc3 is not a child or parent of any of the objects between the stage and the event target. Therefore, it’s outside this event flow, as seen in Figure 3-4.

Event propagation process
Figure 3-4. Event propagation process

Event propagation can be used to great advantage with just a little bit of planning. For example, let’s say both nested movie clips in Figure 3-4, mc2 and mc3, were designed to react to mouse over and mouse out events. Whenever the user rolled the mouse over either of the clips, it would change its alpha value. In the most direct case, you would attach a listener for each event to each movie clip. The following code shows the script for this scenario using two movie clips, folder0 and folder1, and Figure 3-5 depicts the result.

1    folder0.addEventListener(MouseEvent.MOUSE_OVER, onFolderOver);
2    folder0.addEventListener(MouseEvent.MOUSE_OUT, onFolderOut);
3    folder1.addEventListener(MouseEvent.MOUSE_OVER, onFolderOver);
4    folder1.addEventListener(MouseEvent.MOUSE_OUT, onFolderOut);
5
6    function onFolderOver(evt:MouseEvent):void {
7        evt.target.alpha = 0.5;
8    }
9
10    function onFolderOut(evt:MouseEvent):void {
11        evt.target.alpha = 1;
12    }
The effect of the changing alpha values using mouse over and mouse out events
Figure 3-5. The effect of the changing alpha values using mouse over and mouse out events
Using the parent movie clip to propagate events
Figure 3-6. Using the parent movie clip to propagate events

Note

It’s important to note that not all events propagate through the display list. Frame events, for example, which we’ll discuss in the next section, are dispatched directly to the event target. Before relying on event propagation, check the documentation to see how the event behaves. In particular, the bubbles property of an event class is a Boolean that indicates whether an event bubbles back up through the display list after reaching its target.

For more information, see the companion website, which includes discussions about event phases, priority of execution, stopping event propagation, and more. Consult Essential ActionScript 3.0, Chapters 12 and 21, for more discussions on event propagation.

Now imagine having to use the same approach for many folders, as seen in Figure 3-6. The code could get quite extensive with all those listeners for each folder. However, with event propagation, it’s possible to attach the listener to the parent movie clip. In this example, all of the folders are inside a movie clip called folder_group, symbolized by the dashed line in Figure 3-6. If we attach the listener to the parent movie clip, the event will cascade through the display list, and the listener functions will be able to determine the object target from the data sent into the function. The code that follows is significantly simplified, thanks to event propagation, and can be seen in the source file event_propagation2.fla.

1    folder_group.addEventListener(MouseEvent.MOUSE_OVER, onFolderOver);
2    folder_group.addEventListener(MouseEvent.MOUSE_OUT, onFolderOut);
3
4    function onFolderOver(evt:MouseEvent):void {
5        evt.target.alpha = 0.5;
6    }
7
8    function onFolderOut(evt:MouseEvent):void {
9        evt.target.alpha = 1;
10    }

Note

To see another example of the difference between the target and currentTarget event properties, change target in lines 5 and 9 to currentTarget in the code at right. Because the listener is attached to the parent movie clip, which contains all the folders, currentTarget causes the parent clip to fade, affecting all its children. Used judiciously, these properties could be used to highlight a single folder, or all folders as a group.

Frame and Timer Events

We’ve been using mouse and keyboard events because you’re almost certainly familiar with them to some degree, and they are ideally suited to this tutorial context. However, there are many events in the ActionScript language. While it’s not possible to cover every one, we would like to round out the chapter with two other significant event types: frame and timer.

Frame Events

Frame events are not triggered by user input the way mouse and keyboard events are. Instead, they occur naturally as the SWF plays. Each time the playhead enters a frame, a frame script is executed. This means that frame scripts execute only once for the life of the frame, making them an excellent location for seldom executed tasks, such as initializations. In other words, for a frame script to execute more than once, the playhead must leave the frame and return—either because of an ActionScript navigation instruction, or a playback loop that returns the playhead to frame 1 when it reaches the end of the timeline. Single-frame FLA files, therefore, execute their single frame scripts only once.

However, using an event listener, you can listen for a recurring enter frame event that some display objects have, including the main timeline, movie clips, and even the stage. An enter frame event is fired at the same pace as the document frame rate. For example, the default frame rate of an FLA created by Flash Professional CS4 and later is 24 frames per second, so the default enter frame frequency is 24 times per second. Using the enter frame event allows your file to update frequently—a handy thing for updating visual assets.

The frame_events.fla file in the accompanying source code demonstrates this event by updating the position of a unicycle every time an enter frame event is detected. It places the unicycle at the location of the mouse and, as a further review of properties, it rotates the child movie clip in which the wheel resides. Figure 3-7 demonstrates the effect. As you move your mouse to the right on the stage, the unicycle will move to the right, and the wheel will rotate clockwise.

Visual depiction of the unicycle movements
Figure 3-7. Visual depiction of the unicycle movements

The code for this example follows. The first line adds an enter frame event listener to the main timeline, specifying the event using the ENTER_FRAME constant of the Event class. The function sets the unicycle’s x coordinate and rotation to the x coordinate of the mouse.

1    stage.addEventListener(Event.ENTER_FRAME, onFrameLoop);
2
3    function onFrameLoop(evt:Event):void {
4        cycle.x = mouseX;
5        cycle.wheel.rotation = mouseX;
6    }

Note

This example demonstrates a scripting shortcut aided by ActionScript. When specifying a rotation higher than 360 degrees, ActionScript will understand the fact that an angle of rotation cannot exceed 360 and use the correct value. That is, 360 degrees is one full rotation around a circle, bringing you back to degree 0 (720 degrees is twice around the circle and also equates to 0). Similarly, 370 degrees is equivalent to 10 degrees, as it is 10 degrees past degree 0, and so on. This allows you to set the rotation of the wheel movie clip to the x coordinate of the mouse, without worrying about rotation ceasing after moving past the 360th pixel on the stage.

Timer Events

An alternative to using enter frame events to trigger actions on a recurring basis is to use time-based events. Although it’s among the most straightforward options, using the enter frame event exclusively for this purpose has disadvantages. For example, Flash Player can reliably achieve only moderate frame rates—somewhere between the default 24 frames per second (fps) and perhaps 60 or so fps on the high end. Your mileage may vary, but that’s fairly accurate when averaging the CPU population at large. More importantly, the rate at which the enter frame fires is not always consistent.

On the other hand, time-based events are measured in milliseconds and can therefore sometimes fire more quickly. Further, time-based events don’t vary as much from scenario to scenario, so they are more reliable and consistent.

Previous versions of ActionScript used the setInterval() method for ongoing recurring events and the setTimeout() method for finitely recurring events. ActionScript 3.0 wraps up these approaches neatly behind the scenes of the new Timer class, simplifying the process of using timers.

The first step in using the Timer class is to create an instance of the class. Fortunately, creating instances in ActionScript 3.0 is very consistent, so this may look familiar. A variable is declared and typed using a data type that matches the class being instantiated. The new keyword creates a new instance of the class and that instance is stored in the variable:

var timer:Timer = new Timer(delay, repeatCount);

In this case, the class constructor can take two arguments. The first is mandatory and specifies the delay, in milliseconds, before the timer event is fired. The second is optional and is the number of times the event fires. Omitting the second argument will cause the event to fire indefinitely, each time after the specified delay. Using a positive value, such as 3, will cause the event to fire that finite number of times (again, after the specified delay).

Note

As described in Chapter 2, frame and timer loops, such as those seen in the previous examples, are often an attractive alternative to for loops because they allow additional updates to occur throughout the file. A code loop, such as a for loop, is one of the most processor-intensive structures and will execute only the code inside the loop until the loop is finished. This means that animation, sound, or video updates, for example, will all be halted while the loop is working.

In the sample timer_events.fla in the accompanying source code, the timer event (consistently specified as the constant TIMER in the TimerEvent class), occurs every second (or, in Timer units, every 1,000 milliseconds) and calls a function that increases the rotation of a hand nested inside a watch movie clip. The rotation increases 6 degrees every second, making one full 360-degree journey in 60 seconds.

1    var timer:Timer = new Timer(1000);
2    timer.addEventListener(TimerEvent.TIMER, onTimer);
3    timer.start();
4
5    function onTimer(evt:TimerEvent):void {
6        watch.hand.rotation += 6;
7    }

One important thing to note is line 3. The timer you instantiate does not start automatically. This gives you greater flexibility and control over your timer events. You can also stop the timer using the stop() method, and reset the timer using the reset() method. The latter stops the timer and also resets the repeat count to zero. For example, if you specified that the timer call a function five times, but reset it after the third call, the timer would begin counting again from zero rather than picking up from three at the point when it was reset. Figure 3-8 shows the watch used in timer_events.fla.

Use of the timer event in a stopwatch
Figure 3-8. Use of the timer event in a stopwatch

Removing Event Listeners

Though event listeners make most event handling easy to add and maintain, leaving them in place when unneeded can wreak havoc. From a logic standpoint, consider what could happen if you kept an unwanted listener in operation. Imagine a weeklong promotion for radio station 101 FM, which rewards customer number 101 who enters a store each day of that week. The manager of the store is set up to listen for “customer enter” events, and when customer 101 enters the store, oodles of prizes and cash are bestowed upon the lucky winner. Now imagine if you left that listener in place after the promo week was over. Oodles of prizes and cash would continue to be awarded at great, unexpected expense.

Unwanted events are not the only problem, however. Every listener created occupies a small amount of memory. Injudiciously creating many event listeners, without cleaning up after yourself, uses memory without releasing it, which reduces available memory over time. This effect is called a memory leak. Therefore, it’s a good idea to remove listeners when you know they will no longer be needed.

To do so, just use the removeEventListener() method. This method must be invoked by the object to which the listener was originally attached and requires two parameters: the event and function specified when the listener was created. Specifying the correct object, event, and function is important because you may have multiple listeners set up for the same object or event and you’ll want to remove the correct listener.

Let’s show how this works by adding to the previous example and removing the timer event listener when the rotation of the watch hand meets or exceeds 30 degrees of rotation. The new code is in bold and can be found in the source file removing_listeners.fla.

1    var timer:Timer = new Timer(1000);
2    timer.addEventListener(TimerEvent.TIMER, onTimer);
3    timer.start();
4
5    function onTimer(evt:TimerEvent):void {
6        watch.hand.rotation += 6;
7        if (watch.hand.rotation >= 30) {
8            timer.removeEventListener(TimerEvent.TIMER, onTimer);
9        }
10    }

This can be accomplished using a repeat count in the timer, like this:

var timer:Timer = new Timer(1000, 5);

However, the point of the example is to show you how to remove the listener from your logic flow and, equally important, from memory, when it is no longer needed. We briefly discuss an additional scenario for removing listeners in the upcoming Garbage Collection: A Recommended Optional Parameter for Event Listeners sidebar, but in all cases, it’s good practice to remove any listeners that you know you’ll no longer need.

What’s Next?

This chapter has demonstrated ways to manipulate ActionScript objects, but in the case of our example movie clip, we have assumed that the movie clip already existed on the stage. This is an acceptable assumption for projects authored primarily using the timeline, but it’s limiting. If all files are to be constrained by using only elements manually added to the stage at time of authoring, and used only in the manner and order in which they were originally added, the files cannot be as dynamic as the ActionScript language allows.

Coming up, we’ll talk more about the display list—an excellent means of managing visual assets. Understanding the basics of the display list is instrumental not only in dynamically adding elements at runtime, but also in manipulating existing stage-bound objects to their fullest potential.

In the next chapter, we’ll discuss:

  • Adding new children to the display list

  • Removing existing children from the display list

  • Swapping depths of objects in the display list to change their visual stacking order dynamically

  • Managing the hierarchical relationship of display list objects and how to change that relationship through reparenting

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

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