Chapter 1. Introducing ActionScript 3.0

If you chase perfection, you often catch excellence.

William Fowble

The term “perfect” is a powerful word. From a practical standpoint, it represents a state that arguably cannot be achieved. Hey, that’s a relief already! This book doesn’t expect the impossible. This isn’t the print version of an office know-it-all, itching for you to slip up. You won’t hear any anxious hand wringing in these pages over why you haven’t yet upgraded to, much less mastered, ActionScript 3.0. (Yes, even though it was available in Flash CS3 Professional.) Instead, the following chapters will take their cue from a sage observation by William Fowble: If you chase perfection, you often catch excellence. In other words, chin up! Aim for the best and enjoy the road trip. ActionScript 3.0—the current version of the programming language for the Adobe Flash Platform—is a language that indeed catches excellence. This book is designed to explain a bit about why that is. In so doing, our hope is to help you chase perfection by introducing you to the improved organization, syntax, and workflows of the new language. Catching excellence, for all of us, is a matter of practice, and comes with time.

This book is going to introduce you to new ways of thinking about the Flash Platform. ActionScript 3.0 requires these new ways because the language is actually structured around them. That’s a big part of why the new language improves on previous versions. Like its precursor, but to a greater extent, ActionScript 3.0 is based on a specification called ECMAScript, which is a standard proposed by a body of experts known as Ecma International. This group is something like the World Wide Web Consortium (W3C), whose responsibility includes HTML, XML, CSS, and other widely used markup languages. Such a standard’s benefit is that ActionScript 3.0 isn’t just an arbitrary language invented to meet Adobe’s needs. ECMAScript is a relatively mature specification, already in its third revision. The Ecma International team includes authorities from industry powerhouses like Microsoft, the Mozilla Foundation, and Adobe. The specification is built on the collective insight and success of these diverse experts in the field. Of all the versions of ActionScript, the current version comes closest into full compliance with this specification—at this point, closer even than the other famous ECMAScript derivative, JavaScript. This makes ActionScript 3.0 a model of best practices, habits you can use in both Flash CS4 Professional and Flex Builder 3. In many cases, you may even find that these practices benefit your involvement with existing projects coded in previous versions of ActionScript. Sure, the syntactical details change, but achievement in programming is all about structure and purpose. It’s the concepts and good habits that carry you.

For the nuts and bolts, the relevant ActionScript Language Reference is always a mere keystroke away (the F1 key). Even so, a new set of Help docs can be daunting, especially if you’re already well-versed in ActionScript 2.0. Fortunately, the ActionScript 3.0 documentation is every bit as helpful as it used to be, even if it looks different. The layout of the Help docs is still organized around the layout of the language itself—around the classes that define the objects you will use—and its class entries still summarize the usable apparatus of each object: its characteristics, called properties; the things it can do, called methods; and the things it can react to, called events. In the new documentation, code samples are presented as custom classes, rather than frame scripts. This requires you test them as standalone, simple text files, according to the new document class concept described in Chapter 6. Fortunately, this also means you can test these classes in other programs, such as Flex Builder. This book will help you get familiar not only with the new language, but also with the documentation that explains it.

Keep in mind, ramping up to ActionScript 3.0 isn’t merely about learning the latest syntax: it’s about becoming a better, more efficient programmer. This isn’t meant to slight ActionScript 2.0 at all, but plenty has changed since its introduction in late 2003. It’s no exaggeration to say that several aspects of the language have been completely overhauled. In fact, ActionScript 3.0 requires an entirely new virtual machine, which is the module inside Flash Player that interprets compiled ActionScript. As of Flash Player 9, the runtime that displays Flash movies does so with two virtual machines: AVM1 for legacy SWF files based on ActionScript 1.0 and 2.0, and the new AVM2 for ActionScript 3.0. That’s a first in the history of Flash Player. Thanks to the new virtual machine, ActionScript 3.0 runs faster and more efficiently by an order of magnitude. This bodes well for the overriding goal of the new language: to facilitate a wide range of interactive media and Rich Internet Applications (RIAs)—to do so simply, with better performance, and highly compatible with industry standards. As you can imagine, an upgrade of this scale means you may have to reshape some of your current habits. But take heart. Reshape doesn’t necessarily mean tear down and rebuild. As ActionScript has matured, it has consistently moved in the direction it currently stands. Again, honing your skills in light of ActionScript 3.0 will help you in your current projects and also in legacy project maintenance. Migration can be intimidating, but much of that uncertainty comes from trying to find your stride. Once you take the first few steps, the momentum keeps you going.

Here’s a look at some of the new features.

Examining ActionScript 3.0, the Language

Section 4 of the ECMAScript standard (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) defines an important facet of any language that implements it. Such languages “will provide not only the objects and other facilities described in this specification but also certain environment-specific host objects, whose description and behaviour are beyond the scope of this specification.” In other words, any ECMAScript derivative needs a set core functionality that stands on its own and will then provide additional functionality specific to the environment that interprets it. This is exactly what ActionScript 3.0 does, and its host environments include Flash Player for web browsers, intended for Flash-enabled websites such as http://YouTube.com; Flash Lite for devices, such as video games for your cell phone; and Adobe Integrated Runtime (AIR) for applications installed on the hard drive, such as eBay Desktop (http://desktop.ebay.com/).

Here is a brief summary of a number of core updates.

Runtime Exceptions

In ActionScript 2.0, many runtime errors failed without drawing attention to themselves. On the plus side—and this is a very weak plus—this meant that errors of this sort often failed “gracefully.” In other words, they might not halt someone’s experience with something abrupt or laden with technical jargon, such as an alert or dialog box. On the minus side, this also meant such errors might go unnoticed by the developer—until complaints started rolling in that people were experiencing slow playback or even lockups. Such errors could be hard for developers to pinpoint and repair, precisely because they were silent.

ActionScript 3.0 allows for a variety of runtime exceptions to be handled with purpose. This includes Error objects generated both by the runtime environment and, potentially, by the programmer. In ActionScript 3.0, the Error class is considerably more robust than its forerunner, and tailor-made Error objects can be built from this class as desired, inheriting and extending its functionality to provide highly customized error messages. Exceptions can even provide source file and line number information, which greatly enhances the debugging experience, letting developers quickly track down errors.

Runtime Types

ActionScript 2.0 introduced the ability to strongly type variables, parameters, and function return values. This was, and still is, an optional way to let Flash know exactly what sort of data a particular variable, parameter, or return value could cope with. This ability was a boon to developers in terms of debugging, because it gave you a way to display error messages in cases of a type mismatch. For example, if you were going to perform a math operation on two numbers provided by the user, you might take those numbers from input text fields. This would actually make them strings, which meant your math operation would give you unexpected results (for example, 1 + 2 would become “12” instead of 3). By strongly typing the parameters of the function that performed this operation—in other words, by specifying intended variable types with a colon (:), then the type—you could benefit from a meaningful error message in the Output panel such as this:

// ActionScript 2.0
var userVar1:String = inputField1.text;
var userVar2:String = inputField2.text;

function getSum(a:Number, b:Number):Number {
    return a + b;
}

trace(getSum(userVar1, userVar2));
// Displays:
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 8: Type mismatch.
    getSum(userVar1, userVar2);.

A type mismatch notice is a great reminder to use something like parseInt() or parseFloat() to convert those strings into numeric values. Useful indeed, but this was only a first step in a good direction. In ActionScript 2.0, this sort of error checking only occurred at compile time. Under many circumstances—such as evaluating data from dynamic sources like XML—the feature wasn’t “smart” enough to catch every contingency. In ActionScript 3.0, it is.

Sealed Classes

Following in the same vein as runtime exceptions and runtime types, ActionScript 3.0 establishes the concept of sealed classes in a stricter, more formalized way than in ActionScript 2.0. A sealed class is one that can’t have properties or methods assigned to it at runtime, such as String. By default, classes in ActionScript 3.0 are sealed, but this can be overruled when you write your own.

var str:String = "" // Or: new String();
str.customProperty = "This generates a compiler error.";
// Displays: Access of possibly undefined property customProperty
// through a reference with static type String.

In contrast, a class that actually can have properties and methods assigned to it at runtime is called dynamic. One of the most familiar dynamic classes is MovieClip, though historically speaking, many frame script developers haven’t considered movie clips in terms of a class. The same could be said of buttons and text fields, because you can create such elements with Flash’s drawing tools. (Of the elements just mentioned, only movie clips are dynamic.) For frame script coders, movie clips are often thought of simply as symbols or timelines, and timelines have always been able to receive new variables at runtime. True enough. What’s really going on, though, is that variables defined in keyframe scripts are in reality dynamic properties of a MovieClip instance; functions are actually dynamic methods.

Declaring a variable in a keyframe of the main timeline or in a movie clip’s timeline is conceptually the same as the following:

var mc:MovieClip = new MovieClip();
mc.customProperty = "This is perfectly acceptable.";

Custom classes in ActionScript 3.0 can behave this way too, if and only if they are declared with the dynamic attribute:

package {
    public dynamic class CustomClass() {
        // class code here
    }
}

On paper, this is also how it was in ActionScript 2.0, but in fact, even non-dynamic classes could be altered at runtime by manipulation of the Object.prototype property (inherited by all objects) or by the array access operator ([]). Advanced programmers who used such an approach in the past will find it no longer works in ActionScript 3.0 for sealed classes.

// ActionScript 2.0
var str:String = "";
str.customProperty = "Secret back door.";
// Displays: There is no property with the name 'customProperty'.

str["customProperty"] = "Secret back door.";
// Works just fine in ActionScript 2.0, but in 3.0 displays:
    Cannot create property customProperty on String.

In ActionScript 3.0, non-dynamic classes actually are what they claim to be. This makes for stricter compile-time checking and improves memory usage because class instances can now be guaranteed to require no more than a pre-declared amount of system memory.

Method Closures

Of all the updates to ActionScript 3.0, it’s no surprise that developers, regardless of skill level, encounter one in particular early on: method closures. Why? Because the introduction of method closures changes the point of view, or scope, of methods in ActionScript 3.0.

Scope refers to the conceptual area of a program in which code executes. The availability of code definitions, such as variables, functions, properties, and methods, depends on the scope of the code being executed. For example, if a variable is declared in a timeline frame, that variable can be referenced by any other code in that frame, as long as that code appears after the declaration. Even a function defined in that frame can reference the variable scoped to the timeline, because scopes can be nested, and the flow moves from outer scope to inner: the timeline’s definitions become available to the function.

// A variable declared here ...
var favoriteCereal:String = "Star Crunchers!";

// can be referenced here ...
trace(favoriteCereal); // Displays: Star Crunchers!

function myFunction():void {
    // and here ...
    trace(favoriteCereal); // Displays: Star Crunchers!
}
myFunction();

In contrast, a variable declared inside a function can only be referenced by that function, because the scope of the function is confined to itself.

function myFunction():void {
    // A variable declared here ...
    var favoriteCereal:String = "Star Crunchers!";

    // can only be referenced here ...
    trace(favoriteCereal); // Displays: Star Crunchers!
}
myFunction();

// but not in the outer scope ...
trace(favoriteCereal);
// Displays:
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 10:
    Access of undefined property favoriteCereal.

Up to now, this should be familiar to ActionScript 2.0 developers. How, then, have things changed? Consider the next few examples.

In ActionScript 2.0, a button click might be handled like this:

// ActionScript 2.0
myButton.onRelease = buttonHandler;
function buttonHandler():Void {
    trace(this); // Displays: _level0.myButton
    // other event handler code
}

Prior to ActionScript 3.0, the scope of the function shown belonged to the myButton instance. In this case, the button code could conveniently be abbreviated with the use of the this keyword, which self-referenced the current scope (myButton). In some cases, this made for a handy way to achieve certain goals. For example, to repeatedly loop a Sound instance in ActionScript 2.0, the following would do:

// ActionScript 2.0
var audio:Sound = new Sound();
audio.loadSound("externalFile.mp3", true);
audio.onSoundComplete = completeHandler;
function completeHandler():Void {
    this.start();
}

Again, the function is scoped to the instance. In this case, the expression this.start() amounts to invoking the Sound.start() method on the audio instance. Although convenient in this sort of situation, difficulties arose when the event handler needed to reference objects outside the scope of the function, especially in custom classes.

To a large extent, this issue could be addressed in ActionScript 2.0 with the Delegate class, which allowed you to reroute the scope as desired:

// ActionScript 2.0
import mx.utils.Delegate;
var audio:Sound = new Sound();
audio.loadSound("externalFile.mp3", true);
audio.onSoundComplete = Delegate.create(this, completeHandler);

function completeHandler():Void {
    audio.start();
}

The Delegate.create() method accepted two parameters: first, the desired scope; second, the function or method to execute in that scope. Note that because of this change, the function invokes audio.start() directly. In this case, the this keyword no longer refers to the audio instance to which the listener was attached, but rather to the timeline frame in which the listener was assigned.

In ActionScript 3.0, method closures let a function or method remember where it was defined. In short, you get the best of both worlds. In the following ActionScript 3.0, written in a keyframe, the reference to this shows that the scope belongs to the main timeline—to the frame in which the function is defined, rather than to the myButton instance. No extra baggage, like the Delegate class, is required.

myButton.addEventListener(MouseEvent.CLICK, buttonHandler);
function buttonHandler(evt:MouseEvent):void {
    trace(this); // Displays: [object MainTimeline]
}

To reference the button rather than the frame, use the Event.target property of the parameter that is passed into the function automatically by the event. In this snippet, the parameter is arbitrarily named evt:

myButton.addEventListener(MouseEvent.CLICK, buttonHandler);
function buttonHandler(evt:MouseEvent):void {
    trace(evt.target);      // Displays: [object SimpleButton]
    trace(evt.target.name); // Displays: myButton
}

ECMAScript for XML (E4X)

Flash has long supported XML, but the addition of ECMAScript for XML (E4X) syntax is a significant productivity boost. Like ActionScript, E4X is an Ecma International specification, which affords a powerful yet concise set of language constructs for retrieving data from XML, and manipulating it.

In ActionScript 2.0, you can certainly navigate among the nodes of a loaded XML document, but the effort becomes progressively more tedious as the XML’s complexity increases. The ActionScript 2.0 XML class provides a handful of necessary navigation properties, such as firstChild, nextSibling, lastChild, and childNodes. Choosing from these, and assuming an XML document has already been loaded and parsed into an XML instance named myXML, you might select the title of the fifth track of The Beatles’ Abbey Road album (“Octopus’s Garden”) like this:

// ActionScript 2.0
myXML.firstChild.firstChild.firstChild.childNodes[4].attributes.¬ 
    title;

// Contents of the loaded XML document
<?xml version="1.0" encoding="iso-8859-1"?>
<library>
    <artist name="The Beatles">
        <album name="Abbey Road">
            <track title="Come Together" />
            <track title="Something" />
            <track title="Maxwell's Silver Hammer" />
            <track title="Oh! Darling" />
            <track title="Octopus's Garden" />
            <track title="I Want You (She's So Heavy)" />
            <track title="Here Comes the Sun" />
            <track title="Because" />
            <track title="You Never Give Me Your Money" />
            <track title="Sun King" />
            <track title="Mean Mr. Mustard" />
            <track title="Polythene Pam" />
            <track title="She Came in Through the Bathroom Window" />
            <track title="Golden Slumbers" />
            <track title="Carry That Weight" />
            <track title="The End" />
            <track title="Her Majesty" />
        </album>
    </artist>
</library>

In the preceding whopping expression, myXML refers to the parsed XML document; the three mentions of firstChild refer, respectively, to the <library>, <artist>, and <album> nodes; and childNodes[4] refers to the fifth <track> node (bear in mind, childNodes returns an array, and arrays start at zero). Finally, the attributes property leads to the title attribute of the selected node.

E4X lets parsed XML be referenced as if it were a native object. This lets you traverse the loaded data incredibly more intuitively. In the ActionScript 3.0 equivalent, the same track can be referenced like this:

// ActionScript 3.0
myXML.artist[0].album[0].track[4].@title;

or, thanks to the descendent accessor operator (..), even something as short as this:

myXML..track[4].@title;

Which would you rather type?

In addition, you can compare data using a familiar set of operators. For example, if the XML document at hand contains numerous recording artists, The Beatles’ <artist> node could be singled out as easily as this:

myXML.artist.(@name == "The Beatles")

Note

The E4X specification is available in Adobe PDF format at the Ecma International website: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf.

Regular Expressions

The term regular expressions refers to a set of specialized language constructs for retrieving data from strings (that is, text content), and manipulating such data. In this regard, regular expressions (often abbreviated as regex) shares a number of similarities with E4X: both mechanisms are compact and efficient in their tasks. The syntax of regex tends to be initially harder to grasp than E4X—here, normal letters and punctuation are used to represent whole sets of characters, in addition to filtering rules—but the results are well worth the effort.

What can you do with regular expressions? To answer that, consider two familiar methods of the String class, indexOf() and lastIndexOf(), which have been available in ActionScript for years. These methods both accept two parameters: first, a string to look for within a container string; second, optionally, where to start looking within the container string. Each method takes its starting point from opposite ends of the container string.

var pangram:String = "The quick, brown fox jumps over a lazy dog.";

trace(pangram.indexOf("o"));     // Displays 13
trace(pangram.indexOf("o", 14)); // Displays 18
trace(pangram.lastIndexOf("o")); // Displays 40

In the first trace() statement, only one parameter is supplied, "o", and the return value is 13 because the letter “o” makes its first appearance at index 13 (starting with 0, the thirteenth character in the string pangram). In the second statement, the return value is 18 because of the optional second parameter 14, which instructs the method to begin after the index of the first “o”. In the third statement, the return value is 40 because the method lastIndexOf() begins its search from the end of the string.

For simple searches, indexOf() and lastIndexOf() fit the bill, but what if the requirement is something like “find all US ZIP codes,” which could be any 5-number combination, or “find all words in this paragraph that contain three or more vowels”? Suddenly, the task seems considerably more difficult, if not impossible. Believe it or not, the RegExp class in ActionScript 3.0 handles this requirement very easily. The solution requires a pattern of specialized characters, expressed either as an instance of the RegExp class or passed as a parameter to one of the regex-related methods of the String class (match(), replace(), or search()).

Given a variable, paragraph, set to the text content of the previous paragraph, the following code shows how to retrieve words with three or more vowels:

var re:RegExp = /\b(\w*[aeiou]\w*){3}\b/gi;

var result:Object = re.exec(paragraph);
while (result != null) {
    trace(result[0]);
    result = re.exec(paragraph);
}
// Displays: searches, indexOf, lastIndexOf, requirement,
// something, and other words with three or more vowels

A full discussion of regular expressions syntax is beyond the scope of this book, but here’s a brief overview of how the previous example works. A variable, re, is set to an instance of the RegExp class by way of the RegExp delimiter operator (/pattern/flags). Between the two slashes of this operator, the pattern \b(\w*[aeiou]\w*){3}\b spells out the search requirement. After the second slash, the flags (gi) configure the pattern as global and case insensitive. The RegExp.exec() method executes the pattern on the string paragraph and returns an object (result) that contains information about the search. The search is repeated until result is null.

If the preceding example seems outlandish, imagine the same sort of power applied to the validation of user input. You can manage even potentially complex requirements without much difficulty. These include questions such as, “Is this email address correctly formed?” (Checking for the “@” character isn’t enough!) “Is this a valid telephone number?” (People might enter anything from (123) 456-7890 to 123.456.46789 to 123456789.) “Has the user tried to sneak in an inappropriate word by using a nonstandard spelling?” Patterns that match these requirements not only find the strings in question, but can also manipulate them in order to, for example, format telephone numbers consistently or replace questionable words with Xs.

Note

For an exhaustive and highly regarded treatise on regular expressions, be sure to read Mastering Regular Expressions, by Jeffrey Friedl (O’Reilly). Numerous tutorials are also available online at the unrelated http://www.regular-expressions.info/ website.

Namespaces

In advanced programming scenarios, the concept of namespaces brings a valuable new mechanism to ActionScript 3.0. In short, namespaces are essentially custom access specifiers—like public, private, protected, and internal—except with names you choose. Namespaces let you control the visibility of your properties and methods, even to the point of overriding package structures. They also let you qualify members under various guises. As a quick example, you might develop an AIR application that performs one behavior while an Internet connection is present, and another when no connection is present. By using namespaces, you can define multiple versions of the same method that, for instance, checks an online inventory when the user’s WiFi connection is available but defaults to a cached version otherwise. Or you might define series of variables in several languages, where the value of a variable depends on the user’s regional settings. These distinctions are determined by custom prefixes and the name qualifier operator (::):

// Three versions of the same String variable
english::newFeatures // Value of "Lots of new stuff"
german::newFeatures  // Value of "Viele neue Sachen"
french::newFeatures  // Value of "Plien de nouvelles choses"

Namespaces are outfitted with a Universal Resource Identifier (URI) to avoid collisions, and are also used to represent XML namespaces when working with E4X.

New Primitive Types

ActionScript 3.0 introduces two new primitive types, int and uint, bringing the full list to Boolean, int, Null, Number, String, uint, and void (note the change in capitalization from Void). These new numeric types reduce memory usage in cases when a numeric value need only be an integer. How? The familiar Number data type is an IEEE-754 double-precision floating-point number, which, thanks to its structure, always requires 64 bits of memory. Number objects range from 1.79e+308 (1.79 with over 300 zeroes after it!) down to 5e-324. That’s an unimaginably large range, which isn’t always necessary. Sometimes you just want to count through a for loop, and all you need is an integer.

Enter int, which is a relatively small 32-bit number (only 4 bytes), whose range is still an impressive 2,147,483,647 (over two billion) down to −2,147,483,648. That range should do for most of the for loops you’ll encounter. By contrast, uint numbers (unsigned integers) range from 0 to 4,294,967,295, which is the same span as int, but entirely on the positive side of the number line. If your for loop’s counter, or any other integer value, needs a higher range than offered by int, uint makes a good choice—provided the range doesn’t dip below zero. Neither type ever requests more than 32 bits of system memory.

Warning

One note of caution: because uint values are always positive, take care when trying to subtract a uint into negative territory. A uint rolls around to 4,294,967,295 if you subtract it past zero, as the following code demonstrates.

var n:uint = 0;
trace(n); // Displays 0

n--;
trace(n); // Displays 4294967295

Exploring Flash Player API Updates

In the “ActionScript 3.0, the Language” section of this chapter, you learned that the ECMAScript specification on which ActionScript is based actually expects the language to provide functionality tailored to the platform that hosts it. In the case of ActionScript, hosts include Flash Player, AIR, and Flash Lite—all various flavors of the Flash Platform. Though each host is designed to meet specific needs—websites, desktop applications, and mobile content, respectively—their overlap is considerable. ActionScript 3.0 institutes a significant restructuring of its application programming interface (API), summarized handily in the colossal migration table available on the Adobe LiveDocs website (http://help.adobe.com/en_US/AS3LCR/Flash_10.0/migration.html) and also in the Help panel in the appendices of the ActionScript 3.0 Language and Component Reference, under the heading “ActionScript 2.0 Migration”. In large part, existing functionality has been restructured into packages that make better sense from an organizational standpoint. However, Flash does have a number of philosophical changes in the way it carries out its fundamental tasks. The following paragraphs list some of the more notable updates.

Note

As of the publication of this book, Flash Lite does not yet support ActionScript 3.0, due to the inherent processor and memory limitations of mobile devices. The features recounted here apply to Flash Player 9 (and higher) and AIR, but won’t apply to Flash Lite until that runtime adds support for ActionScript 3.0.

DOM3 Event Model

Before ActionScript 3.0, you could handle events in Flash in at least five different ways, some of which were interchangeable:

  • The legacy on() handler, available since Flash 2 and still in wide use, even in ActionScript 2.0 scenarios, but gone in ActionScript 3.0

  • The legacy onClipEvent() handler, also widely used and unavailable in ActionScript 3.0

  • The dot notation syntax that combined and replaced on() and onClipevent() (for example Button.onPress = functionDefinition, MovieClip.onEnterFrame, and so on)

  • The addListener() method of several—but not all!—ActionScript 2.0 classes, such as TextField, Mouse, and MovieClipLoader

  • The addEventListener() method used by the v2 component set (user interface, data, and media components)

This varied assortment was a result of incremental improvements to ActionScript with every new release of the authoring tool, with the older approaches retained for backward compatibility. For longtime Flash developers, each new technique was simply a small addition to the workflow, but newcomers to recent versions, such as Flash 8 or Flash CS3, were understandably confused by an API with so many seemingly arbitrary possibilities.

Note

Are on() and onClipEvent() really so bad? From a workflow standpoint, no. From a practical standpoint, they aren’t nearly as valuable as their dot notation replacement. In ActionScript 2.0, the combination of on() and onClipEvent() provide access to only slightly more than half the events available to movie clips and buttons. In addition, you can’t assign, manipulate, or remove their event handlers at runtime. Their absence in ActionScript 3.0 marks the end of a long transition period from ActionScript 1.0 through 2.0.

Because ActionScript 3.0 relies on a new virtual machine, it can afford to make a clean break in the way it handles events. With one small exception (discussed in Chapter 4), event handling is now consolidated across the board into a single, consistent approach: the EventDispatcher.addEventListener() method. This mechanism is based on the W3C’s Document Object Model (DOM) Level 3 Events Specification (http://www.w3.org/TR/DOM-Level-3-Events/). This means that in ActionScript 3.0, event handling syntax is the same in nearly all cases, no matter if the event dispatcher is a button, an audio clip, or a loader object for XML or JPEG files. The basic structure looks like this:

eventDispatchingObject.addEventListener(
    EventType,
    functionToPerform
);

Display List API

In ActionScript 3.0, movie clips can be instantiated with the new keyword as easily as this:

var mc:MovieClip = new MovieClip();

which is more intuitive than what it took in ActionScript 2.0:

var mc:MovieClip = existingMovieClip.createEmptyMovieClip(¬
 instanceName, depth);

And it gets better. Depth management is now automatic. Notice that the expression new MovieClip() does not require a depth parameter. This change is due to a fundamental new approach to the display of visual objects in ActionScript 3.0: a concept called the display list, which represents the hierarchical display of all graphical objects in Flash Player. This concept is embodied in the DisplayObjectContainer class, the base class for all objects that can serve as visual containers, including movie clips, the new Sprite and Loader classes, and more. Thanks to inheritance, DisplayObjectContainer provides new methods to these classes for considerably better control over the management of object z-order. For example, while the MovieClip class in ActionScript 2.0 featured getDepth() and swapDepths(), the ActionScript 3.0 version offers all of these:

  • addChild()

  • addChildAt()

  • contains()

  • getChildAt()

  • getChildByName()

  • getChildIndex()

  • removeChild()

  • removeChildAt()

  • setChildIndex()

  • swapChildren()

  • swapChildtenAt()

How’s that for control?

These methods are also available to Sprite, which is effectively a movie clip without the overhead of a timeline; Loader, which loads external SWF files and image files (JPEG, PNG, or GIF) at runtime; and any other class in the DisplayObjectContainer family tree.

Under the display list system, objects can be re-parented at any time. This ability simplifies cases in which groups of objects need to be manipulated at once. Consider a jigsaw puzzle game, for example. If you want to combine partially solved areas, so that snapped-together pieces move as one unit, you can simply remove the piece from its current parent and add it as a child to the parent that represents the partially solved group. Before ActionScript 3.0, this action would have required individual sophisticated tracking of each jigsaw piece.

New Sound APIs

Flash Player 8 was the first to support 32 simultaneous sound channels, a significant increase from the original eight-sound channel limit. Although present for as long as Flash Player has supported sound, these sound channels, as such, had no clear representation in code before ActionScript 3.0. In previous versions of the language, the Sound class was self-contained, handling all of its functionality in a relatively simple manner, but at the cost of some clarity of purpose. For example, in order to control the volume and panning of one sound distinctly from another, you had to associate each sound with its own movie clip. You made this association by way of an optional “target” parameter in the Sound constructor function. Because target movie clips might or might not contain other content, their ambiguous roles had the potential to confuse.

ActionScript 3.0 clarifies programmed sound by complementing the Sound class with three companions: SoundChannel, SoundTransform, and SoundMixer. These new APIs give you more explicit control over imported and embedded sounds. The SoundMixer.computeSpectrum() method even lets you retrieve spectral data from sounds, which you can use to program responses to changes in audio pitch and volume.

Binary Data and Sockets

The new ByteArray class enables interoperability with existing custom protocols, and lets advanced developers read, write, and manipulate data on the byte level. This has led adventurous programmers to cultivate projects previously unheard of in Flash, such as Tinic Uro’s PNG encoder (http://www.kaourantin.net/2005/10/png-encoder-in-as3.html, now updated and featured in the as3corelib library at http://code.google.com/p/as3corelib/) and a dynamic tone generator by André Michelle and Joa Ebert, capable of playing MIDI-like Amiga MOD files (http://8bitboy.popforge.de/).

Understanding Players and Support

Although this book focuses primarily on the Flash authoring tool, it’s important to realize that Adobe offers two official ActionScript 3.0 compilers. One of these compilers is built into Flash CS4 itself. As you would expect, this one takes into consideration objects in the document’s Library, as well as global SWF file settings, such as background color and frame rate, as configured in the Property inspector. This compiler can also compile previous versions of ActionScript. Separate from that, there’s the command line compiler included with the free Flex Software Development Kit (SDK) available at http://www.adobe.com/go/flex_trial/. This second compiler is the one used by the Flex Builder integrated development environment (IDE), which doesn’t include drawing tools, timelines, or a library. In addition to ActionScript 3.0, the Flex compiler understands MXML, the declarative markup language used for laying out Flex applications. For want of a library, the second compiler lets metadata embed assets into resultant SWF files. The Flash authoring tool supports only limited metadata, an undocumented feature at the time of writing.

These distinct compilers serve independent workflows. To facilitate the development of RIAs, the Flex SDK features an elaborate framework of user controls and data handlers that aren’t available to the Flash authoring tool, even though the framework is written in ActionScript 3.0. By comparison, Flash offers a modest subset of user controls in its Components panel, including support for the playback and manipulation of Flash video files (FLV).

In the end, there’s only one ActionScript 3.0, and it behaves the same when compiled under either tool. The reason for this consistency is that Flash CS4 and the Flex SDK both publish SWF files for the same Flash Player 9 or higher. It’s quite possible—and often done—to create custom classes that can be used under either circumstance. The concept of the document class (see Chapter 6), introduced in Flash CS3, means that an entire application, composed of numerous external classes, can be compiled by Flash or the Flex command line compiler (including Flex Builder) from identical source files.

Because ActionScript 3.0 requires AVM2, as mentioned earlier in this chapter, Flash Player 9 is the minimum required runtime to display such content. Flash Player 9 runs on numerous operating systems, including several versions of Windows, Macintosh, Linux, and Solaris. Due to the varied nature of these operating systems and occasional bug fixes required by each, in addition to ongoing new features, Flash Player 9 includes a number of minor point releases, as summarized in Table 1-1. Flash CS4’s default output is aimed at Flash Player 10, which may eventually see a list of minor point releases just as long. Time will tell. To determine what version of Flash Player the user has installed, reference the static version property of the Capabilities class.

Table 1-1. Flash Player 9 minor point releases

Flash Player version

Notable changes

9.0.16.0

ActionScript 3.0, including runtime exceptions and error handling, sealed classes, method closures, ECMAScript for XML (E4X), regular expressions, namespaces, new primitive types, DOM3 event model, display list APIs, new sound APIs, and binary data and sockets.

9.0.20.0

Bug fixes and optimizations related to the Intel-based Macintosh platform.

9.0.28.0

Support for Windows Vista operating system. Addition of ADDED_TO_STAGE and REMOVED_FROM_STAGE event constants to let a DisplayObject monitor and know when it can or cannot access its stage property. Security enhancements.

9.0.31.0

Support for Linux operating systems.

9.0.45.0

Bug fixes and improvements for Adobe Flash CS3 Professional. Affects only Windows and Macintosh platforms.

9.0.47.0

Support for Solaris operating system. Security enhancements.

9.0.48.0

Linux security enhancements.

9.0.115.0

H.264 video and High Efficiency AAC (HE-AAC) audio codec support. Hardware acceleration, hardware scaling, multi-threaded video decoding, and enhanced image scaling. Flash Player cache enables common components, such as the Flex Framework, to be cached locally and then used by any SWF from any domain. Flash Media Server buffering maintains stream buffer while a stream is paused.

9.0.124.0

Media streaming security patch and minor display update for Windows Vista.

Note

A full listing of all Flash Player release notes, including bug fixes, can be found at http://www.adobe.com/support/documentation/en/flashplayer/releasenotes.html.

Learning ActionScript 3.0 on the Heels of 2.0

Pretend for a moment you’re a carpenter. For years, you were making do with a hand-crank drill, but then the Macromedia Hardware Company introduced an electric model called ActionScript 1.0 stamped with gold letters on the handle. Beautiful thing! No reason to ever use anything else. Sure, you could operate the drill only within six feet of an electrical outlet (because that was the length of the cord), but the advantages were resoundingly clear. Plus, you could always carry around an extension cable. A few years later, Macromedia announced a new and improved ActionScript 2.0 model. This drill had an optional battery back. For some, the new battery pack was a godsend, because it freed them from the previous six foot limitation. They embraced the new feature and literally found themselves running with it. Other carpenters found the battery pack a bit too advanced. They weren’t sure, for example, if they were supposed to drain the batteries completely before recharging. And honestly, that was fine: the drill still had a cord, of course, so they continued within their previous comfort zone, which was still a considerable improvement over the hand-crank days. Carpenters were a happy bunch. Eventually, the Macromedia Hardware Company became Adobe. Everyone looked forward to the new drill—ActionScript 3.0—and when it came ... they found that the cord had been replaced with a docking station. Suddenly, carpenters who had opted not to use the ActionScript 2.0 battery pack felt trapped. They had no experience with batteries, but if they were going to use an ActionScript 3.0 model, they had no choice.

It goes without saying that every analogy has its flaws. Certainly, the changes in ActionScript 3.0 amount to more than the obvious benefit of a battery pack. Clearly, the new APIs are more complex than the question of how to recharge a set of batteries. In any case, ActionScript does a lot more than drill holes! Still, it can be useful to think of ActionScript 2.0 as a preparatory transitional period between, on one hand, the very roots of the language—that is, ActionScript 1.0 and even earlier—and, on the other hand, the current version. As with the carpenter story, numerous features in ActionScript 2.0, such as strict typing (:Number, :Void, etc.) and formalized custom class files, were optional. (Unlike the analogy, those particular features are still optional in ActionScript 3.0.) Voluntary though they were, such then-new conventions were an early invitation to practice a more efficient workflow. Developers who opted to experiment with object-oriented programming (OOP), to the point of writing their own custom classes, may feel more at home with ActionScript 3.0 than others. For those who were perfectly comfortable with the conventions of ActionScript 1.0, they might understandably feel trepidation in light of the current version, especially now that ActionScript 3.0 has dropped support for some previously optional features, such as on() and onClipEvent(). Flipping through the ActionScript 3.0 Language and Components Reference takes considerably longer than before. Everything has been arranged into a potentially overwhelming new hierarchy of packages. Most of the Help panel sample code has been written as class files, to make it applicable both for keyframe and class file programmers.

These changes are big, but not insurmountable. One of this book’s driving purposes is to help you feel caught up, whether or not you pursued the optional new conventions of ActionScript 2.0—the features that, in hindsight, were a gentle ramp up to today’s recommended best practices. The important thing to keep in mind is that ActionScript 3.0 is scalable in terms of complexity. If you want to plunge headlong into OOP principles such as inheritance and design patterns, ActionScript 3.0 will oblige. If you prefer to stick with traditional timeline coding, ActionScript 3.0 will oblige—with a number of provisos covered in the following chapters.

Deciding to Migrate or Write Code from Scratch

If you work with a set of in-house templates, be they FLA files, custom classes, or a combination of both, sooner or later you’ll have to decide how to update them. For the sake of discussion, these files are stable ones that have made your company money for years, and they work just fine. Nonetheless, you’d like to take advantage of the speed increases—or any of the other benefits—afforded by ActionScript 3.0. Should you painstakingly tinker with existing files, tweaking as you go, or should you ditch everything and start from square one? Which approach would require less effort?

For better or worse, there is no sure-fire way to determine which endeavor is more advantageous in a given situation. While you can theoretically upgrade a FLA file’s Publish Settings to ActionScript 3.0 and compile without errors or warnings, the prospect becomes progressively more unlikely as a project gains in complexity. Chances are high that one incompatibility will occur in concert with many: in other words, when it rains, it pours. That said, here are a few thoughts to consider.

If all or most of your code exists on frames in a FLA file, you may have no realistic choice but to migrate the ActionScript in place, for the obvious reason that the code is so closely tied to the file’s visual design. To start from scratch could require careful transportation of symbols from one FLA file to another, possibly including intricate nested timeline effects. For simple banner ads and linear slideshows, an in-place update may not be as difficult as it sounds. Standalone calls to stop(), gotoAndPlay(), and the like, will carry over without a hitch. By all means, select File→Publish Settings→Flash→Script→ActionScript 3.0, and then hold your breath and see what happens.

Don’t forget to exhale if the compile works, and frankly, prepare yourself now for numerous entries in the Compiler Errors panel. If any of the frame code involves event handlers, loads external assets, or even calls a new web page (getURL() is now navigateToURL()), you’ll have to update it. The good news is, the Compiler Errors panel is one of many helpful new tools in Flash CS4 (introduced in Flash CS3). This panel not only tells you where the erroneous code is, by class file, scene, layer, keyframe, and line number, it often makes suggestions on what to change, including a list of common migration issues.

Note

The Compiler Errors panel and other debugging tools are covered in Chapter 11.

If most of your code exists in external class files, your project probably involves more than a smattering of ActionScript. Although this likely means you’ll spend more time on code migration (because there’s more of it!), the fact that your code is separate means you can test and revise each class individually. In either case, frame code or class files, this book will help you get your bearings.

Get The ActionScript 3.0 Quick Reference Guide now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.