ActionScript 3.0 language fundamentals

ActionScript 3.0 syntax

The syntax of a language is the set of rules you must follow when writing code.

Case sensitivity

ActionScript 3.0 is a case-sensitive language. Identifiers that differ only in case are considered different identifiers. For example, the following code creates two different variables:

 var sampleVariable:int; 
 var SampleVariable:int;

Semicolons

The semicolon character ( ; ) is used to terminate a statement. If you omit the semicolon, the compiler assumes that each line of code represents a single statement. Terminating each statement with a semicolon is good practice and makes your code easier to read.

Parentheses

You can use parentheses ( () ) in three ways in ActionScript 3.0. First, you can use parentheses to change the order of operations in an expression. Operations that are grouped inside parentheses are always executed first. For example, parentheses are used to alter the order of operations in the following code:

trace(2 + 3 * 4); // 14 
trace((2 + 3) * 4); // 20

Second, you can use parentheses with the comma operator ( , ) to evaluate a series of expressions and return the result of the final expression. This technique is shown in the following example:

var a:int = 2; 
var b:int = 3; 
trace((a++, b++, a+b)); // 7

Third, you can use parentheses to pass one or more parameters to functions or methods. In the following example, a String value is passed to the trace() function:

trace("hello"); // hello

Code blocks

One or more lines of code enclosed in curly brackets ( { } ) is called a block. Code is grouped together and organized into blocks in ActionScript 3.0. The bodies of most programming constructs like classes, functions, and loops are contained inside blocks.

function sampleFunction():void{ 
    var sampleVariable:String = "Hello, world."; 
    trace(sampleVariable); 
} 
 
for(var i:uint=10; i>0; i--){ 
    trace(i); 
}

Whitespace

Any spacing in code—spaces, tabs, line breaks, and so on—is referred to as whitespace. The compiler ignores extra whitespace that is used to make code easier to read. For example, the following two examples are equivalent:

for(var i:uint=0; i<10; i++){ 
    trace(i); 
} 
 
for(var i:uint=0; i<10; i++){trace(i);}

Comments

As you write ActionScript, you can leave notes to yourself or others. For example, use comments to explain how certain lines of code work or why you made a particular choice. Code comments are a tool you can use to write text that the computer ignores in your code. ActionScript 3.0 code supports two types of comments: single-line comments and multiline comments. The compiler ignores text that is marked as a comment.

Single-line comments begin with two forward slash characters ( // ) and continue until the end of the line. For example, the following code contains a single-line comment:

// a single line comment

Multiline or block comments begin with a forward slash and asterisk ( /* ) and end with an asterisk and forward slash ( */ ).

/* This is multiline comment that can span 
more than one line of code. */

Another common use of comments is to temporarily “turn off” one or more lines of code. For example, use comments to figure out why certain ActionScript code isn’t working the way you expect. You can also use comments to test a different way of doing something.

Literals

A literal is any fixed value that appears directly in your code. The following examples are literals:

17 
"hello" 
-3 
9.4 
null 
undefined 
true 
false

Literals can also be grouped to form compound literals. The following example shows a compound literal being passed as a parameter to the Array class constructor.

var myStrings:Array = new Array(["alpha", "beta", "gamma"]); 
var myNumbers:Array = new Array([1,2,3,5,8]); 

Keywords and reserved words

Reserved words are words that you cannot use as identifiers in your code because the words are reserved for use by ActionScript. Reserved words include lexical keywords , which are removed from the program namespace by the compiler. The compiler reports an error if you use a lexical keyword as an identifier. The following table lists ActionScript 3.0 lexical keywords.

as

if

return

break

implements

super

case

import

switch

catch

in

this

class

instanceof

throw

const

interface

to

default

internal

true

delete

is

try

do

native

typeof

else

new

use

extends

null

var

false

package

void

finally

private

while

for

protected

with

function

public

There is a small set of keywords, called syntactic keywords , that can be used as identifiers, but that have special meaning in certain contexts. The following table lists ActionScript 3.0 syntactic keywords.

each

include

override

get

dynamic

static

set

final

namespace

native

There are also several identifiers that are sometimes referred to as future reserved words . These identifiers are not currently reserved in ActionScript 3.0. However, Adobe recommends avoiding these words because a subsequent version of the language may include them as keywords.

abstract

export

throws

boolean

float

to

byte

goto

transient

cast

intrinsic

type

char

long

virtual

debugger

prototype

volatile

double

short

enum

synchronized

Slash syntax

Slash syntax is not supported in ActionScript 3.0. Slash syntax was used in earlier versions of ActionScript to indicate the path of a movie clip or variable.

Variables

Almost everything you do in programming requires variables. A variable is a name that relates to a location in the computer’s memory that contains a value. Any time the computer sees a variable name in your code, the computer looks in its memory and uses the value it finds there. For example, if you have two variables named firstVariable and secondVariable , each containing a number, to add those two numbers you write the statement:
firstVariable + secondVariable

If firstVariable contained 5 and secondVariable contained 43, the arithmetic above results in 48.

A memory location can only hold one value at any given time. Therefore, a variable only refers to one value at any given time. That value can vary as your program runs. If secondVariable changes to 23, summing the two variables would result in 28.

Naming limitations and conventions

Each variable must have a unique name. In ActionScript 3.0, you can name variables using words that remind you what the variables are. Once you properly name a variable, you only have to call the variable by name when you want to use it.

Each programming language has its own rules about naming variables. For example, some languages limit name length or prohibit certain characters or words. If you break one of these rules, an error occurs and your code does not run.

Naming limitations for variables in ActionScript 3.0
  • Variable names cannot be a reserved word or keyword. For more information, see ActionScript 3.0 syntax

  • Variable names must start with a letter, an underscore, or a dollar sign

  • Variable names cannot use special characters (except _ and $ in certain situations)

  • Variable names must be unique

In addition to observing the limitations of the language, programmers also follow conventions when naming their variables. Some conventions are considered standard practices within a professional community and therefore have shared meaning. Managers, development teams, or clients sometimes dictate conventions. Programmers also develop naming conventions as part of their own personal coding style. Unlike failure to observe the naming limitations of a language, failure to follow conventions does not prompt errors. However, following naming conventions can actually be more important to a successful development process.

Naming conventions for variables in ActionScript 3.0
  • Use camel case: Start with a lowercase letter and include uppercase letters, for example totalCost or dailyTotalsArray

  • Use an underscore ( _ )only to start the name of a private variable

  • Use a dollar ( $ ) sign only to start the name of a static variable

  • Use descriptive variable names so that the content of any variable is obvious, no matter where the variable appears in code

Access control attributes

You control access to variables, classes, functions, and methods using access control attributes. Access control attributes help achieve encapsulation. Encapsulation is an important concept in object-oriented programming; for more information, see Encapsulation .

You use these access control attribute keywords when you declare variables to control access in ActionScript 3.0

Access control attribute keyword

Access

public

available to any caller

private

available only to the class that defines it

protected

available only to the class that defines it and to any subclasses of that class

internal

available to any caller within the same package

Variable declaration

Creating a variable is called variable declaration. ActionScript 3.0 requires the use of a keyword— var —to signal that you are declaring a variable. Including the keyword var , there are four parts to (non-local) variable declaration in ActionScript 3.0:
  1. access control attribute keyword

  2. var

  3. variable name

  4. data type

Here are some examples of variable declaration:
public var userName:String; 
private var correctAnswer:Boolean; 
internal var userAge:uint; 
protected var predictedTemperature:int; 
private var productPrice:Number;
Note: For more information on data types, see Data types .

Data assignment

Putting data into a variable is called assignment. It uses the assignment operator =. Use the assignment operator with a variable name on the left and the data on the right. You can assign data anytime after a variable has been declared.

The following example declares a variable named userAge to hold an integer and then assigns it the value of 21.
internal var userAge:int; 
userAge = 21;
Because you can assign data anytime after a variable has been declared, you can do it immediately after declaration within the same statement.
public var userName:String = "Jane"; 
private var correctAnswer:Boolean = true; 
internal var userAge:uint = 19; 
protected var predictedTemperature:int = -5; 
private var productPrice:Number = 5.99;

Assignment can take place any time after a variable has been declared—at declaration, many lines later, or after an event occurs. Assignment takes place when the data is known.

Constants

Constants are properties with a fixed value that cannot be altered. You can assign a value to a constant only once, and the assignment must occur in proximity to the declaration of the constant. An error results if you attempt to change the data in a constant.

Constants are declared using the const keyword instead of var . By convention, constant names are all caps with words separated by an underscore

Example: You are building an application that converts miles to kilometers. Miles are multiplied by a conversion value to get kilometers. If that conversion value changes, the conversions are no longer correct. Use a constant to hold the conversion value.

const MILES_KM_CONVERSION_VALUE:Number = 1.61;

Data types

Data types

Computers handle different types of data differently. Possible values, operations that can be performed, and storage methods vary across the types of data a programming language supports. Assigning the data type for a variable limits what the variable can contain, what can be done to the value, and how it is stored.

Using data types can seem like an extra step because you must plan how your application handles data before you start writing code. However, when you use data types, your code is more predictable and your applications are more stable. Data types are also invaluable during the debugging process.

Think about the toy that helps toddlers learn to recognize shapes. Star shaped blocks only fit in the star holes. Cubes only fit in the square holes. Cylinders only fit in the circle holes. The box gives toddlers an immediate error—the block doesn’t fit—when they try to put the star into the square hole. Similarly, the computer throws an error when you try to fit one type of data into a variable that was typed with a different data type.

ActionScript 3.0 has many data types to use as the type for the variables you create. A primitive value is a value that belongs to one of the following data types: String , Number , int , uint , Boolean , Null , and void .

  • String : a textual value, like a name or the text of a book chapter

  • Numeric: ActionScript 3.0 includes three specific data types for numeric data:

    • Number : any numeric value, including values with or without a fraction

    • int : an integer (a whole number without a fraction)

    • uint : an “unsigned” integer, meaning a whole number that is not negative

  • Boolean : a true-or-false value, such as whether a switch is on or whether two values are equal

Primitive values are usually faster than complex values because ActionScript 3.0 stores primitive values in a special way that makes memory and speed optimizations possible.

Note: For readers interested in the technical details, ActionScript 3.0 stores primitive values internally as immutable objects. The fact that they are stored as immutable objects means that passing by reference is effectively the same as passing by value. This cuts down on memory usage and increases execution speed, because references are usually significantly smaller than the values themselves.

A complex value is a value that is not a primitive value. Data types that define sets of complex values include: Object , Array , Date , Error , Function , RegExp , XML , and XMLList . All values in ActionScript 3.0, whether they are primitive or complex , are objects.

The ActionScript 3.0 core classes include all of the primitive and complex data types listed above. The core classes allow you to create objects using literal values instead of using the new operator. For example, you can create an array using a literal value or the Array class constructor, as follows:
var someArray:Array = [1, 2, 3]; // literal value 
var someArray:Array = new Array(1,2,3); // Array constructor

Type checking

Type checking can occur at either compile time or runtime. Statically typed languages report type errors at compile time, which requires type information to be known at compile time. Dynamically typed languages type check at runtime which allows flexibility in code structure. However, in runtime reporting, type errors are not discovered until later. As a dynamically typed language, ActionScript 3.0 has runtime type checking. However, in strict mode , type checking occurs at both compile time and runtime. In standard mode, type checking occurs only at runtime.

Compile-time type checking

Compile-time type checking is favored as a project’s size grows because catching type errors as early as possible becomes more important than data type flexibility. By default, the ActionScript compiler in Flash Professional and Flash Builder is set to run in strict mode to catch errors early.

To provide compile-time type checking, the compiler must know the data type information for the variables or expressions in your code. To explicitly declare a data type for a variable, use the colon operator ( : ) followed by the data type as a suffix to the variable name. To associate a data type with a parameter, use the colon operator followed by the data type. For example, the following code adds data type information to the sampleParameter parameter and declares a variable sampleData with an explicit data type:

function runtimeTest(sampleParameter:String) 
{ 
    trace(sampleParameter); 
} 
var sampleData:String = "hello"; 
runtimeTest(sampleData);

In strict mode, the ActionScript compiler reports type mismatches as compiler errors. For example, the following code declares a function parameter sampleParameter , of type Object, but later attempts to assign values of type String and Number to that parameter. In strict mode, a compiler error results.

function dynamicTest(sampleParameter:Object) 
{ 
    if (sampleParameter is String) 
    { 
        var exampleString:String = sampleParameter; // compiler error in strict mode 
        trace("String: " + exampleString); 
    } 
    else if (sampleParameter is Number) 
    { 
        var exampleNumber:Number = sampleParameter; // compiler error in strict mode 
        trace("Number: " + exampleNumber); 
    } 
}

Runtime type checking

Runtime type checking occurs in ActionScript 3.0 whether you compile in strict mode or standard mode. Consider a situation in which the value 3 is passed as an argument to a function that expects an array. In strict mode, the compiler generates an error, because the value 3 is not compatible with the data type Array . If you run in standard mode, the compiler does not complain about the type mismatch, but runtime type checking results in a runtime error.

The following example shows a function named typeTest() that expects an Array argument but is passed a value of 3. The incorrect type causes a runtime error in standard mode, because the value 3 is not a member of the parameter’s declared data type (Array).

function typeTest(sampleParameter:Array) 
{ 
    trace(sampleParameter); 
} 
var exampleNumber:Number = 3; 
typeTest(exampleNumber);  
// run-time error in ActionScript 3.0 standard mode

There are also situations where you get a runtime type error even when you are operating in strict mode. This error is possible if you use strict mode, but opt out of compile-time type checking by using an untyped variable. When you use an untyped variable, you are not eliminating type checking but rather deferring it until runtime. For example, if the exampleNumber variable in the previous example does not have a declared data type, the compiler cannot detect the type mismatch. However, a runtime error occurs because ActionScript compares the runtime value of exampleNumber , which is 3, with the type of sampleParameter , which is set to the Array data type.

function typeTest(sampleParameter:Array) 
{ 
    trace(sampleParameter); 
} 
var exampleNumber = 3; 
typeTest(exampleNumber);  
// run-time error in ActionScript 3.0

The is operator

The is operator tests whether a variable or expression is compatible with a given data type. It examines the proper inheritance hierarchy and can be used to check whether an object is an instance of a particular class. It can also check whether an object is an instance of a class that implements a particular interface. The following example creates an instance of the Sprite class named mySprite . Then it uses the is operator to test whether mySprite is an instance of the Sprite and DisplayObject classes, and whether it implements the IEventDispatcher interface:
var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

The is operator checks the inheritance hierarchy and properly reports that mySprite is compatible with the Sprite and DisplayObject classes. The is operator also checks whether mySprite inherits from any classes that implement the IEventDispatcher interface. Because the Sprite class inherits from the EventDispatcher class, which implements the IEventDispatcher interface, the is operator correctly reports that mySprite implements the same interface.

Data type descriptions

The primitive data types include Boolean , int , Null , Number , String , uint , and void . The ActionScript core classes also define the following complex data types: Object , Array , Date , Error , Function , RegExp , XML , and XMLList .

Boolean data type

The Boolean data type includes two values: true and false . No other values are valid for variables of Boolean type. The default value of a Boolean variable that has been declared but not initialized is false .

Number data type

In ActionScript 3.0, the Number data type can represent all types of numbers—integers, unsigned integers, and floating‑point numbers. It is the most flexible of numeric data types in ActionScript 3.0. However, to maximize performance, use the Number data type only for floating-point numbers or for integer values larger than the 32‑bit int and uint types can store.

Storage of floating-point numbers

The Number data type uses the 64‑bit double-precision format as specified by the IEEE Standard for Binary Floating‑Point Arithmetic (IEEE-754). This standard dictates how floating-point numbers are stored using the 64 available bits. One bit is used to designate whether the number is positive or negative. Eleven bits are used for the exponent, which is stored as base 2. The remaining 52 bits are used to store the significand (also called mantissa ), the number that is raised to the power indicated by the exponent.

By using some of its bits to store an exponent, the Number data type can store floating-point numbers significantly larger than if it used all of its bits for the significand. For example, if the Number data type used all 64 bits to store the significand, it could store a number as large as 2 65 - 1. By using 11 bits to store an exponent, the Number data type can raise its significand to a power of 2 1023 .

Although this range of numbers is enormous, it comes at the cost of precision. Because the Number data type uses 52 bits to store the significand, numbers that require more than 52 bits for accurate representation, such as the fraction 1/3, are only approximations. If your application requires absolute precision with decimal numbers, use software that implements decimal floating-point arithmetic as opposed to binary floating-point arithmetic.

To store a floating-point number, include a decimal point in the number. If you omit a decimal point, the number is stored as an integer.

NaN and other special Number values

The default value of an unassigned Number variable is NaN . The NaN value is also the result of any operation that should return a number but does not. For example, if you attempt to calculate the square root of a negative number or divide 0 by 0, the result is NaN . Other special Number values include positive infinity and negative infinity.

Note: The result of division by 0 is only NaN if the divisor is also 0. Division by 0 produces infinity when the dividend is positive or -infinity when the dividend is negative.

Int data type

The int data type includes all positive and negative whole numbers from ‑2,147,483,648 (‑2 31 ) through 2,147,483,647 (2 31 – 1) inclusive. It is stored as a 32‑bit integer. If you do not need floating-point numbers, use the int type instead of Number because it is faster and more efficient. For values outside the range of int , use the Number data type. The int type is commonly used in counters and loops. The default value for unassigned int variables is 0.

If you try to assign a floating-point value to an int variable, ActionScript ignores the fractional (decimal) part.

Uint data type

The uint data type includes all positive whole numbers from 0 through 4,294,967,295 (2 32 – 1) inclusive. It is stored as a 32‑bit integer. The default value for unassigned uint variables is 0. As with int , if you try to assign a floating‑point value to a uint variable, ActionScript ignores the fractional (decimal) part.

A uint value is always a simple binary translation of the value. Use a uint for all bit math and when working with hexadecimal values for color.

Null data type

The Null data type contains only one value, null . This value is the default value for the String data type and all classes that define complex data types, including the Object class. None of the other primitive data types, Boolean , Number , int , and uint , contain the value null . At runtime, the value null is converted to the appropriate default value if you attempt to assign null to variables of type Boolean , Number , int , or uint .

Do not confuse value null with the special value undefined . When null and undefined are compared with the equality ( == ) operator, they compare as equal. However, when null and undefined are compared with the strict equality ( === ) operator, they compare as not equal.

String data type

The String data type represents a sequence of 16‑bit characters. Strings are stored internally as Unicode characters, using the UTF‑16 format. Strings are immutable values. An operation on a String value returns a new instance of the string. The default value for a variable declared with the String data type is null . The value nul is not the same as the empty string ( "" ). The value null means that the variable has no value stored in it. The empty string means that the variable has a value that is a String containing no characters.

void data type

The void data type contains only one value, undefined . You can only assign a value of undefined to variables that are untyped. Untyped variables are variables that either lack any type annotation, or use the asterisk ( * ) symbol for type annotation. You can use void only as a return type annotation.

Object data type

The Object class defines the Object data type. The Object class serves as the base class for all class definitions in ActionScript. The default value for instances of the Object class is null .

Type conversions

A type conversion is said to occur when a value of one data type is transformed into a value of a different data type. Type conversions can be either implicit or explicit . Implicit conversion, also called coercion , is sometimes performed at runtime. For example, if the value 2 is assigned to a Boolean typed variable, the value 2 is converted to the Boolean value true before assignment. Explicit conversion, also called casting , occurs when your code instructs the compiler to treat a variable of one data type as if it belongs to a different data type. When primitive values are involved, casting actually converts values from one data type to another. To cast an object to a different type, you wrap the object name in parentheses and precede it with the name of the new type. For example, the following code takes a Boolean value and casts it to an integer:

var myBoolean:Boolean = true; 
var myINT:int = int(myBoolean); 
trace(myINT); // 1

Implicit conversions

Implicit conversions happen at runtime in a number of contexts:

  • In assignment statements

  • When values are passed as function arguments

  • When values are returned from functions

  • In expressions using certain operators, such as the addition ( + ) operator

For user-defined types, implicit conversions succeed when the value to be converted is an instance of the destination class or a class that derives from the destination class. If an implicit conversion is unsuccessful, an error occurs. For example, the following code contains a successful implicit conversion and an unsuccessful implicit conversion:

class A {} 
class B extends A {} 
 
var objA:A = new A(); 
var objB:B = new B(); 
var arr:Array = new Array(); 
 
objA = objB; // Conversion succeeds. 
objB = arr; // Conversion fails.

For primitive types, implicit conversions are handled by calling the same internal conversion algorithms that are called by the explicit conversion functions.

Explicit conversions

It’s helpful to use explicit conversions when you compile in strict mode, because there are times when you do not want to generate a compile-time error. Use explicit conversions when you know that coercion will convert your values correctly at runtime. For example, when working with data received from a form, cast certain string values to numeric values. The following code generates a compile-time error even though the code would run correctly in standard mode:

var quantityField:String = "3"; 
var quantity:int = quantityField; // compile time error in strict mode

If you want to continue using strict mode, but would like the string converted to an integer, you can use explicit conversion, as follows:

var quantityField:String = "3"; 
var quantity:int = int(quantityField); // Explicit conversion succeeds.

Casting to int, uint, and Number

You can cast any data type into one of the three number types: int , uint , and Number . If the number can’t be converted, the default value of 0 is assigned for int and uint data types, and the default value of NaN is assigned for the Number data type. If you convert a Boolean value to a number, true becomes the value 1 and false becomes the value 0.

var exampleBoolean:Boolean = true; 
var exampleUINT:uint = uint(exampleBoolean); 
var exampleINT:int = int(exampleBoolean); 
var exampleNumber:Number = Number(exampleBoolean); 
trace(exampleUINT, exampleINT, exampleNumber); // 1 1 1 
exampleBoolean = false; 
exampleUINT = uint(exampleBoolean); 
exampleINT = int(exampleBoolean); 
exampleNumber = Number(exampleBoolean); 
trace(exampleUINT, exampleINT, exampleNumber); // 0 0 0

String values that contain only digits can be successfully converted into one of the number types. The number types can also convert strings that look like negative numbers or strings that represent a hexadecimal value (for example, 0x1A ). The conversion process ignores leading and trailing white space characters in the string value. You can also cast strings that look like floating-point numbers using Number() . The inclusion of a decimal point causes uint() and int() to return an integer, truncating the decimal and the characters following it. For example, the following string values can be cast into numbers:

trace(uint("5")); // 5 
trace(uint("-5")); // 4294967291. It wraps around from MAX_VALUE 
trace(uint(" 27 ")); // 27 
trace(uint("3.7")); // 3 
trace(int("3.7")); // 3 
trace(int("0x1A")); // 26 
trace(Number("3.7")); // 3.7

String values that contain non-numeric characters return 0 when cast with int() or uint() and NaN when cast with Number() . The conversion process ignores leading and trailing white space, but returns 0 or NaN if a string has white space separating two numbers.

trace(uint("5a")); // 0 
trace(uint("ten")); // 0 
trace(uint("17 63")); // 0

Casting is not necessary when a value of one numeric type is assigned to a variable of a different numeric type. Even in strict mode, the numeric types are implicitly converted to the other numeric types. In some cases, this implicit conversion causes unexpected values to result when the range of a type is exceeded. The following examples all compile in strict mode, though some generate unexpected values:

var exampleUint:uint = -3; // Assign int/Number value to uint variable 
trace(exampleUint); // 4294967293 
 
var exampleNumber:Number = exampleUint; // Assign int/uint value to Number variable 
trace(exampleNumber) // 4294967293 
 
var exampleInt:int = Number.MAX_VALUE + 1; // Assign Number value to int variable 
trace(exampleInt); // 0 
 
exampleInt = uint.MAX_VALUE + 1; // Assign uint value to int variable 
trace(exampleInt); // 0

The following table summarizes the results of casting to the Number , int , or uint data type from other data types.

Data type or value

Result of conversion to Number, int, or uint

Boolean

If the value is true , 1; otherwise, 0.

Date

The internal representation of the Date object, which is the number of milliseconds since midnight January 1, 1970, universal time.

null

0

Object

If the instance is null and converted to Number , NaN ; otherwise, 0.

String

A number if the string can be converted to a number; otherwise, NaN if converted to Number , or 0 if converted to int or uint .

undefined

If converted to Number , NaN ; if converted to int or uint , 0.

Casting to Boolean

Casting to Boolean from any of the numeric data types ( uint , int , and Number ) results in false if the numeric value is 0, and true otherwise. For the Number data type, the value NaN also results in false . The following example shows the results of casting the numbers -1, 0, and 1:

var numberToCast:Number; 
for (numberToCast = -1; numberToCast<2; numberToCast++) 
{ 
    trace("Boolean(" + numberToCast +") is " + Boolean(numberToCast)); 
}

The output from the example shows that, of the three numbers, only 0 returns a value of false :

Boolean(-1) is true 
Boolean(0) is false 
Boolean(1) is true

Casting to Boolean from a String value returns false if the string is either null or an empty string ( "" ). Otherwise, it returns true .

var stringToCast:String; // Uninitialized string is null. 
trace(Boolean(stringToCast)); // false 
 
var emptyStringToCast:String = ""; // empty string 
trace(Boolean(emptyStringToCast)); // false 
 
var wsStringToCast:String = " "; // white space only 
trace(Boolean(wsStringToCast)); // true

Casting to Boolean from an instance of the Object class returns false if the instance is null ; otherwise, it returns true :

var objectToCast:Object; // Uninitialized object is null. 
trace(Boolean(objectToCast)); // false 
 
objectToCast = new Object(); // instantiate  
trace(Boolean(objectToCast)); // true
Boolean variables get special treatment in strict mode in that you can assign values of any data type to a Boolean variable without casting. In other words, unlike almost all other data types, casting to Boolean is not necessary to avoid strict mode errors. The following examples all compile in strict mode and behave as expected at runtime:
var objectToCast:Object = new Object(); 
var sampleBoolean:Boolean = objectToCast; 
trace(sampleBoolean); // true 
sampleBoolean = "random string"; 
trace(sampleBoolean); // true 
sampleBoolean = new Array(); 
trace(sampleBoolean); // true 
sampleBoolean = NaN; 
trace(sampleBoolean); // false

The following table summarizes the results of casting to the Boolean data type from other data types:

Data type or value

Result of conversion to Boolean

String

false if the value is null or the empty string ( "" ); true otherwise.

null

false

Number , int , or uint

false if the value is NaN or 0; true otherwise.

Object

false if the instance is null ; true otherwise.

Casting to String

Casting to the String data type from any of the numeric data types returns a string representation of the number. Casting to the String data type from a Boolean value returns the string "true" if the value is true , and returns the string "false" if the value is false .

Casting to the String data type from an instance of the Object class returns the string "null" if the instance is null . Otherwise, casting to the String type from the Object class returns the string "[object Object]" .

Casting to String from an instance of the Array class returns a string made up of a comma-delimited list of all the array elements. For example, the following cast to the String data type returns one string containing all three elements of the array:
var sampleArray:Array = ["primary", "secondary", "tertiary"]; 
trace(String(sampleArray)); // primary,secondary,tertiary
Casting to String from an instance of the Date class returns a string representation of the date that the instance contains. For example, the following example returns a string representation of the Date class instance (the output shows result for Pacific Daylight Time):
var sampleDate:Date = new Date(2005,6,1); 
trace(String(sampleDate)); // Fri Jul 1 00:00:00 GMT-0700 2005

The following table summarizes the results of casting to the String data type from other data types.

Data type or value

Result of conversion to string

Array

A string made up of all array elements.

Boolean

" true " or " false "

Date

A string representation of the Date object.

null

"null"

Number , int , or uint

A string representation of the number.

Object

If the instance is null, "null" ; otherwise, "[object Object]".

The as operator

The as operator attempts to perform a type cast. If it succeeds, the value of the expression is returned. If the cast fails, null is returned. The following example shows the results of using the as operator in the simple case of checking whether a Sprite instance is a member of the DisplayObject, IEventDispatcher, and Number data types.

var mySprite:Sprite = new Sprite(); 
trace(mySprite as Sprite);                 // [object Sprite] 
trace(mySprite as DisplayObject);                 // [object Sprite] 
trace(mySprite as IEventDispatcher);                 // [object Sprite] 
trace(mySprite as Number);                                       // null

When you use the as operator, the operand on the right must be a data type. An attempt to use an expression other than a data type as the operand on the right results in an error.

Default values

A default value is the value that a variable contains before you set its value. You initialize a variable when you assign it a value for the first time. If you declare a variable, but do not assign it a value, that variable is uninitialized . The value of an uninitialized variable depends on its data type. The following table describes the default values of variables, organized by data type:

Data type

Default value

Boolean

false

int

0

Number

NaN

Object

null

String

null

uint

0

Not declared (equivalent to type annotation * )

undefined

All other classes, including user-defined classes.

null

If you declare a variable, but do not declare its data type, the default data type * applies, which actually means that the variable is untyped. If you also do not initialize an untyped variable with a value, its default value is undefined .

The value null is not a valid value for variables of type Boolean , Number , int , or uint . If you attempt to assign a value of null to a such a variable, the value is converted to the default value for that data type. For variables of type Object , you can assign a value of null . If you attempt to assign the value undefined to a variable of type Object , the value is converted to null .

Operators

Operators and operands

Operators are special symbols (or occasionally words) that are used to perform calculations and to compare, modify, or combine values of variables, objects, properties, and expressions. They take one or more operands and frequently return a value.

An operand is a value—a literal, a variable, or an expression—that an operator uses as input. For example, in the following code, the addition ( + ) and multiplication ( * ) operators are used with three literal operands (2, 3, and 4 ) to return a value. The assignment ( = ) operator then assigns the returned value, 14, to the variable sumNumber .
var sumNumber:uint = 2 + 3 * 4; // sumNumber is now 14

Prefix operators come before their operand. Logical NOT ( ! ) and negation ( - ) are examples of prefix operators. Postfix operators come after their operands. Increment ( ++ ) and decrement ( -- ) are examples of postfix operators. Interfix operators come between operands. In 2 * y , the multiplication operator is an interfix operator.

Operators can be unary, binary, or ternary. A unary operator, such as the increment operator ( ++ ), takes one operand. A binary operator, like the division operator ( / ), takes two operands. A ternary operator takes three operands. It is important to provide the correct number of operands.

Some operators are overloaded , which means that they behave differently depending on the type or quantity of operands passed to them. The addition ( + ) operator is an example of an overloaded operator that behaves differently depending on the data type of the operands. If both operands are numbers, the addition operator returns the sum of the values. If both operands are strings, the addition operator returns the concatenation of the two operands. The following example code shows how the operator behaves differently depending on the operands:
trace(5 + 5); // 10 
trace("Hello" + "world"); // Helloworld 
trace("5" + "5"); // 55

Types of operators

Arithmetic operators

The additive and multiplicative operators ( + , - , * , / ) take two operands and perform the appropriate calculation. The modulo operator returns the remainder after a division operation. Increment ( ++ ) and decrement ( -- ) are unary operators and therefore only require one operand. They either add (increment) or subtract (decrement) 1 from the expression they are used on. They can be used as either prefix or postfix operators.

Operator

Operation performed

+

Addition : Adds numeric expressions

-

Subtraction : Negates or subtracts numeric expressions

*

Multiplication: Multiplies two numerical expressions

/

Division : Divides expression1 by expression2

%

Modulo : Calculates the remainder of expression1 divided by expression2

++

Increment : Adds 1 to a numeric expression

--

Decrement: Subtracts 1 from a numeric expression

The increment ( ++ ) and decrement ( -- ) operators can be used as prefix or postfix operators . When used as prefix operators, the increment or decrement operation is completed before the value of the overall expression is returned. For example, the following code shows how the value of the expression ++xNum is returned after the value is incremented:
var xNum:Number = 0; 
trace(++xNum); // 1 
trace(xNum); // 1
When increment or decrement is used as a postfix operator, the expression’s value is returned before the postfix operator is processed. For example, the following code shows how the value of the expression xNum++ is returned before the value is incremented:
var xNum:Number = 0; 
trace(xNum++); // 0 
trace(xNum); // 1

Assignment and compound assignment operators

The assignment operator assigns the value of the expression on the right to the operand on the left. The operand on the right can be any expression that ActionScript 3.0 can evaluate. The operand on the left must be a single variable, array element, or property.

Compound assignment operators perform arithmetic on a variable and then store the result in that same variable.

Operator

Operation performed

Example

=

Assignment: Assigns the value of expression2 (the operand on the right) to the variable, array element, or property in expression1 (the operand on the left)

var x:uint = 10; 
// x is now 10 
var y:uint = (5+7)/2; 
// y is now 6 
var text:String = "Hello"; 
// text is now Hello

+=

Addition assignment : Assigns expression1 the value of expression1 + expression2

var x:uint = 5; 
x += 5; // x is now 10

-=

Subtraction assignment : Assigns expression1 the value of expression1 - expression2

var x:uint = 5; 
x -= 5; // x is now 0

*=

Multiplication assignment : Assigns expression1 the value of expression1 * expression2

var x:uint = 5; 
x *= 5; // x is now 25

/=

Division assignment : Assigns expression1 the value of expression1 / expression2

var x:uint = 5; 
x /= 5; // x is now 1

%=

Modulo assignment : Assigns expression1 the value of expression1 % expression2

var x:uint = 13; 
x %= 5; // x is now 3

Equality and comparison operators

The equality operators take two operands, compare their values, and return a Boolean value. The relational operators take two operands, compare their values, and return a Boolean value.

Operator

Operation performed

Example

==

Equality : Tests two expressions for equality. The result is true if the expressions are equal.

var a:uint = 13; 
var b:uint = 13; 
trace(a==b); // true 
 
var c:String = "Hello"; 
var d:String = "World"; 
trace(c==d); // false

!=

Inequality : Tests for the exact opposite of the equality ( == ) operator. If expression1 is equal to expression2 , the result is false .

var a:uint = 13; 
var b:uint = 13; 
trace(a!=b); // false 
 
var c:String = "Hello"; 
var d:String = "World"; 
trace(c==d); // true

===

Strict equality : Tests two expressions for equality, but does not perform automatic data conversion. The result is true if both expressions, including their data types, are equal.

var a:uint = 13; 
var b:Number = 13; 
trace(a===b); // false 
 
var c:uint = 22; 
var d:uint = 22; 
trace(c===d); // true

!==

Strict inequality : Tests for the exact opposite of the strict equality (===) operator. If expression1 is equal to expression2 , and their data types are equal, the result is false .

var a:uint = 13; 
var b:Number = 13; 
trace(a!==b); // true 
 
var c:uint = 22; 
var d:uint = 22; 
trace(c!==d); // false

<

Less than : Compares two expressions and determines whether expression1 is less than expression2 ; if it is, the result is true

var x:int = 27; 
var y:int = 42; 
var z:int = 101; 
trace(x<y); // true 
trace(z<y); // false

>

Greater than : Compares two expressions and determines whether expression1 is greater than expression2 ; if it is, the result is true

var x:int = 27; 
var y:int = 42; 
var z:int = 101; 
trace(x>y); // false 
trace(z>y); // true

<=

Less than or equal to : Compares two expressions and determines whether expression1 is less than or equal to expression2 ; if it is, the result is true

var x:int = 27; 
var y:int = 42; 
var z:int = 42; 
trace(x<=y); // true 
trace(y<=z); // true

>=

Greater than or equal to : Compares two expressions and determines whether expression1 is greater than or equal to expression2 ; if it is, the result is true

var x:int = 27; 
var y:int = 42; 
var z:int = 42; 
trace(x>=y); // false 
trace(y>=z); // true

Logical operators

The logical operators take two operands and return a Boolean result. They are frequently used to combine conditions.

Operator

Operation performed

!

Logical NOT : Inverts the Boolean value of a variable or expression

&&

Logical AND : Returns expression1 if it is false or can be converted to false , and expression2 otherwise. If both operands are of type Boolean, the result is true only if both operands are true

||

Logical OR : Returns expression1 if it is true or can be converted to true, and expression2 otherwise. If both operands are of type Boolean, the result is true if either or both expressions are true; the result is false only if both expressions are false.

&&=

Logical AND assignment : Assigns expression1 the value of expression1 && expression2

||=

Logical OR assignment : Assigns expression1 the value of expression1 || expression2

Bitwise logical operators

The bitwise logical operators take two operands and perform bit-level logical operations.

Operator

Operation performed

~

Bitwise NOT : Converts expression to a 32-bit signed integer, and then applies a bitwise one's complement

&

Bitwise AND : Converts expression1 and expression2 to 32-bit unsigned integers, and performs a Boolean AND operation on each bit of the integer parameters

|

Bitwise OR : Converts expression1 and expression2 to 32-bit unsigned integers, and places a 1 in each bit position where the corresponding bits of either expression1 or expression2 are 1

^

Bitwise XOR: Converts expression1 and expression2 to 32-bit unsigned integers, and places a 1 in each bit position where the corresponding bits in expression1 or expression2 , but not both, are 1

&=

Bitwise AND assignment : Assigns expression1 the value of expression1 & expression2

|=

Bitwise OR assignment : Assigns expression1 the value of expression1 | expression2

^=

Bitwise XOR assignment : Assigns expression1 the value of expression1 ^ expression2

Bitwise shift operators

The bitwise shift operators take two operands and shift the bits of the first operand to the extent specified by the second operand.

Operator

Operation performed

<<

Bitwise left shift : Converts expression1 and shiftCount to 32-bit integers, and shifts all the bits in expression1 to the left by the number of places specified by the integer resulting from the conversion of shiftCount

>>

Bitwise right shift : Converts expression1 and shiftCount to 32-bit integers, and shifts all the bits in expression to the right by the number of places specified by the integer that results from the conversion of shiftCount

>>>

Bitwise unsigned right shift : The same as the bitwise right shift ( >> ) operator except that it does not preserve the sign of the original expression because the bits on the left are always filled with 0

<<=

Bitwise left shift assignment : Performs a bitwise left shift operation and stores the contents as a result in expression1

>>=

Bitwise right shift assignment : Performs a bitwise right shift operation and stores the contents as a result in expression1

>>>=

Bitwise unsigned right shift assignment : Performs an unsigned bitwise right-shift operation and stores the result in expression1

Other operators

The primary operators include those operators used for creating Array and Object literals, grouping expressions, calling functions, instantiating class instances, and accessing properties.

The conditional operator is a ternary operator, which means that it takes three operands. The conditional operator is a shorthand method of applying the if..else conditional statement.

Operator

Operation performed

[]

Array access : Initializes a new array or accesses elements in an array

as

As : Evaluates whether an expression specified by the first operand is a member of the data type specified by the second operand

?:

Conditional : Evaluates expression1 , and if the value of expression1 is true , the result is the value of expression2 ; otherwise the result is the value of expression3

delete

Delete -Destroys the object property specified by reference; the result is true if the property does not exist after the operation completes, and false otherwise

.

Dot : Accesses class variables and methods, gets and sets object properties, and delimits imported packages or classes

in

In : Evaluates whether a property is part of a specific object

instanceof

Instance of : Evaluates whether an expression's prototype chain includes the prototype object for function

is

Is : Evaluates whether an object is compatible with a specific data type, class, or interface

::

Name qualifier : Identifies the namespace of a property, a method, an XML property, or an XML attribute.

new

New : Instantiates a class instance.

{x:y}

Object initializer : Creates an object and initializes it with the specified name and value property pairs

()

Parentheses : Performs a grouping operation on one or more parameters, performs sequential evaluation of expressions, or surrounds one or more parameters and passes them as arguments to a function that precedes the parentheses

/

RegExp delimiter : When used before and after characters, indicates that the characters have a literal value and are considered a regular expression (RegExp), not a variable, string, or other ActionScript element

:

Type : Used for assigning a data type; this operator specifies the variable type, function return type, or function parameter type

typeof

Type of : Evaluates expression and returns a string specifying the expression's data type

void

Void : Evaluates an expression and then discards its value, returning undefined

Operator precedence and associativity

Operator precedence and associativity determine the order in which operators are processed. The compiler needs explicit instructions about which operators to process first. Such instructions are collectively referred to as operator precedence . Higher precedence operators are processed before lower precedence operators. The order of operations of arithmetic is maintained within the default operator precedence of ActionScript 3.0. You can alter the default precedence using the parentheses ( () ) operator. For example, the following code alters the default precedence in the previous example to force the compiler to process the addition operator before the multiplication operator:
var sumNumber:uint = (2 + 3) * 4; // sumNumber is 20

If two or more operators of the same precedence appear in the same expression, the compiler uses the rules of associativity to determine which operator to process first. All of the binary operators, except the assignment operators, are left-associative , which means that operators on the left are processed before operators on the right. The assignment operators and the conditional ( ?: ) operator are right-associative , which means that the operators on the right are processed before operators on the left.

For example, consider the less-than ( < ) and greater-than ( > ) operators, which have the same precedence. If both operators are used in the same expression, the operator on the left is processed first because both operators are left-associative. This means that the following two statements produce the same output:
trace(3 > 2 < 1); // false 
trace((3 > 2) < 1); // false
The greater-than operator is processed first, which results in a value of true , because the operand 3 is greater than the operand 2. The value true is then passed to the less-than operator along with the operand 1. The following code represents this intermediate state:
trace((true) < 1); 
The less-than operator converts the value true to the numeric value 1 and compares that numeric value to the second operand 1 to return the value false .
trace(1 < 1); // false
You can alter the default left associativity with the parentheses operator. You can instruct the compiler to process the less-than operator first by enclosing that operator and its operands in parentheses. The following example uses the parentheses operator to produce a different output using the same numbers as the previous example:
trace(3 > (2 < 1)); // true
The less-than operator is processed first, which results in a value of false because the operand 2 is not less than the operand 1. The value false is then passed to the greater-than operator along with the operand 3. The following code represents this intermediate state:
trace(3 > (false)); 
The greater-than operator converts the value false to the numeric value 0 and compares that numeric value to the other operand 3 to return true .
trace(3 > 0); // true

The following table lists the operators for ActionScript 3.0 in order of decreasing precedence. Each row of the table contains operators of the same precedence. Each row of operators has higher precedence than the row appearing below it in the table.

Group

Operators

Primary

[] {x:y} () f(x) new x.y x[y] <></> @ :: ..

Postfix

x++ x--

Unary

++x --x + - ~ ! delete typeof void

Multiplicative

* / %

Additive

+ -

Bitwise shift

<< >> >>>

Relational

< > <= >= as in instanceof is

Equality

== != === !==

Bitwise AND

&

Bitwise XOR

^

Bitwise OR

|

Logical AND

&&

Logical OR

||

Conditional

?:

Assignment

= *= /= %= += -= <<= >>= >>>= &= ^= |=

Comma

,

Numbers and math

Types of numbers

ActionScript 3.0 can manipulate different types of numbers. Understanding the different types of numbers and how they work is advantageous for a programmer. You can select the appropriate numerical data types when programming, know the limitations of each type within the language, and find solutions to problems that can occur.

Natural numbers

Natural numbers are the numbers you are most familiar with. You use them to count the things around you. A natural number is zero and any number obtained by repeatedly adding 1—in other words, 0 and any positive, whole number. Examples of natural numbers are 100, 0, 45,645, 32.

Integers

Integers include all natural numbers plus all negative whole numbers. Examples of integers are ‑24, ‑1, 100, 0, 45,645.

Real numbers

Any rational or irrational number is a real number. A rational number is any number that can be expressed as the quotient or fraction of two integers or with a decimal. Examples of rational numbers are ‑249, ‑1, 0, 3/7, ‑2/5, and .342. Irrational numbers are numbers that can’t accurately be expressed as a fraction or with a decimal. The best-known irrational numbers are π, e, and the √2. Floating-point numbers represent real numbers in computers.

Numerical data types in ActionScript 3.0

ActionScript 3.0 has different numerical data types to work with the different types of numbers.

Number data type

In ActionScript 3.0, the Number data type can represent all types of numbers—integers, unsigned integers, and floating‑point numbers. It is the most flexible of numeric data types in ActionScript 3.0. However, to maximize performance, use the Number data type only for floating-point numbers or for integer values larger than the 32-bit int and uint types can store.

Storage of floating-point numbers

The Number data type uses the 64‑bit double-precision format as specified by the IEEE Standard for Binary Floating‑Point Arithmetic (IEEE-754). This standard dictates how floating-point numbers are stored using the 64 available bits. One bit is used to designate whether the number is positive or negative. Eleven bits are used for the exponent, which is stored as base 2. The remaining 52 bits are used to store the significand (also called mantissa ), the number that is raised to the power indicated by the exponent.

By using some of its bits to store an exponent, the Number data type can store floating-point numbers significantly larger than if it used all of its bits for the significand. For example, if the Number data type used all 64 bits to store the significand, it could store a number as large as 2 65 - 1. By using 11 bits to store an exponent, the Number data type can raise its significand to a power of 2 1023 .

Although this range of numbers is enormous, it comes at the cost of precision. Because the Number data type uses 52 bits to store the significand, numbers that require more than 52 bits for accurate representation, such as the fraction 1/3, are only approximations. If your application requires absolute precision with decimal numbers, use software that implements decimal floating-point arithmetic as opposed to binary floating-point arithmetic.

To store a floating-point number, include a decimal point in the number. If you omit a decimal point, the number is stored as an integer.

NaN and other special Number values

The default value of an unassigned Number variable is NaN . The NaN value is also the result of any operation that should return a number but does not. For example, if you attempt to calculate the square root of a negative number or divide 0 by 0, the result is NaN . Other special Number values include positive infinity and negative infinity.

Note: The result of division by 0 is only NaN if the divisor is also 0. Division by 0 produces infinity when the dividend is positive or -infinity when the dividend is negative.

Int data type

The int data type includes all positive and negative whole numbers from ‑2,147,483,648 (‑2 31 ) through 2,147,483,647 (2 31 – 1) inclusive. It is stored as a 32‑bit integer. If you do not need floating-point numbers, use the int type instead of Number because it is faster and more efficient. For values outside the range of int , use the Number data type. The int type is commonly used in counters and loops. The default value for unassigned int variables is 0.

If you try to assign a floating-point value to an int variable, ActionScript ignores the fractional (decimal) part.

Uint data type

The uint data type includes all positive whole numbers from 0 through 4,294,967,295 (2 32 – 1) inclusive. It is stored as a 32‑bit integer. The default value for unassigned uint variables is 0. As with int , if you try to assign a floating‑point value to a uint variable, ActionScript ignores the fractional (decimal) part.

A uint value is always a simple binary translation of the value. Use a uint for all bit math and when working with hexadecimal values for color.

Math class

ActionScript 3.0 includes a core class dedicated to doing mathematical functions. The Math class contains constants and methods that are used to perform arithmetic and trigonometric calculations. All the properties and methods of the Math class are static. Call them using the syntax Math.method( parameter ) or Math.constant . All constants are defined with the maximum precision of double-precision IEEE-754 floating-point numbers.

Dates

Working with dates and times

Timing might not be everything, but it's usually a key factor in software applications. ActionScript 3.0 provides powerful ways to manage calendar dates, times, and time intervals. Two main classes provide most of this timing functionality: the Date class and the new Timer class in the flash.utils package.

Dates and times are a common type of information used in ActionScript programs. For instance, you might need to know the current day of the week or to measure how much time a user spends on a particular screen, among many other possibilities. In ActionScript, you can use the Date class to represent a single moment in time, including date and time information. Within a Date instance are values for the individual date and time units, including year, month, date, day of the week, hour, minutes, seconds, milliseconds, and time zone. For more advanced uses, ActionScript also includes the Timer class, which you can use to perform actions after a certain delay or at repeated intervals.

Controlling time intervals

When you develop applications using Adobe Flash CS4 Professional, you have access to the timeline, which provides a steady, frame-by-frame progression through your application. In pure ActionScript projects, however, you must rely on other timing mechanisms.

Loops versus timers

In some programming languages, you must devise your own timing schemes using loop statements like for or do..while.

Loop statements generally execute as fast as the local machine allows, which means that the application runs faster on some machines and slower on others. If your application needs a consistent timing interval, you need to tie it to an actual calendar or clock time. Many applications, such as games, animations, and real-time controllers, need regular, time-driven ticking mechanisms that are consistent from machine to machine.

The ActionScript 3.0 Timer class provides a powerful solution. Using the ActionScript 3.0 event model, the Timer class dispatches timer events whenever a specified time interval is reached.

The Timer class

The preferred way to handle timing functions in ActionScript 3.0 is to use the Timer class (flash.utils.Timer), which can be used to dispatch events whenever an interval is reached.

To start a timer, you first create an instance of the Timer class, telling it how often to generate a timer event and how many times to do so before stopping.

For example, the following code creates a Timer instance that dispatches an event every second and continues for 60 seconds:

var oneMinuteTimer:Timer = new Timer(1000, 60);

The Timer object dispatches a TimerEvent object each time the given interval is reached. A TimerEvent object’s event type is timer (defined by the constant TimerEvent.TIMER ). A TimerEvent object contains the same properties as a standard Event object.

If the Timer instance is set to a fixed number of intervals, it will also dispatch a timerComplete event (defined by the constant TimerEvent.TIMER_COMPLETE ) when it reaches the final interval.

Here is a small sample application showing the Timer class in action:

package  
{ 
    import flash.display.Sprite; 
    import flash.events.TimerEvent; 
    import flash.utils.Timer; 
 
    public class ShortTimer extends Sprite 
    { 
        public function ShortTimer()  
        { 
            // creates a new five-second Timer 
            var minuteTimer:Timer = new Timer(1000, 5); 
             
            // designates listeners for the interval and completion events 
            minuteTimer.addEventListener(TimerEvent.TIMER, onTick); 
            minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete); 
             
            // starts the timer ticking 
            minuteTimer.start(); 
        } 
 
        public function onTick(event:TimerEvent):void  
        { 
            // displays the tick count so far 
            // The target of this event is the Timer instance itself. 
            trace("tick " + event.target.currentCount); 
        } 
 
        public function onTimerComplete(event:TimerEvent):void 
        { 
            trace("Time's Up!"); 
        } 
    } 
}

When the ShortTimer class is created, it creates a Timer instance that will tick once per second for five seconds. Then it adds two listeners to the timer: one that listens to each tick, and one that listens for the timerComplete event.

Next, it starts the timer ticking, and from that point forward, the onTick() method executes at one-second intervals.

The onTick() method simply displays the current tick count. After five seconds have passed, the onTimerComplete() method executes, telling you that the time is up.

When you run this sample, you should see the following lines appear in your console or trace window at the rate of one line per second:

tick 1 
tick 2 
tick 3 
tick 4 
tick 5 
Time's Up!
Timing functions in the flash.utils package

ActionScript 3.0 contains a number of timing functions similar to those that were available in ActionScript 2.0. These functions are provided as package-level functions in the flash.utils package, and they operate just as they did in ActionScript 2.0.

Function

Description

clearInterval(id:uint):void

Cancels a specified setInterval() call.

clearTimeout(id:uint):void

Cancels a specified setTimeout() call.

getTimer():int

Returns the number of milliseconds that have elapsed since Adobe® Flash® Player or Adobe® AIR™ was initialized.

setInterval(closure:Function, delay:Number, ... arguments):uint

Runs a function at a specified interval (in milliseconds).

setTimeout(closure:Function, delay:Number, ... arguments):uint

Runs a specified function after a specified delay (in milliseconds).

These functions remain in ActionScript 3.0 for backward compatibility. Adobe does not recommend that you use them in new ActionScript 3.0 applications. In general, it is easier and more efficient to use the Timer class in your applications.

Date and time example: Simple analog clock

A simple analog clock example illustrates these two date and time concepts:

  • Getting the current date and time and extracting values for the hours, minutes, and seconds

  • Using a Timer to set the pace of an application

    To get the application files for this sample, see www.adobe.com/go/learn_programmingAS3samples_flash . The SimpleClock application files can be found in the folder Samples/SimpleClock. The application consists of the following files:

    File

    Description

    SimpleClockApp.mxml

    or

    SimpleClockApp.fla

    The main application file in Flash (FLA) or Flex (MXML).

    com/example/programmingas3/simpleclock/SimpleClock.as

    The main application file.

    com/example/programmingas3/simpleclock/AnalogClockFace.as

    Draws a round clock face and hour, minute, and seconds hands based on the time.

Defining the SimpleClock class

The clock example is simple, but it’s a good idea to organize even simple applications well so you could easily expand them in the future. To that end, the SimpleClock application uses the SimpleClock class to handle the startup and time-keeping tasks, and then uses another class named AnalogClockFace to actually display the time.

Here is the code that defines and initializes the SimpleClock class (note that in the Flash version, SimpleClock extends the Sprite class instead):

public class SimpleClock extends UIComponent 
{ 
    /** 
     * The time display component. 
     */ 
    private var face:AnalogClockFace; 
     
    /** 
     * The Timer that acts like a heartbeat for the application. 
     */ 
    private var ticker:Timer;

The class has two important properties:

  • The face property, which is an instance of the AnalogClockFace class

  • The ticker property, which is an instance of the Timer class

    The SimpleClock class uses a default constructor. The initClock() method takes care of the real setup work, creating the clock face and starting the Timer instance ticking.

Creating the clock face

The next lines in the SimpleClock code create the clock face that is used to display the time:

    /** 
     * Sets up a SimpleClock instance. 
     */ 
    public function initClock(faceSize:Number = 200)  
    { 
        // creates the clock face and adds it to the display list 
        face = new AnalogClockFace(Math.max(20, faceSize)); 
        face.init(); 
        addChild(face); 
         
        // draws the initial clock display 
        face.draw();

The size of the face can be passed in to the initClock() method. If no faceSize value is passed, a default size of 200 pixels is used.

Next, the application initializes the face and then adds it to the display list using the addChild() method inherited from the DisplayObjectContainer class. Then it calls the AnalogClockFace.draw() method to display the clock face once, showing the current time.

Starting the timer

After creating the clock face, the initClock() method sets up a timer:

        // creates a Timer that fires an event once per second 
        ticker = new Timer(1000);  
     
        // designates the onTick() method to handle Timer events 
        ticker.addEventListener(TimerEvent.TIMER, onTick); 
 
        // starts the clock ticking 
        ticker.start();

First this method instantiates a Timer instance that will dispatch an event once per second (every 1000 milliseconds). Since no second repeatCount parameter is passed to the Timer() constructor, the Timer will keep repeating indefinitely.

The SimpleClock.onTick() method will execute once per second when the timer event is received:

    public function onTick(event:TimerEvent):void  
    { 
        // updates the clock display 
        face.draw(); 
    }

The AnalogClockFace.draw() method simply draws the clock face and hands.

Displaying the current time

Most of the code in the AnalogClockFace class involves setting up the clock face’s display elements. When the AnalogClockFace is initialized, it draws a circular outline, places a numeric text label at each hour mark, and then creates three Shape objects, one each for the hour hand, the minute hand, and the second hand on the clock.

Once the SimpleClock application is running, it calls the AnalogClockFace.draw() method each second, as follows:

    /** 
     * Called by the parent container when the display is being drawn. 
     */ 
    public override function draw():void 
    { 
        // stores the current date and time in an instance variable 
        currentTime = new Date(); 
        showTime(currentTime); 
    }

This method saves the current time in a variable, so the time can’t change in the middle of drawing the clock hands. Then it calls the showTime() method to display the hands, as the following shows:

    /** 
     * Displays the given Date/Time in that good old analog clock style. 
     */ 
    public function showTime(time:Date):void  
    { 
        // gets the time values 
        var seconds:uint = time.getSeconds(); 
        var minutes:uint = time.getMinutes(); 
        var hours:uint = time.getHours(); 
 
        // multiplies by 6 to get degrees 
        this.secondHand.rotation = 180 + (seconds * 6); 
        this.minuteHand.rotation = 180 + (minutes * 6); 
 
        // Multiply by 30 to get basic degrees, then 
        // add up to 29.5 degrees (59 * 0.5) 
        // to account for the minutes. 
        this.hourHand.rotation = 180 + (hours * 30) + (minutes * 0.5); 
    }

First, this method extracts the values for the hours, minutes, and seconds of the current time. Then it uses these values to calculate the angle for each hand. Since the second hand makes a full rotation in 60 seconds, it rotates 6 degrees each second (360/60). The minute hand rotates the same amount each minute.

The hour hand updates every minute, too, so it can show some progress as the minutes tick by. It rotates 30 degrees each hour (360/12), but it also rotates half a degree each minute (30 degrees divided by 60 minutes).

Managing calendar dates and times

All of the calendar date and time management functions in ActionScript 3.0 are concentrated in the top-level Date class. The Date class contains methods and properties that let you handle dates and times in either Coordinated Universal Time (UTC) or in local time specific to a time zone. UTC is a standard time definition that is essentially the same as Greenwich Mean Time (GMT).

Creating Date objects

The Date class boasts one of the most versatile constructor methods of all the core classes. You can invoke it four different ways.

First, if given no parameters, the Date() constructor returns a Date object containing the current date and time, in local time based on your time zone. Here’s an example:

var now:Date = new Date();

Second, if given a single numeric parameter, the Date() constructor treats that as the number of milliseconds since January 1, 1970, and returns a corresponding Date object. Note that the millisecond value you pass in is treated as milliseconds since January 1, 1970, in UTC. However, the Date object shows values in your local time zone, unless you use the UTC-specific methods to retrieve and display them. If you create a new Date object using a single milliseconds parameter, make sure you account for the time zone difference between your local time and UTC. The following statements create a Date object set to midnight on the day of January 1, 1970, in UTC:

var millisecondsPerDay:int = 1000 * 60 * 60 * 24; 
// gets a Date one day after the start date of 1/1/1970 
var startTime:Date = new Date(millisecondsPerDay);

Third, you can pass multiple numeric parameters to the Date() constructor. It treats those parameters as the year, month, day, hour, minute, second, and millisecond, respectively, and returns a corresponding Date object. Those input parameters are assumed to be in local time rather than UTC. The following statements get a Date object set to midnight at the start of January 1, 2000, in local time:

var millenium:Date = new Date(2000, 0, 1, 0, 0, 0, 0);

Fourth, you can pass a single string parameter to the Date() constructor. It will try to parse that string into date or time components and then return a corresponding Date object. If you use this approach, it’s a good idea to enclose the Date() constructor in a try..catch block to trap any parsing errors. The Date() constructor accepts a number of different string formats (which are listed in the ActionScript 3.0 Reference for the Adobe Flash Platform ). The following statement initializes a new Date object using a string value:

var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM");

If the Date() constructor cannot successfully parse the string parameter, it will not raise an exception. However, the resulting Date object will contain an invalid date value.

Getting time unit values

You can extract the values for various units of time within a Date object using properties or methods of the Date class. Each of the following properties gives you the value of a time unit in the Date object:

  • The fullYear property

  • The month property, which is in a numeric format with 0 for January up to 11 for December

  • The date property, which is the calendar number of the day of the month, in the range of 1 to 31

  • The day property, which is the day of the week in numeric format, with 0 standing for Sunday

  • The hours property, in the range of 0 to 23

  • The minutes property

  • The seconds property

  • The milliseconds property

    In fact, the Date class gives you a number of ways to get each of these values. For example, you can get the month value of a Date object in four different ways:

  • The month property

  • The getMonth() method

  • The monthUTC property

  • The getMonthUTC() method

    All four ways are essentially equivalent in terms of efficiency, so you can use whichever approach suits your application best.

    The properties just listed all represent components of the total date value. For example, the milliseconds property will never be greater than 999, since when it reaches 1000 the seconds value increases by 1 and the milliseconds property resets to 0.

    If you want to get the value of the Date object in terms of milliseconds since January 1, 1970 (UTC), you can use the getTime() method. Its counterpart, the setTime() method, lets you change the value of an existing Date object using milliseconds since January 1, 1970 (UTC).

Performing date and time arithmetic

You can perform addition and subtraction on dates and times with the Date class. Date values are kept internally in terms of milliseconds, so you should convert other values to milliseconds before adding them to or subtracting them from Date objects.

If your application will perform a lot of date and time arithmetic, you might find it useful to create constants that hold common time unit values in terms of milliseconds, like the following:

public static const millisecondsPerMinute:int = 1000 * 60; 
public static const millisecondsPerHour:int = 1000 * 60 * 60; 
public static const millisecondsPerDay:int = 1000 * 60 * 60 * 24;

Now it is easy to perform date arithmetic using standard time units. The following code sets a date value to one hour from the current time using the getTime() and setTime() methods:

var oneHourFromNow:Date = new Date(); 
oneHourFromNow.setTime(oneHourFromNow.getTime() + millisecondsPerHour);

Another way to set a date value is to create a new Date object using a single milliseconds parameter. For example, the following code adds 30 days to one date to calculate another:

// sets the invoice date to today's date 
var invoiceDate:Date = new Date(); 
 
// adds 30 days to get the due date 
var dueDate:Date = new Date(invoiceDate.getTime() + (30 * millisecondsPerDay));

Next, the millisecondsPerDay constant is multiplied by 30 to represent 30 days’ time and the result is added to the invoiceDate value and used to set the dueDate value.

Converting between time zones

Date and time arithmetic comes in handy when you want to convert dates from one time zone to another. So does the getTimezoneOffset() method, which returns the value in minutes by which the Date object’s time zone differs from UTC. It returns a value in minutes because not all time zones are set to even-hour increments—some have half-hour offsets from neighboring zones.

The following example uses the time zone offset to convert a date from local time to UTC. It does the conversion by first calculating the time zone value in milliseconds and then adjusting the Date value by that amount:

// creates a Date in local time 
var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); 
 
// converts the Date to UTC by adding or subtracting the time zone offset 
var offsetMilliseconds:Number = nextDay.getTimezoneOffset() * 60 * 1000; 
nextDay.setTime(nextDay.getTime() + offsetMilliseconds);

Strings

Working with strings

The String class contains methods that let you work with text strings. Strings are important in working with many objects. The methods described here are useful for working with strings used in objects such as TextField, StaticText, XML, ContextMenu, and FileReference objects.

Strings are sequences of characters. ActionScript 3.0 supports ASCII and Unicode characters.

Basics of strings

In programming parlance, a string is a text value—a sequence of letters, numbers, or other characters strung together into a single value. For instance, this line of code creates a variable with the data type String and assigns a literal string value to that variable:

var albumName:String = "Three for the money";

As this example shows, in ActionScript you can denote a string value by surrounding text with double or single quotation marks. Here are several more examples of strings:

"Hello" 
"555-7649" 
"http://www.adobe.com/"

Any time you manipulate a piece of text in ActionScript, you are working with a string value. The ActionScript String class is the data type you can use to work with text values. String instances are frequently used for properties, method parameters, and so forth in many other ActionScript classes.

Important concepts and terms

The following reference list contains important terms related to strings that you will encounter:

ASCII
A system for representing text characters and symbols in computer programs. The ASCII system supports the 26-letter English alphabet, plus a limited set of additional characters.

Character
The smallest unit of text data (a single letter or symbol).

Concatenation
Joining multiple string values together by adding one to the end of the other, creating a new string value.

Empty string
A string that contains no text, white space, or other characters, written as "" . An empty string value is different from a String variable with a null value—a null String variable is a variable that does not have a String instance assigned to it, whereas an empty string has an instance with a value that contains no characters.

String
A textual value (sequence of characters).

String literal (or “literal string”)
A string value written explicitly in code, written as a text value surrounded by double quotation marks or single quotation marks.

Substring
A string that is a portion of another string.

Unicode
A standard system for representing text characters and symbols in computer programs. The Unicode system allows for the use of any character in any writing system.

Creating strings

The String class is used to represent string (textual) data in ActionScript 3.0. ActionScript strings support both ASCII and Unicode characters. The simplest way to create a string is to use a string literal. To declare a string literal, use straight double quotation mark ( " ) or single quotation mark ( ' ) characters. For example, the following two strings are equivalent:

var str1:String = "hello"; 
var str2:String = 'hello';

You can also declare a string by using the new operator, as follows:

var str1:String = new String("hello");   
var str2:String = new String(str1); 
var str3:String = new String();       // str3 == ""

The following two strings are equivalent:

var str1:String = "hello";  
var str2:String = new String("hello");

To use single quotation marks ( ' ) within a string literal defined with single quotation mark ( ' ) delimiters, use the backslash escape character ( \ ). Similarly, to use double quotation marks ( " ) within a string literal defined with double quotation marks ( " ) delimiters, use the backslash escape character ( \ ). The following two strings are equivalent:

var str1:String = "That's \"A-OK\""; 
var str2:String = 'That\'s "A-OK"';

You may choose to use single quotation marks or double quotation marks based on any single or double quotation marks that exist in a string literal, as in the following:

var str1:String = "ActionScript <span class='heavy'>3.0</span>"; 
var str2:String = '<item id="155">banana</item>';

Keep in mind that ActionScript distinguishes between a straight single quotation mark ( ' ) and a left or right single quotation mark ( ' or ' ). The same is true for double quotation marks. Use straight quotation marks to delineate string literals. When pasting text from another source into ActionScript, be sure to use the correct characters.

As the following table shows, you can use the backslash escape character ( \ ) to define other characters in string literals:

Escape sequence

Character

\b

Backspace

\f

Form feed

\n

Newline

\r

Carriage return

\t

Tab

\u nnnn

The Unicode character with the character code specified by the hexadecimal number nnnn ; for example, \u263a is the smiley character.

\\x nn

The ASCII character with the character code specified by the hexadecimal number nn

\'

Single quotation mark

\"

Double quotation mark

\\

Single backslash character

The length property

Every string has a length property, which is equal to the number of characters in the string:

var str:String = "Adobe"; 
trace(str.length);            // output: 5

An empty string and a null string both have a length of 0, as the following example shows:

var str1:String = new String(); 
trace(str1.length);           // output: 0 
 
str2:String = ''; 
trace(str2.length);           // output: 0

Working with characters in strings

Every character in a string has an index position in the string (an integer). The index position of the first character is 0. For example, in the following string, the character y is in position 0 and the character w is in position 5:

"yellow"

You can examine individual characters in various positions in a string using the charAt() method and the charCodeAt() method, as in this example:

var str:String = "hello world!"; 
for (var i:int = 0; i < str.length; i++) 
{ 
    trace(str.charAt(i), "-", str.charCodeAt(i)); 
}

When you run this code, the following output is produced:

h - 104 
e - 101 
l - 108 
l - 108 
o - 111 
- 32 
w - 119 
o - 111 
r - 114 
l - 108 
d - 100 
! - 33 

You can also use character codes to define a string using the fromCharCode() method, as the following example shows:

var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33); 
        // Sets myStr to "hello world!"

Comparing strings

You can use the following operators to compare strings: < , <= , != , == , => , and > . These operators can be used with conditional statements, such as if and while , as the following example shows:

var str1:String = "Apple"; 
var str2:String = "apple"; 
if (str1 < str2) 
{ 
    trace("A < a, B < b, C < c, ..."); 
}

When using these operators with strings, ActionScript considers the character code value of each character in the string, comparing characters from left to right, as in the following:

trace("A" < "B"); // true 
trace("A" < "a"); // true  
trace("Ab" < "az"); // true  
trace("abc" < "abza"); // true

Use the == and != operators to compare strings with each other and to compare strings with other types of objects, as the following example shows:

var str1:String = "1"; 
var str1b:String = "1"; 
var str2:String = "2"; 
trace(str1 == str1b); // true 
trace(str1 == str2); // false 
var total:uint = 1; 
trace(str1 == total); // true

Obtaining string representations of other objects

You can obtain a String representation for any kind of object. All objects have a toString() method for this purpose:

var n:Number = 99.47; 
var str:String = n.toString(); 
    // str == "99.47"

When using the + concatenation operator with a combination of String objects and objects that are not strings, you do not need to use the toString() method. For details on concatenation, see the next section.

The String() global function returns the same value for a given object as the value returned by the object calling the toString() method.

Concatenating strings

Concatenation of strings means taking two strings and joining them sequentially into one. For example, you can use the + operator to concatenate two strings:

var str1:String = "green"; 
var str2:String = "ish"; 
var str3:String = str1 + str2; // str3 == "greenish"

You can also use the += operator to the produce the same result, as the following example shows:

var str:String = "green"; 
str += "ish"; // str == "greenish"

Additionally, the String class includes a concat() method, which can be used as follows:

var str1:String = "Bonjour"; 
var str2:String = "from"; 
var str3:String = "Paris"; 
var str4:String = str1.concat(" ", str2, " ", str3); 
// str4 == "Bonjour from Paris"

If you use the + operator (or the += operator) with a String object and an object that is not a string, ActionScript automatically converts the nonstring object to a String object in order to evaluate the expression, as shown in this example:

var str:String = "Area = "; 
var area:Number = Math.PI * Math.pow(3, 2); 
str = str + area; // str == "Area = 28.274333882308138"

However, you can use parentheses for grouping to provide context for the + operator, as the following example shows:

trace("Total: $" + 4.55 + 1.45); // output: Total: $4.551.45 
trace("Total: $" + (4.55 + 1.45)); // output: Total: $6

Finding substrings and patterns in strings

Substrings are sequential characters within a string. For example, the string "abc" has the following substrings: "" , "a" , "ab" , "abc" , "b" , "bc" , "c" . You can use ActionScript methods to locate substrings of a string.

Patterns are defined in ActionScript by strings or by regular expressions. For example, the following regular expression defines a specific pattern—the letters A, B, and C followed by a digit character (the forward slashes are regular expression delimiters):

/ABC\d/

ActionScript includes methods for finding patterns in strings and for replacing found matches with replacement substrings. These methods are described in the following sections.

Regular expressions can define intricate patterns. For more information, see Using regular expressions.

Finding a substring by character position

The substr() and substring() methods are similar. Both return a substring of a string. Both take two parameters. In both methods, the first parameter is the position of the starting character in the given string. However, in the substr() method, the second parameter is the length of the substring to return, and in the substring() method, the second parameter is the position of the character at the end of the substring (which is not included in the returned string). This example shows the difference between these two methods:

var str:String = "Hello from Paris, Texas!!!"; 
trace(str.substr(11,15)); // output: Paris, Texas!!! 
trace(str.substring(11,15)); // output: Pari

The slice() method functions similarly to the substring() method. When given two non-negative integers as parameters, it works exactly the same. However, the slice() method can take negative integers as parameters, in which case the character position is taken from the end of the string, as shown in the following example:

var str:String = "Hello from Paris, Texas!!!"; 
trace(str.slice(11,15)); // output: Pari 
trace(str.slice(-3,-1)); // output: !! 
trace(str.slice(-3,26)); // output: !!! 
trace(str.slice(-3,str.length)); // output: !!! 
trace(str.slice(-8,-3)); // output: Texas

You can combine non-negative and negative integers as the parameters of the slice() method.

Finding the character position of a matching substring

You can use the indexOf() and lastIndexOf() methods to locate matching substrings within a string, as the following example shows:

var str:String = "The moon, the stars, the sea, the land"; 
trace(str.indexOf("the")); // output: 10

Notice that the indexOf() method is case-sensitive.

You can specify a second parameter to indicate the index position in the string from which to start the search, as follows:

var str:String = "The moon, the stars, the sea, the land" 
trace(str.indexOf("the", 11)); // output: 21

The lastIndexOf() method finds the last occurrence of a substring in the string:

var str:String = "The moon, the stars, the sea, the land" 
trace(str.lastIndexOf("the")); // output: 30

If you include a second parameter with the lastIndexOf() method, the search is conducted from that index position in the string working backward (from right to left):

var str:String = "The moon, the stars, the sea, the land" 
trace(str.lastIndexOf("the", 29)); // output: 21
Creating an array of substrings segmented by a delimiter

You can use the split() method to create an array of substrings, which is divided based on a delimiter. For example, you can segment a comma-delimited or tab-delimited string into multiple strings.

The following example shows how to split an array into substrings with the ampersand (&) character as the delimiter:

var queryStr:String = "first=joe&last=cheng&title=manager&StartDate=3/6/65"; 
var params:Array = queryStr.split("&", 2); // params == ["first=joe","last=cheng"]

The second parameter of the split() method, which is optional, defines the maximum size of the array that is returned.

You can also use a regular expression as the delimiter character:

var str:String = "Give me\t5." 
var a:Array = str.split(/\s+/); // a == ["Give","me","5."]

For more information, see Using regular expressions and the ActionScript 3.0 Reference for the Adobe Flash Platform .

Finding patterns in strings and replacing substrings

The String class includes the following methods for working with patterns in strings:

  • Use the match() and search() methods to locate substrings that match a pattern.

  • Use the replace() method to find substrings that match a pattern and replace them with a specified substring.

These methods are described in the following sections.

You can use strings or regular expressions to define patterns used in these methods. For more information on regular expressions, see Using regular expressions.

Finding matching substrings

The search() method returns the index position of the first substring that matches a given pattern, as shown in this example:

var str:String = "The more the merrier."; 
// (This search is case-sensitive.) 
trace(str.search("the")); // output: 9 

You can also use regular expressions to define the pattern to match, as this example shows:

var pattern:RegExp = /the/i; 
var str:String = "The more the merrier."; 
trace(str.search(pattern)); // 0

The output of the trace() method is 0, because the first character in the string is index position 0. The i flag is set in the regular expression, so the search is not case-sensitive.

The search() method finds only one match and returns its starting index position, even if the g (global) flag is set in the regular expression.

The following example shows a more intricate regular expression, one that matches a string in double quotation marks:

var pattern:RegExp = /"[^"]*"/; 
var str:String = "The \"more\" the merrier."; 
trace(str.search(pattern)); // output: 4 
 
str = "The \"more the merrier."; 
trace(str.search(pattern)); // output: -1  
// (Indicates no match, since there is no closing double quotation mark.)

The match() method works similarly. It searches for a matching substring. However, when you use the global flag in a regular expression pattern, as in the following example, match() returns an array of matching substrings:

var str:String = "bob@example.com, omar@example.org"; 
var pattern:RegExp = /\w*@\w*\.[org|com]+/g; 
var results:Array = str.match(pattern);

The results array is set to the following:

["bob@example.com","omar@example.org"]

For more information on regular expressions, see Using regular expressions.

Replacing matched substrings

You can use the replace() method to search for a specified pattern in a string and replace matches with the specified replacement string, as the following example shows:

var str:String = "She sells seashells by the seashore."; 
var pattern:RegExp = /sh/gi; 
trace(str.replace(pattern, "sch")); //sche sells seaschells by the seaschore. 

Note that in this example, the matched strings are not case-sensitive because the i ( ignoreCase ) flag is set in the regular expression, and multiple matches are replaced because the g ( global ) flag is set. For more information, see Using regular expressions.

You can include the following $ replacement codes in the replacement string. The replacement text shown in the following table is inserted in place of the $ replacement code:

$ Code

Replacement Text

$$

$

$&

The matched substring.

$`

The portion of the string that precedes the matched substring. This code uses the straight left single quotation mark character ( ` ), not the straight single quotation mark ( ' ) or the left curly single quotation mark ( ' ).

$'

The portion of the string that follows the matched substring. This code uses the straight single quotation mark ( ' ).

$ n

The n th captured parenthetical group match, where n is a single digit, 1-9, and $n is not followed by a decimal digit.

$ nn

The nn th captured parenthetical group match, where nn is a two-digit decimal number, 01–99. If the nn th capture is undefined, the replacement text is an empty string.

For example, the following shows the use of the $2 and $1 replacement codes, which represent the first and second capturing group matched:

var str:String = "flip-flop"; 
var pattern:RegExp = /(\w+)-(\w+)/g; 
trace(str.replace(pattern, "$2-$1")); // flop-flip

You can also use a function as the second parameter of the replace() method. The matching text is replaced by the returned value of the function.

var str:String = "Now only $9.95!"; 
var price:RegExp = /\$([\d,]+.\d+)+/i; 
trace(str.replace(price, usdToEuro)); 
 
function usdToEuro(matchedSubstring:String,                                  capturedMatch1:String,                                  index:int,                                  str:String):String 
{ 
    var usd:String = capturedMatch1; 
    usd = usd.replace(",", ""); 
    var exchangeRate:Number = 0.853690; 
    var euro:Number = parseFloat(usd) * exchangeRate; 
    const euroSymbol:String = String.fromCharCode(8364); 
    return euro.toFixed(2) + " " + euroSymbol; 
}

When you use a function as the second parameter of the replace() method, the following arguments are passed to the function:

  • The matching portion of the string.

  • Any capturing parenthetical group matches. The number of arguments passed this way will vary depending on the number of parenthetical matches. You can determine the number of parenthetical matches by checking arguments.length - 3 within the function code.

  • The index position in the string where the match begins.

  • The complete string.

Converting strings between uppercase and lowercase

As the following example shows, the toLowerCase() method and the toUpperCase() method convert alphabetical characters in the string to lowercase and uppercase, respectively:

var str:String = "Dr. Bob Roberts, #9." 
trace(str.toLowerCase()); // dr. bob roberts, #9. 
trace(str.toUpperCase()); // DR. BOB ROBERTS, #9.

After these methods are executed, the source string remains unchanged. To transform the source string, use the following code:

str = str.toUpperCase();

These methods work with extended characters, not simply a–z and A–Z:

var str:String = "José Barça"; 
trace(str.toUpperCase(), str.toLowerCase()); // JOSÉ BARÇA josé barça

TOPIC_TITLE

Functions

Functions

Functions are named blocks of code that carry out specific tasks and can be reused in your program. There are two types of functions in ActionScript 3.0: methods and function closures . The context in which the function is defined determines whether a function is a called a method or a function. A function is called a method if you define it as part of a class definition or attach it to an instance of an object. A function is called a function if it is defined in any other way.

Keep in mind that a good function does only one task. When a function performs multiple tasks, it becomes difficult to debug and its reusability is reduced.

For example, pretend you are developing an application that allows the user to select which shape to draw and the shape’s color and then draws the user’s selection on the screen. You should write five functions:
  • A function to ask the user to select a shape

  • A function to handle the data of the user’s shape selection

  • A function to ask the user to select a color

  • A function to handle the data of the user’s color selection

  • A function to use the shape and color data to draw the selection on the screen

Could you put all of the code into one function? Technically, yes. But what happens when you test the application and nothing gets drawn on the screen? Which part of your one long function doesn’t work? By writing five separate functions, you could easily test each function individually to find the bug. What if you decide that one of the shapes does not have a color selection option? If you had written one long function, you must rewrite the entire function to change it. With separate functions, you could not call the color selection function when the user selects that one shape. Keeping your functions focused on a single task makes your life as a programmer easier.

Basic function concepts

Defining functions

Creating a function is called function definition. ActionScript 3.0 requires the use of a keyword— function —to signal that you are defining a function. Include the following six parts to define a function in ActionScript 3.0:
  1. access control attribute keyword

  2. function

  3. function name

  4. function parameters, in a comma-delimited list enclosed in parentheses (optional)

  5. return type

  6. function body—the ActionScript code to be executed when the function is called, enclosed in curly brackets

The following code defines a function named myTraceFunction that does not return any data. This function does not have a parameter.
private function myTraceFunction():void{ 
    trace("Hello world"); 
} 
 
myTraceFunction(); // Hello world
The following code defines a function named myMathFunction that does return an integer. This function requires a parameter to complete the equation.
public function myMathFunction(intParameter:int):int{ 
    return(intParameter * 5); 
} 
myMathFunction(5); //returns the int value 25
The following code defines a function named anotherMathFunction that returns an integer. This function has an optional parameter with a default value of 2. The first function call shown does not pass a value, therefore, the default value is used. The second function call does pass a value.
private function anotherMathFunction(intParamter:int = 2):int{ 
    return(intParameter * 10); 
} 
anotherMathFunction(); //returns the int value 20 
anotherMathFunction(5); //retunrs the int value 50

Calling functions

A function doesn’t do anything until it is called. The computer only executes the code inside the { } when the function is called. You call a function by using its name followed by the parentheses operator ( () ). You use the parentheses operator to enclose any function arguments you want to send to the function. For example, the trace() function is a top-level function in ActionScript 3.0. It displays the parameter passed to it in the console window when the code is debugged:
trace("Use trace to help debug your code");
If you are calling a function with no parameters, an empty pair of parentheses is required. For example, use the Math.random() method, which takes no parameters, to generate a random number:
var randomNum:Number = Math.random();

Function parameters and arguments

Sometimes functions need data to successfully complete their defined tasks. When defining a function, the needed data is referred to as a parameter . When the data is being used within the function body, it is also referred to as a parameter. The actual data sent to a function at the time of a function call, is referred to as an argument . Two different names are used to distinguish where the data is.

To create parameters for a function, declare a list of parameters and their data types in the parenthesis in a function definition. Separate the parameters with commas. Not all functions require data—only declare parameters when a function needs data to complete its task.

If a function has parameters defined, providing arguments at the time the function is called is required.

Default parameter values

In ActionScript 3.0, you can declare default parameter values for a function. If you assign a value to the parameter in the function definition, the parameter becomes optional. If a call to a function with default parameter values omits a parameter with a default value, the default value for that parameter is used. The values assigned as default values must be compile-time constants. List optional parameters after required parameters in the parameter list.

For example, the following code creates a function with three parameters, two of which have default values. When the function is called with only one parameter, the default values for the parameters are used.

private function optionalParameterExample(x:int, y:int = 3, z:int = 5):void { 
    trace(x, y, z); 
} 
optionalParameterExample(1); // 1 3 5

Passing arguments by value or by reference

Primitive values—Boolean, Number, int, uint, and String—are passed by value into a function. When an argument is passed by value, the value is copied into a local variable for use within the function. The original value is unaffected and remains unchanged regardless of what happens within the function.

For example, the following code creates a function named passPrimitives() that defines two parameters named firstPrimParam , an int, and secondPrimParam , a String. The function is called with the arguments firstPrimValue and secondPrimValue . Because the arguments are primitives, they are passed by value. Within the passPrimitives() function, the value of firstPrimParam is incremented and the value of secondPrimParam appends string characters. The values of firstPrimValue and secondPrimValue are unaffected as shown in the last trace statement.
public function passPrimitives(firstPrimParam:int, secondPrimParam:String):void{ 
    firstPrimParam++; 
    secondPrimParam+="test"; 
    trace(firstPrimParam, secondPrimParam); 
} 
 
var firstPrimValue:int = 10; 
var secondPrimValue:String = "Hello world"; 
trace(firstPrimValue, secondPrimValue);// 10 Hello world 
passPrimitives(firstPrimValue, secondPrimValue); // 11 Hello world test 
trace(firstPrimValue, secondPrimValue);// 10 Hello world

Complex data types are passed by reference into a function. When an argument is passed by reference, only a reference to the argument is passed. A copy of the actual argument is not made. When the function runs, the code in the function body will change the object that is passed.

For example, the following code creates an object named objVar with two properties, x and y . The object is passed as an argument to the passByRef() function. Because the object is not a primitive type, the object is passed by reference. Changes made to the parameters within the function affect the object properties outside the function.
public function passByRef(objParam:Object):void { 
    objParam.x++; 
    objParam.y++; 
    trace(objParam.x, objParam.y); 
} 
var objVar:Object = {x:10, y:15}; 
trace(objVar.x, objVar.y); // 10 15 
passByRef(objVar); // 11 16 
trace(objVar.x, objVar.y); // 11 16

The objParam parameter references the same object as the global objVar variable. As you can see from the trace statements in the example, changes to the x and y properties of the objParam object are reflected in the objVar object.

The ... (rest) parameter

The ... (rest) parameter accepts a variable number of arguments which will be stored as an Array. Follow ... (rest) with the name of the argument list. Use that name in the function body. This parameter declaration must be the last parameter specified.

The following example shows the traceArgs() function using the ... (rest) parameter
public function traceArgs(... args):void { 
    for (var i:int = 0; i < args.length; i++){ 
        trace(args[i]); 
    } 
} 
 
traceArgs(10, 25, 40); 
 
// output: 
// 10 
// 25 
// 40
The ... (rest) parameter can also be used with other parameters, as long as it is the last parameter listed. The following example modifies the traceArgs() function so that its first parameter, firstParam , is of type int, and the second parameter uses the ... parameter. The output does not include the first value, because the first argument is no longer part of the array created by the ... (rest) parameter.
public function traceArgs(firstParam:int, ... args){ 
    for (var i:int = 0; i < args.length; i++){ 
        trace(args[i]); 
    } 
} 
 
traceArgs(10, 25, 40); 
 
// output: 
// 25 
// 40

Returning values from functions

Some functions simply perform a task. If you are asked to raise your hand, you raise your hand. You do not say anything or do anything but raise your hand. Functions can be similar, only doing a task.

Other functions do a task and return data. If you are asked to tell someone your name, you say (task) your name (returned data). Functions that return data work in the same way as you did when asked your name. Typically the data a function returns is the result of a calculation or conditional test.

A function’s return type informs the compiler what type of data the function returns upon its completion. A type error occurs if the function does not return data of the declared type. Use the void return type for functions that perform a task but do not return data. The function in the following example does not return data. It has a void return type.
private function myTraceFunction():void{ 
    trace("Hello world"); 
} 
 
myTraceFunction(); // Hello world
To return a value from your function, use the return statement followed by the expression or literal value that you want to return. For example, the following code returns an expression representing the parameter:
public function doubledValue(baseNum:int):int { 
    return (baseNum * 2); 
}
The return statement terminates the function. Any statements written after a return statement are not executed, as follows:
public function doubledValue(baseNum:int):int { 
    return (baseNum * 2); 
    trace("after return"); // This trace statement will not be executed. 
}

Function scope

In ActionScript, all variables and functions exist within a specific scope. Scope determines a variable’s or function’s accessibility from different parts of the program. If your code attempts to access a variable or function that is out of scope, the compiler will not recognize it and throw an error. Variables or functions that have a global scope are accessible from anywhere in the code. Local scope limits accessibility to within the scope the variable or function is defined.

Function closures

A function closure is an object that contains a snapshot of a function and its lexical environment . A function’s lexical environment includes all the variables, properties, methods, and objects in the function’s scope chain, along with their values. Function closures are created any time a function is executed apart from an object or a class. Because function closures retain the scope in which they were defined, interesting results occur when a function is passed as an argument into a different scope.

For example, the following code creates two functions: foo() , which returns a nested function named rectArea() that calculates the area of a rectangle, and bar() , which calls foo() and stores the returned function closure in a variable named myProduct . Even though the bar() function defines its own local variable x (with a value of 2), when the function closure myProduct() is called, it retains the variable x (with a value of 40) defined in function foo(). The bar() function therefore returns the value 160 instead of 8 .

function foo():Function { 
    var x:int = 40; 
    function rectArea(y:int):int // function closure defined { 
        return x * y 
    }  
    return rectArea; 
} 
function bar():void { 
    var x:int = 2; 
    var y:int = 4; 
    var myProduct:Function = foo(); 
    trace(myProduct(4)); // function closure called 
} 
bar(); // 160

Functions as objects

Functions passed as arguments to another function are passed by reference and not by value. When you pass a function as an argument, you use only the identifier and not the parentheses operator that you use to call the method. For example, the following code passes a function named clickListener() as an argument to the addEventListener() method:
addEventListener(MouseEvent.CLICK, clickListener);
Functions have properties and methods, just as any other object can. Every function has a read-only property named length that stores the number of parameters defined for the function. The code below shows the length property being used.
function traceLength(x:uint, y:uint):void { 
    trace("arguments expected: " + traceLength.length); 
} 
 
traceLength(3, 5); 
/* output: 
arguments expected: 2 

Anonymous functions

ActionScript supports anonymous functions (also called function expressions). These functions are called anonymous because they have no name. Anonymous functions were widely used in versions of ActionScript before version 3.0.

Creating anonymous functions

Creating an anonymous function and storing it in a variable is similar to defining a function statement. Include the following nine parts to define an anonymous function in ActionScript 3.0:
  1. var

  2. variable name

  3. Colon operator :

  4. Function class to indicate the data type

  5. The assignment operator =

  6. function

  7. function parameters, in a comma-delimited list enclosed in parentheses (optional)

  8. return type

  9. function body—the ActionScript code to be executed when the function is called, enclosed in curly brackets

In the following example, an anonymous function is assigned to a variable named traceParameter :
var traceParameter:Function = function (aParam:String){ 
    trace(aParam); 
}; 
traceParameter("hello"); // hello

Choosing between function statements and anonymous functions

Unlike defined functions (also called function statements), anonymous functions are expressions rather than statements. Therefore, an anonymous function cannot stand on its own as a function statement can. It can only be used as a part of a statement, usually an assignment statement. A summary of the difference between anonymous functions and defined functions is in the following table.

Anonymous function

Defined function

Cannot be used as a method

Can be used as a method of an object

Exists only in the scope in which it is defined

Exists within the object it is defined in

Can only be called in the scope in which it is defined

Can be called at any point in the code

Can be reassigned a new value or deleted

Cannot be deleted or changed

As a rule, use a function statement unless specific circumstances call for the use of an expression. Function statements are easier to read than assignment statements that contain function expressions. Function statements make your code more concise; they are less confusing than function expressions, which require you to use both the var and function keywords.

There are some circumstances in which anonymous functions are useful. Use an anonymous function for functions that are used only once and then discarded. If the functionality of a function must change at runtime, use an anonymous function. If a function is only useful within another function, use an anonymous function. When working in a functional programming paradigm, use anonymous functions.

Take into account two subtle differences between defined functions and anonymous functions when choosing which technique to use. First, anonymous functions do not exist independently as objects with regard to memory management and garbage collection. If the object to which an anonymous function is attached goes out of scope, you no longer have access to the anonymous function. If the object is deleted, the memory that the anonymous function uses becomes eligible for garbage collection.

Second, defined functions exist throughout the scope in which they are defined, including in statements that appear before the function definition. Anonymous functions are defined only for subsequent statements. For example, the following code successfully calls the scopeTest() function before it is defined:
statementTest(); // statementTest 
 

public function statementTest():void{ 
    trace("statementTest"); 
}
Anonymous functions are not available before they are defined, so the following code results in a runtime error:
expressionTest(); // run-time error 
 
var expressionTest:Function = function ():void{ 
    trace("expressionTest"); 
}

Display objects and display list

Basics of display programming

Each application built with ActionScript 3.0 has a hierarchy of displayed objects known as the display list , illustrated below. The display list contains all the visible elements in the application.

<Display list hierarchy>

As the illustration shows, display elements fall into one or more of the following groups:

  • The Stage

    The Stage is the base container of display objects. Each application has one Stage object, which contains all on-screen display objects. The Stage is the top-level container and is at the top of the display list hierarchy:

    Each SWF file has an associated ActionScript class, known as the main class of the SWF file . When a SWF file opens in Flash Player or Adobe AIR, Flash Player or AIR calls the constructor function for that class and the instance that is created (which is always a type of display object) is added as a child of the Stage object. The main class of a SWF file always extends the Sprite class (for more information, see Advantages of the display list approach).

    You can access the Stage through the stage property of any DisplayObject instance. For more information, see Setting Stage properties.

  • Display objects

    In ActionScript 3.0, all elements that appear on screen in an application are types of display objects . The flash.display package includes a DisplayObject class, which is a base class extended by a number of other classes. These different classes represent different types of display objects, such as vector shapes, movie clips, and text fields, to name a few. For an overview of these classes, see Advantages of the display list approach.

  • Display object containers

    Display object containers are special types of display objects that, in addition to having their own visual representation, can also contain child objects that are also display objects.

    The DisplayObjectContainer class is a subclass of the DisplayObject class. A DisplayObjectContainer object can contain multiple display objects in its child list . For example, the following illustration shows a type of DisplayObjectContainer object known as a Sprite that contains various display objects:

    <Sprite containing display objects>
    A.
    A SimpleButton object. This type of display object has different “up,” “down,” and “over” states.

    B.
    A Bitmap object. In this case, the Bitmap object was loaded from an external JPEG through a Loader object.

    C.
    A Shape object. The “picture frame” contains a rounded rectangle that is drawn in ActionScript. This Shape object has a Drop Shadow filter applied to it.

    D.
    A TextField object.

    In the context of discussing display objects, DisplayObjectContainer objects are also known as display object containers or simply containers . As noted earlier, the Stage is a display object container.

    Although all visible display objects inherit from the DisplayObject class, the type of each is of a specific subclass of DisplayObject class. For example, there is a constructor function for the Shape class or the Video class, but there is no constructor function for the DisplayObject class.

Important concepts and terms

The following reference list contains important terms that you will encounter when programming ActionScript graphics:

Alpha
The color value representing the amount of transparency (or more correctly, the amount of opacity) in a color. For example, a color with an alpha channel value of 60% only shows 60% of its full strength, and is 40% transparent.

Bitmap graphic
A graphic that is defined in the computer as a grid (rows and columns) of colored pixels. Commonly bitmap graphics include digital photos and similar images.

Blending mode
A specification of how the contents of two overlapping images should interact. Commonly an opaque image on top of another image simply blocks the image underneath so that it isn’t visible at all; however, different blending modes cause the colors of the images to blend together in different ways so the resulting content is some combination of the two images.

Display list
The hierarchy of display objects that will be rendered as visible screen content by Flash Player and AIR. The Stage is the root of the display list, and all the display objects that are attached to the Stage or one of its children form the display list (even if the object isn’t actually rendered, for example if it’s outside the boundaries of the Stage).

Display object
An object which represents some type of visual content in Flash Player or AIR. Only display objects can be included in the display list, and all display object classes are subclasses of the DisplayObject class.

Display object container
A special type of display object which can contain child display objects in addition to (generally) having its own visual representation.

Main class of the SWF file
The class that defines the behavior for the outermost display object in a SWF file, which conceptually is the class for the SWF file itself. For instance, in a SWF created in Flash authoring, the main class is the document class. It has a “main timeline” which contains all other timelines; the main class of the SWF file is the class of which the main timeline is an instance.

Masking
A technique of hiding from view certain parts of an image (or conversely, only allowing certain parts of an image to display). The portions of the mask image become transparent, so content underneath shows through. The term is related to painter’s masking tape that is used to prevent paint from being applied to certain areas.

Stage
The visual container that is the base or background of all visual content in a SWF.

Transformation
An adjustment to a visual characteristic of a graphic, such as rotating the object, altering its scale, skewing or distorting its shape, or altering its color.

Vector graphic
A graphic that is defined in the computer as lines and shapes drawn with particular characteristics (such as thickness, length, size, angle, and position).

Core display classes

The ActionScript 3.0 flash.display package includes classes for visual objects that can appear in Flash Player or AIR. The following illustration shows the subclass relationships of these core display object classes.

The illustration shows the class inheritance of display object classes. Note that some of these classes, specifically StaticText, TextField, and Video, are not in the flash.display package, but they still inherit from the DisplayObject class.

All classes that extend the DisplayObject class inherit its methods and properties. For more information, see Properties and methods of the DisplayObject class.

You can instantiate objects of the following classes contained in the flash.display package:

  • Bitmap—You use the Bitmap class to define bitmap objects, either loaded from external files or rendered through ActionScript. You can load bitmaps from external files through the Loader class. You can load GIF, JPG, or PNG files. You can also create a BitmapData object with custom data and then create a Bitmap object that uses that data. You can use the methods of the BitmapData class to alter bitmaps, whether they are loaded or created in ActionScript. For more information, see Loading display objects and Working with bitmaps.

  • Loader—You use the Loader class to load external assets (either SWF files or graphics). For more information, see Loading display content dynamically.

  • Shape—You use the Shape class to create vector graphics, such as rectangles, lines, circles, and so on. For more information, see Using the drawing API.

  • SimpleButton—A SimpleButton object is the ActionScript representation of a button symbol created in the Flash authoring tool. A SimpleButton instance has four button states: up, down, over, and hit test (the area that responds to mouse and keyboard events).

  • Sprite—A Sprite object can contain graphics of its own, and it can contain child display objects. (The Sprite class extends the DisplayObjectContainer class). For more information, see Working with display object containers and Using the drawing API.

  • MovieClip—A MovieClip object is the ActionScript form of a movie clip symbol created in the Flash authoring tool. In practice, a MovieClip is similar to a Sprite object, except that it also has a timeline. For more information, see Working with movie clips.

The following classes, which are not in the flash.display package, are subclasses of the DisplayObject class:

  • The TextField class, included in the flash.text package, is a display object for text display and input. For more information, see Basics of Working with text.

  • The TextLine class, included in the flash.text.engine package, is the display object used to display lines of text composed by the Flash Text Engine and the Text Layout Framework. For more information, see Using the Flash Text Engine and Using the Text Layout Framework.

  • The Video class, included in the flash.media package, is the display object used for displaying video files. For more information, see Working with video.

The following classes in the flash.display package extend the DisplayObject class, but you cannot create instances of them. Instead, they serve as parent classes for other display objects, combining common functionality into a single class.

  • AVM1Movie—The AVM1Movie class is used to represent loaded SWF files that are authored in ActionScript 1.0 and 2.0.

  • DisplayObjectContainer—The Loader, Stage, Sprite, and MovieClip classes each extend the DisplayObjectContainer class. For more information, see Working with display object containers.

  • InteractiveObject—InteractiveObject is the base class for all objects used to interact with the mouse and keyboard. SimpleButton, TextField, Loader, Sprite, Stage, and MovieClip objects are all subclasses of the InteractiveObject class. For more information on creating mouse and keyboard interaction, see Capturing user input.

  • MorphShape—These objects are created when you create a shape tween in the Flash authoring tool. You cannot instantiate them using ActionScript, but they can be accessed from the display list.

  • Stage—The Stage class extends the DisplayObjectContainer class. There is one Stage instance for an application, and it is at the top of the display list hierarchy. To access the Stage, use the stage property of any DisplayObject instance. For more information, see Setting Stage properties.

Also, the StaticText class, in the flash.text package, extends the DisplayObject class, but you cannot create an instance of it in code. Static text fields are created only in Flash.

The following classes are not display objects or display object containers, and do not appear in the display list, but do display graphics on the stage. These classes draw into a rectangle, called a viewport, positioned relative to the stage.

  • StageVideo—The StageVideo class displays video content, using hardware acceleration, when possible. This class is available starting in Flash Player 10.2 and AIR 2.5 (in the AIR for TV profiles). For more information, see Using the StageVideo class for hardware-accelerated rendering.

  • StageWebView—The StageWebView class displays HTML content. This class is available starting in AIR 2.5. For more information, see StageWebView objects.

The following fl.display classes provide functionality that parallels the flash.display.Loader and LoaderInfo classes. Use these classes instead of their flash.display counterparts if you are developing in the Flash Professional environment (CS5.5 or later). In that environment, these classes help solve issues involving TLF with RSL preloading. For more information, see Using the ProLoader and ProLoaderInfo classes.

  • fl.display.ProLoader—Analogous to flash.display.Loader

  • fl.display.ProLoaderInfo—Analogous to flash.display.LoaderInfo

Working with display objects

Now that you understand the basic concepts of the Stage, display objects, display object containers, and the display list, this section provides you with some more specific information about working with display objects in ActionScript 3.0.

Properties and methods of the DisplayObject class

All display objects are subclasses of the DisplayObject class, and as such they inherit the properties and methods of the DisplayObject class. The properties inherited are basic properties that apply to all display objects. For example, each display object has an x property and a y property that specifies the object’s position in its display object container.

You cannot create a DisplayObject instance using the DisplayObject class constructor. You must create another type of object (an object that is a subclass of the DisplayObject class), such as a Sprite, to instantiate an object with the new operator. Also, if you want to create a custom display object class, you must create a subclass of one of the display object subclasses that has a usable constructor function (such as the Shape class or the Sprite class). For more information, see the DisplayObject class description in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Adding display objects to the display list

When you instantiate a display object, it will not appear on-screen (on the Stage) until you add the display object instance to a display object container that is on the display list. For example, in the following code, the myText TextField object would not be visible if you omitted the last line of code. In the last line of code, the this keyword must refer to a display object container that is already added to the display list.

import flash.display.*; 
import flash.text.TextField; 
var myText:TextField = new TextField(); 
myText.text = "Buenos dias."; 
this.addChild(myText);

When you add any visual element to the Stage, that element becomes a child of the Stage object. The first SWF file loaded in an application (for example, the one that you embed in an HTML page) is automatically added as a child of the Stage. It can be an object of any type that extends the Sprite class.

Any display objects that you create without using ActionScript—for example, by adding an MXML tag in a Flex MXML file or by placing an item on the Stage in Flash Professional—are added to the display list. Although you do not add these display objects through ActionScript, you can access them through ActionScript. For example, the following code adjusts the width of an object named button1 that was added in the authoring tool (not through ActionScript):

button1.width = 200;

Working with display object containers

If a DisplayObjectContainer object is deleted from the display list, or if it is moved or transformed in some other way, each display object in the DisplayObjectContainer is also deleted, moved, or transformed.

A display object container is itself a type of display object—it can be added to another display object container. For example, the following image shows a display object container, pictureScreen , that contains one outline shape and four other display object containers (of type PictureFrame):

View full size graphic
A.
A shape defining the border of the pictureScreen display object container

B.
Four display object containers that are children of the pictureScreen object

In order to have a display object appear in the display list, you must add it to a display object container that is on the display list. You do this by using the addChild() method or the addChildAt() method of the container object. For example, without the final line of the following code, the myTextField object would not be displayed:

var myTextField:TextField = new TextField(); 
myTextField.text = "hello"; 
this.root.addChild(myTextField);

In this code sample, this.root points to the MovieClip display object container that contains the code. In your actual code, you may specify a different container.

Use the addChildAt() method to add the child to a specific position in the child list of the display object container. These zero-based index positions in the child list relate to the layering (the front-to-back order) of the display objects. For example, consider the following three display objects. Each object was created from a custom class called Ball.

The layering of these display objects in their container can be adjusted using the addChildAt() method. For example, consider the following code:

ball_A = new Ball(0xFFCC00, "a"); 
ball_A.name = "ball_A"; 
ball_A.x = 20; 
ball_A.y = 20; 
container.addChild(ball_A); 
 
ball_B = new Ball(0xFFCC00, "b"); 
ball_B.name = "ball_B"; 
ball_B.x = 70; 
ball_B.y = 20; 
container.addChild(ball_B); 
 
ball_C = new Ball(0xFFCC00, "c"); 
ball_C.name = "ball_C"; 
ball_C.x = 40; 
ball_C.y = 60; 
container.addChildAt(ball_C, 1);

After executing this code, the display objects are positioned as follows in the container DisplayObjectContainer object. Notice the layering of the objects.

To reposition an object to the top of the display list, simply re-add it to the list. For example, after the previous code, to move ball_A to the top of the stack, use this line of code:

container.addChild(ball_A);

This code effectively removes ball_A from its location in container ’s display list, and re-adds it to the top of the list—which has the end result of moving it to the top of the stack.

You can use the getChildAt() method to verify the layer order of the display objects. The getChildAt() method returns child objects of a container based on the index number you pass it. For example, the following code reveals names of display objects at different positions in the child list of the container DisplayObjectContainer object:

trace(container.getChildAt(0).name); // ball_A 
trace(container.getChildAt(1).name); // ball_C 
trace(container.getChildAt(2).name); // ball_B

If you remove a display object from the parent container’s child list, the higher elements on the list each move down a position in the child index. For example, continuing with the previous code, the following code shows how the display object that was at position 2 in the container DisplayObjectContainer moves to position 1 if a display object that is lower in the child list is removed:

container.removeChild(ball_C); 
trace(container.getChildAt(0).name); // ball_A 
trace(container.getChildAt(1).name); // ball_B

The removeChild() and removeChildAt() methods do not delete a display object instance entirely. They simply remove it from the child list of the container. The instance can still be referenced by another variable. (Use the delete operator to completely remove an object.)

Because a display object has only one parent container, you can add an instance of a display object to only one display object container. For example, the following code shows that the display object tf1 can exist in only one container (in this case, a Sprite, which extends the DisplayObjectContainer class):

tf1:TextField = new TextField(); 
tf2:TextField = new TextField(); 
tf1.name = "text 1"; 
tf2.name = "text 2"; 
 
container1:Sprite = new Sprite(); 
container2:Sprite = new Sprite(); 
 
container1.addChild(tf1); 
container1.addChild(tf2); 
container2.addChild(tf1); 
 
trace(container1.numChildren); // 1 
trace(container1.getChildAt(0).name); // text 2 
trace(container2.numChildren); // 1 
trace(container2.getChildAt(0).name); // text 1

If you add a display object that is contained in one display object container to another display object container, it is removed from the first display object container’s child list.

In addition to the methods described above, the DisplayObjectContainer class defines several methods for working with child display objects, including the following:

  • contains() : Determines whether a display object is a child of a DisplayObjectContainer.

  • getChildByName() : Retrieves a display object by name.

  • getChildIndex() : Returns the index position of a display object.

  • setChildIndex() : Changes the position of a child display object.

  • swapChildren() : Swaps the front-to-back order of two display objects.

  • swapChildrenAt() : Swaps the front-to-back order of two display objects, specified by their index values.

For more information, see the relevant entries in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Recall that a display object that is off the display list—one that is not included in a display object container that is a child of the Stage—is known as an off-list display object.

Traversing the display list

As you’ve seen, the display list is a tree structure. At the top of the tree is the Stage, which can contain multiple display objects. Those display objects that are themselves display object containers can contain other display objects, or display object containers.

The DisplayObjectContainer class includes properties and methods for traversing the display list, by means of the child lists of display object containers. For example, consider the following code, which adds two display objects, title and pict , to the container object (which is a Sprite, and the Sprite class extends the DisplayObjectContainer class):

var container:Sprite = new Sprite(); 
var title:TextField = new TextField(); 
title.text = "Hello"; 
var pict:Loader = new Loader(); 
var url:URLRequest = new URLRequest("banana.jpg"); 
pict.load(url); 
pict.name = "banana loader"; 
container.addChild(title); 
container.addChild(pict);

The getChildAt() method returns the child of the display list at a specific index position:

trace(container.getChildAt(0) is TextField); // true

You can also access child objects by name. Each display object has a name property, and if you don’t assign it, Flash Player or AIR assigns a default value, such as "instance1" . For example, the following code shows how to use the getChildByName() method to access a child display object with the name "banana loader" :

trace(container.getChildByName("banana loader") is Loader); // true

Using the getChildByName() method can result in slower performance than using the getChildAt() method.

Since a display object container can contain other display object containers as child objects in its display list, you can traverse the full display list of the application as a tree. For example, in the code excerpt shown earlier, once the load operation for the pict Loader object is complete, the pict object will have one child display object, which is the bitmap, loaded. To access this bitmap display object, you can write pict.getChildAt(0) . You can also write container.getChildAt(0).getChildAt(0) (since container.getChildAt(0) == pict ).

The following function provides an indented trace() output of the display list from a display object container:

function traceDisplayList(container:DisplayObjectContainer,                                                indentString:String = ""):void 
{ 
    var child:DisplayObject; 
    for (var i:uint=0; i < container.numChildren; i++) 
    { 
        child = container.getChildAt(i); 
        trace(indentString, child, child.name);  
        if (container.getChildAt(i) is DisplayObjectContainer) 
        { 
            traceDisplayList(DisplayObjectContainer(child), indentString + "    ") 
        } 
    } 
}

Adobe Flex

If you use Flex, you should know that Flex defines many component display object classes, and these classes override the display list access methods of the DisplayObjectContainer class. For example, the Container class of the mx.core package overrides the addChild() method and other methods of the DisplayObjectContainer class (which the Container class extends). In the case of the addChild() method, the class overrides the method in such a way that you cannot add all types of display objects to a Container instance in Flex. The overridden method, in this case, requires that the child object that you are adding be a type of mx.core.UIComponent object.

Setting Stage properties

The Stage class overrides most properties and methods of the DisplayObject class. If you call one of these overridden properties or methods, Flash Player and AIR throw an exception. For example, the Stage object does not have x or y properties, since its position is fixed as the main container for the application. The x and y properties refer to the position of a display object relative to its container, and since the Stage is not contained in another display object container, these properties do not apply.

Note: Some properties and methods of the Stage class are only available to display objects that are in the same security sandbox as the first SWF file loaded. For details, see Stage security.
Controlling the playback frame rate

The frameRate property of the Stage class is used to set the frame rate for all SWF files loaded into the application. For more information, see the ActionScript 3.0 Reference for the Adobe Flash Platform .

Controlling Stage scaling

When the portion of the screen representing Flash Player or AIR is resized, the runtime automatically adjusts the Stage contents to compensate. The Stage class’s scaleMode property determines how the Stage contents are adjusted. This property can be set to four different values, defined as constants in the flash.display.StageScaleMode class:

  • StageScaleMode.EXACT_FIT scales the SWF to fill the new stage dimensions without regard for the original content aspect ratio. The scale factors might not be the same for width and height, so the content can appear squeezed or stretched if the aspect ratio of the stage is changed.

  • StageScaleMode.SHOW_ALL scales the SWF to fit entirely within the new stage dimensions without changing the content aspect ratio. This scale mode displays all of the content, but can result in “letterbox” borders, like the black bars that appear when viewing a wide-screen movie on a standard television.

  • StageScaleMode.NO_BORDER scales the SWF to entirely fill the new stage dimensions without changing the aspect ratio of the content. This scale mode makes full use of the stage display area, but can result in cropping.

  • StageScaleMode.NO_SCALE — does not scale the SWF. If the new stage dimensions are smaller, the content is cropped; if larger, the added space is blank.

    In the StageScaleMode.NO_SCALE scale mode only, the stage Width and stage Height properties of the Stage class can be used to determine the actual pixel dimensions of the resized stage. (In the other scale modes, the stageWidth and stageHeight properties always reflect the original width and height of the SWF.) In addition, when scaleMode is set to StageScaleMode.NO_SCALE and the SWF file is resized, the Stage class’s resize event is dispatched, allowing you to make adjustments accordingly.

    Consequently, having scaleMode set to StageScaleMode.NO_SCALE allows you to have greater control over how the screen contents adjust to the window resizing if you desire. For example, in a SWF containing a video and a control bar, you might want to make the control bar stay the same size when the Stage is resized, and only change the size of the video window to accommodate the Stage size change. This is demonstrated in the following example:

    // videoScreen is a display object (e.g. a Video instance) containing a 
    // video; it is positioned at the top-left corner of the Stage, and 
    // it should resize when the SWF resizes. 
     
    // controlBar is a display object (e.g. a Sprite) containing several 
    // buttons; it should stay positioned at the bottom-left corner of the 
    // Stage (below videoScreen) and it should not resize when the SWF 
    // resizes. 
     
    import flash.display.Stage; 
    import flash.display.StageAlign; 
    import flash.display.StageScaleMode; 
    import flash.events.Event; 
     
    var swfStage:Stage = videoScreen.stage; 
    swfStage.scaleMode = StageScaleMode.NO_SCALE; 
    swfStage.align = StageAlign.TOP_LEFT; 
     
    function resizeDisplay(event:Event):void 
    { 
        var swfWidth:int = swfStage.stageWidth; 
        var swfHeight:int = swfStage.stageHeight; 
     
        // Resize the video window. 
        var newVideoHeight:Number = swfHeight - controlBar.height; 
        videoScreen.height = newVideoHeight; 
        videoScreen.scaleX = videoScreen.scaleY; 
         
        // Reposition the control bar. 
        controlBar.y = newVideoHeight; 
    } 
     
    swfStage.addEventListener(Event.RESIZE, resizeDisplay);

Setting the stage scale mode for AIR windows

The stage scaleMode property determines how the stage scales and clips child display objects when a window is resized. Only the noScale mode should be used in AIR. In this mode, the stage is not scaled. Instead, the size of the stage changes directly with the bounds of the window. Objects may be clipped if the window is resized smaller.

The stage scale modes are designed for use in a environments such as a web browser where you don't always have control over the size or aspect ratio of the stage. The modes let you choose the least bad compromise when the stage does not match the ideal size or aspect ratio of your application. In AIR, you always have control of the stage, so in most cases re-laying out your content or adjusting the dimensions of your window will give you better results than enabling stage scaling.

In the browser and for the initial AIR window, the relationship between the window size and the initial scale factor is read from the loaded SWF file. However, when you create a NativeWindow object, AIR chooses an arbitrary relationship between the window size and the scale factor of 72:1. Thus, if your window is 72x72 pixels, a 10x10 rectangle added to the window is drawn the correct size of 10x10 pixels. However, if the window is 144x144 pixels, then a 10x10 pixel rectangle is scaled to 20x20 pixels. If you insist on using a scaleMode other than noScale for a window stage, you can compensate by setting the scale factor of any display objects in the window to the ratio of 72 pixels to the current width and height of the stage. For example, the following code calculates the required scale factor for a display object named client :

if(newWindow.stage.scaleMode != StageScaleMode.NO_SCALE){ 
client.scaleX = 72/newWindow.stage.stageWidth; 
client.scaleY = 72/newWindow.stage.stageHeight; 
}
Note: Flex and HTML windows automatically set the stage scaleMode to noScale . Changing the scaleMode disturbs the automatic layout mechanisms used in these types of windows.
Working with full-screen mode

Full-screen mode allows you to set a movie’s stage to fill a viewer’s entire monitor without any container borders or menus. The Stage class’s displayState property is used to toggle full-screen mode on and off for a SWF. The displayState property can be set to one of the values defined by the constants in the flash.display.StageDisplayState class. To turn on full-screen mode, set the displayState property to StageDisplayState.FULL_SCREEN :

stage.displayState = StageDisplayState.FULL_SCREEN; 

In Flash Player, full-screen mode can only be initiated through ActionScript in response to a mouse click (including right-click) or keypress. AIR content running in the application security sandbox does not require that full-screen mode be entered in response to a user gesture.

To exit full-screen mode, set the displayState property to StageDisplayState.NORMAL .

stage.displayState = StageDisplayState.NORMAL; 

In addition, a user can choose to leave full-screen mode by switching focus to a different window or by using one of several key combinations: the Esc key (all platforms), Control-W (Windows), Command-W (Mac), or Alt-F4 (Windows).

Enabling full-screen mode in Flash Player

To enable full-screen mode for a SWF file embedded in an HTML page, the HTML code to embed Flash Player must include a param tag and embed attribute with the name allowFullScreen and value true , like this:

<object> 
    ... 
    <param name="allowFullScreen" value="true" /> 
    <embed ... allowfullscreen="true" /> 
</object>

In the Flash authoring tool, select File -> Publish Settings and in the Publish Settings dialog box, on the HTML tab, select the Flash Only - Allow Full Screen template.

In Flex, ensure that the HTML template includes <object> and <embed> tags that support full screen.

If you are using JavaScript in a web page to generate the SWF-embedding tags, you must alter the JavaScript to add the allowFullScreen param tag and attribute. For example, if your HTML page uses the AC_FL_RunContent() function (which is used in HTML pages generated by Flash Professional and Flash Builder), you should add the allowFullScreen parameter to that function call as follows:

AC_FL_RunContent( 
    ... 
    'allowFullScreen','true', 
    ... 
    ); //end AC code

This does not apply to SWF files running in the stand-alone Flash Player.

Note: If you set the Window Mode (wmode in the HTML) to Opaque Windowless (opaque) or Transparent Windowless (transparent), the full-screen window is always opaque

There are also security-related restrictions for using full-screen mode with Flash Player in a browser. These restrictions are described in Flash Player security.

Full screen stage size and scaling

The Stage.fullScreenHeight and Stage.fullScreenWidth properties return the height and the width of the monitor that’s used when going to full-screen size, if that state is entered immediately. These values can be incorrect if the user has the opportunity to move the browser from one monitor to another after you retrieve these values but before entering full-screen mode. If you retrieve these values in the same event handler where you set the Stage.displayState property to StageDisplayState.FULL_SCREEN , the values are correct.For users with multiple monitors, the SWF content expands to fill only one monitor. Flash Player and AIR use a metric to determine which monitor contains the greatest portion of the SWF, and uses that monitor for full-screen mode. The fullScreenHeight and fullScreenWidth properties only reflect the size of the monitor that is used for full-screen mode. For more information, see Stage.fullScreenHeight and Stage.fullScreenWidth in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Stage scaling behavior for full-screen mode is the same as under normal mode; the scaling is controlled by the Stage class’s scaleMode property. If the scaleMode property is set to StageScaleMode.NO_SCALE , the Stage’s stageWidth and stageHeight properties change to reflect the size of the screen area occupied by the SWF (the entire screen, in this case); if viewed in the browser the HTML parameter for this controls the setting.

You can use the Stage class’s fullScreen event to detect and respond when full-screen mode is turned on or off. For example, you might want to reposition, add, or remove items from the screen when entering or leaving full-screen mode, as in this example:

import flash.events.FullScreenEvent; 
 
function fullScreenRedraw(event:FullScreenEvent):void 
{ 
    if (event.fullScreen) 
    { 
        // Remove input text fields. 
        // Add a button that closes full-screen mode. 
    } 
    else 
    { 
        // Re-add input text fields. 
        // Remove the button that closes full-screen mode. 
    } 
} 
 
mySprite.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenRedraw);

As this code shows, the event object for the fullScreen event is an instance of the flash.events.FullScreenEvent class, which includes a fullScreen property indicating whether full-screen mode is enabled ( true ) or not ( false ).

Keyboard support in full-screen mode

When Flash Player runs in a browser, all keyboard-related ActionScript, such as keyboard events and text entry in TextField instances, is disabled in full-screen mode. The exceptions (the keys that are enabled) are:

  • Selected non-printing keys, specifically the arrow keys, space bar, and tab key

  • Keyboard shortcuts that terminate full-screen mode: Esc (Windows and Mac), Control-W (Windows), Command-W (Mac), and Alt-F4

These restrictions are not present for SWF content running in the stand-alone Flash Player or in AIR. AIR supports an interactive full-screen mode that allows keyboard input.

Hardware scaling in full-screen mode

You can use the Stage class’s fullScreenSourceRect property to set Flash Player or AIR to scale a specific region of the stage to full-screen mode. Flash Player and AIR scale in hardware, if available, using the graphics and video card on a user's computer, and generally display content more quickly than software scaling.

To take advantage of hardware scaling, you set the whole stage or part of the stage to full-screen mode. The following ActionScript 3.0 code sets the whole stage to full-screen mode:

import flash.geom.*;  
{ 
    stage.fullScreenSourceRect = new Rectangle(0,0,320,240); 
    stage.displayState = StageDisplayState.FULL_SCREEN; 
}

When this property is set to a valid rectangle and the displayState property is set to full-screen mode, Flash Player and AIR scale the specified area. The actual Stage size in pixels within ActionScript does not change. Flash Player and AIR enforce a minimum limit for the size of the rectangle to accommodate the standard “Press Esc to exit full-screen mode” message. This limit is usually around 260 by 30 pixels but can vary depending on platform and Flash Player version.

The fullScreenSourceRect property can only be set when Flash Player or AIR is not in full-screen mode. To use this property correctly, set this property first, then set the displayState property to full-screen mode.

To enable scaling, set the fullScreenSourceRect property to a rectangle object.

stage.fullScreenSourceRect = new Rectangle(0,0,320,240);

To disable scaling, set the fullScreenSourceRect property to null .

stage.fullScreenSourceRect = null;

To take advantage of all hardware acceleration features with Flash Player, enable it through the Flash Player Settings dialog box. To load the dialog box, right-click (Windows) or Control-click (Mac) inside Flash Player content in your browser. Select the Display tab, which is the first tab, and click the checkbox: Enable hardware acceleration.

Direct and GPU-compositing window modes

Flash Player 10 introduces two window modes, direct and GPU compositing, which you can enable through the publish settings in the Flash authoring tool. These modes are not supported in AIR. To take advantage of these modes, you must enable hardware acceleration for Flash Player.

Direct mode uses the fastest, most direct path to push graphics to the screen, which is advantageous for video playback.

GPU Compositing uses the graphics processing unit on the video card to accelerate compositing. Video compositing is the process of layering multiple images to create a single video image. When compositing is accelerated with the GPU it can improve the performance of YUV conversion, color correction, rotation or scaling, and blending. YUV conversion refers to the color conversion of composite analog signals, which are used for transmission, to the RGB (red, green, blue) color model that video cameras and displays use. Using the GPU to accelerate compositing reduces the memory and computational demands that are otherwise placed on the CPU. It also results in smoother playback for standard-definition video.

Be cautious in implementing these window modes. Using GPU compositing can be expensive for memory and CPU resources. If some operations (such as blend modes, filtering, clipping or masking) cannot be carried out in the GPU, they are done by the software. Adobe recommends limiting yourself to one SWF file per HTML page when using these modes and you should not enable these modes for banners. The Flash Test Movie facility does not use hardware acceleration but you can use it through the Publish Preview option.

Setting a frame rate in your SWF file that is higher than 60, the maximum screen refresh rate, is useless. Setting the frame rate from 50 through 55 allows for dropped frames, which can occur for various reasons from time to time.

Using direct mode requires Microsoft DirectX 9 with VRAM 128 MB on Windows and OpenGL for Apple Macintosh, Mac OS X v10.2 or higher. GPU compositing requires Microsoft DirectX 9 and Pixel Shader 2.0 support on Windows with 128 MB of VRAM. On Mac OS X and Linux, GPU compositing requires OpenGL 1.5 and several OpenGL extensions (framebuffer object, multitexture, shader objects, shading language, fragment shader).

You can activate direct and gpu acceleration modes on a per-SWF basis through the Flash Publish Settings dialog box, using the Hardware Acceleration menu on the Flash tab. If you choose None, the window mode reverts to default , transparent , or opaque , as specified by the Window Mode setting on the HTML tab.

Choosing a DisplayObject subclass

With several options to choose from, one of the important decisions you’ll make when you’re working with display objects is which display object to use for what purpose. Here are some guidelines to help you decide. These same suggestions apply whether you need an instance of a class or you’re choosing a base class for a class you’re creating:

  • If you don’t need an object that can be a container for other display objects (that is, you just need one that serves as a stand-alone screen element), choose one of these DisplayObject or InteractiveObject subclasses, depending on what it will be used for:

    • Bitmap for displaying a bitmap image.

    • TextField for adding text.

    • Video for displaying video.

    • Shape for a “canvas” for drawing content on-screen. In particular, if you want to create an instance for drawing shapes on the screen, and it won’t be a container for other display objects, you’ll gain significant performance benefits using Shape instead of Sprite or MovieClip.

    • MorphShape, StaticText, or SimpleButton for items created by the Flash authoring tool. (You can’t create instances of these classes programmatically, but you can create variables with these data types to refer to items created using the Flash authoring tool.)

  • If you need a variable to refer to the main Stage, use the Stage class as its data type.

  • If you need a container for loading an external SWF file or image file, use a Loader instance. The loaded content will be added to the display list as a child of the Loader instance. Its data type will depend on the nature of the loaded content, as follows:

    • A loaded image will be a Bitmap instance.

    • A loaded SWF file written in ActionScript 3.0 will be a Sprite or MovieClip instance (or an instance of a subclass of those classes, as specified by the content creator).

    • A loaded SWF file written in ActionScript 1.0 or ActionScript 2.0 will be an AVM1Movie instance.

  • If you need an object to serve as a container for other display objects (whether or not you’ll also be drawing onto the display object using ActionScript), choose one of the DisplayObjectContainer subclasses:

    • Sprite if the object will be created using only ActionScript, or as the base class for a custom display object that will be created and manipulated solely with ActionScript.

    • MovieClip if you’re creating a variable to refer to a movie clip symbol created in the Flash authoring tool.

  • If you are creating a class that will be associated with a movie clip symbol in the Flash library, choose one of these DisplayObjectContainer subclasses as your class’s base class:

    • MovieClip if the associated movie clip symbol has content on more than one frame

    • Sprite if the associated movie clip symbol has content only on the first frame

Packages

Packages

Most software projects contain many classes. Sometimes a project contains hundreds, if not thousands, of classes. Organizing those classes into related groups is standard practice and helpful. You use packages to organize your classes into related groups. The compiler also uses packages to define the full name for the classes they contain and to add a level of access control.

Organization and hierarchy

Organize your classes into related groups. If you were building an application that draws, performs special calculations, and uses custom user interface components, place all of your drawing classes in a draw package, your calculations classes into a calculations package, and your user interface component classes in a ui package.

You can also include embedded dots (dot syntax) in your package name to create nested packages. Dot syntax allows you to create a hierarchical organization of packages. A good example of this practice is the flash.display package provided by ActionScript 3.0. The display package is nested inside the flash package.

The organization and hierarchy you create in code is also visible on your file system. Your class files exist in folders with the same names and nested structure as your packages.

Fully qualified names and uniqueness

Each class has a class name and a fully qualified name. The class name is the name defined in the class statement. The compiler creates the fully qualified name at compile time. The fully qualified name combines the package name with the class name using dot syntax. In the following example, the name of the package is samples . The name of the class is SampleCode . Because the class is inside the samples package, the fully qualified name of the class is samples.SampleCode .
package samples { 
    public class SampleCode { 
        public var sampleGreeting:String; 
         
        public function SampleCode() { 
        } 
        public function sampleFunction() { 
            trace(sampleGreeting + " from sampleFunction()"); 
        } 
    } 
}

The compiler also qualifies the names of any properties or methods, so that sampleGreeting and sampleFunction() become samples.SampleCode.sampleGreeting and samples.SampleCode.sampleFunction() , respectively.

Fully qualified names resolve name conflicts that could occur when using libraries, frameworks, or code written by multiple developers. Multiple classes with the same class name are not uncommon when code is shared. Without packages, the compiler does not know which class to use. If each of those classes is in a different package, the fully qualified name for each class is unique. The naming conflict is avoided. In the previous example code, the class SampleCode was created inside the samples package. In the example code below, a SampleCode class is created inside the langref package
package langref { 
    public class SampleCode {} 
}
Use the fully qualified names of both SampleCode classes to avoid a name conflict:
package { 
    import samples.SampleCode; 
    import langref.SampleCode; 
    public class TestApplication { 
        var firstExampleVar:samples.SampleCode = new samples.SampleCode(); 
        var secondExampleVar:langref.SampleCode = new langref.SampleCode(); 
        public function TestApplication(){ } 
    } 
}
To further avoid naming conflicts when using shared code, use unique names for packages. Developers often place packages in a structure that uses a reversed domain name for the naming scheme. Domain names are unique so using them as part of the package naming scheme guarantees packages names are unique. For example, if you were deploying your application to http://www.example.com , you would create a com package that contained an example package that contained all other packages. The SampleCode class in the samples packages in the example above now has a fully qualified name of com.example.samples.SampleCode :
package com.example.samples { 
    public class SampleCode { 
        public var sampleGreeting:String; 
         
        public function SampleCode() { 
        } 
        public function sampleFunction() { 
            trace(sampleGreeting + " from sampleFunction()"); 
        } 
    } 
}

Access control

You control where your code is available by using access control attributes when declaring variables and defining functions. You control where classes are available by using access control attributes with packages.

When a package is created, internal is the default access control attribute keyword applied to all members of that package. internal package members are only visible to other members of that package. Use the public access control attribute keyword to make package members available outside the package. For example, the following package contains two classes, SampleCode and CodeFormatter:
// SampleCode.as file 
package samples 
{ 
    public class SampleCode {} 
} 
 
// CodeFormatter.as file 
package samples 
{ 
    class CodeFormatter {} 
}
The SampleCode class is visible outside the package because it is declared as a public class. The CodeFormatter class, however, is visible only within the samples package itself. If you attempt to access the CodeFormatter class outside the samples package, an error results, as the following example shows:
package examples{ 
    import samples.SampleCode; 
    import samples.CodeFormatter; 
    public class UsingPackages { 
        var mySample:SampleCode = new SampleCode(); // okay, public class 
        var myFormatter:CodeFormatter = new CodeFormatter(); // error 
         
        public function UsingPackages(){ 
        } 
    } 
}

Creating packages

You use the package statement to declare a package in ActionScript 3.0. In the following example, the samples package is declared. It contains the class SampleCode.
package samples { 
    public class SampleCode { 
        public function SampleCode() { 
        } 
    } 
}

In ActionScript 3.0 files, only one public class can be contained in the package block. The name of the file and the name of the class are the same. The file path corresponds to the package. The example code directly above would exist in a file named SampleCode.as which is in a package named samples.

You can also declare variables, functions, or namespaces at the top level of a package. Two limitations exist if you choose to make package declarations. First, the only access control attributes available at that level are public and internal . Second, only one package-level declaration per file can use the public attribute, whether that declaration is a class, variable, function, or namespace. The name of the file must match the name of the one public item.

Importing packages

To use a class that is inside a package, import either the entire package or the specific class using an import statement. The import statement tells the computer where to find the class definitions. If you try to use a class without importing it, an error results. Consider the SampleCode class example from above. The class resides in a package named samples. Use the following import statement to import the SampleCode class:
import samples.SampleCode;
Place the import statements inside the package block but outside the class block.
package { 
    import samples.SampleCode; 
    import samples.SampleShape; 
    public class ExampleClass { 
        public var mySample:SampleCode = new Sample Code(); 
        public var myShape:SampeShape = new Sample Shape(); 
        public function ExampleClass(){ 
        } 
    } 
}
Use the wildcard operator ( * ) to import all of the classes in a particular package:
package { 
    import samples.*; 
    public class ExampleClass { 
        public function ExampleClass(){ 
            var mySample:SampleCode = new Sample Code(); 
            var myShape:SampeShape = new Sample Shape(); 
        } 
    } 
}
Note: Imported classes are not automatically included in your compiled SWF file. Only classes that are used in executable code are compiled and included. Your compiled SWF file does not include classes that have been imported but not used.
Note: Programmers with a C++ background often confuse the import statement with #include . The #include directive is necessary in C++ because C++ compilers process one file at a time and don’t look in other files for class definitions unless a header file is explicitly included. ActionScript 3.0 has an include directive, but it is not designed to import classes and packages. To import classes or packages in ActionScript 3.0, use the import statement and place the source file that contains the package in the class path.

Namespaces

A namespace is a set of unique names. You use namespaces to control the visibility of identifiers, such as property and method names. You create a namespace every time you create a package, but you can also explicitly define a namespace and apply it to code regardless of the code’s package. Namespaces allow you to break out of the organization imposed by packages and overrule the limitations of access control attributes.

Defining namespaces

Namespaces contain one value, the Uniform Resource Identifier (URI), which is sometimes called the namespace name . A URI allows you to ensure that your namespace definition is unique.

You create a namespace by declaring a namespace definition in one of two ways. You can either define a namespace with an explicit URI or you can omit the URI. The following example shows how to define a namespace using a URI:
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
The URI serves as a unique identification string for that namespace. If you omit the URI, as in the following example, the compiler creates a unique internal identification string in place of the URI. You do not have access to this internal identification string.
namespace flash_proxy;

Once you define a namespace, with or without a URI, that namespace cannot be redefined in the same scope. An attempt to define a namespace that has been defined earlier in the same scope results in a compiler error.

If a namespace is defined within a package or a class, the namespace is not visible outside that package or class unless the appropriate access control specifier is used. For example, the following code shows the flash_proxy namespace defined within the flash.utils package. The lack of an access control attribute keyword means that the flash_proxy namespace is visible only to code within the flash.utils package:
package flash.utils 
{ 
    namespace flash_proxy; 
}
The following code uses the public attribute to make the flash_proxy namespace visible to code outside the package:
package flash.utils 
{ 
    public namespace flash_proxy; 
}

Applying namespaces

Applying a namespace means placing a definition into a namespace. Definitions that can be placed into namespaces include functions, variables, and constants (you cannot place a class into a custom namespace).

Consider, for example, a function declared using the public access control namespace. Using the public attribute in a function definition places the function into the public namespace, which makes the function available to all code. Once you have defined a namespace, you can use it the same way you would use the public attribute, and the definition is available to code that can reference your custom namespace. For example, if you define a namespace example1 , you can add a method called myFunction() using example1 as an attribute, as the following example shows:
namespace example1; 
class someClass 
{ 
    example1 myFunction() {} 
}

Declaring the myFunction() method using the namespace example1 as an attribute means that the method belongs to the example1 namespace.

Keep in mind the following when applying namespaces:

  • You can apply only one namespace to each declaration.

  • There is no way to apply a namespace attribute to more than one definition at a time. If you want to apply your namespace to ten different functions, you must add your namespace as an attribute to each of the ten function definitions.

  • If you apply a namespace, you cannot also specify an access control specifier because namespaces and access control specifiers are mutually exclusive. In other words, you cannot declare a function or property as public , private , protected, or internal in addition to applying your namespace.

Referencing namespaces

You do not need to explicitly reference a namespace when you use a method or property declared with any of the access control attributes— public , private , protected , and internal —because the context controls access to these special namespaces. For example, definitions placed into the private namespace are automatically available to code within the same class. For namespaces that you define, however, such context sensitivity does not exist. To use a method or property that you have placed into a custom namespace, you must reference the namespace.

You can reference namespaces with the use namespace directive or you can qualify the name with the namespace using the name qualifier ( :: ) punctuator. Referencing a namespace with the use namespace directive “opens” the namespace, so that it can apply to any identifiers that are not qualified. For example, if you have defined the example1 namespace, you can access names in that namespace by using use namespace example1 :
use namespace example1; 
myFunction();

You can open more than one namespace at a time. Once you open a namespace with use namespace , it remains open throughout the block of code in which it was opened. There is no way to explicitly close a namespace.

Having more than one open namespace, however, increases the likelihood of name conflicts. If you prefer not to open a namespace, you can avoid the use namespace directive by qualifying the method or property name with the namespace and the name qualifier punctuator. For example, the following code shows how you can qualify the name myFunction() with the example1 namespace:
example1::myFunction();

Using namespaces

You can find a real-world example of a namespace that is used to prevent name conflicts in the flash.utils.Proxy class that is part of ActionScript 3.0. The Proxy class, which is the replacement for the Object.__resolve property from ActionScript 2.0, allows you to intercept references to undefined properties or methods before an error occurs. All of the methods of the Proxy class reside in the flash_proxy namespace to prevent name conflicts.

To better understand how the flash_proxy namespace is used, first understand how to use the Proxy class. The functionality of the Proxy class is available only to classes that inherit from it. In other words, if you want to use the methods of the Proxy class on an object, the object’s class definition must extend the Proxy class. For example, if you want to intercept attempts to call an undefined method, extend the Proxy class and then override the callProperty() method of the Proxy class.

You may recall that implementing namespaces is usually a three-step process of defining, applying, and then referencing a namespace. Because you never explicitly call any of the Proxy class methods, however, the flash_proxy namespace is only defined and applied, but never referenced. ActionScript 3.0 defines the flash_proxy namespace and applies it in the Proxy class. Your code only needs to apply the flash_proxy namespace to classes that extend the Proxy class.

The flash_proxy namespace is defined in the flash.utils package in a manner similar to the following:

package flash.utils 
{ 
    public namespace flash_proxy; 
}

The namespace is applied to the methods of the Proxy class as shown in the following excerpt from the Proxy class:

public class Proxy 
{ 
    flash_proxy function callProperty(name:*, ... rest):* 
    flash_proxy function deleteProperty(name:*):Boolean 
    ... 
}

As the following code shows, first import both the Proxy class and the flash_proxy namespace. Then, declare your class such that it extends the Proxy class (you must also add the dynamic attribute if you are compiling in strict mode). When you override the callProperty() method, use the flash_proxy namespace.

package 
{ 
    import flash.utils.Proxy; 
    import flash.utils.flash_proxy; 
 
    dynamic class MyProxy extends Proxy 
    { 
        flash_proxy override function callProperty(name:*, ...rest):* 
        { 
            trace("method call intercepted: " + name); 
        } 
    } 
}

If you create an instance of the MyProxy class and call an undefined method, such as the testing() method called in the following example, your Proxy object intercepts the method call and executes the statements inside the overridden callProperty() method (in this case, a simple trace() statement).

var mySample:MyProxy = new MyProxy(); 
mySample.testing(); // method call intercepted: testing

There are two advantages to having the methods of the Proxy class inside the flash_proxy namespace. First, having a separate namespace reduces clutter in the public interface of any class that extends the Proxy class. (There are about a dozen methods in the Proxy class that you can override, all of which are not designed to be called directly. Placing all of them in the public namespace could be confusing.) Second, use of the flash_proxy namespace avoids name conflicts in case your Proxy subclass contains instance methods with names that match any of the Proxy class methods. For example, you may want to name one of your own methods callProperty() . The following code is acceptable, because your version of the callProperty() method is in a different namespace:

dynamic class MyProxy extends Proxy 
{ 
    public function callProperty() {} 
    flash_proxy override function callProperty(name:*, ...rest):* 
    { 
        trace("method call intercepted: " + name); 
    } 
}

Namespaces can also be helpful when you want to provide access to methods or properties in a way that cannot be accomplished with the four access control specifiers ( public , private , internal , and protected ). For example, you may have a few utility methods that are spread out across several packages. You want these methods available to all of your packages, but you don’t want the methods to be public. To accomplish this, you can create a namespace and use it as your own special access control specifier.

The following example uses a user-defined namespace to group two functions that reside in different packages. By grouping them into the same namespace, you can make both functions visible to a class or package through a single use namespace statement.

This example uses four files to demonstrate the technique. All of the files must be within your classpath. The first file, myInternal.as, is used to define the myInternal namespace. Because the file is in a package named example, you must place the file into a folder named example. The namespace is marked as public so that it can be imported into other packages.

// myInternal.as in folder example 
package example 
{ 
    public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; 
}

The second and third files, Utility.as and Helper.as, define the classes that contain methods that should be available to other packages. The Utility class is in the example.alpha package, which means that the file should be placed inside a folder named alpha that is a subfolder of the example folder. The Helper class is in the example.beta package, which means that the file should be placed inside a folder named beta that is also a subfolder of the example folder. Both of these packages, example.alpha and example.beta, must import the namespace before using it.

// Utility.as in the example/alpha folder 
package example.alpha 
{ 
    import example.myInternal; 
     
    public class Utility 
    { 
        private static var _taskCounter:int = 0; 
     
        public static function someTask() 
        { 
            _taskCounter++; 
        } 
         
        myInternal static function get taskCounter():int 
        { 
            return _taskCounter; 
        } 
    } 
} 
 
// Helper.as in the example/beta folder 
package example.beta 
{ 
    import example.myInternal; 
     
    public class Helper 
    { 
        private static var _timeStamp:Date; 
         
        public static function someTask() 
        { 
            _timeStamp = new Date(); 
        } 
         
        myInternal static function get lastCalled():Date 
        { 
            return _timeStamp; 
        } 
    } 
}

The fourth file, NamespaceUseCase.as, is the main application class, and should be a sibling to the example folder. In Flash Professional, this class would be used as the document class for the FLA. The NamespaceUseCase class also imports the myInternal namespace and uses it to call the two static methods that reside in the other packages. The example uses static methods only to simplify the code. Both static and instance methods can be placed in the myInternal namespace.

// NamespaceUseCase.as 
package 
{ 
    import flash.display.MovieClip; 
    import example.myInternal; // import namespace 
    import example.alpha.Utility;// import Utility class 
    import example.beta.Helper;// import Helper class 
     
    public class NamespaceUseCase extends MovieClip 
    { 
        public function NamespaceUseCase() 
        { 
            use namespace myInternal; 
             
            Utility.someTask(); 
            Utility.someTask(); 
            trace(Utility.taskCounter); // 2 
             
            Helper.someTask(); 
            trace(Helper.lastCalled); // [time someTask() was last called] 
        } 
    } 
}

Loops

Looping

Looping statements allow you to perform a specific block of code repeatedly using a series of values or variables. Adobe recommends that you always enclose the block of code in curly brackets ( {} ). Although you can omit the curly brackets if the block of code contains only one statement, this practice is not recommended for the same reason that it is not recommended for conditionals: it increases the likelihood that statements added later are inadvertently excluded from the block of code. If you later add a statement that you want to include in the block of code, but forget to add the necessary curly brackets, the statement are not executed as part of the loop.

for

The for loop allows you to iterate through a variable for a specific range of values. You must supply three expressions in a for statement: a variable that is set to an initial value, a conditional statement that determines when the looping ends, and an expression that changes the value of the variable with each loop. For example, the following code loops five times. The value of the variable i starts at 0 and ends at 4, and the output is the numbers 0 through 4, each on its own line.

var i:int; 
for (i = 0; i < 5; i++) 
{ 
    trace(i); 
}

for..in

The for..in loop iterates through the properties of an object, or the elements of an array. For example, you can use a for..in loop to iterate through the properties of a generic object (object properties are not kept in any particular order, so properties may appear in a seemingly random order):

var myObj:Object = {x:20, y:30}; 
for (var i:String in myObj) 
{ 
    trace(i + ": " + myObj[i]); 
} 
// output: 
// x: 20 
// y: 30

You can also iterate through the elements of an array:

var myArray:Array = ["one", "two", "three"]; 
for (var i:String in myArray) 
{ 
    trace(myArray[i]); 
} 
// output: 
// one 
// two 
// three

What you cannot do is iterate through the properties of an object if it is an instance of a sealed class (including built-in classes and user-defined classes). You can only iterate through the properties of a dynamic class. Even with instances of dynamic classes, you can only iterate through properties that are added dynamically.

for each..in

The for each..in loop iterates through the items of a collection, which can be tags in an XML or XMLList object, the values held by object properties, or the elements of an array. For example, as the following excerpt shows, you can use a for each..in loop to iterate through the properties of a generic object, but unlike the for..in loop, the iterator variable in a for each..in loop contains the value held by the property instead of the name of the property:

var myObj:Object = {x:20, y:30}; 
for each (var num in myObj) 
{ 
    trace(num); 
} 
// output: 
// 20 
// 30

You can iterate through an XML or XMLList object, as the following example shows:

var myXML:XML = <users> 
    <fname>Jane</fname> 
    <fname>Susan</fname> 
    <fname>John</fname> 
</users>; 
 
for each (var item in myXML.fname) 
{ 
    trace(item); 
} 
/* output 
Jane 
Susan 
John 
*/

You can also iterate through the elements of an array, as this example shows:

var myArray:Array = ["one", "two", "three"]; 
for each (var item in myArray) 
{ 
    trace(item); 
} 
// output: 
// one 
// two 
// three

You cannot iterate through the properties of an object if the object is an instance of a sealed class. Even for instances of dynamic classes, you cannot iterate through any fixed properties, which are properties defined as part of the class definition.

while

The while loop is like an if statement that repeats as long as the condition is true . For example, the following code produces the same output as the for loop example:

var i:int = 0; 
while (i < 5) 
{ 
    trace(i); 
    i++; 
}

One disadvantage of using a while loop instead of a for loop is that infinite loops are easier to write with while loops. The for loop example code does not compile if you omit the expression that increments the counter variable, but the while loop example does compile if you omit that step. Without the expression that increments i , the loop becomes an infinite loop.

do..while

The do..while loop is a while loop that guarantees that the code block is executed at least once, because the condition is checked after the code block is executed. The following code shows a simple example of a do..while loop that generates output even though the condition is not met:

var i:int = 5; 
do 
{ 
    trace(i); 
    i++; 
} while (i < 5); 
// output: 5

Conditionals

Conditionals

ActionScript 3.0 provides three basic conditional statements that you can use to control program flow.

if..else

The if..else conditional statement allows you to test a condition and execute a block of code if that condition exists, or execute an alternative block of code if the condition does not exist. For example, the following code tests whether the value of x exceeds 20, generates a trace() function if it does, or generates a different trace() function if it does not:

if (x > 20) 
{ 
    trace("x is > 20"); 
} 
else 
{ 
    trace("x is <= 20"); 
}

If you do not want to execute an alternative block of code, you can use the if statement without the else statement.

if..else if

You can test for more than one condition using the if..else if conditional statement. For example, the following code not only tests whether the value of x exceeds 20, but also tests whether the value of x is negative:

if (x > 20) 
{ 
    trace("x is > 20"); 
} 
else if (x < 0) 
{ 
    trace("x is negative"); 
}

If an if or else statement is followed by only one statement, the statement does not need to be enclosed in curly brackets. For example, the following code does not use curly brackets:

if (x > 0) 
    trace("x is positive"); 
else if (x < 0)  
    trace("x is negative"); 
else 
    trace("x is 0");

However, Adobe recommends that you always use curly brackets, because unexpected behavior can occur if statements are later added to a conditional statement that lacks curly brackets. For example, in the following code the value of positiveNums increases by 1 whether or not the condition evaluates to true :

var x:int; 
var positiveNums:int = 0; 
 
if (x > 0) 
    trace("x is positive"); 
    positiveNums++; 
 
trace(positiveNums); // 1

switch

The switch statement is useful if you have several execution paths that depend on the same condition expression. It provides functionality similar to a long series of if..else if statements, but is somewhat easier to read. Instead of testing a condition for a Boolean value, the switch statement evaluates an expression and uses the result to determine which block of code to execute. Blocks of code begin with a case statement and end with a break statement. For example, the following switch statement prints the day of the week, based on the day number returned by the Date.getDay() method:

var someDate:Date = new Date(); 
var dayNum:uint = someDate.getDay(); 
switch(dayNum) 
{ 
    case 0: 
        trace("Sunday"); 
        break; 
    case 1: 
        trace("Monday"); 
        break; 
    case 2: 
        trace("Tuesday"); 
        break; 
    case 3: 
        trace("Wednesday"); 
        break; 
    case 4: 
        trace("Thursday"); 
        break; 
    case 5: 
        trace("Friday"); 
        break; 
    case 6: 
        trace("Saturday"); 
        break; 
    default: 
        trace("Out of range"); 
        break; 
}

Arrays (basic)

Working with arrays

Arrays allow you to store multiple values in a single data structure. You can use simple indexed arrays that store values using fixed ordinal integer indexes or complex associative arrays that store values using arbitrary keys. Arrays can also be multidimensional, containing elements that are themselves arrays. Finally, you can use a Vector for an array whose elements are all instances of the same data type.

Basics of arrays

Often in programming you’ll need to work with a set of items rather than a single object. For example, in a music player application, you might want to have a list of songs waiting to be played. You wouldn’t want to have to create a separate variable for each song on that list. It would be preferable to have all the Song objects together in a bundle, and be able to work with them as a group.

An array is a programming element that acts as a container for a set of items, such as a list of songs. Most commonly all the items in an array are instances of the same class, but that is not a requirement in ActionScript. The individual items in an array are known as the array’s elements . You can think of an array as a file drawer for variables. Variables can be added as elements in the array, which is like placing a folder into the file drawer. You can work with the array as a single variable (like carrying the whole drawer to a different location). You can work with the variables as a group (like flipping through the folders one by one searching for a piece of information). You can also access them individually (like opening the drawer and selecting a single folder).

For example, imagine you’re creating a music player application where a user can select multiple songs and add them to a playlist. In your ActionScript code, you have a method named addSongsToPlaylist() , which accepts a single array as a parameter. No matter how many songs you want to add to the list (a few, a lot, or even only one), you call the addSongsToPlaylist() method only one time, passing it the array containing the Song objects. Inside the addSongsToPlaylist() method, you can use a loop to go through the array’s elements (the songs) one by one and actually add them to the playlist.

The most common type of ActionScript array is an indexed array . In an indexed array each item is stored in a numbered slot (known as an index ). Items are accessed using the number, like an address. Indexed arrays work well for most programming needs. The Array class is one common class that’s used to represent an indexed array.

Often, an indexed array is used to store multiple items of the same type (objects that are instances of the same class). The Array class doesn’t have any means for restricting the type of items it contains. The Vector class is a type of indexed array in which all the items in a single array are the same type. Using a Vector instance instead of an Array instance can also provide performance improvements and other benefits. The Vector class is available starting with Flash Player 10 and Adobe AIR 1.5.

A special use of an indexed array is a multidimensional array . A multidimensional array is an indexed array whose elements are indexed arrays (which in turn contain other elements).

Another type of array is an associative array , which uses a string key instead of a numeric index to identify individual elements. Finally, ActionScript 3.0 also includes the Dictionary class, which represents a dictionary . A dictionary is an array that allows you to use any type of object as a key to distinguish between elements.

Important concepts and terms

The following reference list contains important terms that you will encounter when programming array and vector handling routines:

Array
An object that serves as a container to group multiple objects.

Array access ([]) operator
A pair of square brackets surrounding an index or key that uniquely identifies an array element. This syntax is used after an array variable name to specify a single element of the array rather than the entire array.

Associative array
An array that uses string keys to identify individual elements.

Base type
The data type of the objects that a Vector instance is allowed to store.

Dictionary
An array whose items consist of pairs of objects, known as the key and the value. The key is used instead of a numeric index to identify a single element.

Element
A single item in an array.

Index
The numeric “address” used to identify a single element in an indexed array.

Indexed array
The standard type of array that stores each element in a numbered position, and uses the number (index) to identify individual elements.

Key
The string or object used to identify a single element in an associative array or a dictionary.

Multidimensional array
An array containing items that are arrays rather than single values.

T
The standard convention that’s used in this documentation to represent the base type of a Vector instance, whatever that base type happens to be. The T convention is used to represent a class name, as shown in the Type parameter description. (“T” stands for “type,” as in “data type.”).

Type parameter
The syntax that’s used with the Vector class name to specify the Vector’s base type (the data type of the objects that it stores). The syntax consists of a period ( . ), then the data type name surrounded by angle brackets ( <> ). Put together, it looks like this: Vector.<T> . In this documentation, the class specified in the type parameter is represented generically as T .

Vector
A type of array whose elements are all instances of the same data type.

Indexed arrays

Indexed arrays store a series of one or more values organized such that each value can be accessed using an unsigned integer value. The first index is always the number 0, and the index increments by 1 for each subsequent element added to the array. In ActionScript 3.0, two classes are used as indexed arrays: the Array class and the Vector class.

Indexed arrays use an unsigned 32-bit integer for the index number. The maximum size of an indexed array is 2 32 - 1 or 4,294,967,295. An attempt to create an array that is larger than the maximum size results in a run-time error.

To access an individual element of an indexed array, you use the array access ( [] ) operator to specify the index position of the element you wish to access. For example, the following code represents the first element (the element at index 0) in an indexed array named songTitles :

songTitles[0]

The combination of the array variable name followed by the index in square brackets functions as a single identifier. (In other words, it can be used in any way a variable name can). You can assign a value to an indexed array element by using the name and index on the left side of an assignment statement:

songTitles[1] = "Symphony No. 5 in D minor";

Likewise, you can retrieve the value of an indexed array element by using the name and index on the right side of an assignment statement:

var nextSong:String = songTitles[2];

You can also use a variable in the square brackets rather than providing an explicit value. (The variable must contain a non-negative integer value such as a uint, a positive int, or a positive integer Number instance). This technique is commonly used to “loop over” the elements in an indexed array and perform an operation on some or all the elements. The following code listing demonstrates this technique. The code uses a loop to access each value in an Array object named oddNumbers . It uses the trace() statement to print each value in the form “oddNumber[ index ] = value ”:

var oddNumbers:Array = [1, 3, 5, 7, 9, 11]; 
var len:uint = oddNumbers.length; 
for (var i:uint = 0; i < len; i++) 
{ 
    trace("oddNumbers[" + i.toString() + "] = " + oddNumbers[i].toString()); 
}

The Array class

The first type of indexed array is the Array class. An Array instance can hold a value of any data type. The same Array object can hold objects that are of different data types. For example, a single Array instance can have a String value in index 0, a Number instance in index 1, and an XML object in index 2.

The Vector class

Another type of indexed array that’s available in ActionScript 3.0 is the Vector class. A Vector instance is a typed array , which means that all the elements in a Vector instance always have the same data type.

Note: The Vector class is available starting with Flash Player 10 and Adobe AIR 1.5.

When you declare a Vector variable or instantiate a Vector object, you explicitly specify the data type of the objects that the Vector can contain. The specified data type is known as the Vector’s base type . At run time and at compile time (in strict mode), any code that sets the value of a Vector element or retrieves a value from a Vector is checked. If the data type of the object being added or retrieved doesn’t match the Vector’s base type, an error occurs.

In addition to the data type restriction, the Vector class has other restrictions that distinguish it from the Array class:

  • A Vector is a dense array. An Array object may have values in indices 0 and 7 even if it has no values in positions 1 through 6. However, a Vector must have a value (or null ) in each index.

  • A Vector can optionally be fixed-length. This means that the number of elements the Vector contains can’t change.

  • Access to a Vector’s elements is bounds-checked. You can never read a value from an index greater than the final element ( length - 1). You can never set a value with an index more than one beyond the current final index. (In other words, you can only set a value at an existing index or at index [length] .)

As a result of its restrictions, a Vector has three primary benefits over an Array instance whose elements are all instances of a single class:

  • Performance: array element access and iteration are much faster when using a Vector instance than when using an Array instance.

  • Type safety: in strict mode the compiler can identify data type errors. Examples of such errors include assigning a value of the incorrect data type to a Vector or expecting the wrong data type when reading a value from a Vector. At run time, data types are also checked when adding data to or reading data from a Vector object. Note, however, that when you use the push() method or unshift() method to add values to a Vector, the arguments’ data types are not checked at compile time. When using those methods the values are still checked at run time.

  • Reliability: runtime range checking (or fixed-length checking) increases reliability significantly over Arrays.

Aside from the additional restrictions and benefits, the Vector class is very much like the Array class. The properties and methods of a Vector object are similar—for the most part identical—to the properties and methods of an Array. In most situations where you would use an Array in which all the elements have the same data type, a Vector instance is preferable.

Creating arrays

You can use several techniques to create an Array instance or a Vector instance. However, the techniques to create each type of array are somewhat different.

Creating an Array instance

You create an Array object by calling the Array() constructor or by using Array literal syntax.

The Array() constructor function can be used in three ways. First, if you call the constructor with no arguments, you get an empty array. You can use the length property of the Array class to verify that the array has no elements. For example, the following code calls the Array() constructor with no arguments:

var names:Array = new Array(); 
trace(names.length); // output: 0

Second, if you use a number as the only parameter to the Array() constructor, an array of that length is created, with each element’s value set to undefined . The argument must be an unsigned integer between the values 0 and 4,294,967,295. For example, the following code calls the Array() constructor with a single numeric argument:

var names:Array = new Array(3); 
trace(names.length); // output: 3 
trace(names[0]); // output: undefined 
trace(names[1]); // output: undefined 
trace(names[2]); // output: undefined

Third, if you call the constructor and pass a list of elements as parameters, an array is created, with elements corresponding to each of the parameters. The following code passes three arguments to the Array() constructor:

var names:Array = new Array("John", "Jane", "David"); 
trace(names.length); // output: 3 
trace(names[0]); // output: John 
trace(names[1]); // output: Jane 
trace(names[2]); // output: David

You can also create arrays with Array literals. An Array literal can be assigned directly to an array variable, as shown in the following example:

var names:Array = ["John", "Jane", "David"];
Creating a Vector instance

You create a Vector instance by calling the Vector.<T>() constructor. You can also create a Vector by calling the Vector.<T>() global function. That function converts a specified object to a Vector instance. In Flash Professional CS5 and later, Flash Builder 4 and later, and Flex 4 and later, you can also create a vector instance by using Vector literal syntax.

Any time you declare a Vector variable (or similarly, a Vector method parameter or method return type) you specify the base type of the Vector variable. You also specify the base type when you create a Vector instance by calling the Vector.<T>() constructor. Put another way, any time you use the term Vector in ActionScript, it is accompanied by a base type.

You specify the Vector’s base type using type parameter syntax. The type parameter immediately follows the word Vector in the code. It consists of a dot ( . ), then the base class name surrounded by angle brackets ( <> ), as shown in this example:

var v:Vector.<String>; 
v = new Vector.<String>();

In the first line of the example, the variable v is declared as a Vector.<String> instance. In other words, it represents an indexed array that can only hold String instances. The second line calls the Vector() constructor to create an instance of the same Vector type (that is, a Vector whose elements are all String objects). It assigns that object to v .

Using the Vector.<T>() constructor

If you use the Vector.<T>() constructor without any arguments, it creates an empty Vector instance. You can test that a Vector is empty by checking its length property. For example, the following code calls the Vector.<T>() constructor with no arguments:

var names:Vector.<String> = new Vector.<String>(); 
trace(names.length); // output: 0

If you know ahead of time how many elements a Vector initially needs, you can pre-define the number of elements in the Vector. To create a Vector with a certain number of elements, pass the number of elements as the first parameter (the length parameter). Because Vector elements can’t be empty, the elements are filled with instances of the base type. If the base type is a reference type that allows null values, the elements all contain null . Otherwise, the elements all contain the default value for the class. For example, a uint variable can’t be null . Consequently, in the following code listing the Vector named ages is created with seven elements, each containing the value 0:

var ages:Vector.<uint> = new Vector.<uint>(7); 
trace(ages); // output: 0,0,0,0,0,0,0 

Finally, using the Vector.<T>() constructor you can also create a fixed-length Vector by passing true for the second parameter (the fixed parameter). In that case the Vector is created with the specified number of elements and the number of elements can’t be changed. Note, however, that you can still change the values of the elements of a fixed-length Vector.

Using the Vector literal syntax constructor

In Flash Professional CS5 and later, Flash Builder 4 and later, and Flex 4 and later, you can pass a list of values to the Vector.<T>() constructor to specify the Vector’s initial values:

// var v:Vector.<T> = new <T>[E0, ..., En-1 ,]; 
// For example: 
var v:Vector.<int> = new <int>[0,1,2,];

The following information applies to this syntax:

  • The trailing comma is optional.

  • Empty items in the array are not supported; a statement such as var v:Vector.<int> = new <int>[0,,2,] throws a compiler error.

  • You can't specify a default length for the Vector instance. Instead, the length is the same as the number of elements in the initialization list.

  • You can't specify whether the Vector instance has a fixed length. Instead, use the fixed property.

  • Data loss or errors can occur if items passed as values don't match the specified type. For example:
    var v:Vector.<int> = new <int>[4.2]; // compiler error when running in strict mode 
    trace(v[0]); //returns 4 when not running in strict mode

Using the Vector.<T>() global function

In addition to the Vector.<T>() and Vector literal syntax constructors, you can also use the Vector.<T>() global function to create a Vector object. The Vector.<T>() global function is a conversion function. When you call the Vector.<T>() global function you specify the base type of the Vector that the method returns. You pass a single indexed array (Array or Vector instance) as an argument. The method then returns a Vector with the specified base type, containing the values in the source array argument. The following code listing shows the syntax for calling the Vector.<T>() global function:

var friends:Vector.<String> = Vector.<String>(["Bob", "Larry", "Sarah"]);

The Vector.<T>() global function performs data type conversion on two levels. First, when an Array instance is passed to the function, a Vector instance is returned. Second, whether the source array is an Array or Vector instance the function attempts to convert the source array’s elements to values of the base type. The conversion uses standard ActionScript data type conversion rules. For example, the following code listing converts the String values in the source Array to integers in the result Vector. The decimal portion of the first value ( "1.5" ) is truncated, and the non-numeric third value ( "Waffles" ) is converted to 0 in the result:

var numbers:Vector.<int> = Vector.<int>(["1.5", "17", "Waffles"]); 
trace(numbers); // output: 1,17,0

If any of the source elements can’t be converted, an error occurs.

When code calls the Vector.<T>() global function, if an element in the source array is an instance of a subclass of the specified base type, the element is added to the result Vector (no error occurs). Using the Vector.<T>() global function is the only way to convert a Vector with base type T to a Vector with a base type that’s a superclass of T .

Inserting array elements

The most basic way to add an element to an indexed array is to use the array access ( [] ) operator. To set the value of an indexed array element, use the Array or Vector object name and index number on the left side of an assignment statement:

songTitles[5] = "Happy Birthday";

If the Array or Vector doesn’t already have an element at that index, the index is created and the value is stored there. If a value exists at that index, the new value replaces the existing one.

An Array object allows you to create an element at any index. However, with a Vector object you can only assign a value to an existing index or to the next available index. The next available index corresponds to the Vector object’s length property. The safest way to add a new element to a Vector object is to use code like this listing:

myVector[myVector.length] = valueToAdd;

Three of the Array and Vector class methods— push() , unshift() , and splice() —allow you to insert elements into an indexed array. The push() method appends one or more elements to the end of an array. In other words, the last element inserted into the array using the push() method will have the highest index number. The unshift() method inserts one or more elements at the beginning of an array, which is always at index number 0. The splice() method will insert any number of items at a specified index in the array.

The following example demonstrates all three methods. An array named planets is created to store the names of the planets in order of proximity to the Sun. First, the push() method is called to add the initial item, Mars . Second, the unshift() method is called to insert the item that belongs at the front of the array, Mercury . Finally, the splice() method is called to insert the items Venus and Earth after Mercury , but before Mars . The first argument sent to splice() , the integer 1, directs the insertion to begin at index 1. The second argument sent to splice() , the integer 0, indicates that no items should be deleted. Finally, the third and fourth arguments sent to splice() , Venus and Earth , are the items to be inserted.

var planets:Array = new Array(); 
planets.push("Mars"); // array contents: Mars 
planets.unshift("Mercury"); // array contents: Mercury,Mars 
planets.splice(1, 0, "Venus", "Earth"); 
trace(planets); // array contents: Mercury,Venus,Earth,Mars

The push() and unshift() methods both return an unsigned integer that represents the length of the modified array. The splice() method returns an empty array when used to insert elements, which may seem strange, but makes more sense in light of the splice() method’s versatility. You can use the splice() method not only to insert elements into an array, but also to remove elements from an array. When used to remove elements, the splice() method returns an array containing the elements removed.

Note: If a Vector object’s fixed property is true , the total number of elements in the Vector can’t change. If you try to add a new element to a fixed-length Vector using the techniques described here, an error occurs.
Retrieving values and removing array elements

The simplest way to retrieve the value of an element from an indexed array is to use the array access ( [] ) operator. To retrieve the value of an indexed array element, use the Array or Vector object name and index number on the right side of an assignment statement:

var myFavoriteSong:String = songTitles[3];

It’s possible to attempt to retrieve a value from an Array or Vector using an index where no element exists. In that case, an Array object returns the value undefined and a Vector throws a RangeError exception.

Three methods of the Array and Vector classes— pop() , shift() , and splice() —allow you to remove elements. The pop() method removes an element from the end of the array. In other words, it removes the element at the highest index number. The shift() method removes an element from the beginning of the array, which means that it always removes the element at index number 0. The splice() method, which can also be used to insert elements, removes an arbitrary number of elements starting at the index number specified by the first argument sent to the method.

The following example uses all three methods to remove elements from an Array instance. An Array named oceans is created to store the names of large bodies of water. Some of the names in the Array are lakes rather than oceans, so they need to be removed.

First, the splice() method is used to remove the items Aral and Superior , and insert the items Atlantic and Indian . The first argument sent to splice() , the integer 2, indicates that the operation should start with the third item in the list, which is at index 2. The second argument, 2, indicates that two items should be removed. The remaining arguments, Atlantic and Indian , are values to be inserted at index 2.

Second, the pop() method is used to remove last element in the array, Huron . And third, the shift() method is used to remove the first item in the array, Victoria .

var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian", "Huron"]; 
oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior 
oceans.pop(); // removes Huron 
oceans.shift(); // removes Victoria 
trace(oceans);// output: Pacific,Arctic,Atlantic,Indian

The pop() and shift() methods both return the item that was removed. For an Array instance, the data type of the return value is Object because arrays can hold values of any data type. For a Vector instance, the data type of the return value is the base type of the Vector. The splice() method returns an Array or Vector containing the values removed. You can change the oceans Array example so that the call to splice() assigns the returned Array to a new Array variable, as shown in the following example:

var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic"); 
trace(lakes); // output: Aral,Superior

You may come across code that uses the delete operator on an Array object element. The delete operator sets the value of an Array element to undefined , but it does not remove the element from the Array. For example, the following code uses the delete operator on the third element in the oceans Array, but the length of the Array remains 5:

var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"]; 
delete oceans[2]; 
trace(oceans);// output: Arctic,Pacific,,Indian,Atlantic 
trace(oceans[2]); // output: undefined 
trace(oceans.length); // output: 5

You can truncate an Array or Vector using an array’s length property. If you set the length property of an indexed array to a length that is less than the current length of the array, the array is truncated, removing any elements stored at index numbers higher than the new value of length minus 1. For example, if the oceans array were sorted such that all valid entries were at the beginning of the array, you could use the length property to remove the entries at the end of the array, as shown in the following code:

var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"]; 
oceans.length = 2; 
trace(oceans); // output: Arctic,Pacific
Note: If a Vector object’s fixed property is true , the total number of elements in the Vector can’t change. If you try to remove an element from or truncate a fixed-length Vector using the techniques described here, an error occurs.
Sorting an array

There are three methods— reverse() , sort() , and sortOn() —that allow you to change the order of an indexed array, either by sorting or reversing the order. All of these methods modify the existing array. The following table summarizes these methods and their behavior for Array and Vector objects:

Method

Array behavior

Vector behavior

reverse()

Changes the order of the elements so that the last element becomes the first element, the penultimate element becomes the second, and so on

Identical to Array behavior

sort()

Allows you to sort the Array’s elements in a variety of predefined ways, such as alphabetical or numeric order. You can also specify a custom sorting algorithm.

Sorts the elements according to the custom sorting algorithm that you specify

sortOn()

Allows you to sort objects that have one or more common properties, specifying the property or properties to use as the sort keys

Not available in the Vector class

The reverse() method

The reverse() method takes no parameters and does not return a value, but allows you to toggle the order of your array from its current state to the reverse order. The following example reverses the order of the oceans listed in the oceans array:

var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"]; 
oceans.reverse(); 
trace(oceans); // output: Pacific,Indian,Atlantic,Arctic

Basic sorting with the sort() method (Array class only)

For an Array instance, the sort() method rearranges the elements in an array using the default sort order . The default sort order has the following characteristics:

  • The sort is case-sensitive, which means that uppercase characters precede lowercase characters. For example, the letter D precedes the letter b.

  • The sort is ascending, which means that lower character codes (such as A) precede higher character codes (such as B).

  • The sort places identical values adjacent to each other but in no particular order.

  • The sort is string-based, which means that elements are converted to strings before they are compared (for example, 10 precedes 3 because the string "1" has a lower character code than the string "3" has).

You may find that you need to sort your Array without regard to case, or in descending order, or perhaps your array contains numbers that you want to sort numerically instead of alphabetically. The Array class’s sort() method has an options parameter that allows you to alter each characteristic of the default sort order. The options are defined by a set of static constants in the Array class, as shown in the following list:

  • Array.CASEINSENSITIVE : This option makes the sort disregard case. For example, the lowercase letter b precedes the uppercase letter D.

  • Array.DESCENDING: This reverses the default ascending sort. For example, the letter B precedes the letter A.

  • Array.UNIQUESORT: This causes the sort to abort if two identical values are found.

  • Array.NUMERIC: This causes numerical sorting, so that 3 precedes 10.

The following example highlights some of these options. An Array named poets is created that is sorted using several different options.

var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; 
poets.sort(); // default sort 
trace(poets); // output: Angelou,Blake,Dante,cummings 
 
poets.sort(Array.CASEINSENSITIVE); 
trace(poets); // output: Angelou,Blake,cummings,Dante 
 
poets.sort(Array.DESCENDING); 
trace(poets); // output: cummings,Dante,Blake,Angelou 
 
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options 
trace(poets); // output: Dante,cummings,Blake,Angelou

Custom sorting with the sort() method (Array and Vector classes)

In addition to the basic sorting that’s available for an Array object, you can also define a custom sorting rule. This technique is the only form of the sort() method that is available for the Vector class. To define a custom sort, you write a custom sort function and pass it as an argument to the sort() method.

For example, if you have a list of names in which each list element contains a person’s full name, but you want to sort the list by last name, you must use a custom sort function to parse each element and use the last name in the sort function. The following code shows how this can be done with a custom function that is used as a parameter to the Array.sort() method:

var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones"); 
function orderLastName(a, b):int 
{ 
    var lastName:RegExp = /\b\S+$/; 
    var name1 = a.match(lastName); 
    var name2 = b.match(lastName); 
    if (name1 < name2) 
    { 
        return -1; 
    } 
    else if (name1 > name2) 
    { 
        return 1; 
    } 
    else 
    { 
        return 0; 
    } 
} 
trace(names); // output: John Q. Smith,Jane Doe,Mike Jones 
names.sort(orderLastName); 
trace(names); // output: Jane Doe,Mike Jones,John Q. Smith

The custom sort function orderLastName() uses a regular expression to extract the last name from each element to use for the comparison operation. The function identifier orderLastName is used as the sole parameter when calling the sort() method on the names array. The sort function accepts two parameters, a and b , because it works on two array elements at a time. The sort function’s return value indicates how the elements should be sorted:

  • A return value of -1 indicates that the first parameter, a , precedes the second parameter, b .

  • A return value of 1 indicates that the second parameter, b , precedes the first, a .

  • A return value of 0 indicates that the elements have equal sorting precedence.

The sortOn() method (Array class only)

The sortOn() method is designed for Array objects with elements that contain objects. These objects are expected to have at least one common property that can be used as the sort key. The use of the sortOn() method for arrays of any other type yields unexpected results.

Note: The Vector class does not include a sortOn() method. This method is only available for Array objects.

The following example revises the poets Array so that each element is an object instead of a string. Each object holds both the poet’s last name and year of birth.

var poets:Array = new Array(); 
poets.push({name:"Angelou", born:"1928"}); 
poets.push({name:"Blake", born:"1757"}); 
poets.push({name:"cummings", born:"1894"}); 
poets.push({name:"Dante", born:"1265"}); 
poets.push({name:"Wang", born:"701"});

You can use the sortOn() method to sort the Array by the born property. The sortOn() method defines two parameters, fieldName and options . The fieldName argument must be specified as a string. In the following example, sortOn() is called with two arguments, " born" and Array.NUMERIC . The Array.NUMERIC argument is used to ensure that the sort is done numerically instead of alphabetically. This is a good practice even when all the numbers have the same number of digits because it ensures that the sort will continue to behave as expected if a number with fewer or more digits is later added to the array.

poets.sortOn("born", Array.NUMERIC); 
for (var i:int = 0; i < poets.length; ++i) 
{ 
    trace(poets[i].name, poets[i].born); 
} 
/* output: 
Wang 701 
Dante 1265 
Blake 1757 
cummings 1894 
Angelou 1928 
*/

Sorting without modifying the original array (Array class only)

Generally, the sort() and sortOn() methods modify an Array. If you wish to sort an Array without modifying the existing array, pass the Array.RETURNINDEXEDARRAY constant as part of the options parameter. This option directs the methods to return a new Array that reflects the sort and to leave the original Array unmodified. The Array returned by the methods is a simple Array of index numbers that reflects the new sort order and does not contain any elements from the original Array. For example, to sort the poets Array by birth year without modifying the Array, include the Array.RETURNINDEXEDARRAY constant as part of the argument passed for the options parameter.

The following example stores the returned index information in an Array named indices and uses the indices array in conjunction with the unmodified poets array to output the poets in order of birth year:

var indices:Array; 
indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY); 
for (var i:int = 0; i < indices.length; ++i) 
{ 
    var index:int = indices[i]; 
    trace(poets[index].name, poets[index].born); 
} 
/* output: 
Wang 701 
Dante 1265 
Blake 1757 
cummings 1894 
Angelou 1928 
*/
Querying an array

Four methods of the Array and Vector classes— concat() , join() , slice() , and toString() —all query the array for information, but do not modify the array. The concat() and slice() methods both return new arrays, while the join() and toString() methods both return strings. The concat() method takes a new array or list of elements as arguments and combines it with the existing array to create a new array. The slice() method has two parameters, aptly named startIndex and an endIndex , and returns a new array containing a copy of the elements “sliced” from the existing array. The slice begins with the element at startIndex and ends with the element just before endIndex . That bears repeating: the element at endIndex is not included in the return value.

The following example uses concat() and slice() to create new arrays using elements of other arrays:

var array1:Array = ["alpha", "beta"]; 
var array2:Array = array1.concat("gamma", "delta"); 
trace(array2); // output: alpha,beta,gamma,delta 
 
var array3:Array = array1.concat(array2); 
trace(array3); // output: alpha,beta,alpha,beta,gamma,delta 
 
var array4:Array = array3.slice(2,5); 
trace(array4); // output: alpha,beta,gamma

You can use the join() and toString() methods to query the array and return its contents as a string. If no parameters are used for the join() method, the two methods behave identically—they return a string containing a comma-delimited list of all elements in the array. The join() method, unlike the toString() method, accepts a parameter named delimiter , which allows you to choose the symbol to use as a separator between each element in the returned string.

The following example creates an Array called rivers and calls both join() and toString() to return the values in the Array as a string. The toString() method is used to return comma-separated values ( riverCSV ), while the join() method is used to return values separated by the + character.

var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"]; 
var riverCSV:String = rivers.toString(); 
trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi 
var riverPSV:String = rivers.join("+"); 
trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi

One issue to be aware of with the join() method is that any nested Array or Vector instances are always returned with comma-separated values, no matter what separator you specify for the main array elements, as the following example shows:

var nested:Array = ["b","c","d"]; 
var letters:Array = ["a",nested,"e"];  
var joined:String = letters.join("+"); 
trace(joined); // output: a+b,c,d+e

Events

Working with objects

ActionScript is what’s known as an object-oriented programming language. Object-oriented programming is simply an approach to programming. It’s really nothing more than a way to organize the code in a program, using objects.

Earlier the term “computer program” was defined as a series of steps or instructions that the computer performs. Conceptually, then, you can imagine a computer program as just a single long list of instructions. However, in object-oriented programming, the program instructions are divided among different objects. The code is grouped into chunks of functionality, so related types of functionality or related pieces of information are grouped in one container.

Adobe Flash Professional

If you’ve worked with symbols in Flash Professional, you’re already used to working with objects. Imagine you’ve defined a movie clip symbol such as a drawing of a rectangle and you’ve placed a copy of it on the Stage. That movie clip symbol is also (literally) an object in ActionScript; it’s an instance of the MovieClip class.

There are various characteristics of the movie clip that you can modify. When it’s selected you can change values in the Property inspector like its x coordinate or its width. You can also make various color adjustments like changing its alpha (transparency) or applying a drop-shadow filter to it. Other Flash Professional tools let you make more changes, like using the Free Transform tool to rotate the rectangle. All of these ways that you can modify a movie clip symbol in Flash Professional are also available in ActionScript. You modify the movie clip in ActionScript by changing the pieces of data that are all put together into a single bundle called a MovieClip object.

In ActionScript object-oriented programming, there are three types of characteristics that any class can include:

  • Properties

  • Methods

  • Events

These elements are used to manage the pieces of data used by the program and to decide what actions are carried out and in what order.

Properties

A property represents one of the pieces of data that are bundled together in an object. An example song object can have properties named artist and title ; the MovieClip class has properties like rotation , x , width , and alpha . You work with properties like individual variables. In fact, you can think of properties as simply the “child” variables contained in an object.

Here are some examples of ActionScript code that uses properties. This line of code moves the MovieClip named square to the x coordinate 100 pixels:

square.x = 100;

This code uses the rotation property to make the square MovieClip rotate to match the rotation of the triangle MovieClip:

square.rotation = triangle.rotation;

This code alters the horizontal scale of the square MovieClip making it one-and-a-half times wider than it used to be:

square.scaleX = 1.5;

Notice the common structure: you use a variable ( square , triangle ) as the name of the object, followed by a period ( . ) and then the name of the property ( x , rotation , scaleX ). The period, known as the dot operator , is used to indicate that you’re accessing one of the child elements of an object. The whole structure together, “variable name-dot-property name,” is used like a single variable, as a name for a single value in the computer’s memory.

Methods

A method is an action that an object can perform. For example, suppose you’ve made a movie clip symbol in Flash Professional with several keyframes and animation on its timeline. That movie clip can play, or stop, or be instructed to move the playhead to a particular frame.

This code instructs the MovieClip named shortFilm to start playing:

shortFilm.play();

This line makes the MovieClip named shortFilm stop playing (the playhead stops in place, like pausing a video):

shortFilm.stop();

This code makes a MovieClip named shortFilm move its playhead to Frame 1 and stop playing (like rewinding a video):

shortFilm.gotoAndStop(1);

Methods, like properties, are accessed by writing the object’s name (a variable), then a period, and then the name of the method followed by parentheses. The parentheses are the way that you indicate that you are calling the method, or in other words, instructing the object to perform that action. Sometimes values (or variables) are placed in the parentheses, as a way to pass along additional information that is necessary to carry out the action. These values are known as method parameters . For example, the gotoAndStop() method needs information about which frame to go to, so it requires a single parameter in the parentheses. Other methods, like play() and stop() , are self-explanatory, so they don’t require extra information. Nevertheless, they are still written with parentheses.

Unlike properties (and variables), methods aren’t used as value placeholders. However, some methods can perform calculations and return a result that can be used like a variable. For example, the Number class’s toString() method converts the numeric value to its text representation:

var numericData:Number = 9; 
var textData:String = numericData.toString();

For example, you would use the toString() method if you wanted to display the value of a Number variable in a text field on the screen. The TextField class’s text property is defined as a String, so it can contain only text values. (The text property represents the actual text content displayed on the screen). This line of code converts the numeric value in the variable numericData to text. It then makes the value show up on the screen in the TextField object named calculatorDisplay :

calculatorDisplay.text = numericData.toString();

Events

A computer program is a series of instructions that the computer carries out step-by-step. Some simple computer programs consist of nothing more than a few steps that the computer performs, at which point the program ends. However, ActionScript programs are designed to keep running, waiting for user input or other things to happen. Events are the mechanism that determines which instructions the computer carries out and when.

In essence, events are things that happen that ActionScript is aware of and can respond to. Many events are related to user interaction, such as a user clicking a button or pressing a key on the keyboard. There are also other types of events. For example, if you use ActionScript to load an external image, there is an event that can let you know when the image has finished loading. When an ActionScript program is running, conceptually it just sits and waits for certain things to happen. When those things happen, the specific ActionScript code that you’ve specified for those events runs.

Basic event handling

The technique for specifying certain actions to perform in response to particular events is known as event handling . When you are writing ActionScript code to perform event handling, there are three important elements you’ll want to identify:

  • The event source: Which object is the one the event is going to happen to? For example, which button was clicked, or which Loader object is loading the image? The event source is also known as the event target . It has this name because it’s the object where the computer targets the event (that is, where the event actually happens).

  • The event: What is the thing that is going to happen, the thing that you want to respond to? The specific event is important to identify, because many objects trigger several events.

  • The response: What steps do you want performed when the event happens?

Any time you write ActionScript code to handle events, it requires these three elements. The code follows this basic structure (elements in bold are placeholders you’d fill in for your specific case):

function eventResponse(eventObject:EventType):void 
{ 
    // Actions performed in response to the event go here. 
} 
  
eventSource.addEventListener(EventType.EVENT_NAME, eventResponse);

This code does two things. First, it defines a function, which is the way to specify the actions you want performed in response to the event. Next, it calls the addEventListener() method of the source object. Calling addEventListener() essentially “subscribes” the function to the specified event. When the event happens, the function’s actions are carried out. Consider each of these parts in more detail.

A function provides a way for you to group actions with a single name that is like a shortcut name to carry out the actions. A function is identical to a method except that it isn’t necessarily associated with a specific class. (In fact, the term “method” could be defined as a function that is associated with a particular class.) When you're creating a function for event handling, you choose the name for the function (named eventResponse in this case). You also specify one parameter (named eventObject in this example). Specifying a function parameter is like declaring a variable, so you also have to indicate the data type of the parameter. (In this example, the parameter's data type is EventType .)

Each type of event that you want to listen to has an ActionScript class associated with it. The data type you specify for the function parameter is always the associated class of the specific event you want to respond to. For example, a click event (triggered when the user clicks an item with the mouse) is associated with the MouseEvent class. To write a listener function for a click event, you define the listener function with a parameter with the data type MouseEvent. Finally, between the opening and closing curly brackets ( { ... } ), you write the instructions you want the computer to carry out when the event happens.

The event-handling function is written. Next you tell the event source object (the object that the event happens to, for example the button) that you want it to call your function when the event happens. You register your function with the event source object by calling the addEventListener() method of that object (all objects that have events also have an addEventListener() method). The addEventListener() method takes two parameters:

  • First, the name of the specific event you want to respond to. Each event is affiliated with a specific class. Every event class has a special value, which is like a unique name, defined for each of its events. You use that value for the first parameter.

  • Second, the name of your event response function. Note that a function name is written without parentheses when it’s passed as a parameter.

The event-handling process

The following is a step-by-step description of the process that happens when you create an event listener. In this case, it’s an example of creating a listener function that is called when an object named myButton is clicked.

The actual code written by the programmer is as follows:

function eventResponse(event:MouseEvent):void 
{ 
    // Actions performed in response to the event go here. 
} 
 
myButton.addEventListener(MouseEvent.CLICK, eventResponse);

Here is how this code would actually work when it’s running:

  1. When the SWF file loads, the computer makes note of the fact that there’s a function named eventResponse() .

  2. The computer then runs the code (specifically, the lines of code that aren’t in a function). In this case that’s only one line of code: calling the addEventListener() method on the event source object (named myButton ) and passing the eventResponse function as a parameter.

    Internally, myButton keeps a list of functions that are listening to each of its events. When its addEventListener() method is called, myButton stores the eventResponse() function in its list of event listeners.

  3. At some point, the user clicks the myButton object, triggering its click event (identified as MouseEvent.CLICK in the code).

    At that point, the following occurs:

    1. An object is created that’s an instance of the class associated with the event in question (MouseEvent in this example). For many events, this object is an instance of the Event class. For mouse events, it is a MouseEvent instance. For other events, it is an instance of the class that’s associated with that event. This object that’s created is known as the event object , and it contains specific information about the event that happened: what type of event it is, where it happened, and other event-specific information if applicable.

    2. The computer then looks at the list of event listeners stored by myButton . It goes through these functions one by one, calling each function and passing the event object to the function as a parameter. Since the eventResponse() function is one of myButton ’s listeners, as part of this process the computer calls the eventResponse() function.

    3. When the eventResponse() function is called, the code in that function runs, so your specified actions are carried out.

Event-handling examples

Here are a few more concrete examples of event handling code. These examples are meant to give you an idea of some of the common event elements and possible variations available when you write event-handling code:

  • Clicking a button to start the current movie clip playing. In the following example, playButton is the instance name of the button, and this is a special name meaning “the current object”:

    this.stop(); 
     
    function playMovie(event:MouseEvent):void 
    { 
        this.play(); 
    } 
     
    playButton.addEventListener(MouseEvent.CLICK, playMovie);
  • Detecting typing in a text field. In this example, entryText is an input text field, and outputText is a dynamic text field:

    function updateOutput(event:TextEvent):void 
    { 
        var pressedKey:String = event.text; 
        outputText.text = "You typed: " + pressedKey; 
    } 
     
    entryText.addEventListener(TextEvent.TEXT_INPUT, updateOutput);
  • Clicking a button to navigate to a URL. In this case, linkButton is the instance name of the button:

    function gotoAdobeSite(event:MouseEvent):void 
    { 
        var adobeURL:URLRequest = new URLRequest("http://www.adobe.com/"); 
        navigateToURL(adobeURL); 
    } 
     
    linkButton.addEventListener(MouseEvent.CLICK, gotoAdobeSite);

Creating object instances

Before you can use an object in ActionScript, the object has to exist in the first place. One part of creating an object is declaring a variable; however, declaring a variable only creates an empty place in the computer’s memory. Always assign an actual value to the variable (create an object and store it in the variable) before you attempt to use or manipulate it. The process of creating an object is known as instantiating the object. In other words, you create an instance of a particular class.

One simple way to create an object instance doesn’t involve ActionScript at all. In Flash Professional place a movie clip symbol, button symbol, or text field on the Stage and assign it an instance name. Flash Professional automatically declares a variable with that instance name, creates an object instance, and stores that object in the variable. Similarly, in Flex you create a component in MXML either by coding an MXML tag or by placing the component on the editor in Flash Builder Design mode. When you assign an ID to that component, that ID becomes the name of an ActionScript variable containing that component instance.

However, you don’t always want to create an object visually, and for non-visual objects you can’t. There are several additional ways you can create object instances using only ActionScript.

With several ActionScript data types, you can create an instance using a literal expression , which is a value written directly into the ActionScript code. Here are some examples:

  • Literal numeric value (enter the number directly):

    var someNumber:Number = 17.239; 
    var someNegativeInteger:int = -53; 
    var someUint:uint = 22;
  • Literal String value (surround the text with double quotation marks):

    var firstName:String = "George"; 
    var soliloquy:String = "To be or not to be, that is the question...";
  • Literal Boolean value (use the literal values true or false ):

    var niceWeather:Boolean = true; 
    var playingOutside:Boolean = false;
  • Literal Array value (wrap a comma-separated list of values in square brackets):

    var seasons:Array = ["spring", "summer", "autumn", "winter"];
  • Literal XML value (enter the XML directly):

    var employee:XML = <employee> 
            <firstName>Harold</firstName> 
            <lastName>Webster</lastName> 
        </employee>;

ActionScript also defines literal expressions for the Array, RegExp, Object, and Function data types.

The most common way to create an instance for any data type is to use the new operator with the class name, as shown here:

var raceCar:MovieClip = new MovieClip(); 
var birthday:Date = new Date(2006, 7, 9);

Creating an object using the new operator is often described as “calling the class’s constructor.” A constructor is a special method that is called as part of the process of creating an instance of a class. Notice that when you create an instance in this way, you put parentheses after the class name. Sometimes you specify parameter values in the parentheses. These are two things that you also do when calling a method.

Even for those data types that let you create instances using a literal expression, you can also use the new operator to create an object instance. For example, these two lines of code do the same thing:

var someNumber:Number = 6.33; 
var someNumber:Number = new Number(6.33);

It’s important to be familiar with the new ClassName () way of creating objects. Many ActionScript data types don’t have a visual representation. Consequently, they can’t be created by placing an item on the Flash Professional Stage or the Design mode of Flash Builder’s MXML editor. You can only create an instance of any of those data types in ActionScript using the new operator.

Adobe Flash Professional

In Flash Professional, the new operator can also be used to create an instance of a movie clip symbol that is defined in the Library but isn’t placed on the Stage.

Handling events

An event-handling system allows programmers to respond to user input and system events in a convenient way. The ActionScript 3.0 event model is not only convenient, but also standards-compliant, and well integrated with the display list. Based on the Document Object Model (DOM) Level 3 Events Specification, an industry-standard event-handling architecture, the new event model provides a powerful yet intuitive event-handling tool for ActionScript programmers.

The ActionScript 3.0 event-handling system interacts closely with the display list. To gain a basic understanding of the display list, read Display programming.

Basics of handling events

You can think of events as occurrences of any kind in your SWF file that are of interest to you as a programmer. For example, most SWF files support user interaction of some sort—whether it's something as simple as responding to a mouse click or something more complex, such as accepting and processing data entered into a form. Any such user interaction with your SWF file is considered an event. Events can also occur without any direct user interaction, such as when data has finished loading from a server or when an attached camera has become active.

In ActionScript 3.0, each event is represented by an event object, which is an instance of the Event class or one of its subclasses. An event object not only stores information about a specific event, but also contains methods that facilitate manipulation of the event object. For example, when Flash Player or AIR detects a mouse click, it creates an event object (an instance of the MouseEvent class) to represent that particular mouse click event.

After creating an event object, Flash Player or AIR dispatches it, which means that the event object is passed to the object that is the target of the event. An object that serves as the destination for a dispatched event object is called an event target . For example, when an attached camera becomes active, Flash Player dispatches an event object directly to the event target, which in this case is the object that represents the camera. If the event target is on the display list, however, the event object is passed down through the display list hierarchy until it reaches the event target. In some cases, the event object then “bubbles” back up the display list hierarchy along the same route. This traversal of the display list hierarchy is called the event flow .

You can “listen” for event objects in your code using event listeners. Event listeners are the functions or methods that you write to respond to specific events. To ensure that your program responds to events, you must add event listeners either to the event target or to any display list object that is part of an event object’s event flow.

Any time you write event listener code, it follows this basic structure (elements in bold are placeholders you’d fill in for your specific case):

function eventResponse(eventObject:EventType):void 
{ 
    // Actions performed in response to the event go here. 
} 
 
eventTarget.addEventListener(EventType.EVENT_NAME, eventResponse);

This code does two things. First, it defines a function, which is the way to specify the actions that will be performed in response to the event. Next, it calls the addEventListener() method of the source object, in essence “subscribing” the function to the specified event so that when the event happens, the function’s actions are carried out. When the event actually happens, the event target checks its list of all the functions and methods that are registered as event listeners. It then calls each one in turn, passing the event object as a parameter.

You need to alter four things in this code to create your own event listener. First, you must change the name of the function to the name you want to use (this must be changed in two places, where the code says eventResponse ). Second, you must specify the appropriate class name of the event object that is dispatched by the event you want to listen for ( EventType in the code), and you must specify the appropriate constant for the specific event ( EVENT_NAME in the listing). Third, you must call the addEventListener() method on the object that will dispatch the event ( eventTarget in this code). Optionally, you can change the name of the variable used as the function’s parameter ( eventObject in this code).

Important concepts and terms

The following reference list contains important terms that you will encounter when writing event-handling routines:

Bubbling
Bubbling occurs for some events so that a parent display object can respond to events dispatched by its children.

Bubbling phase
The part of the event flow in which an event propagates up to parent display objects. The bubbling phase occurs after the capture and target phases.

Capture phase
The part of the event flow in which an event propagates down from the most general target to the most specific target object. The capture phase occurs before the target and bubbling phases.

Default behavior
Some events include a behavior that normally happens along with the event, known as the default behavior. For example, when a user types text in a text field, a text input event is raised. The default behavior for that event is to actually display the character that was typed into the text field—but you can override that default behavior (if for some reason you don’t want the typed character to be displayed).

Dispatch
To notify event listeners that an event has occurred.

Event
Something that happens to an object that the object can tell other objects about.

Event flow
When events happen to an object on the display list (an object displayed on the screen), all the objects that contain the object are notified of the event and notify their event listeners in turn. This process starts with the Stage and proceeds through the display list to the actual object where the event occurred, and then proceeds back to the Stage again. This process is known as the event flow.

Event object
An object that contains information about a particular event’s occurrence, which is sent to all listeners when an event is dispatched.

Event target
The object that actually dispatches an event. For example, if the user clicks a button that is inside a Sprite that is in turn inside the Stage, all those objects dispatch events, but the event target is the one where the event actually happened—in this case, the clicked button.

Listener
An object or function that has registered itself with an object, to indicate that it should be notified when a specific event takes place.

Target phase
The point of the event flow at which an event has reached the most specific possible target. The target phase occurs between the capture and the bubbling phases.

The event flow

Flash Player or AIR dispatches event objects whenever an event occurs. If the event target is not on the display list, Flash Player or AIR dispatches the event object directly to the event target. For example, Flash Player dispatches the progress event object directly to a URLStream object. If the event target is on the display list, however, Flash Player dispatches the event object into the display list, and the event object travels through the display list to the event target.

The event flow describes how an event object moves through the display list. The display list is organized in a hierarchy that can be described as a tree. At the top of the display list hierarchy is the Stage, which is a special display object container that serves as the root of the display list. The Stage is represented by the flash.display.Stage class and can only be accessed through a display object. Every display object has a property named stage that refers to the Stage for that application.

When Flash Player or AIR dispatches an event object for a display list-related event, that event object makes a round-trip journey from the Stage to the target node . The DOM Events Specification defines the target node as the node representing the event target. In other words, the target node is the display list object where the event occurred. For example, if a user clicks on a display list object named child1 , Flash Player or AIR will dispatch an event object using child1 as the target node.

The event flow is conceptually divided into three parts. The first part is called the capture phase; this phase comprises all of the nodes from the Stage to the parent of the target node. The second part is called the target phase, which consists solely of the target node. The third part is called the bubbling phase. The bubbling phase comprises the nodes encountered on the return trip from the parent of the target node back to the Stage.

The names of the phases make more sense if you conceive of the display list as a vertical hierarchy with the Stage at the top, as shown in the following diagram:

If a user clicks on Child1 Node , Flash Player or AIR dispatches an event object into the event flow. As the following image shows, the object’s journey starts at Stage , moves down to Parent Node , then moves to Child1 Node, and then “bubbles” back up to Stage , moving through Parent Node again on its journey back to Stage .

In this example, the capture phase comprises Stage and Parent Node during the initial downward journey. The target phase comprises the time spent at Child1 Node . The bubbling phase comprises Parent Node and Stage as they are encountered during the upward journey back to the root node.

The event flow contributes to a more powerful event-handling system than that previously available to ActionScript programmers. In previous versions of ActionScript, the event flow does not exist, which means that event listeners can be added only to the object that generates the event. In ActionScript 3.0, you can add event listeners not only to a target node, but also to any node along the event flow.

The ability to add event listeners along the event flow is useful when a user interface component comprises more than one object. For example, a button object often contains a text object that serves as the button’s label. Without the ability to add a listener to the event flow, you would have to add a listener to both the button object and the text object to ensure that you receive notification about click events that occur anywhere on the button. The existence of the event flow, however, allows you to place a single event listener on the button object that handles click events that occur either on the text object or on the areas of the button object that are not obscured by the text object.

Not every event object, however, participates in all three phases of the event flow. Some types of events, such as the enterFrame and init event types, are dispatched directly to the target node and participate in neither the capture phase nor the bubbling phase. Other events may target objects that are not on the display list, such as events dispatched to an instance of the Socket class. These event objects will also flow directly to the target object, without participating in the capture and bubbling phases.

To find out how a particular event type behaves, you can either check the API documentation or examine the event object's properties. Examining the event object’s properties is described in the following section.

Event objects

Event objects serve two main purposes in the new event-handling system. First, event objects represent actual events by storing information about specific events in a set of properties. Second, event objects contain a set of methods that allow you to manipulate event objects and affect the behavior of the event-handling system.

To facilitate access to these properties and methods, the Flash Player API defines an Event class that serves as the base class for all event objects. The Event class defines a fundamental set of properties and methods that are common to all event objects.

This section begins with a discussion of the Event class properties, continues with a description of the Event class methods, and concludes with an explanation of why subclasses of the Event class exist.

Understanding Event class properties

The Event class defines a number of read-only properties and constants that provide important information about an event object.The following are especially important:

  • Event object types are represented by constants and stored in the Event.type property.

  • Whether an event’s default behavior can be prevented is represented by a Boolean value and stored in the Event.cancelable property.

  • Event flow information is contained in the remaining properties.

Event object types

Every event object has an associated event type. Event types are stored in the Event.type property as string values. It is useful to know the type of an event object so that your code can distinguish objects of different types from one another. For example, the following code specifies that the clickHandler() listener function should respond to any mouse click event objects that are passed to myDisplayObject :

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);

Some two dozen event types are associated with the Event class itself and are represented by Event class constants, some of which are shown in the following excerpt from the Event class definition:

package flash.events 
{ 
    public class Event 
    { 
        // class constants 
        public static const ACTIVATE:String = "activate"; 
        public static const ADDED:String= "added"; 
        // remaining constants omitted for brevity 
    } 
}

These constants provide an easy way to refer to specific event types. You should use these constants instead of the strings they represent. If you misspell a constant name in your code, the compiler will catch the mistake, but if you instead use strings, a typographical error may not manifest at compile time and could lead to unexpected behavior that could be difficult to debug. For example, when adding an event listener, use the following code:

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);

rather than:

myDisplayObject.addEventListener("click", clickHandler);

Default behavior information

Your code can check whether the default behavior for any given event object can be prevented by accessing the cancelable property. The cancelable property holds a Boolean value that indicates whether or not a default behavior can be prevented. You can prevent, or cancel, the default behavior associated with a small number of events using the preventDefault() method. For more information, see Cancelling default event behavior under Understanding Event class methods.

Event flow information

The remaining Event class properties contain important information about an event object and its relationship to the event flow, as described in the following list:

  • The bubbles property contains information about the parts of the event flow in which the event object participates.

  • The eventPhase property indicates the current phase in the event flow.

  • The target property stores a reference to the event target.

  • The currentTarget property stores a reference to the display list object that is currently processing the event object.

The bubbles property

An event is said to bubble if its event object participates in the bubbling phase of the event flow, which means that the event object is passed from the target node back through its ancestors until it reaches the Stage. The Event.bubbles property stores a Boolean value that indicates whether the event object participates in the bubbling phase. Because all events that bubble also participate in the capture and target phases, any event that bubbles participates in all three of the event flow phases. If the value is true , the event object participates in all three phases. If the value is false , the event object does not participate in the bubbling phase.

The eventPhase property

You can determine the event phase for any event object by investigating its eventPhase property. The eventPhase property contains an unsigned integer value that represents one of the three phases of the event flow. The Flash Player API defines a separate EventPhase class that contains three constants that correspond to the three unsigned integer values, as shown in the following code excerpt:

package flash.events 
{ 
    public final class EventPhase 
    { 
        public static const CAPTURING_PHASE:uint = 1; 
        public static const AT_TARGET:uint = 2; 
        public static const BUBBLING_PHASE:uint= 3; 
    } 
}

These constants correspond to the three valid values of the eventPhase property. You can use these constants to make your code more readable. For example, if you want to ensure that a function named myFunc() is called only if the event target is in the target stage, you can use the following code to test for this condition:

if (event.eventPhase == EventPhase.AT_TARGET) 
{ 
    myFunc(); 
}

The target property

The target property holds a reference to the object that is the target of the event. In some cases, this is straightforward, such as when a microphone becomes active, the target of the event object is the Microphone object. If the target is on the display list, however, the display list hierarchy must be taken into account. For example, if a user inputs a mouse click on a point that includes overlapping display list objects, Flash Player and AIR always choose the object that is farthest away from the Stage as the event target.

For complex SWF files, especially those in which buttons are routinely decorated with smaller child objects, the target property may not be used frequently because it will often point to a button’s child object instead of the button. In these situations, the common practice is to add event listeners to the button and use the currentTarget property because it points to the button, whereas the target property may point to a child of the button.

The currentTarget property

The currentTarget property contains a reference to the object that is currently processing the event object. Although it may seem odd not to know which node is currently processing the event object that you are examining, keep in mind that you can add a listener function to any display object in that event object's event flow, and the listener function can be placed in any location. Moreover, the same listener function can be added to different display objects. As a project increases in size and complexity, the currentTarget property becomes more and more useful.

Understanding Event class methods

There are three categories of Event class methods:

  • Utility methods, which can create copies of an event object or convert it to a string

  • Event flow methods, which remove event objects from the event flow

  • Default behavior methods, which prevent default behavior or check whether it has been prevented

Event class utility methods

There are two utility methods in the Event class. The clone() method allows you to create copies of an event object. The toString() method allows you to generate a string representation of the properties of an event object along with their values. Both of these methods are used internally by the event model system, but are exposed to developers for general use.

For advanced developers creating subclasses of the Event class, you must override and implement versions of both utility methods to ensure that the event subclass will work properly.

Stopping event flow

You can call either the Event.stopPropagation() method or the Event.stopImmediatePropagation() method to prevent an event object from continuing on its way through the event flow. The two methods are nearly identical and differ only in whether the current node’s other event listeners are allowed to execute:

  • The Event.stopPropagation() method prevents the event object from moving on to the next node, but only after any other event listeners on the current node are allowed to execute.

  • The Event.stopImmediatePropagation() method also prevents the event object from moving on to the next node, but does not allow any other event listeners on the current node to execute.

Calling either of these methods has no effect on whether the default behavior associated with an event occurs. Use the default behavior methods of the Event class to prevent default behavior.

Cancelling default event behavior

The two methods that pertain to cancelling default behavior are the preventDefault() method and the isDefaultPrevented() method. Call the preventDefault() method to cancel the default behavior associated with an event. To check whether preventDefault() has already been called on an event object, call the isDefaultPrevented() method, which returns a value of true if the method has already been called and false otherwise.

The preventDefault() method will work only if the event’s default behavior can be cancelled. You can check whether this is the case by referring to the API documentation for that event type, or by using ActionScript to examine the cancelable property of the event object.

Cancelling the default behavior has no effect on the progress of an event object through the event flow. Use the event flow methods of the Event class to remove an event object from the event flow.

Subclasses of the Event class

For many events, the common set of properties defined in the Event class is sufficient. Other events, however, have unique characteristics that cannot be captured by the properties available in the Event class. For these events, ActionScript 3.0 defines several subclasses of the Event class.

Each subclass provides additional properties and event types that are unique to that category of events. For example, events related to mouse input have several unique characteristics that cannot be captured by the properties defined in the Event class. The MouseEvent class extends the Event class by adding ten properties that contain information such as the location of the mouse event and whether specific keys were pressed during the mouse event.

An Event subclass also contains constants that represent the event types that are associated with the subclass. For example, the MouseEvent class defines constants for several mouse event types, include the click , doubleClick , mouseDown , and mouseUp event types.

As described in the section on Event class utility methods under Event objects, when creating an Event subclass you must override the clone() and toString() methods to provide functionality specific to the subclass.

Event listeners

Event listeners, which are also called event handlers, are functions that Flash Player and AIR execute in response to specific events. Adding an event listener is a two-step process. First, you create a function or class method for Flash Player or AIR to execute in response to the event. This is sometimes called the listener function or the event handler function. Second, you use the addEventListener() method to register your listener function with the target of the event or any display list object that lies along the appropriate event flow.

Creating a listener function

The creation of listener functions is one area where the ActionScript 3.0 event model deviates from the DOM event model. In the DOM event model, there is a clear distinction between an event listener and a listener function: an event listener is an instance of a class that implements the EventListener interface, whereas a listener function is a method of that class named handleEvent() . In the DOM event model, you register the class instance that contains the listener function rather than the actual listener function.

In the ActionScript 3.0 event model, there is no distinction between an event listener and a listener function. ActionScript 3.0 does not have an EventListener interface, and listener functions can be defined outside a class or as part of a class. Moreover, listener functions do not have to be named handleEvent() —they can be named with any valid identifier. In ActionScript 3.0, you register the name of the actual listener function.

Listener function defined outside of a class

The following code creates a simple SWF file that displays a red square shape. A listener function named clickHandler() , which is not part of a class, listens for mouse click events on the red square.

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
} 
 
function clickHandler(event:MouseEvent):void 
{ 
    trace("clickHandler detected an event of type: " + event.type); 
    trace("the this keyword refers to: " + this); 
}

When a user interacts with the resulting SWF file by clicking on the square, Flash Player or AIR generates the following trace output:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

Notice that the event object is passed as an argument to clickHandler() . This allows your listener function to examine the event object. In this example, you use the event object's type property to ascertain that the event is a click event.

The example also checks the value of the this keyword. In this case, this represents the global object, which makes sense because the function is defined outside of any custom class or object.

Listener function defined as a class method

The following example is identical to the previous example that defines the ClickExample class except that the clickHandler() function is defined as a method of the ChildSprite class:

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
    private function clickHandler(event:MouseEvent):void 
    { 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
    } 
}

When a user interacts with the resulting SWF file by clicking on the red square, Flash Player or AIR generates the following trace output:

clickHandler detected an event of type: click 
the this keyword refers to: [object ChildSprite]

Note that the this keyword refers to the ChildSprite instance named child . This is a change in behavior from ActionScript 2.0. If you used components in ActionScript 2.0, you may remember that when a class method was passed in to UIEventDispatcher.addEventListener() , the scope of the method was bound to the component that broadcast the event instead of the class in which the listener method was defined. In other words, if you used this technique in ActionScript 2.0, the this keyword would refer to the component broadcasting the event instead of the ChildSprite instance.

This was a significant issue for some programmers because it meant that they could not access other methods and properties of the class containing the listener method. As a workaround, ActionScript 2.0 programmers could use the mx.util.Delegate class to change the scope of the listener method. This is no longer necessary, however, because ActionScript 3.0 creates a bound method when addEventListener() is called. As a result, the this keyword refers to the ChildSprite instance named child , and the programmer has access to the other methods and properties of the ChildSprite class.

Event listener that should not be used

There is a third technique in which you create a generic object with a property that points to a dynamically assigned listener function, but it is not recommended. It is discussed here because it was commonly used in ActionScript 2.0, but should not be used in ActionScript 3.0. This technique is not recommended because the this keyword will refer to the global object instead of your listener object.

The following example is identical to the previous ClickExample class example, except that the listener function is defined as part of a generic object named myListenerObj :

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); 
    } 
} 
 
var myListenerObj:Object = new Object(); 
myListenerObj.clickHandler = function (event:MouseEvent):void 
{ 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
}

The results of the trace will look like this:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

You would expect that this would refer to myListenerObj and that the trace output would be [object Object] , but instead it refers to the global object. When you pass in a dynamic property name as an argument to addEventListener() , Flash Player or AIR is unable to create a bound method. This is because what you are passing as the listener parameter is nothing more than the memory address of your listener function, and Flash Player and AIR have no way to link that memory address with the myListenerObj instance .

Managing event listeners

You can manage your listener functions using the methods of the IEventDispatcher interface. The IEventDispatcher interface is the ActionScript 3.0 version of the EventTarget interface of the DOM event model. Although the name IEventDispatcher may seem to imply that its main purpose is to send (or dispatch) event objects, the methods of this class are actually used much more frequently to register event listeners, check for event listeners, and remove event listeners. The IEventDispatcher interface defines five methods, as shown in the following code:

package flash.events 
{ 
    public interface IEventDispatcher 
    { 
        function addEventListener(eventName:String,  
                        listener:Object, 
                        useCapture:Boolean=false, 
                        priority:Integer=0, 
                        useWeakReference:Boolean=false):Boolean; 
 
        function removeEventListener(eventName:String,  
                    listener:Object, 
                    useCapture:Boolean=false):Boolean; 
 
        function dispatchEvent(eventObject:Event):Boolean; 
 
        function hasEventListener(eventName:String):Boolean; 
        function willTrigger(eventName:String):Boolean; 
    } 
}

The Flash Player API implements the IEventDispatcher interface with the EventDispatcher class, which serves as a base class for all classes that can be event targets or part of an event flow. For example, the DisplayObject class inherits from the EventDispatcher class. This means that any object on the display list has access to the methods of the IEventDispatcher interface.

Adding event listeners

The addEventListener() method is the workhorse of the IEventDispatcher interface. You use it to register your listener functions. The two required parameters are type and listener . You use the type parameter to specify the type of event. You use the listener parameter to specify the listener function that will execute when the event occurs. The listener parameter can be a reference to either a function or a class method.

Do not use parentheses when you specify the listener parameter. For example, the clickHandler() function is specified without parentheses in the following call to the addEventListener() method:
addEventListener(MouseEvent.CLICK, clickHandler)

The useCapture parameter of the addEventListener() method allows you to control the event flow phase on which your listener will be active. If useCapture is set to true , your listener will be active during the capture phase of the event flow. If useCapture is set to false , your listener will be active during the target and bubbling phases of the event flow. To listen for an event during all phases of the event flow, you must call addEventListener() twice, once with useCapture set to true , and then again with useCapture set to false .

The priority parameter of the addEventListener() method is not an official part of the DOM Level 3 event model. It is included in ActionScript 3.0 to provide you with more flexibility in organizing your event listeners. When you call addEventListener() , you can set the priority for that event listener by passing an integer value as the priority parameter. The default value is 0, but you can set it to negative or positive integer values. The higher the number, the sooner that event listener will be executed. Event listeners with the same priority are executed in the order that they were added, so the earlier a listener is added, the sooner it will be executed.

The useWeakReference parameter allows you to specify whether the reference to the listener function is weak or normal. Setting this parameter to true allows you to avoid situations in which listener functions persist in memory even though they are no longer needed. Flash Player and AIR use a technique called garbage collection to clear objects from memory that are no longer in use. An object is considered no longer in use if no references to it exist. The garbage collector disregards weak references, which means that a listener function that has only a weak reference pointing to it is eligible for garbage collection.

Removing event listeners

You can use the removeEventListener() method to remove an event listener that you no longer need. It is a good idea to remove any listeners that will no longer be used. Required parameters include the eventName and listener parameters, which are the same as the required parameters for the addEventListener() method. Recall that you can listen for events during all event phases by calling addEventListener() twice, once with useCapture set to true , and then again with it set to false . To remove both event listeners, you would need to call removeEventListener() twice, once with useCapture set to true , and then again with it set to false .

Dispatching events

The dispatchEvent() method can be used by advanced programmers to dispatch a custom event object into the event flow. The only parameter accepted by this method is a reference to an event object, which must be an instance of the Event class or a subclass of the Event class. Once dispatched, the target property of the event object is set to the object on which dispatchEvent() was called.

Checking for existing event listeners

The final two methods of the IEventDispatcher interface provide useful information about the existence of event listeners. The hasEventListener() method returns true if an event listener is found for a specific event type on a particular display list object. The willTrigger() method also returns true if a listener is found for a particular display list object, but willTrigger() checks for listeners not only on that display object, but also on all of that display list object’s ancestors for all phases of the event flow.

Error events without listeners

Exceptions, rather than events, are the primary mechanism for error handling in ActionScript 3.0, but exception handling does not work for asynchronous operations such as loading files. If an error occurs during such an asynchronous operation, Flash Player and AIR dispatch an error event object. If you do not create a listener for the error event, the debugger versions of Flash Player and AIR will bring up a dialog box with information about the error. For example, the debugger version of Flash Player produces the following dialog box describing the error when the application attempts to load a file from an invalid URL:

Most error events are based on the ErrorEvent class, and as such will have a property named text that is used to store the error message that Flash Player or AIR displays. The two exceptions are the StatusEvent and NetStatusEvent classes. Both of these classes have a level property ( StatusEvent.level and NetStatusEvent.info.level ). When the value of the level property is " error ", these event types are considered to be error events.

An error event will not cause a SWF file to stop running. It will manifest only as a dialog box on the debugger versions of the browser plug-ins and stand-alone players, as a message in the output panel in the authoring player, and as an entry in the log file for Adobe Flash Builder. It will not manifest at all in the release versions of Flash Player or AIR.

Handling events for display objects

The DisplayObject class inherits from the EventDispatcher class. This means that every display object can participate fully in the event model (described in Handling events). Every display object can use its addEventListener() method—inherited from the EventDispatcher class—to listen for a particular event, but only if the listening object is part of the event flow for that event.

When Flash Player or AIR dispatches an event object, that event object makes a round-trip journey from the Stage to the display object where the event occurred. For example, if a user clicks on a display object named child1 , Flash Player dispatches an event object from the Stage through the display list hierarchy down to the child1 display object.

The event flow is conceptually divided into three phases, as illustrated in this diagram:

<Three phases of event flow>

For more information, see Handling events.

One important issue to keep in mind when working with display object events is the effect that event listeners can have on whether display objects are automatically removed from memory (garbage collected) when they’re removed from the display list. If a display object has objects subscribed as listeners to its events, that display object will not be removed from memory even when it’s removed from the display list, because it will still have references to those listener objects. For more information, see Managing event listeners.

Keyboard input

Your application can capture and respond to keyboard input and can manipulate an IME to let users type non-ASCII text characters in multibyte languages. Note that this section assumes that you are already familiar with the ActionScript 3.0 event model. For more information, see Handling events.

For information on discovering what kind of keyboard support is available (such as physical, virtual, alphanumeric, or 12-button numeric) during runtime, see Discovering input types.

An Input Method Editor (IME) allows users to type complex characters and symbols using a standard keyboard. You can use the IME classes to enable users to take advantage of their system IME in your applications.

Capturing keyboard input

Display objects that inherit their interaction model from the InteractiveObject class can respond to keyboard events by using event listeners. For example, you can place an event listener on the Stage to listen for and respond to keyboard input. In the following code, an event listener captures a key press, and the key name and key code properties are displayed:

function reportKeyDown(event:KeyboardEvent):void 
{ 
    trace("Key Pressed: " + String.fromCharCode(event.charCode) +         " (character code: " + event.charCode + ")"); 
} 
stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);

Some keys, such as the Ctrl key, generate events even though they have no glyph representation.

In the previous code example, the keyboard event listener captured keyboard input for the entire Stage. You can also write an event listener for a specific display object on the Stage; this event listener is triggered when the object has the focus.

In the following example, keystrokes are reflected in the Output panel only when the user types inside the TextField instance. Holding the Shift key down temporarily changes the border color of the TextField to red.

This code assumes there is a TextField instance named tf on the Stage.

tf.border = true; 
tf.type = "input"; 
tf.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown); 
tf.addEventListener(KeyboardEvent.KEY_UP,reportKeyUp); 
 
function reportKeyDown(event:KeyboardEvent):void 
{ 
    trace("Key Pressed: " + String.fromCharCode(event.charCode) +         " (key code: " + event.keyCode + " character code: "         + event.charCode + ")"); 
    if (event.keyCode == Keyboard.SHIFT) tf.borderColor = 0xFF0000; 
} 
 
function reportKeyUp(event:KeyboardEvent):void 
{ 
    trace("Key Released: " + String.fromCharCode(event.charCode) +         " (key code: " + event.keyCode + " character code: " +         event.charCode + ")"); 
    if (event.keyCode == Keyboard.SHIFT) 
    { 
        tf.borderColor = 0x000000; 
    } 
}

The TextField class also reports a textInput event that you can listen for when a user enters text. For more information, see Capturing text input.

Note: In the AIR runtime, a keyboard event can be canceled. In the Flash Player runtime, a keyboard event cannot be canceled.
Key codes and character codes

You can access the keyCode and charCode properties of a keyboard event to determine what key was pressed and then trigger other actions. The keyCode property is a numeric value that corresponds to the value of a key on the keyboard. The charCode property is the numeric value of that key in the current character set. (The default character set is UTF-8, which supports ASCII.)

The primary difference between the key code and character values is that a key code value represents a particular key on the keyboard (the 1 on a keypad is different than the 1 in the top row, but the key that generates “1” and the key that generates “!” are the same key) and the character value represents a particular character (the R and r characters are different).

Note: For the mappings between keys and their character code values in ASCII, see the flash.ui.Keyboard class in the ActionScript 3.0 Reference for the Adobe Flash Platform .

The mappings between keys and their key codes is dependent on the device and the operating system. For this reason, you should not use key mappings to trigger actions. Instead, you should use the predefined constant values provided by the Keyboard class to reference the appropriate keyCode properties. For example, instead of using the key mapping for the Shift key, use the Keyboard.SHIFT constant (as shown in the preceding code sample).

KeyboardEvent precedence

As with other events, the keyboard event sequence is determined by the display object hierarchy and not the order in which addEventListener() methods are assigned in code.

For example, suppose you place a text field called tf inside a movie clip called container and add an event listener for a keyboard event to both instances, as the following example shows:

container.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown); 
container.tf.border = true; 
container.tf.type = "input"; 
container.tf.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown); 
 
function reportKeyDown(event:KeyboardEvent):void 
{ 
    trace(event.currentTarget.name + " hears key press: " +         String.fromCharCode(event.charCode) + " (key code: " +         event.keyCode + " character code: " + event.charCode + ")"); 
}

Because there is a listener on both the text field and its parent container, the reportKeyDown() function is called twice for every keystroke inside the TextField. Note that for each key pressed, the text field dispatches an event before the container movie clip dispatches an event.

The operating system and the web browser will process keyboard events before Adobe Flash Player or AIR. For example, in Microsoft Internet Explorer, pressing Ctrl+W closes the browser window before any contained SWF file dispatches a keyboard event.

Mouse input

Your application can create interactivity by capturing and responding to mouse input. Note that this section assumes that you are already familiar with the ActionScript 3.0 event model. For more information, see Handling events.

For information on discovering what kind of mouse support is available (such as persistent cursor, stylus or touch input) during runtime, see Discovering input types.

Capturing mouse input

Mouse clicks create mouse events that can be used to trigger interactive functionality. You can add an event listener to the Stage to listen for mouse events that occur anywhere within the SWF file. You can also add event listeners to objects on the Stage that inherit from InteractiveObject (for example, Sprite or MovieClip); these listeners are triggered when the object is clicked.

As with keyboard events, mouse events bubble. In the following example, because square is a child of the Stage, the event dispatches both from the sprite square as well as from the Stage object when the square is clicked:

var square:Sprite = new Sprite(); 
square.graphics.beginFill(0xFF0000); 
square.graphics.drawRect(0,0,100,100); 
square.graphics.endFill(); 
square.addEventListener(MouseEvent.CLICK, reportClick); 
square.x = 
square.y = 50; 
addChild(square); 
 
stage.addEventListener(MouseEvent.CLICK, reportClick); 
 
function reportClick(event:MouseEvent):void 
{ 
    trace(event.currentTarget.toString() +         " dispatches MouseEvent. Local coords [" +         event.localX + "," + event.localY + "] Stage coords [" +         event.stageX + "," + event.stageY + "]"); 
}

In the previous example, notice that the mouse event contains positional information about the click. The localX and localY properties contain the location of the click on the lowest child in the display chain. For example, clicking at the top-left corner of square reports local coordinates of [0,0] because that is the registration point of square . Alternatively, the stageX and stageY properties refer to the global coordinates of the click on the Stage. The same click reports [50,50] for these coordinates, because square was moved to these coordinates. Both of these coordinate pairs can be useful depending on how you want to respond to user interaction.

The MouseEvent object also contains altKey , ctrlKey , and shiftKey Boolean properties. You can use these properties to check if the Alt, Ctrl, or Shift key is also being pressed at the time of the mouse click.

Dragging Sprites around the stage

You can allow users to drag a Sprite object around the stage using the startDrag() method of the Sprite class. The following code shows an example of this:

import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
var circle:Sprite = new Sprite(); 
circle.graphics.beginFill(0xFFCC00); 
circle.graphics.drawCircle(0, 0, 40); 
 
var target1:Sprite = new Sprite(); 
target1.graphics.beginFill(0xCCFF00); 
target1.graphics.drawRect(0, 0, 100, 100); 
target1.name = "target1"; 
 
var target2:Sprite = new Sprite(); 
target2.graphics.beginFill(0xCCFF00); 
target2.graphics.drawRect(0, 200, 100, 100); 
target2.name = "target2"; 
 
addChild(target1); 
addChild(target2); 
addChild(circle); 
 
circle.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)  
 
function mouseDown(event:MouseEvent):void 
{ 
    circle.startDrag(); 
} 
circle.addEventListener(MouseEvent.MOUSE_UP, mouseReleased); 
 
function mouseReleased(event:MouseEvent):void 
{ 
    circle.stopDrag(); 
    trace(circle.dropTarget.name); 
}

For more details, see the section on creating mouse drag interaction in Changing position.

Drag-and-drop in AIR

In Adobe AIR, you can enable drag-and-drop support to allow users to drag data into and out of your application. For more details, see Drag and drop in AIR.

Customizing the mouse cursor

The mouse cursor (mouse pointer) can be hidden or swapped for any display object on the Stage. To hide the mouse cursor, call the Mouse.hide() method. Customize the cursor by calling Mouse.hide() , listening to the Stage for the MouseEvent.MOUSE_MOVE event, and setting the coordinates of a display object (your custom cursor) to the stageX and stageY properties of the event. The following example illustrates a basic execution of this task:

var cursor:Sprite = new Sprite(); 
cursor.graphics.beginFill(0x000000); 
cursor.graphics.drawCircle(0,0,20); 
cursor.graphics.endFill(); 
addChild(cursor); 
 
stage.addEventListener(MouseEvent.MOUSE_MOVE,redrawCursor); 
Mouse.hide(); 
 
function redrawCursor(event:MouseEvent):void 
{ 
    cursor.x = event.stageX; 
    cursor.y = event.stageY; 
}

Loading

HTTP communications

Adobe® AIR® and Adobe® Flash® Player applications can communicate with HTTP-based servers to load data, images, video and to exchange messages.

Loading external data

ActionScript 3.0 includes mechanisms for loading data from external sources. Those sources can provide static content such as text files, or dynamic content generated by a web script. The data can be formatted in various ways, and ActionScript provides functionality for decoding and accessing the data. You can also send data to the external server as part of the process of retrieving data.

Using the URLRequest class

Many APIs that load external data use the URLRequest class to define the properties of necessary network request.

URLRequest properties

You can set the following properties of a URLRequest object in any security sandbox:

Property

Description

contentType

The MIME content type of any data sent with the URL request. If no contentType is set, values are sent as application/x-www-form-urlencoded .

data

An object containing data to be transmitted with the URL request.

digest

A string that uniquely identifies the signed Adobe platform component to be stored to (or retrieved from) the Adobe® Flash® Player cache.

method

The HTTP request method, such as a GET or POST. (Content running in the AIR application security domain can specify strings other than "GET" or "POST" as the method property. Any HTTP verb is allowed and "GET" is the default method. See AIR security.)

requestHeaders

The array of HTTP request headers to be appended to the HTTP request. Note that permission to set some headers is restricted in Flash Player as well as in AIR content running outside the application security sandbox.

url

Specifies the URL to be requested.

In AIR, you can set additional properties of the URLRequest class, which are only available to AIR content running in the application security sandbox. Content in the application sandbox can also define URLs using new URL schemes (in addition to standard schemes like file and http ).

Property

Description

followRedirects

Specifies whether redirects are to be followed ( true , the default value) or not ( false ). This is only supported in the AIR application sandbox.

manageCookies

Specifies whether the HTTP protocol stack should manage cookies ( true , the default value) or not ( false ) for this request. Setting this property is only supported in the AIR application sandbox.

authenticate

Specifies whether authentication requests should be handled ( true ) for this request. Setting this property is only supported in the AIR application sandbox. The default is to authenticate requests—which may cause an authentication dialog box to be displayed if the server requires credentials. You can also set the user name and password using the URLRequestDefaults class—see Setting URLRequest defaults.

cacheResponse

Specifies whether response data should be cached for this request. Setting this property is only supported in the AIR application sandbox. The default is to cache the response ( true ).

useCache

Specifies whether the local cache should be consulted before this URLRequest fetches data. Setting this property is only supported in the AIR application sandbox. The default ( true ) is to use the local cached version, if available.

userAgent

Specifies the user-agent string to be used in the HTTP request.

Note: The HTMLLoader class has related properties for settings pertaining to content loaded by an HTMLLoader object. For details, see About the HTMLLoader class.
Setting URLRequest defaults (AIR only)

The URLRequestDefaults class lets you define application-specific default settings for URLRequest objects. For example, the following code sets the default values for the manageCookies and useCache properties. All new URLRequest objects will use the specified values for these properties instead of the normal defaults:

URLRequestDefaults.manageCookies = false; 
URLRequestDefaults.useCache = false;
Note: The URLRequestDefaults class is defined for content running in Adobe AIR only. It is not supported in Flash Player.

The URLRequestDefaults class includes a setLoginCredentialsForHost() method that lets you specify a default user name and password to use for a specific host. The host, which is defined in the hostname parameter of the method, can be a domain, such as "www.example.com" , or a domain and a port number, such as "www.example.com:80" . Note that "example.com" , "www.example.com" , and "sales.example.com" are each considered unique hosts.

These credentials are only used if the server requires them. If the user has already authenticated (for example, by using the authentication dialog box), then calling the setLoginCredentialsForHost() method does not change the authenticated user.

The following code sets the default user name and password to use for requests sent to www.example.com:

URLRequestDefaults.setLoginCredentialsForHost("www.example.com", "Ada", "love1816$X"); 

The URLRequestDefaults settings only apply to the current application domain, with one exception. The credentials passed to the setLoginCredentialsForHost() method are used for requests made in any application domain within the AIR application.

For more information, see the URLRequestDefaults class in the ActionScript 3.0 Reference for the Adobe Flash Platform .

URI schemes

The standard URI schemes, such as the following, can be used in requests made from any security sandbox:

http: and https:

Use these for standard Internet URLs (in the same way that they are used in a web browser).

file:

Use file: to specify the URL of a file located on the local file system. For example:

file:///c:/AIR Test/test.txt 

In AIR, you can also use the following schemes when defining a URL for content running in the application security sandbox:

app:

Use app: to specify a path relative to the root directory of the installed application. For example, the following path points to a resources subdirectory of the directory of the installed application:

app:/resources 

When an AIR application is launched using the AIR Debug Launcher (ADL), the application directory is the directory that contains the application descriptor file.

The URL (and url property) for a File object created with File.applicationDirectory uses the app URI scheme, as in the following:

var dir:File = File.applicationDirectory; 
dir = dir.resolvePath("assets"); 
trace(dir.url); // app:/assets 

app-storage:

Use app-storage: to specify a path relative to the data storage directory of the application. For each installed application (and user), AIR creates a unique application storage directory, which is a useful place to store data specific to that application. For example, the following path points to a prefs.xml file in a settings subdirectory of the application store directory:

app-storage:/settings/prefs.xml 

The URL (and url property) for a File object created with File.applicationStorageDirectory uses the app-storage URI scheme, as in the following:

var prefsFile:File = File.applicationStorageDirectory; 
prefsFile = prefsFile.resolvePath("prefs.xml"); 
trace(dir.prefsFile); // app-storage:/prefs.xml 

mailto:

You can use the mailto scheme in URLRequest objects passed to the navigateToURL() function. See Opening a URL in the default system web browser.

You can use a URLRequest object that uses any of these URI schemes to define the URL request for a number of different objects, such as a FileStream or a Sound object. You can also use these schemes in HTML content running in AIR; for example, you can use them in the src attribute of an img tag.

However, you can only use these AIR-specific URI schemes ( app: and app-storage: ) in content in the application security sandbox. For more information, see AIR security.

Setting URL variables

While you can add variables to the URL string directly, it can be easier to use the URLVariables class to define any variables needed for a request.

There are three ways in which you can add parameters to a URLVariables object:

  • Within the URLVariables constructor

  • With the URLVariables.decode() method

  • As dynamic properties of the URLVariables object itself

The following example illustrates all three methods and also how to assign the variables to a URLRequest object:

var urlVar:URLVariables = new URLVariables( "one=1&two=2" ); 
urlVar.decode("amp=" + encodeURIComponent( "&" ) ); 
urlVar.three = 3; 
urlVar.amp2 = "&&"; 
trace(urlVar.toString()); //amp=%26&amp2=%26%26&one=1&two=2&three=3 
 
var urlRequest:URLRequest = new URLRequest( "http://www.example.com/test.cfm" ); 
urlRequest.data = urlVar;

When you define variables within the URLVariables constructor or within the URLVariables.decode() method, make sure that you URL-encode the characters that have a special meaning in a URI string. For example, when you use an ampersand in a parameter name or value, you must encode the ampersand by changing it from & to %26 because the ampersand acts as a delimiter for parameters. The top-level encodeURIComponent() function can be used for this purpose.

Using the URLLoader class

The URLLoader class let you send a request to a server and access the information returned. You can also use the URLLoader class to access files on the local file system in contexts where local file access is permitted (such as the Flash Player local-with-filesystem sandbox and the AIR application sandbox). The URLLoader class downloads data from a URL as text, binary data, or URL-encoded variables. The URLLoader class dispatches events such as complete , httpStatus , ioError , open , progress , and securityError .

The ActionScript 3.0 event-handling model is significantly different than the ActionScript 2.0 model, which used the LoadVars.onData , LoadVars.onHTTPStatus , and LoadVars.onLoad event handlers. For more information on handling events in ActionScript 3.0, see Handling events

Downloaded data is not available until the download has completed. You can monitor the progress of the download (bytes loaded and bytes total) by listening for the progress event to be dispatched. However, if a file loads quickly enough a progress event might not be dispatched. When a file has successfully downloaded, the complete event is dispatched. By setting the URLLoader dataFormat property, you can receive the data as text, raw binary data, or as a URLVariables object.

The URLLoader.load() method (and optionally the URLLoader class’s constructor) takes a single parameter, request , which is a URLRequest object. A URLRequest object contains all of the information for a single HTTP request, such as the target URL, request method ( GET or POST ), additional header information, and the MIME type.

For example, to upload an XML packet to a server-side script, you could use the following code:

var secondsUTC:Number = new Date().time; 
var dataXML:XML =  
    <clock> 
        <time>{secondsUTC}</time> 
    </clock>; 
var request:URLRequest = new URLRequest("http://www.yourdomain.com/time.cfm"); 
request.contentType = "text/xml"; 
request.data = dataXML.toXMLString(); 
request.method = URLRequestMethod.POST; 
var loader:URLLoader = new URLLoader(); 
loader.load(request); 

The previous snippet creates an XML document named dataXML that contains the XML packet to be sent to the server. The example sets the URLRequest contentType property to "text/xml" and assigns the XML document to the URLRequest data property. Finally, the example creates a URLLoader object and sends the request to the remote script by using the load() method.

Using the URLStream class

The URLStream class provides access to the downloading data as the data arrives. The URLStream class also lets you close a stream before it finishes downloading. The downloaded data is available as raw binary data.

When reading data from a URLStream object, use the bytesAvailable property to determine whether sufficient data is available before reading it. An EOFError exception is thrown if you attempt to read more data than is available.

The httpResponseStatus event (AIR)

In Adobe AIR, the URLStream class dispatches an httpResponseStatus event in addition to the httpStatus event. The httpResponseStatus event is delivered before any response data. The httpResponseStatus event (represented by the HTTPStatusEvent class) includes a responseURL property, which is the URL that the response was returned from, and a responseHeaders property, which is an array of URLRequestHeader objects representing the response headers that the response returned.

Loading data from external documents

When you build dynamic applications, it can be useful to load data from external files or from server-side scripts. This lets you build dynamic applications without having to edit or recompile your application. For example, if you build a “tip of the day” application, you can write a server-side script that retrieves a random tip from a database and saves it to a text file once a day. Then your application can load the contents of a static text file instead of querying the database each time.

The following snippet creates a URLRequest and URLLoader object, which loads the contents of an external text file, params.txt:

var request:URLRequest = new URLRequest("params.txt"); 
var loader:URLLoader = new URLLoader(); 
loader.load(request);
By default, if you do not define a request method, Flash Player and Adobe AIR load the content using the HTTP GET method. To send the request using the POST method, set the request.method property to POST using the static constant URLRequestMethod.POST , as the following code shows:
var request:URLRequest = new URLRequest("sendfeedback.cfm"); 
request.method = URLRequestMethod.POST;

The external document, params.txt, that is loaded at run time contains the following data:

monthNames=January,February,March,April,May,June,July,August,September,October,November,December&dayNames=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday

The file contains two parameters, monthNames and dayNames . Each parameter contains a comma-separated list that is parsed as strings. You can split this list into an array using the String.split() method.

Avoid using reserved words or language constructs as variable names in external data files, because doing so makes reading and debugging your code more difficult.
Once the data has loaded, the complete event is dispatched, and the contents of the external document are available to use in the URLLoader’s data property, as the following code shows:
function completeHandler(event) 
{ 
    var loader2 = event.target; 
    air.trace(loader2.data); 
}

If the remote document contains name-value pairs, you can parse the data using the URLVariables class by passing in the contents of the loaded file, as follows:

private function completeHandler(event:Event):void 
{ 
    var loader2:URLLoader = URLLoader(event.target); 
    var variables:URLVariables = new URLVariables(loader2.data); 
    trace(variables.dayNames); 
}

Each name-value pair from the external file is created as a property in the URLVariables object. Each property within the variables object in the previous code sample is treated as a string. If the value of the name-value pair is a list of items, you can convert the string into an array by calling the String.split() method, as follows:

var dayNameArray:Array = variables.dayNames.split(",");
If you are loading numeric data from external text files, convert the values into numeric values by using a top-level function, such as int() , uint() , or Number() .

Instead of loading the contents of the remote file as a string and creating a new URLVariables object, you could instead set the URLLoader.dataFormat property to one of the static properties found in the URLLoaderDataFormat class. The three possible values for the URLLoader.dataFormat property are as follows:

  • URLLoaderDataFormat.BINARY —The URLLoader.data property will contain binary data stored in a ByteArray object.

  • URLLoaderDataFormat.TEXT —The URLLoader.data property will contain text in a String object.

  • URLLoaderDataFormat.VARIABLES —The URLLoader.data property will contain URL-encoded variables stored in a URLVariables object.

The following code demonstrates how setting the URLLoader.dataFormat property to URLLoaderDataFormat.VARIABLES allows you to automatically parse loaded data into a URLVariables object:

package 
{ 
    import flash.display.Sprite; 
    import flash.events.*; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
 
    public class URLLoaderDataFormatExample extends Sprite 
    { 
        public function URLLoaderDataFormatExample() 
        { 
            var request:URLRequest = new URLRequest("http://www.[yourdomain].com/params.txt"); 
            var variables:URLLoader = new URLLoader(); 
            variables.dataFormat = URLLoaderDataFormat.VARIABLES; 
            variables.addEventListener(Event.COMPLETE, completeHandler); 
            try 
            { 
                variables.load(request); 
            }  
            catch (error:Error) 
            { 
                trace("Unable to load URL: " + error); 
            } 
        } 
        private function completeHandler(event:Event):void 
        { 
        var loader:URLLoader = URLLoader(event.target); 
        trace(loader.data.dayNames); 
        } 
    } 
}
Note: The default value for URLLoader.dataFormat is URLLoaderDataFormat.TEXT .

As the following example shows, loading XML from an external file is the same as loading URLVariables. You can create a URLRequest instance and a URLLoader instance and use them to download a remote XML document. When the file has completely downloaded, the Event.COMPLETE event is dispatched and the contents of the external file are converted to an XML instance, which you can parse using XML methods and properties.

package 
{ 
    import flash.display.Sprite; 
    import flash.errors.*; 
    import flash.events.*; 
    import flash.net.URLLoader; 
    import flash.net.URLRequest; 
 
    public class ExternalDocs extends Sprite 
    { 
        public function ExternalDocs() 
        { 
            var request:URLRequest = new URLRequest("http://www.[yourdomain].com/data.xml"); 
            var loader:URLLoader = new URLLoader(); 
            loader.addEventListener(Event.COMPLETE, completeHandler); 
            try 
            { 
                loader.load(request); 
            } 
            catch (error:ArgumentError) 
            { 
                trace("An ArgumentError has occurred."); 
            } 
            catch (error:SecurityError) 
            { 
                trace("A SecurityError has occurred."); 
            } 
        } 
        private function completeHandler(event:Event):void 
        { 
            var dataXML:XML = XML(event.target.data); 
            trace(dataXML.toXMLString()); 
        } 
    } 
}

Communicating with external scripts

In addition to loading external data files, you can also use the URLVariables class to send variables to a server-side script and process the server’s response. This is useful, for example, if you are programming a game and want to send the user’s score to a server to calculate whether it should be added to the high scores list, or even send a user’s login information to a server for validation. A server-side script can process the user name and password, validate it against a database, and return confirmation of whether the user-supplied credentials are valid.

The following snippet creates a URLVariables object named variables, which creates a new variable called name . Next, a URLRequest object is created that specifies the URL of the server-side script to send the variables to. Then you set the method property of the URLRequest object to send the variables as an HTTP POST request. To add the URLVariables object to the URL request, you set the data property of the URLRequest object to the URLVariables object created earlier. Finally, the URLLoader instance is created and the URLLoader.load() method is invoked, which initiates the request.

var variables:URLVariables = new URLVariables("name=Franklin"); 
var request:URLRequest = new URLRequest(); 
request.url = "http://www.[yourdomain].com/greeting.cfm"; 
request.method = URLRequestMethod.POST; 
request.data = variables; 
var loader:URLLoader = new URLLoader(); 
loader.dataFormat = URLLoaderDataFormat.VARIABLES; 
loader.addEventListener(Event.COMPLETE, completeHandler); 
try 
{ 
    loader.load(request); 
} 
catch (error:Error) 
{ 
    trace("Unable to load URL"); 
} 
 
function completeHandler(event:Event):void 
{ 
    trace(event.target.data.welcomeMessage); 
}

The following code contains the contents of the Adobe ColdFusion® greeting.cfm document used in the previous example:

<cfif NOT IsDefined("Form.name") OR Len(Trim(Form.Name)) EQ 0> 
    <cfset Form.Name = "Stranger" /> 
</cfif> 
<cfoutput>welcomeMessage=#UrlEncodedFormat("Welcome, " & Form.name)# 
</cfoutput>

Loading display content dynamically

You can load any of the following external display assets into an ActionScript 3.0 application:

  • A SWF file authored in ActionScript 3.0—This file can be a Sprite, MovieClip, or any class that extends Sprite. In AIR applications on iOS, only SWF files that do not contain ActionScript bytecode can be loaded. This means that SWF files containing embedded data, such as images and sound can be loaded, but not SWF files containing executable code.

  • An image file—This includes JPG, PNG, and GIF files.

  • An AVM1 SWF file—This is a SWF file written in ActionScript 1.0 or 2.0. (not supported in mobile AIR applications)

You load these assets by using the Loader class.

Loading display objects

Loader objects are used to load SWF files and graphics files into an application. The Loader class is a subclass of the DisplayObjectContainer class. A Loader object can contain only one child display object in its display list—the display object representing the SWF or graphic file that it loads. When you add a Loader object to the display list, as in the following code, you also add the loaded child display object to the display list once it loads:

var pictLdr:Loader = new Loader(); 
var pictURL:String = "banana.jpg" 
var pictURLReq:URLRequest = new URLRequest(pictURL); 
pictLdr.load(pictURLReq); 
this.addChild(pictLdr);

Once the SWF file or image is loaded, you can move the loaded display object to another display object container, such as the container DisplayObjectContainer object in this example:

import flash.display.*; 
import flash.net.URLRequest; 
import flash.events.Event; 
var container:Sprite = new Sprite(); 
addChild(container); 
var pictLdr:Loader = new Loader(); 
var pictURL:String = "banana.jpg" 
var pictURLReq:URLRequest = new URLRequest(pictURL); 
pictLdr.load(pictURLReq); 
pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded);  
function imgLoaded(event:Event):void 
{ 
    container.addChild(pictLdr.content);  
}

Monitoring loading progress

Once the file has started loading, a LoaderInfo object is created. A LoaderInfo object provides information such as load progress, the URLs of the loader and loadee, the number of bytes total for the media, and the nominal height and width of the media. A LoaderInfo object also dispatches events for monitoring the progress of the load.

The following diagram shows the different uses of the LoaderInfo object—for the instance of the main class of the SWF file, for a Loader object, and for an object loaded by the Loader object:

The LoaderInfo object can be accessed as a property of both the Loader object and the loaded display object. As soon as loading begins, the LoaderInfo object can be accessed through the contentLoaderInfo property of the Loader object. Once the display object has finished loading, the LoaderInfo object can also be accessed as a property of the loaded display object through the display object’s loaderInfo property. The loaderInfo property of the loaded display object refers to the same LoaderInfo object as the contentLoaderInfo property of the Loader object. In other words, a LoaderInfo object is shared between a loaded object and the Loader object that loaded it (between loader and loadee).

In order to access properties of loaded content, you will want to add an event listener to the LoaderInfo object, as in the following code:

import flash.display.Loader; 
import flash.display.Sprite; 
import flash.events.Event; 
 
var ldr:Loader = new Loader(); 
var urlReq:URLRequest = new URLRequest("Circle.swf"); 
ldr.load(urlReq); 
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded); 
addChild(ldr); 
 
function loaded(event:Event):void 
{ 
    var content:Sprite = event.target.content; 
    content.scaleX = 2; 
}

For more information, see Handling events.

Specifying loading context

When you load an external file into Flash Player or AIR through the load() or loadBytes() method of the Loader class, you can optionally specify a context parameter. This parameter is a LoaderContext object.

The LoaderContext class includes three properties that let you define the context of how the loaded content can be used:

  • checkPolicyFile : Use this property only when loading an image file (not a SWF file). If you set this property to true , the Loader checks the origin server for a policy file (see Website controls (policy files)). This is necessary only for content originating from domains other than that of the SWF file containing the Loader object. If the server grants permission to the Loader domain, ActionScript from SWF files in the Loader domain can access data in the loaded image; in other words, you can use the BitmapData.draw() command to access data in the loaded image.

    Note that a SWF file from other domains than that of the Loader object can call Security.allowDomain() to permit a specific domain.

  • securityDomain : Use this property only when loading a SWF file (not an image). Specify this for a SWF file from a domain other than that of the file containing the Loader object. When you specify this option, Flash Player checks for the existence of a policy file, and if one exists, SWF files from the domains permitted in the cross-policy file can cross-script the loaded SWF content. You can specify flash.system.SecurityDomain.currentDomain as this parameter.

  • applicationDomain : Use this property only when loading a SWF file written in ActionScript 3.0 (not an image or a SWF file written in ActionScript 1.0 or 2.0). When loading the file, you can specify that the file be included in the same application domain as that of the Loader object, by setting the applicationDomain parameter to flash.system.ApplicationDomain.currentDomain . By putting the loaded SWF file in the same application domain, you can access its classes directly. This can be useful if you are loading a SWF file that contains embedded media, which you can access via their associated class names. For more information, see Working with application domains.

Here’s an example of checking for a policy file when loading a bitmap from another domain:

var context:LoaderContext = new LoaderContext(); 
context.checkPolicyFile = true; 
var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/photo11.jpg"); 
var ldr:Loader = new Loader(); 
ldr.load(urlReq, context);

Here’s an example of checking for a policy file when loading a SWF from another domain, in order to place the file in the same security sandbox as the Loader object. Additionally, the code adds the classes in the loaded SWF file to the same application domain as that of the Loader object:

var context:LoaderContext = new LoaderContext(); 
context.securityDomain = SecurityDomain.currentDomain; 
context.applicationDomain = ApplicationDomain.currentDomain; 
var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/library.swf"); 
var ldr:Loader = new Loader(); 
ldr.load(urlReq, context);

For more information, see the LoaderContext class in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Using the ProLoader and ProLoaderInfo classes

To help with remote shared library (RSL) preloading, Flash Professional CS5.5 introduces the fl.display.ProLoader and fl.display.ProLoaderInfo classes. These classes mirror the flash.display.Loader and flash.display.LoaderInfo classes but provide a more consistent loading experience.

In particular, ProLoader helps you load SWF files that use the Text Layout Framework (TLF) with RSL preloading. At runtime, SWF files that preload other SWF files or SWZ files, such as TLF, require an internal-only SWF wrapper file. The extra layer of complexity imposed by the SWF wrapper file can result in unwanted behavior. ProLoader solves this complexity to load these files as though they were ordinary SWF files. The solution used by the ProLoader class is transparent to the user and requires no special handling in ActionScript. In addition, ProLoader loads ordinary SWF content correctly.

In Flash Professional CS5.5 and later, you can safely replace all usages of the Loader class with the ProLoader class. Then, export your application to Flash Player 10.2 or higher so that ProLoader can access the required ActionScript functionality. You can also use ProLoader while targeting earlier versions of Flash Player that support ActionScript 3.0. However, you get full advantage of ProLoader features only with Flash Player 10.2 or higher. Always use ProLoader when you use TLF in Flash Professional CS5.5 or later. ProLoader is not needed in environments other than Flash Professional.

Important: For SWF files published in Flash Professional CS5.5 and later, you can always use the fl.display.ProLoader and fl.display.ProLoaderInfo classes instead of flash.display.Loader and flash.display.LoaderInfo.

Issues addressed by the ProLoader class

The ProLoader class addresses issues that the legacy Loader class was not designed to handle. These issues stem from RSL preloading of TLF libraries. Specifically, they apply to SWF files that use a Loader object to load other SWF files. Addressed issues include the following:

  • Scripting between the loading file and the loaded file does not behave as expected. The ProLoader class automatically sets the loading SWF file as the parent of the loaded SWF file. Thus, communications from the loading SWF file go directly to the loaded SWF file.

  • The SWF application must actively manage the loading process. Doing so requires implementation of extra events, such as added , removed , addedToStage , and removedFromStage . If your application targets Flash Player 10.2 or later, ProLoader removes the need for this extra work.

Updating code to use ProLoader instead of Loader

Because ProLoader mirrors the Loader class, you can easily switch the two classes in your code. The following example shows how to update existing code to use the new class:

import flash.display.Loader; 
import flash.events.Event; 
var l:Loader = new Loader(); 
 
addChild(l); 
l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); 
l.load("my.swf"); 
function loadComplete(e:Event) { 
    trace('load complete!'); 
}

This code can be updated to use ProLoader as follows:

import fl.display.ProLoader; 
import flash.events.Event; 
var l:ProLoader = new ProLoader(); 
 
addChild(l); 
l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); 
l.load("my.swf"); 
function loadComplete(e:Event) { 
    trace('load complete!'); 
}

Errors

Basics of error handling

A run-time error is something that goes wrong in your ActionScript code that stops the ActionScript content from running as intended. To ensure that your ActionScript code runs smoothly for users, write code in your application that handles the error—that fixes it, works around it, or at least lets the user know that it has happened. This process is called error handling .

Error handling is a broad category that includes responding to many kinds of errors that are thrown during compilation or while an application is running. Errors that happen at compile time are often easier to identify— fix them to complete the process of creating a SWF file.

Run-time errors can be more difficult to detect, because in order for them to occur the erroneous code must actually be run. If a segment of your program has several branches of code, like an if..then..else statement, test every possible condition, with all the possible input values that real users might use, to confirm that your code is error-free.

Run-time errors can be divided into two categories: program errors are mistakes in your ActionScript code, such as specifying the wrong data type for a method parameter; logical errors are mistakes in the logic (the data checking and value manipulation) of your program, such as using the wrong formula to calculate interest rates in a banking application. Again, both of these types of errors can often be detected and corrected ahead of time by diligently testing your application.

Ideally, you’ll want to identify and remove all errors from your application before it is released to end users. However, not all errors can be foreseen or prevented. For example, suppose your ActionScript application loads information from a particular website that is outside your control. If at some point that website isn’t available, the part of your application that depends on that external data won’t behave correctly. The most important aspect of error handling involves preparing for these unknown cases and handling them gracefully. Users need to continue to use your application, or at least get a friendly error message explaining why it isn’t working.

Run-time errors are represented in two ways in ActionScript:

  • Error classes: Many errors have an error class associated with them. When an error occurs, the Flash runtime (such as Flash Player or Adobe AIR) creates an instance of the specific error class that is associated with that particular error. Your code can use the information contained in that error object to make an appropriate response to the error.

  • Error events: Sometimes an error occurs when the Flash runtime would normally trigger an event. In those cases, an error event is triggered instead. Each error event has a class associated with it, and the Flash runtime passes an instance of that class to the methods that are subscribed to the error event.

To determine whether a particular method can trigger an error or error event, see the method’s entry in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Important concepts and terms

The following reference list contains important terms for programming error handling routines:

Asynchronous
A program command such as a method call that doesn’t provide an immediate result; instead it gives a result (or error) in the form of an event.

Catch
When an exception (a run-time error) occurs and your code becomes aware of the exception, that code is said to catch the exception. Once an exception is caught, the Flash runtime stops notifying other ActionScript code of the exception.

Debugger version
A special version of the Flash runtime, such as the Flash Player dubugger version or the AIR Debug Launcher (ADL), that contains code for notifying users of run-time errors. In the standard version of Flash Player or Adobe AIR (the one that most users have), errors that aren’t handled by your ActionScript code are ignored. In the debugger versions (which are included with Adobe Flash CS4 Professional and Adobe Flash Builder), a warning message appears when an unhandled error happens.

Exception
An error that happens while an application is running and that the Flash runtime can’t resolve on its own.

Re-throw
When your code catches an exception, the Flash runtime no longer notifies other objects of the exception. If it’s important for other objects to receive the exception, your code must re-throw the exception to start the notification process again.

Synchronous
A program command, such as a method call, that provides an immediate result (or immediately throws an error), meaning that the response can be used within the same code block.

Throw
The act of notifying a Flash runtime (and consequently, notifying other objects and ActionScript code) that an error has occurred is known as throwing an error.

Error handling in ActionScript 3.0

Since many applications can run without building the logic to handle errors, developers are tempted to postpone building error handling into their applications. However, without error handling, an application can easily stall or frustrate the user if something doesn’t work as expected. ActionScript 2.0 has an Error class that allows you to build logic into custom functions to throw an exception with a specific message. Because error handling is critical for making a user-friendly application, ActionScript 3.0 includes an expanded architecture for catching errors.

Note: While the ActionScript 3.0 Reference for the Adobe Flash Platform documents the exceptions thrown by many methods, it might not include all possible exceptions for each method. A method might throw an exception for syntax errors or other problems that are not noted explicitly in the method description, even when the description does list some of the exceptions a method throws.

ActionScript 3.0 error-handling elements

ActionScript 3.0 includes many tools for error handling, including:

  • Error classes. ActionScript 3.0 includes a broad range of Error classes to expand the scope of situations that can produce error objects. Each Error class helps applications handle and respond to specific error conditions, whether they are related to system errors (like a MemoryError condition), coding errors (like an ArgumentError condition), networking and communication errors (like a URIError condition), or other situations. For more information on each class, see Comparing the Error classes.

  • Fewer silent failures. In earlier versions of Flash Player, errors were generated and reported only if you explicitly used the throw statement. For Flash Player 9 and later Flash runtimes, native ActionScript methods and properties throw run-time errors. These errors allow you to handle these exceptions more effectively when they occur, then react to each exception, individually.

  • Clear error messages displayed during debugging. When you are using the debugger version of a Flash runtime, problematic code or situations generate robust error messages, which help you easily identify reasons why a particular block of code fails. These messages make fixing errors more efficient. For more information, see Working with the debugger versions of Flash runtimes.

  • Precise errors allow for clear error messages displayed to users. In previous versions of Flash Player, the FileReference.upload() method returned a Boolean value of false if the upload() call was unsuccessful, indicating one of five possible errors. If an error occurs when you call the upload() method in ActionScript 3.0, four specific errors help you display more accurate error messages to end users.

  • Refined error handling. Distinct errors are thrown for many common situations. For example, in ActionScript 2.0, before a FileReference object has been populated, the name property has the value null (so, before you can use or display the name property, ensure that the value is set and not null ). In ActionScript 3.0, if you attempt to access the name property before it has been populated, Flash Player or AIR throws an IllegalOperationError, which informs you that the value has not been set, and you can use try..catch..finally blocks to handle the error. For more information see Using try..catch..finally statements.

  • No significant performance drawbacks. Using try..catch..finally blocks to handle errors takes little or no additional resources compared to previous versions of ActionScript.

  • An ErrorEvent class that allows you to build listeners for specific asynchronous error events. For more information see Responding to error events and status.

Error-handling strategies

As long as your application doesn’t encounter a problematic condition, it can still run successfully if you don’t build error-handling logic into your code. However, if you don’t actively handle errors and your application does encounter a problem, your users will never know why your application fails when it does.

There are different ways you can approach error handling in your application. The following list summarizes the three major options for handling errors:

  • Use try..catch..finally statements. These statements catch synchronous errors as they occur. You can nest your statements into a hierarchy to catch exceptions at various levels of code execution. For more information, see Using try..catch..finally statements.

  • Create your own custom error objects. You can use the Error class to create your own custom error objects to track specific operations in your application that are not covered by built-in error types. Then you can use try..catch..finally statements on your custom error objects. For more information see Creating custom error classes.

  • Write event listeners and handlers to respond to error events. By using this strategy, you can create global error handlers that let you handle similar events without duplicating much code in try..catch..finally blocks. You are also more likely to catch asynchronous errors using this approach. For more information, see Responding to error events and status.

Types of errors

When you develop and run applications, you encounter different types of errors and error terminology. The following list introduces the major error types and terms:

  • Compile-time errors are raised by the ActionScript compiler during code compilation. Compile-time errors occur when syntactical problems in your code prevent your application from being built.

  • Run-time errors occur when you run your application after you compile it. Run-time errors represent errors that are caused while a SWF file plays in a Flash runtime (such as Adobe Flash Player or Adobe AIR). In most cases, you handle run-time errors as they occur, reporting them to the user and taking steps to keep your application running. If the error is a fatal error, such as not being able to connect to a remote website or load required data, you can use error handling to allow your application to finish, gracefully.

  • Synchronous errors are run-time errors that occur at the time a function is called—for example, when you try to use a specific method and the argument you pass to the method is invalid, so the Flash runtime throws an exception. Most errors occur synchronously—at the time the statement executes—and the flow of control passes immediately to the most applicable catch statement.

    For example, the following code excerpt throws a run-time error because the browse() method is not called before the program attempts to upload a file:

    var fileRef:FileReference = new FileReference(); 
    try 
    { 
        fileRef.upload(new URLRequest("http://www.yourdomain.com/fileupload.cfm")); 
    } 
    catch (error:IllegalOperationError) 
    { 
        trace(error); 
        // Error #2037: Functions called in incorrect sequence, or earlier 
        // call was unsuccessful. 
    }

    In this case, a run-time error is thrown synchronously because Flash Player determined that the browse() method was not called before the file upload was attempted.

    For detailed information on synchronous error handling, see Handling synchronous errors in an application.

  • Asynchronous errors are run-time errors that occur at various points during runtime; they generate events and event listeners catch them. An asynchronous operation is one in which a function initiates an operation, but doesn’t wait for it to complete. You can create an error event listener to wait for the application or user to try some operation. If the operation fails, you catch the error with an event listener and respond to the error event. Then, the event listener calls an event handler function to respond to the error event in a useful manner. For example, the event handler could launch a dialog box that prompts the user to resolve the error.

    Consider the file-upload synchronous error example presented earlier. If you successfully call the browse() method before beginning a file upload, Flash Player would dispatch several events. For example, when an upload starts, the open event is dispatched. When the file upload operation completes successfully, the complete event is dispatched. Because event handling is asynchronous (that is, it does not occur at specific, known, predesignated times), use the addEventListener() method to listen for these specific events, as the following code shows:

    var fileRef:FileReference = new FileReference(); 
    fileRef.addEventListener(Event.SELECT, selectHandler); 
    fileRef.addEventListener(Event.OPEN, openHandler); 
    fileRef.addEventListener(Event.COMPLETE, completeHandler); 
    fileRef.browse(); 
     
    function selectHandler(event:Event):void 
    { 
        trace("...select..."); 
        var request:URLRequest = new URLRequest("http://www.yourdomain.com/fileupload.cfm"); 
        request.method = URLRequestMethod.POST; 
        event.target.upload(request); 
    } 
    function openHandler(event:Event):void 
    { 
        trace("...open..."); 
    } 
    function completeHandler(event:Event):void 
    { 
        trace("...complete..."); 
    }

    For detailed information on asynchronous error handling, see Responding to error events and status.

  • Uncaught exceptions are errors thrown with no corresponding logic (like a catch statement) to respond to them. If your application throws an error, and no appropriate catch statement or event handler can be found at the current or higher level to handle the error, the error is considered an uncaught exception.

    When an uncaught error happens, the runtime dispatches an uncaughtError event. This event is also known as a “global error handler.” This event is dispatched by the SWF’s UncaughtErrorEvents object, which is available through the LoaderInfo.uncaughtErrorEvents property. If no listeners are registered for the uncaughtError event, the runtime ignores uncaught errors and tries to continue running, as long as the error doesn’t stop the SWF.

    In addition to dispatching the uncaughtError event, debugger versions of the Flash runtime respond to uncaught errors by terminating the current script. Then, they display the uncaught error in trace statement output or writing the error message to a log file. If the exception object is an instance of the Error class or one of its subclasses, the getStackTrace() method is called. The stack trace information is also displayed in trace statement output or in a log file. For more information about using the debugger version of Flash runtimes, see Working with the debugger versions of Flash runtimes.

    Note: While processing an uncaughtError event, if an error event is thrown from an uncaughtError handler, the event handler is called multiple times. This results in an infinite loop of exceptions. It is recommended that you avoid such a scenario.

Working with the debugger versions of Flash runtimes

Adobe provides developers with special editions of the Flash runtimes to assist debugging efforts. You obtain a copy of the debugger version of Flash Player when you install Adobe Flash Professional or Adobe Flash Builder. You also obtain a utility for the debugging of Adobe AIR applications, which is called ADL, when you install either of those tools, or as part of the Adobe AIR SDK.

There is a notable difference in how the debugger versions and the release versions of Flash Player and Adobe AIR indicate errors. The debugger versions shows the error type (such as a generic Error, IOError, or EOFError), error number, and a human-readable error message. The release versions shows only the error type and error number. For example, consider the following code:

try 
{ 
    tf.text = myByteArray.readBoolean(); 
} 
catch (error:EOFError) 
{ 
    tf.text = error.toString(); 
}

If the readBoolean() method throws an EOFError in the debugger version of Flash Player, the following message displays in the tf text field: “EOFError: Error #2030: End of file was encountered.”

The same code in a release version of Flash Player or Adobe AIR would display the following text: “EOFError: Error #2030.”
Note: The debugger players broadcast an event named "allComplete"; avoid creating custom events with the name “allComplete”. Otherwise, you will encounter unpredictable behavior when debugging.

To keep resources and size to a minimum in the release versions, error message strings are not present. You can look up the error number in the documentation (the appendixes of the ActionScript 3.0 Reference for the Adobe Flash Platform ) to correlate to an error message. Alternatively, you can reproduce the error using the debugger versions of Flash Player and AIR to see the full message.

Handling synchronous errors in an application

The most common error handling is synchronous error-handling logic, where you insert statements into your code to catch synchronous errors while an application is running. This type of error handling lets your application notice and recover from run-time errors when functions fail. The logic for catching a synchronous error includes try..catch..finally statements, which literally try an operation, catch any error response from the Flash runtime, and finally execute some other operation to handle the failed operation.

Using try..catch..finally statements

When you work with synchronous run-time errors, use the try..catch..finally statements to catch errors. When a run-time error occurs, the Flash runtime throws an exception, which means that it suspends normal execution and creates a special object of type Error. The Error object is then thrown to the first available catch block.

The try statement encloses statements that have the potential to create errors. You always use the catch statement with a try statement. If an error is detected in one of the statements in the try statement block, the catch statements that are attached to that try statement run.

The finally statement encloses statements that run whether an error occurs in the try block. If there is no error, the statements within the finally block execute after the try block statements complete. If there is an error, the appropriate catch statement executes first, followed by the statements in the finally block.

The following code demonstrates the syntax for using the try..catch..finally statements:

try 
{ 
    // some code that could throw an error 
} 
catch (err:Error) 
{ 
    // code to react to the error 
} 
finally 
{ 
    // Code that runs whether an error was thrown. This code can clean 
    // up after the error, or take steps to keep the application running. 
}

Each catch statement identifies a specific type of exception that it handles. The catch statement can specify only error classes that are subclasses of the Error class. Each catch statement is checked in order. Only the first catch statement that matches the type of error thrown runs. In other words, if you first check the higher-level Error class and then a subclass of the Error class, only the higher-level Error class matches. The following code illustrates this point:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
}

The previous code displays the following output:

<Error> I am an ArgumentError

To correctly catch the ArgumentError, make sure that the most specific error types are listed first and the more generic error types are listed later, as the following code shows:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
}

Several methods and properties in the ActionScript API throw run-time errors if they encounter errors while they execute. For example, the close() method in the Sound class throws an IOError if the method is unable to close the audio stream, as demonstrated in the following code:

var mySound:Sound = new Sound(); 
try 
{ 
    mySound.close(); 
} 
catch (error:IOError) 
{ 
    // Error #2029: This URLStream object does not have an open stream. 
}

As you become more familiar with the ActionScript 3.0 Reference for the Adobe Flash Platform , you’ll notice which methods throw exceptions, as detailed in each method’s description.

The throw statement

Flash runtimes throw exceptions when they encounter errors in your running application. In addition, you can explicitly throw exceptions yourself using the throw statement. When explicitly throwing errors, Adobe recommends that you throw instances of the Error class or its subclasses. The following code demonstrates a throw statement that throws an instance of the Error class, MyErr , and eventually calls a function, myFunction() , to respond after the error is thrown:

var MyError:Error = new Error("Encountered an error with the numUsers value", 99); 
var numUsers:uint = 0; 
try 
{ 
    if (numUsers == 0) 
    { 
        trace("numUsers equals 0"); 
    } 
} 
catch (error:uint) 
{ 
    throw MyError; // Catch unsigned integer errors. 
} 
catch (error:int) 
{ 
    throw MyError; // Catch integer errors. 
} 
catch (error:Number) 
{ 
    throw MyError; // Catch number errors. 
} 
catch (error:*) 
{ 
    throw MyError; // Catch any other error. 
} 
finally  
{ 
    myFunction(); // Perform any necessary cleanup here. 
}

Notice that the catch statements are ordered so that the most specific data types are listed first. If the catch statement for the Number data type is listed first, neither the catch statement for the uint data type nor the catch statement for the int data type is ever run.

Note: In the Java programming language, each function that can throw an exception must declare this fact, listing the exception classes it can throw in a throws clause attached to the function declaration. ActionScript does not require you to declare the exceptions thrown by a function.

Displaying a simple error message

One of the biggest benefits of the new exception and error event model is that it allows you to tell users when and why an action has failed. Your part is to write the code to display the message and offer options in response.

The following code shows a simple try..catch statement to display the error in a text field:

package 
{ 
    import flash.display.Sprite; 
    import flash.text.TextField; 
     
    public class SimpleError extends Sprite 
    { 
        public var employee:XML =  
            <EmpCode> 
                <costCenter>1234</costCenter> 
                <costCenter>1-234</costCenter> 
            </EmpCode>; 
 
        public function SimpleError() 
        { 
            try 
            { 
                if (employee.costCenter.length() != 1) 
                { 
                    throw new Error("Error, employee must have exactly one cost center assigned."); 
                } 
            }  
            catch (error:Error) 
            { 
                var errorMessage:TextField = new TextField(); 
                errorMessage.autoSize = TextFieldAutoSize.LEFT; 
                errorMessage.textColor = 0xFF0000; 
                errorMessage.text = error.message; 
                addChild(errorMessage); 
            } 
        } 
    } 
}

Using a wider range of error classes and built-in compiler errors, ActionScript 3.0 offers more information than previous versions of ActionScript about why something has failed. This information enables you to build more stable applications with better error handling.

Rethrowing errors

When you build applications, there are several occasions in which you need to rethrow an error if you are unable to handle the error properly. For example, the following code shows a nested try..catch block, which rethrows a custom ApplicationError if the nested catch block is unable to handle the error:

try 
{ 
    try 
    { 
        trace("<< try >>"); 
        throw new ApplicationError("some error which will be rethrown"); 
    } 
    catch (error:ApplicationError) 
    { 
        trace("<< catch >> " + error); 
        trace("<< throw >>"); 
        throw error; 
    } 
    catch (error:Error) 
    { 
        trace("<< Error >> " + error); 
    } 
} 
catch (error:ApplicationError) 
{ 
    trace("<< catch >> " + error); 
}

The output from the previous snippet would be the following:

<< try >> 
<< catch >> ApplicationError: some error which will be rethrown 
<< throw >> 
<< catch >> ApplicationError: some error which will be rethrown

The nested try block throws a custom ApplicationError error that is caught by the subsequent catch block. This nested catch block can try to handle the error, and if unsuccessful, throw the ApplicationError object to the enclosing try..catch block.

Responding to error events and status

One of the most noticeable improvements to error handling in ActionScript 3.0 is the support for error event handling for responding to asynchronous errors while an application is running. (For a definition of asynchronous errors, see Types of errors.)

You can create event listeners and event handlers to respond to the error events. Many classes dispatch error events the same way they dispatch other events. For example, an instance of the XMLSocket class normally dispatches three types of events: Event.CLOSE , Event.CONNECT , and DataEvent.DATA . However, when a problem occurs, the XMLSocket class can dispatch the IOErrorEvent.IOError or the SecurityErrorEvent.SECURITY_ERROR . For more information about event listeners and event handlers, see Handling events.

Error events fit into one of two categories:

  • Error events that extend the ErrorEvent class

    The flash.events.ErrorEvent class contains the properties and methods for managing errors related to networking and communication operations in a running application. The AsyncErrorEvent, IOErrorEvent, and SecurityErrorEvent classes extend the ErrorEvent class. If you’re using the debugger version of a Flash runtime, a dialog box informs you at run-time of any error events without listener functions that the player encounters.

  • Status-based error events

    The status-based error events are related to the netStatus and status properties of the networking and communication classes. If a Flash runtime encounters a problem when reading or writing data, the value of the netStatus.info.level or status.level properties (depending on the class object you’re using) is set to the value "error" . You respond to this error by checking if the level property contains the value "error" in your event handler function.

Working with error events

The ErrorEvent class and its subclasses contain error types for handling errors dispatched by Flash runtimes as they try to read or write data.

The following example uses both a try..catch statement and error event handlers to display any errors detected while trying to read a local file. You can add more sophisticated handling code to provide a user with options or otherwise handle the error automatically in the places indicated by the comment “your error-handling code here”:

package 
{ 
    import flash.display.Sprite; 
    import flash.errors.IOError; 
    import flash.events.IOErrorEvent; 
    import flash.events.TextEvent; 
    import flash.media.Sound; 
    import flash.media.SoundChannel; 
    import flash.net.URLRequest; 
    import flash.text.TextField; 
    import flash.text.TextFieldAutoSize; 
 
    public class LinkEventExample extends Sprite 
    { 
        private var myMP3:Sound; 
        public function LinkEventExample() 
        { 
            myMP3 = new Sound(); 
            var list:TextField = new TextField(); 
            list.autoSize = TextFieldAutoSize.LEFT; 
            list.multiline = true; 
            list.htmlText = "<a href=\"event:track1.mp3\">Track 1</a><br>"; 
            list.htmlText += "<a href=\"event:track2.mp3\">Track 2</a><br>"; 
            addEventListener(TextEvent.LINK, linkHandler); 
            addChild(list); 
        } 
         
        private function playMP3(mp3:String):void 
        { 
            try 
            { 
                myMP3.load(new URLRequest(mp3)); 
                myMP3.play(); 
            } 
            catch (err:Error) 
            { 
                trace(err.message); 
                // your error-handling code here 
            } 
            myMP3.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 
        } 
 
        private function linkHandler(linkEvent:TextEvent):void 
        { 
            playMP3(linkEvent.text); 
            // your error-handling code here 
        } 
         
        private function errorHandler(errorEvent:IOErrorEvent):void 
        { 
            trace(errorEvent.text); 
            // your error-handling code here 
        } 
    } 
}

Working with status change events

Flash runtimes dynamically change the value of the netStatus.info.level or status.level properties for the classes that support the level property while an application is running. The classes that have the netStatus.info.level property are NetConnection, NetStream, and SharedObject. The classes that have the status.level property are HTTPStatusEvent, Camera, Microphone, and LocalConnection. You can write a handler function to respond to the change in level value and track communication errors.

The following example uses a netStatusHandler() function to test the value of the level property. If the level property indicates that an error has been encountered, the code traces the message “Video stream failed”.

package 
{ 
    import flash.display.Sprite; 
    import flash.events.NetStatusEvent; 
    import flash.events.SecurityErrorEvent; 
    import flash.media.Video; 
    import flash.net.NetConnection; 
    import flash.net.NetStream; 
 
    public class VideoExample extends Sprite 
    { 
        private var videoUrl:String = "Video.flv"; 
        private var connection:NetConnection; 
        private var stream:NetStream; 
 
        public function VideoExample() 
        { 
            connection = new NetConnection(); 
            connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
            connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 
            connection.connect(null); 
        } 
 
        private function netStatusHandler(event:NetStatusEvent):void 
        { 
            if (event.info.level == "error") 
            { 
                trace("Video stream failed") 
            } 
            else  
            { 
                connectStream(); 
            } 
        } 
 
        private function securityErrorHandler(event:SecurityErrorEvent):void 
        { 
            trace("securityErrorHandler: " + event); 
        } 
 
        private function connectStream():void 
        { 
            var stream:NetStream = new NetStream(connection); 
            var video:Video = new Video(); 
            video.attachNetStream(stream); 
            stream.play(videoUrl); 
            addChild(video); 
        } 
    } 
}

Comparing the Error classes

ActionScript provides a number of predefined Error classes. But, you can also use the same Error classes in your own code. There are two main types of Error classes in ActionScript 3.0: ActionScript core Error classes and flash.error package Error classes. The flash.error package contains additional classes to aid ActionScript 3.0 application development and debugging.

Core Error classes

The core error classes include the Error, ArgumentError, EvalError, RangeError, ReferenceError, SecurityError, SyntaxError, TypeError, URIError, and VerifyError classes. Each of these classes are located in the top-level namespace.

Class name

Description

Notes

Error

The Error class is for throwing exceptions, and is the base class for the other exception classes defined in ECMAScript: EvalError, RangeError, ReferenceError, SyntaxError, TypeError, and URIError.

The Error class serves as the base class for all run-time errors, and is the recommended base class for any custom error classes.

ArgumentError

The ArgumentError class represents an error that occurs when the parameter values supplied during a function call do not match the parameters defined for that function.

Some examples of argument errors include the following:

  • Too few or too many arguments are supplied to a method.

  • An argument was expected to be a member of an enumeration and was not.

EvalError

An EvalError exception is thrown if any parameters are passed to the Function class’s constructor or if user code calls the eval() function.

In ActionScript 3.0, support for the eval() function has been removed and attempts to use the function result in an error.

Earlier versions of Flash Player used the eval() function to access variables, properties, objects, or movie clips by name.

RangeError

A RangeError exception is thrown if a numeric value falls outside an acceptable range.

For example, a RangeError is thrown by the Timer class if a delay was either negative or was not finite. A RangeError could also be thrown if you attempted to add a display object at an invalid depth.

ReferenceError

A ReferenceError exception is thrown when a reference to an undefined property is attempted on a sealed (nondynamic) object. Versions of the ActionScript compiler before ActionScript 3.0 did not throw an error when access was attempted to a property that was undefined . However ActionScript 3.0 throws the ReferenceError exception in this condition.

Exceptions for undefined variables point to potential bugs, helping you improve software quality. However, if you are not used to having to initialize your variables, this new ActionScript behavior requires some changes in your coding habits.

SecurityError

The SecurityError exception is thrown when a security violation takes place and access is denied.

Some examples of security errors include the following:

  • An unauthorized property access or method call is made across a security sandbox boundary.

  • An attempt was made to access a URL not permitted by the security sandbox.

  • A socket connection was attempted to a port but the necessary socket policy file wasn’t present.

  • An attempt was made to access the user's camera or microphone, and the user denide the access to the device .

SyntaxError

A SyntaxError exception is thrown when a parsing error occurs in your ActionScript code.

A SyntaxError can be thrown under the following circumstances:

  • ActionScript throws SyntaxError exceptions when the RegExp class parses an invalid regular expression.

  • ActionScript throws SyntaxError exceptions when the XMLDocument class parses invalid XML.

TypeError

The TypeError exception is thrown when the actual type of an operand is different from the expected type.

A TypeError can be thrown under the following circumstances:

  • An actual parameter of a function or method could not be coerced to the formal parameter type.

  • A value is assigned to a variable and cannot be coerced to the variable’s type.

  • The right side of the is or instanceof operator is not a valid type.

  • The super keyword is used illegally.

  • A property lookup results in more than one binding, and is therefore ambiguous.

  • A method is called on an incompatible object. For example, a TypeError exception is thrown if a method in the RegExp class is “grafted” onto a generic object and then called.

URIError

The URIError exception is thrown when one of the global URI handling functions is used in a way that is incompatible with its definition.

A URIError can be thrown under the following circumstances:

An invalid URI is specified for a Flash Player API function that expects a valid URI, such as Socket.connect() .

VerifyError

A VerifyError exception is thrown when a malformed or corrupted SWF file is encountered.

When a SWF file loads another SWF file, the parent SWF file can catch a VerifyError generated by the loaded SWF file.

flash.error package Error classes

The flash.error package contains Error classes that are considered part of the Flash runtime API. In contrast to the Error classes described, the flash.error package communicates errors events that are specific to Flash runtimes (such as Flash Player and Adobe AIR).

Class name

Description

Notes

EOFError

An EOFError exception is thrown when you attempt to read past the end of the available data.

For example, an EOFError is thrown when one of the read methods in the IDataInput interface is called and there is insufficient data to satisfy the read request.

IllegalOperationError

An IllegalOperationError exception is thrown when a method is not implemented or the implementation doesn't cover the current usage.

Examples of illegal operation error exceptions include the following:

  • A base class, such as DisplayObjectContainer, provides more functionality than the Stage can support. For example, if you attempt to get or set a mask on the Stage (using stage.mask ), the Flash runtime throws an IllegalOperationError with the message “The Stage class does not implement this property or method.”

  • A subclass inherits a method it does not require and does not want to support.

  • Certain accessibility methods are called when Flash Player is compiled without accessibility support.

  • Authoring-only features are called from a run-time version of Flash Player.

  • You attempt to set the name of an object placed on the timeline.

IOError

An IOError exception is thrown when some type of I/O exception occurs.

You get this error, for example, when a read-write operation is attempted on a socket that is not connected or that has become disconnected.

MemoryError

A MemoryError exception is thrown when a memory allocation request fails.

By default, ActionScript Virtual Machine 2 does not impose a limit on how much memory an ActionScript program allocates. On a desktop system, memory allocation failures are infrequent. You see an error thrown when the system is unable to allocate the memory required for an operation. So, on a desktop system, this exception is rare unless an allocation request is extremely large; for example, a request for 3 billion bytes is impossible because a 32-bit Microsoft® Windows® program can access only 2 GB of address space.

ScriptTimeoutError

A ScriptTimeoutError exception is thrown when a script timeout interval of 15 seconds is reached. By catching a ScriptTimeoutError exception, you can handle the script timeout more gracefully. If there is no exception handler, the uncaught exception handler displays a dialog box with an error message.

To prevent a malicious developer from catching the exception and staying in an infinite loop, only the first ScriptTimeoutError exception thrown in the course of a particular script can be caught. A subsequent ScriptTimeoutError exception cannot be caught by your code and immediately goes to the uncaught exception handler.

StackOverflowError

The StackOverflowError exception is thrown when the stack available to the script has been exhausted.

A StackOverflowError exception might indicate that infinite recursion has occurred.

TOPIC_TITLE

Arrays (advanced)

Associative arrays

An associative array, sometimes called a hash or map , uses keys instead of a numeric index to organize stored values. Each key in an associative array is a unique string that is used to access a stored value. An associative array is an instance of the Object class, which means that each key corresponds to a property name. Associative arrays are unordered collections of key and value pairs. Your code should not expect the keys of an associative array to be in a specific order.

ActionScript 3.0 also includes an advanced type of associative array called a dictionary . Dictionaries, which are instances of the Dictionary class in the flash.utils package, use keys that can be of any data type. In other words, dictionary keys are not limited to values of type String.

Associative arrays with string keys

There are two ways to create associative arrays in ActionScript 3.0. The first way is to use an Object instance. By using an Object instance you can initialize your array with an object literal. An instance of the Object class, also called a generic object , is functionally identical to an associative array. Each property name of the generic object serves as the key that provides access to a stored value.

The following example creates an associative array named monitorInfo , using an object literal to initialize the array with two key and value pairs:

var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"}; 
trace(monitorInfo["type"], monitorInfo["resolution"]);  
// output: Flat Panel 1600 x 1200

If you do not need to initialize the array at declaration time, you can use the Object constructor to create the array, as follows:

var monitorInfo:Object = new Object();

After the array is created using either an object literal or the Object class constructor, you can add new values to the array using either the array access ( [] ) operator or the dot operator ( . ). The following example adds two new values to monitorArray :

monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces 
monitorInfo.colors = "16.7 million"; 
trace(monitorInfo["aspect ratio"], monitorInfo.colors); 
// output: 16:10 16.7 million

Note that the key named aspect ratio contains a space character. This is possible with the array access ( [] ) operator, but generates an error if attempted with the dot operator. Using spaces in your key names is not recommended.

The second way to create an associative array is to use the Array constructor (or the constructor of any dynamic class) and then use either the array access ( [] ) operator or the dot operator ( . ) to add key and value pairs to the array. If you declare your associative array to be of type Array, you cannot use an object literal to initialize the array. The following example creates an associative array named monitorInfo using the Array constructor and adds a key called type and a key called resolution , along with their values:

var monitorInfo:Array = new Array(); 
monitorInfo["type"] = "Flat Panel"; 
monitorInfo["resolution"] = "1600 x 1200"; 
trace(monitorInfo["type"], monitorInfo["resolution"]);  
// output: Flat Panel 1600 x 1200

There is no advantage in using the Array constructor to create an associative array. You cannot use the Array.length property or any of the methods of the Array class with associative arrays, even if you use the Array constructor or the Array data type. The use of the Array constructor is best left for the creation of indexed arrays.

Associative arrays with object keys (Dictionaries)

You can use the Dictionary class to create an associative array that uses objects for keys rather than strings. Such arrays are sometimes called dictionaries, hashes, or maps. For example, consider an application that determines the location of a Sprite object based on its association with a specific container. You can use a Dictionary object to map each Sprite object to a container.

The following code creates three instances of the Sprite class that serve as keys for the Dictionary object. Each key is assigned a value of either GroupA or GroupB . The values can be of any data type, but in this example both GroupA and GroupB are instances of the Object class. Subsequently, you can access the value associated with each key with the array access ( [] ) operator, as shown in the following code:

import flash.display.Sprite; 
import flash.utils.Dictionary; 
 
var groupMap:Dictionary = new Dictionary(); 
 
// objects to use as keys 
var spr1:Sprite = new Sprite(); 
var spr2:Sprite = new Sprite(); 
var spr3:Sprite = new Sprite(); 
 
// objects to use as values 
var groupA:Object = new Object(); 
var groupB:Object = new Object(); 
 
// Create new key-value pairs in dictionary. 
groupMap[spr1] = groupA; 
groupMap[spr2] = groupB; 
groupMap[spr3] = groupB; 
 
if (groupMap[spr1] == groupA) 
{ 
    trace("spr1 is in groupA");  
} 
if (groupMap[spr2] == groupB) 
{ 
    trace("spr2 is in groupB");  
} 
if (groupMap[spr3] == groupB) 
{ 
    trace("spr3 is in groupB");  
}

Iterating with object keys

You can iterate through the contents of a Dictionary object with either a for..in loop or a for each..in loop. A for..in loop allows you to iterate based on the keys, whereas a for each..in loop allows you to iterate based on the values associated with each key.

Use the for..in loop for direct access to the object keys of a Dictionary object. You can also access the values of the Dictionary object with the array access ( [] ) operator. The following code uses the previous example of the groupMap dictionary to show how to iterate through a Dictionary object with the for..in loop:

for (var key:Object in groupMap) 
{ 
    trace(key, groupMap[key]); 
} 
/* output: 
[object Sprite] [object Object] 
[object Sprite] [object Object] 
[object Sprite] [object Object] 
*/

Use the for each..in loop for direct access to the values of a Dictionary object. The following code also uses the groupMap dictionary to show how to iterate through a Dictionary object with the for each..in loop:

for each (var item:Object in groupMap) 
{ 
    trace(item); 
} 
/* output: 
[object Object] 
[object Object] 
[object Object] 
*/

Object keys and memory management

Adobe® Flash® Player and Adobe® AIR™ use a garbage collection system to recover memory that is no longer used. When an object has no references pointing to it, the object becomes eligible for garbage collection, and the memory is recovered the next time the garbage collection system executes. For example, the following code creates a new object and assigns a reference to the object to the variable myObject :

var myObject:Object = new Object();

As long as any reference to the object exists, the garbage collection system will not recover the memory that the object occupies. If the value of myObject is changed such that it points to a different object or is set to the value null , the memory occupied by the original object becomes eligible for garbage collection, but only if there are no other references to the original object.

If you use myObject as a key in a Dictionary object, you are creating another reference to the original object. For example, the following code creates two references to an object—the myObject variable, and the key in the myMap object:

import flash.utils.Dictionary; 
 
var myObject:Object = new Object(); 
var myMap:Dictionary = new Dictionary(); 
myMap[myObject] = "foo";

To make the object referenced by myObject eligible for garbage collection, you must remove all references to it. In this case, you must change the value of myObject and delete the myObject key from myMap , as shown in the following code:

myObject = null; 
delete myMap[myObject];

Alternatively, you can use the useWeakReference parameter of the Dictionary constructor to make all of the dictionary keys weak references . The garbage collection system ignores weak references, which means that an object that has only weak references is eligible for garbage collection. For example, in the following code, you do not need to delete the myObject key from myMap in order to make the object eligible for garbage collection:

import flash.utils.Dictionary; 
 
var myObject:Object = new Object(); 
var myMap:Dictionary = new Dictionary(true); 
myMap[myObject] = "foo"; 
myObject = null; // Make object eligible for garbage collection.

Multidimensional arrays

Multidimensional arrays contain other arrays as elements. For example, consider a list of tasks that is stored as an indexed array of strings:

var tasks:Array = ["wash dishes", "take out trash"];

If you want to store a separate list of tasks for each day of the week, you can create a multidimensional array with one element for each day of the week. Each element contains an indexed array, similar to the tasks array, that stores the list of tasks. You can use any combination of indexed or associative arrays in multidimensional arrays. The examples in the following sections use either two indexed arrays or an associative array of indexed arrays. You might want to try the other combinations as exercises.

Two indexed arrays

When you use two indexed arrays, you can visualize the result as a table or spreadsheet. The elements of the first array represent the rows of the table, while the elements of the second array represent the columns.

For example, the following multidimensional array uses two indexed arrays to track task lists for each day of the week. The first array, masterTaskList , is created using the Array class constructor. Each element of the array represents a day of the week, with index 0 representing Monday, and index 6 representing Sunday. These elements can be thought of as the rows in the table. You can create each day’s task list by assigning an array literal to each of the seven elements that you create in the masterTaskList array. The array literals represent the columns in the table.

var masterTaskList:Array = new Array(); 
masterTaskList[0] = ["wash dishes", "take out trash"]; 
masterTaskList[1] = ["wash dishes", "pay bills"]; 
masterTaskList[2] = ["wash dishes", "dentist", "wash dog"]; 
masterTaskList[3] = ["wash dishes"]; 
masterTaskList[4] = ["wash dishes", "clean house"]; 
masterTaskList[5] = ["wash dishes", "wash car", "pay rent"]; 
masterTaskList[6] = ["mow lawn", "fix chair"];

You can access individual items on any of the task lists using the array access ( [] ) operator. The first set of brackets represents the day of the week, and the second set of brackets represents the task list for that day. For example, to retrieve the second task from Wednesday’s list, first use index 2 for Wednesday, and then use index 1 for the second task in the list.

trace(masterTaskList[2][1]); // output: dentist

To retrieve the first task from Sunday’s list, use index 6 for Sunday and index 0 for the first task on the list.

trace(masterTaskList[6][0]); // output: mow lawn

Associative array with an indexed array

To make the individual arrays easier to access, you can use an associative array for the days of the week and an indexed array for the task lists. Using an associative array allows you to use dot syntax when referring to a particular day of the week, but at the cost of extra run-time processing to access each element of the associative array. The following example uses an associative array as the basis of a task list, with a key and value pair for each day of the week:

var masterTaskList:Object = new Object(); 
masterTaskList["Monday"] = ["wash dishes", "take out trash"]; 
masterTaskList["Tuesday"] = ["wash dishes", "pay bills"]; 
masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"]; 
masterTaskList["Thursday"] = ["wash dishes"]; 
masterTaskList["Friday"] = ["wash dishes", "clean house"]; 
masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"]; 
masterTaskList["Sunday"] = ["mow lawn", "fix chair"];

Dot syntax makes the code more readable by making it possible to avoid multiple sets of brackets.

trace(masterTaskList.Wednesday[1]); // output: dentist 
trace(masterTaskList.Sunday[0]);// output: mow lawn

You can iterate through the task list using a for..in loop, but you must use the array access ( [] ) operator instead of dot syntax to access the value associated with each key. Because masterTaskList is an associative array, the elements are not necessarily retrieved in the order that you may expect, as the following example shows:

for (var day:String in masterTaskList) 
{ 
    trace(day + ": " + masterTaskList[day]) 
} 
/* output: 
Sunday: mow lawn,fix chair 
Wednesday: wash dishes,dentist,wash dog 
Friday: wash dishes,clean house 
Thursday: wash dishes 
Monday: wash dishes,take out trash 
Saturday: wash dishes,wash car,pay rent 
Tuesday: wash dishes,pay bills 
*/

Cloning arrays

The Array class has no built-in method for making copies of arrays. You can create a shallow copy of an array by calling either the concat() or slice() methods with no arguments. In a shallow copy, if the original array has elements that are objects, only the references to the objects are copied rather than the objects themselves. The copy points to the same objects as the original does. Any changes made to the objects are reflected in both arrays.

In a deep copy , any objects found in the original array are also copied so that the new array does not point to the same objects as does the original array. Deep copying requires more than one line of code, which usually calls for the creation of a function. Such a function could be created as a global utility function or as a method of an Array subclass.

The following example defines a function named clone() that does deep copying. The algorithm is borrowed from a common Java programming technique. The function creates a deep copy by serializing the array into an instance of the ByteArray class, and then reading the array back into a new array. This function accepts an object so that it can be used with both indexed arrays and associative arrays, as shown in the following code:

import flash.utils.ByteArray; 
 
function clone(source:Object):* 
{ 
    var myBA:ByteArray = new ByteArray(); 
    myBA.writeObject(source); 
    myBA.position = 0; 
    return(myBA.readObject()); 
}

Vectors

XML

Working with XML

ActionScript 3.0 includes a group of classes based on the ECMAScript for XML (E4X) specification (ECMA-357 edition 2). These classes include powerful and easy-to-use functionality for working with XML data. Using E4X, you will be able to develop code with XML data faster than was possible with previous programming techniques. As an added benefit, the code you produce will be easier to read.

Basics of XML

XML is a standard way of representing structured information so that it is easy for computers to work with and reasonably easy for people to write and understand. XML is an abbreviation for eXtensible Markup Language. The XML standard is available at www.w3.org/XML/ .

XML offers a standard and convenient way to categorize data, to make it easier to read, access, and manipulate. XML uses a tree structure and tag structure that is similar to HTML. Here is a simple example of XML data:

<song> 
    <title>What you know?</title> 
    <artist>Steve and the flubberblubs</artist> 
    <year>1989</year> 
    <lastplayed>2006-10-17-08:31</lastplayed> 
</song>

XML data can also be more complex, with tags nested in other tags as well as attributes and other structural components. Here is a more complex example of XML data:

<album> 
    <title>Questions, unanswered</title> 
    <artist>Steve and the flubberblubs</artist> 
    <year>1989</year> 
    <tracks> 
        <song tracknumber="1" length="4:05"> 
            <title>What do you know?</title> 
            <artist>Steve and the flubberblubs</artist> 
            <lastplayed>2006-10-17-08:31</lastplayed> 
        </song> 
        <song tracknumber="2" length="3:45"> 
            <title>Who do you know?</title> 
            <artist>Steve and the flubberblubs</artist> 
            <lastplayed>2006-10-17-08:35</lastplayed> 
        </song> 
        <song tracknumber="3" length="5:14"> 
            <title>When do you know?</title> 
            <artist>Steve and the flubberblubs</artist> 
            <lastplayed>2006-10-17-08:39</lastplayed> 
        </song> 
        <song tracknumber="4" length="4:19"> 
            <title>Do you know?</title> 
            <artist>Steve and the flubberblubs</artist> 
            <lastplayed>2006-10-17-08:44</lastplayed> 
        </song> 
    </tracks> 
</album>

Notice that this XML document contains other complete XML structures within it (such as the song tags with their children). It also demonstrates other XML structures such as attributes ( tracknumber and length in the song tags), and tags that contain other tags rather than containing data (such as the tracks tag).

Getting started with XML

If you have little or no experience with XML, here is a brief description of the most common aspects of XML data. XML data is written in plain-text form, with a specific syntax for organizing the information into a structured format. Generally, a single set of XML data is known as an XML document . In XML format, data is organized into elements (which can be single data items or containers for other elements) using a hierarchical structure. Every XML document has a single element as the top level or main item; inside this root element there may be a single piece of information, although there are more likely to be other elements, which in turn contain other elements, and so forth. For example, this XML document contains the information about a music album:

<song tracknumber="1" length="4:05"> 
    <title>What do you know?</title> 
    <artist>Steve and the flubberblubs</artist> 
    <mood>Happy</mood> 
    <lastplayed>2006-10-17-08:31</lastplayed> 
</song>

Each element is distinguished by a set of tags —the element’s name wrapped in angle brackets (less-than and greater-than signs). The opening tag, indicating the start of the element, has the element name:

<title>

The closing tag, which marks the end of the element, has a forward slash before the element’s name:

</title>

If an element contains no content, it can be written as an empty element (sometimes called a self-closing element). In XML, this element:

<lastplayed/>

is identical to this element:

<lastplayed></lastplayed>

In addition to the element’s content contained between the opening and closing tags, an element can also include other values, known as attributes , defined in the element’s opening tag. For example, this XML element defines a single attribute named length , with the value "4:19" :

<song length="4:19"></song>

Each XML element has content, which is either a single value, one or more XML elements, or nothing (for an empty element).

Learning more about XML

To learn more about working with XML, there are a number of additional books and resources for learning more about XML, including these web sites:

ActionScript classes for working with XML

ActionScript 3.0 includes several classes that are used for working with XML-structured information. The two main classes are as follows:

  • XML: Represents a single XML element, which can be an XML document with multiple children or a single-value element within a document.

  • XMLList: Represents a set of XML elements. An XMLList object is used when there are multiple XML elements that are “siblings” (at the same level, and contained by the same parent, in the XML document’s hierarchy). For instance, an XMLList instance would be the easiest way to work with this set of XML elements (presumably contained in an XML document):

    <artist type="composer">Fred Wilson</artist> 
    <artist type="conductor">James Schmidt</artist> 
    <artist type="soloist">Susan Harriet Thurndon</artist>

For more advanced uses involving XML namespaces, ActionScript also includes the Namespace and QName classes. For more information, see Using XML namespaces.

In addition to the built-in classes for working with XML, ActionScript 3.0 also includes several operators that provide specific functionality for accessing and manipulating XML data. This approach to working with XML using these classes and operators is known as ECMAScript for XML (E4X), as defined by the ECMA-357 edition 2 specification.

Important concepts and terms

The following reference list contains important terms you will encounter when programming XML handling routines:

Element
A single item in an XML document, identified as the content contained between a starting tag and an ending tag (including the tags). XML elements can contain text data or other elements, or can be empty.

Empty element
An XML element that contains no child elements. Empty elements are often written as self-closing tags (such as <element/> ).

Document
A single XML structure. An XML document can contain any number of elements (or can consist only of a single empty element); however, an XML document must have a single top-level element that contains all the other elements in the document.

Node
Another name for an XML element.

Attribute
A named value associated with an element that is written into the opening tag of the element in attributename="value" format, rather than being written as a separate child element nested inside the element.

The E4X approach to XML processing

The ECMAScript for XML specification defines a set of classes and functionality for working with XML data. These classes and functionality are known collectively as E4X. ActionScript 3.0 includes the following E4X classes: XML, XMLList, QName, and Namespace.

The methods, properties, and operators of the E4X classes are designed with the following goals:

  • Simplicity—Where possible, E4X makes it easier to write and understand code for working with XML data.

  • Consistency—The methods and reasoning behind E4X are internally consistent and consistent with other parts of ActionScript.

  • Familiarity—You manipulate XML data with well-known operators, such as the dot ( . ) operator.

Note: There is a different XML class in ActionScript 2.0. In ActionScript 3.0 that class has been renamed as XMLDocument, so that the name does not conflict with the ActionScript 3.0 XML class that is part of E4X. In ActionScript 3.0, the legacy classes—XMLDocument, XMLNode, XMLParser, and XMLTag—are included in the flash.xml package primarily for legacy support. The new E4X classes are core classes; you need not import a package to use them. For details on the legacy ActionScript 2.0 XML classes, see the flash.xml package in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Here is an example of manipulating data with E4X:

var myXML:XML =  
    <order> 
        <item id='1'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
        <item id='2'> 
            <menuName>fries</menuName> 
            <price>1.45</price> 
        </item> 
    </order>

Often, your application will load XML data from an external source, such as a web service or a RSS feed. However, for clarity, the code examples provided here assign XML data as literals.

As the following code shows, E4X includes some intuitive operators, such as the dot ( . ) and attribute identifier ( @ ) operators, for accessing properties and attributes in the XML:

trace(myXML.item[0].menuName); // Output: burger 
trace(myXML.item.(@id==2).menuName); // Output: fries 
trace(myXML.item.(menuName=="burger").price); // Output: 3.95

Use the appendChild() method to assign a new child node to the XML, as the following snippet shows:

var newItem:XML =  
    <item id="3"> 
        <menuName>medium cola</menuName> 
        <price>1.25</price> 
    </item> 
 
myXML.appendChild(newItem);

Use the @ and . operators not only to read data, but also to assign data, as in the following:

myXML.item[0].menuName="regular burger"; 
myXML.item[1].menuName="small fries"; 
myXML.item[2].menuName="medium cola"; 
 
myXML.item.(menuName=="regular burger").@quantity = "2"; 
myXML.item.(menuName=="small fries").@quantity = "2"; 
myXML.item.(menuName=="medium cola").@quantity = "2";

Use a for loop to iterate through nodes of the XML, as follows:

var total:Number = 0; 
for each (var property:XML in myXML.item) 
{ 
    var q:int = Number(property.@quantity); 
    var p:Number = Number(property.price); 
    var itemTotal:Number = q * p; 
    total += itemTotal; 
    trace(q + " " + property.menuName + " $" + itemTotal.toFixed(2)) 
} 
trace("Total: $", total.toFixed(2));

XML objects

An XML object may represent an XML element, attribute, comment, processing instruction, or text element.

An XML object is classified as having either simple content or complex content . An XML object that has child nodes is classified as having complex content. An XML object is said to have simple content if it is any one of the following: an attribute, a comment, a processing instruction, or a text node.

For example, the following XML object contains complex content, including a comment and a processing instruction:

XML.ignoreComments = false; 
XML.ignoreProcessingInstructions = false; 
var x1:XML =  
    <order> 
        <!--This is a comment. --> 
        <?PROC_INSTR sample ?> 
        <item id='1'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
        <item id='2'> 
            <menuName>fries</menuName> 
            <price>1.45</price> 
        </item> 
    </order>

As the following example shows, you can now use the comments() and processingInstructions() methods to create new XML objects, a comment and a processing instruction:

var x2:XML = x1.comments()[0]; 
var x3:XML = x1.processingInstructions()[0];
XML properties

The XML class has five static properties:

  • The ignoreComments and ignoreProcessingInstructions properties determine whether comments or processing instructions are ignored when the XML object is parsed.

  • The ignoreWhitespace property determines whether white space characters are ignored in element tags and embedded expressions that are separated only by white space characters.

  • The prettyIndent a nd prettyPrinting properties are used to format the text that is returned by the toString() and toXMLString() methods of the XML class.

For details on these properties, see the ActionScript 3.0 Reference for the Adobe Flash Platform .

XML methods

The following methods allow you to work with the hierarchical structure of XML objects:

  • appendChild()

  • child()

  • childIndex()

  • children()

  • descendants()

  • elements()

  • insertChildAfter()

  • insertChildBefore()

  • parent()

  • prependChild()

The following methods allow you to work with XML object attributes:

  • attribute()

  • attributes()

The following methods allow you to you work with XML object properties:

  • hasOwnProperty()

  • propertyIsEnumerable()

  • replace()

  • setChildren()

The following methods are for working with qualified names and namespaces:

  • addNamespace()

  • inScopeNamespaces()

  • localName()

  • name()

  • namespace()

  • namespaceDeclarations()

  • removeNamespace()

  • setLocalName()

  • setName()

  • setNamespace()

The following methods are for working with and determining certain types of XML content:

  • comments()

  • hasComplexContent()

  • hasSimpleContent()

  • nodeKind()

  • processingInstructions()

  • text()

The following methods are for conversion to strings and for formatting XML objects:

  • defaultSettings()

  • setSettings()

  • settings()

  • normalize()

  • toString()

  • toXMLString()

There are a few additional methods:

  • contains()

  • copy()

  • valueOf()

  • length()

For details on these methods, see the ActionScript 3.0 Reference for the Adobe Flash Platform .

XMLList objects

An XMLList instance represents an arbitrary collection of XML objects. It can contain full XML documents, XML fragments, or the results of an XML query.

The following methods allow you to work with the hierarchical structure of XMLList objects:

  • child()

  • children()

  • descendants()

  • elements()

  • parent()

The following methods allow you to work with XMLList object attributes:

  • attribute()

  • attributes()

The following methods allow you to you work with XMLList properties:

  • hasOwnProperty()

  • propertyIsEnumerable()

The following methods are for working with and determining certain types of XML content:

  • comments()

  • hasComplexContent()

  • hasSimpleContent()

  • processingInstructions()

  • text()

The following are for conversion to strings and for formatting the XMLList object:

  • normalize()

  • toString()

  • toXMLString()

There are a few additional methods:

  • contains()

  • copy()

  • length()

  • valueOf()

For details on these methods, see the ActionScript 3.0 Reference for the Adobe Flash Platform .

For an XMLList object that contains exactly one XML element, you can use all properties and methods of the XML class, because an XMLList with one XML element is treated the same as an XML object. For example, in the following code, because doc.div is an XMLList object containing one element, you can use the appendChild() method from the XML class:

var doc:XML =  
        <body> 
            <div> 
                <p>Hello</p> 
            </div> 
        </body>; 
doc.div.appendChild(<p>World</p>);

For a list of XML properties and methods, see XML objects.

Initializing XML variables

You can assign an XML literal to an XML object, as follows:

var myXML:XML =  
    <order> 
        <item id='1'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
        <item id='2'> 
            <menuName>fries</menuName> 
            <price>1.45</price> 
        </item> 
    </order>

As the following snippet shows, you can also use the new constructor to create an instance of an XML object from a string that contains XML data:

var str:String = "<order><item id='1'><menuName>burger</menuName>" 
                            + "<price>3.95</price></item></order>"; 
var myXML:XML = new XML(str);

If the XML data in the string is not well formed (for example, if a closing tag is missing), you will see a run-time error.

You can also pass data by reference (from other variables) into an XML object, as the following example shows:

var tagname:String = "item";  
var attributename:String = "id";  
var attributevalue:String = "5";  
var content:String = "Chicken";  
var x:XML = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>;  
trace(x.toXMLString()) 
    // Output: <item id="5">Chicken</item>

To load XML data from a URL, use the URLLoader class, as the following example shows:

import flash.events.Event; 
import flash.net.URLLoader; 
import flash.net.URLRequest; 
 
var externalXML:XML; 
var loader:URLLoader = new URLLoader(); 
var request:URLRequest = new URLRequest("xmlFile.xml"); 
loader.load(request); 
loader.addEventListener(Event.COMPLETE, onComplete); 
 
function onComplete(event:Event):void 
{ 
    var loader:URLLoader = event.target as URLLoader; 
    if (loader != null) 
    { 
        externalXML = new XML(loader.data); 
        trace(externalXML.toXMLString()); 
    } 
    else 
    { 
        trace("loader is not a URLLoader!"); 
    } 
}

To read XML data from a socket connection, use the XMLSocket class. For more information, see the XMLSocket class in the ActionScript 3.0 Reference for the Adobe Flash Platform .

Assembling and transforming XML objects

Use the prependChild() method or the appendChild() method to add a property to the beginning or end of an XML object’s list of properties, as the following example shows:

var x1:XML = <p>Line 1</p>  
var x2:XML = <p>Line 2</p>  
var x:XML = <body></body> 
x = x.appendChild(x1); 
x = x.appendChild(x2); 
x = x.prependChild(<p>Line 0</p>); 
    // x == <body><p>Line 0</p><p>Line 1</p><p>Line 2</p></body>

Use the insertChildBefore() method or the insertChildAfter() method to add a property before or after a specified property, as follows:

var x:XML =  
    <body> 
        <p>Paragraph 1</p>  
        <p>Paragraph 2</p> 
    </body> 
var newNode:XML = <p>Paragraph 1.5</p>  
x = x.insertChildAfter(x.p[0], newNode) 
x = x.insertChildBefore(x.p[2], <p>Paragraph 1.75</p>)

As the following example shows, you can also use curly brace operators ( { and } ) to pass data by reference (from other variables) when constructing XML objects:

var ids:Array = [121, 122, 123];  
var names:Array = [["Murphy","Pat"], ["Thibaut","Jean"], ["Smith","Vijay"]] 
var x:XML = new XML("<employeeList></employeeList>"); 
 
for (var i:int = 0; i < 3; i++) 
{ 
    var newnode:XML = new XML();  
    newnode = 
        <employee id={ids[i]}> 
            <last>{names[i][0]}</last> 
            <first>{names[i][1]}</first> 
        </employee>; 
 
    x = x.appendChild(newnode) 
}

You can assign properties and attributes to an XML object by using the = operator, as in the following:

var x:XML =  
    <employee> 
        <lastname>Smith</lastname> 
    </employee> 
x.firstname = "Jean"; 
x.@id = "239";

This sets the XML object x to the following:

<employee id="239"> 
    <lastname>Smith</lastname> 
    <firstname>Jean</firstname> 
</employee>

You can use the + and += operators to concatenate XMLList objects:

var x1:XML = <a>test1</a>  
var x2:XML = <b>test2</b>  
var xList:XMLList = x1 + x2; 
xList += <c>test3</c>

This sets the XMLList object xList to the following:

<a>test1</a> 
<b>test2</b> 
<c>test3</c>

Traversing XML structures

One of the powerful features of XML is its ability to provide complex, nested data via a linear string of text characters. When you load data into an XML object, ActionScript parses the data and loads its hierarchical structure into memory (or it sends a run-time error if the XML data is not well formed).

The operators and methods of the XML and XMLList objects make it easy to traverse the structure of XML data.

Use the dot (.) operator and the descendent accessor (..) operator to access child properties of an XML object. Consider the following XML object:

var myXML:XML =  
    <order> 
        <book ISBN="0942407296"> 
            <title>Baking Extravagant Pastries with Kumquats</title> 
            <author> 
                <lastName>Contino</lastName> 
                <firstName>Chuck</firstName> 
            </author> 
            <pageCount>238</pageCount> 
        </book> 
        <book ISBN="0865436401"> 
            <title>Emu Care and Breeding</title> 
            <editor> 
                <lastName>Case</lastName> 
                <firstName>Justin</firstName> 
            </editor> 
            <pageCount>115</pageCount> 
        </book> 
    </order>

The object myXML.book is an XMLList object containing child properties of the myXML object that have the name book . These are two XML objects, matching the two book properties of the myXML object.

The object myXML..lastName is an XMLList object containing any descendent properties with the name lastName . These are two XML objects, matching the two lastName of the myXML object.

The object myXML.book.editor.lastName is an XMLList object containing any children with the name lastName of children with the name editor of children with the name book of the myXML object: in this case, an XMLList object containing only one XML object (the lastName property with the value " Case ").

Accessing parent and child nodes

The parent() method returns the parent of an XML object.

You can use the ordinal index values of a child list to access specific child objects. For example, consider an XML object myXML that has two child properties named book . Each child property named book has an index number associated with it:

myXML.book[0] 
myXML.book[1]

To access a specific grandchild, you can specify index numbers for both the child and grandchild names:

myXML.book[0].title[0]

However, if there is only one child of x.book[0] that has the name title , you can omit the index reference, as follows:

myXML.book[0].title

Similarly, if there is only one book child of the object x , and if that child object has only one title object, you can omit both index references, like this:

myXML.book.title

You can use the child() method to navigate to children with names based on a variable or expression, as the following example shows:

var myXML:XML =  
        <order> 
            <book> 
                <title>Dictionary</title> 
            </book> 
        </order>; 
 
var childName:String = "book"; 
 
trace(myXML.child(childName).title) // output: Dictionary
Accessing attributes

Use the @ symbol (the attribute identifier operator) to access attributes in an XML or XMLList object, as shown in the following code:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.@id); // 6401

You can use the * wildcard symbol with the @ symbol to access all attributes of an XML or XMLList object, as in the following code:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.@*.toXMLString());  
// 6401 
// 233

You can use the attribute() or attributes() method to access a specific attribute or all attributes of an XML or XMLList object, as in the following code:

var employee:XML =  
    <employee id="6401" code="233"> 
        <lastName>Wu</lastName> 
        <firstName>Erin</firstName> 
    </employee>; 
trace(employee.attribute("id")); // 6401 
trace(employee.attribute("*").toXMLString());  
// 6401 
// 233 
trace(employee.attributes().toXMLString());  
// 6401 
// 233

Note that you can also use the following syntax to access attributes, as the following example shows:

employee.attribute("id") 
employee["@id"] 
employee.@["id"]

These are each equivalent to employee.@id . However, the syntax employee.@id is the preferred approach.

Filtering by attribute or element value

You can use the parentheses operators— ( and ) —to filter elements with a specific element name or attribute value. Consider the following XML object:

var x:XML =  
    <employeeList> 
        <employee id="347"> 
            <lastName>Zmed</lastName> 
            <firstName>Sue</firstName> 
            <position>Data analyst</position> 
        </employee> 
        <employee id="348"> 
            <lastName>McGee</lastName> 
            <firstName>Chuck</firstName> 
            <position>Jr. data analyst</position> 
        </employee> 
    </employeeList>

The following expressions are all valid:

  • x.employee.(lastName == "McGee") —This is the second employee node.

  • x.employee.(lastName == "McGee").firstName —This is the firstName property of the second employee node.

  • x.employee.(lastName == "McGee").@id —This is the value of the id attribute of the second employee node.

  • x.employee.(@id == 347) —The first employee node.

  • x.employee.(@id == 347).lastName —This is the lastName property of the first employee node.

  • x.employee.(@id > 300) —This is an XMLList with both employee properties.

  • x.employee.(position.toString().search("analyst") > -1) —This is an XMLList with both position properties.

If you try to filter on attributes or elements that do not exist, an exception is thrown. For example, the final line of the following code generates an error, because there is no id attribute in the second p element:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(@id == '123'));

Similarly, the final line of following code generates an error because there is no b property of the second p element:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(b == 'Bob'));

To avoid these errors, you can identify the properties that have the matching attributes or elements by using the attribute() and elements() methods, as in the following code:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(attribute('id') == '123')); 
trace(doc.p.(elements('b') == 'Bob'));

You can also use the hasOwnProperty() method, as in the following code:

var doc:XML =  
            <body> 
                <p id='123'>Hello, <b>Bob</b>.</p> 
                <p>Hello.</p> 
            </body>; 
trace(doc.p.(hasOwnProperty('@id') && @id == '123')); 
trace(doc.p.(hasOwnProperty('b') && b == 'Bob'));
Using the for..in and the for each..in statements

ActionScript 3.0 includes the for..in statement and the for each..in statement for iterating through XMLList objects. For example, consider the following XML object, myXML , and the XMLList object, myXML.item . The XMLList object, myXML.item, consists of the two item nodes of the XML object.

var myXML:XML =  
    <order> 
        <item id='1' quantity='2'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
        <item id='2' quantity='2'> 
            <menuName>fries</menuName> 
            <price>1.45</price> 
        </item> 
    </order>;

The for..in statement lets you iterate over a set of property names in an XMLList:

var total:Number = 0; 
for (var pname:String in myXML.item) 
{ 
    total += myXML.item.@quantity[pname] * myXML.item.price[pname]; 
}

The for each..in statement lets you iterate through the properties in the XMLList:

var total2:Number = 0; 
for each (var prop:XML in myXML.item) 
{ 
    total2 += prop.@quantity * prop.price; 
}

Using XML namespaces

Namespaces in an XML object (or document) identify the type of data that the object contains. For example, in sending and delivering XML data to a web service that uses the SOAP messaging protocol, you declare the namespace in the opening tag of the XML:

var message:XML =  
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  
        <soap:Body xmlns:w="http://www.test.com/weather/"> 
            <w:getWeatherResponse>  
                <w:tempurature >78</w:tempurature>  
            </w:getWeatherResponse>  
        </soap:Body>  
    </soap:Envelope>;

The namespace has a prefix, soap , and a URI that defines the namespace, http://schemas.xmlsoap.org/soap/envelope/ .

ActionScript 3.0 includes the Namespace class for working with XML namespaces. For the XML object in the previous example, you can use the Namespace class as follows:

var soapNS:Namespace = message.namespace("soap"); 
trace(soapNS); // Output: http://schemas.xmlsoap.org/soap/envelope/ 
 
var wNS:Namespace = new Namespace("w", "http://www.test.com/weather/"); 
message.addNamespace(wNS); 
var encodingStyle:XMLList = message.@soapNS::encodingStyle; 
var body:XMLList = message.soapNS::Body; 
 
message.soapNS::Body.wNS::GetWeatherResponse.wNS::tempurature = "78";

The XML class includes the following methods for working with namespaces: addNamespace() , inScopeNamespaces() , localName() , name() , namespace() , namespaceDeclarations() , removeNamespace() , setLocalName() , setName() , and setNamespace() .

The default xml namespace directive lets you assign a default namespace for XML objects. For example, in the following, both x1 and x2 have the same default namespace:

var ns1:Namespace = new Namespace("http://www.example.com/namespaces/"); 
default xml namespace = ns1; 
var x1:XML = <test1 />; 
var x2:XML = <test2 />;

XML type conversion

You can convert XML objects and XMLList objects to String values. Similarly, you can convert strings to XML objects and XMLList objects. Also, keep in mind that all XML attribute values, names, and text values are strings. The following sections discuss all these forms of XML type conversion.

Converting XML and XMLList objects to strings

The XML and XMLList classes include a toString() method and a toXMLString() method. The toXMLString() method returns a string that includes all tags, attributes, namespace declarations, and content of the XML object. For XML objects with complex content (child elements), the toString() method does exactly the same as the toXMLString() method. For XML objects with simple content (those that contain only one text element), the toString() method returns only the text content of the element, as the following example shows:

var myXML:XML =  
    <order> 
        <item id='1' quantity='2'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
    <order>; 
 
trace(myXML.item[0].menuName.toXMLString());  
    // <menuName>burger</menuName> 
trace(myXML.item[0].menuName.toString()); 
    // burger

If you use the trace() method without specifying toString() or toXMLString() , the data is converted using the toString() method by default, as this code shows:

var myXML:XML =  
    <order> 
        <item id='1' quantity='2'> 
            <menuName>burger</menuName> 
            <price>3.95</price> 
        </item> 
    <order>; 
 
trace(myXML.item[0].menuName);  
    // burger

When using the trace() method to debug code, you will often want to use the toXMLString() method so that the trace() method outputs more complete data.

Converting strings to XML objects

You can use the new XML() constructor to create an XML object from a string, as follows:

var x:XML = new XML("<a>test</a>");

If you attempt to convert a string to XML from a string that represents invalid XML or XML that is not well formed, a run-time error is thrown, as follows:

var x:XML = new XML("<a>test"); // throws an error
Converting attribute values, names, and text values from strings

All XML attribute values, names, and text values are String data types, and you may need to convert these to other data types. For example, the following code uses the Number() function to convert text values to numbers:

var myXML:XML =  
                        <order> 
                            <item> 
                                <price>3.95</price> 
                            </item> 
                            <item> 
                                <price>1.00</price> 
                            </item> 
                        </order>; 
 
var total:XML = <total>0</total>; 
myXML.appendChild(total); 
 
for each (var item:XML in myXML.item) 
{ 
    myXML.total.children()[0] = Number(myXML.total.children()[0])  
                                                + Number(item.price.children()[0]); 
} 
trace(myXML.total); // 4.95;

If this code did not use the Number() function, the code would interpret the + operator as the string concatenation operator, and the trace() method in the last line would output the following:

01.003.95

Reading external XML documents

You can use the URLLoader class to load XML data from a URL. To use the following code in your applications, replace the XML_URL value in the example with a valid URL:

import flash.events.Event; 
import flash.net.URLLoader; 
 
var myXML:XML = new XML(); 
var XML_URL:String = "http://www.example.com/Sample3.xml"; 
var myXMLURL:URLRequest = new URLRequest(XML_URL); 
var myLoader:URLLoader = new URLLoader(myXMLURL); 
myLoader.addEventListener(Event.COMPLETE, xmlLoaded); 
 
function xmlLoaded(event:Event):void 
{ 
    myXML = XML(myLoader.data); 
    trace("Data loaded."); 
}

You can also use the XMLSocket class to set up an asynchronous XML socket connection with a server. For more information, see the ActionScript 3.0 Reference for the Adobe Flash Platform .

Creating new events by subclassing Event

Custom events

You can create custom events as part of defining MXML and ActionScript components. Custom events let you add functionality to your custom components to respond to user interactions, to trigger actions by your custom component, and to take advantage of data binding.

For more information on creating custom events for MXML components, see Advanced MXML Components. For information on creating custom events for ActionScript components, see Simple Visual Components in ActionScript.

About events

Adobe Flex applications are event-driven. Events let an application know when the user interacts with the interface, and also when important changes happen in the appearance or life cycle of a component, such as the creation of a component or its resizing. Events can be generated by user input devices, such as the mouse and keyboard, or by the asynchronous operations, such as the return of a web service call or the firing of a timer.

The core class of the Flex component architecture, mx.core.UIComponent , defines core events, such as updateComplete , resize , move , creationComplete , and others that are fundamental to all components. Subclasses of UIComponent inherit these events.

Custom components that extend existing Flex classes inherit all the events of the base class. Therefore, if you extend the Button class to create the MyButton class, you can use the click event and the events that all controls inherit, such as mouseOver or initialize , as the following example shows:

<?xml version="1.0"?> 
<!-- createcomps_events/EventsMyApplication.mxml --> 
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myComponents.*"> 
    <fx:Script> 
        <![CDATA[ 
            import flash.events.Event; 
 
            // Event listener for the click event. 
            private function handleClick(eventObj:Event):void { 
                // Define event listener. 
            } 
 
            // Event listener for the initialize event. 
            private function handleInit(eventObj:Event):void { 
                // Define event listener. 
            } 
        ]]> 
    </fx:Script> 
 
    <MyComp:MyButton 
        click="handleClick(event);" 
        initialize="handleInit(event);"/> 
 
</s:Application>

In addition to using the events inherited from its superclasses, your custom components can define custom events. You use custom events to support data binding, to respond to user interactions, or to trigger actions by your component.

For more information on the Flex event mechanism, see Using Events.

Using an event object

When a Flex component dispatches an event, it creates an event object, where the properties of the event object contain information describing the event. An event listener takes this event object as an argument and accesses the properties of the object to determine information about the event.

The base class for all event objects is the flash.events.Event class. All event objects are instances of the Event class, or instances of a subclass of the Event class.

The following table describes the public properties of the Event class. The Event class implements these properties using getter methods.

Property

Type

Description

type

String

The name of the event; for example, "click" . The event constructor sets this property.

target

EventDispatcher

A reference to the component instance that dispatches the event. This property is set by the dispatchEvent() method; you cannot change this to a different object.

currentTarget

EventDispatcher

A reference to the component instance that is actively processing the Event object. The value of this property is different from the value of the target property during the event capture and bubbling phase. For more information, see Using Events.

eventPhase

uint

The current phase in the event flow. The property might contain the following values:

  • EventPhase.CAPTURING_PHASE : The capture phase

  • EventPhase.AT_TARGET : The target phase

  • EventPhase.BUBBLING_PHASE : The bubbling phase

bubbles

Boolean

Whether an event is a bubbling event. If the event can bubble, the value for this property is true; otherwise, it is false . You can optionally pass this property as a constructor argument to the Event class. By default, most event classes set this property to false . For more information, see Using Events.

cancelable

Boolean

Whether the event can be canceled. If the event can be canceled, the value for this value is true; otherwise, it is false . You can optionally pass this property as a constructor argument to the Event class. By default, most event classes set this property to false . For more information, see Using Events.

Dispatching custom events

Flex defines many of the most common events, such as the click event for the Button control; however, your application may require that you create events. In your custom Flex components, you can dispatch any of the predefined events inherited by the component from its superclass, and dispatch new events that you define within the component.

To dispatch a new event from your custom component, you must do the following:

  1. (Optional) Create a subclass from the flash.events.Event class to create an event class that describes the event object. For more information, see Creating a subclass from the Event class.

  2. (Optional) Use the [Event] metadata tag to make the event public so that the MXML compiler recognizes it. For more information, see Using the Event metadata tag.

  3. Dispatch the event using the dispatchEvent() method. For more information, see Dispatching an event.

Creating a subclass from the Event class

All events use an event object to transmit information about the event to the event listener, where the base class for all event objects is the flash.events.Event class. When you define a custom event, you can dispatch an event object of the Event type, or you can create a subclass of the Event class to dispatch an event object of a different type. You typically create a subclass of the Event class when your event requires you to add information to the event object, such as a new property to hold information that the event listener requires.

For example, the event objects associated with the Flex Tree control include a property named node , which identifies the node of the Tree control associated with the event. To support the node property, the Tree control dispatches event objects of type TreeEvent, a subclass of the Event class.

Within your subclass of the Event class, you can add properties, add methods, set the value of an inherited property, or override methods inherited from the Event class. For example, you might want to set the bubbles property to true to override the default setting of false , which is inherited from the Event class.

You are required to override the Event.clone() method in your subclass. The clone() method returns a cloned copy of the event object by setting the type property and any new properties in the clone. Typically, you define the clone() method to return an event instance created with the new operator.

Suppose that you want to pass information about the state of your component to the event listener as part of the event object. To do so, you create a subclass of the Event class to create an event, EnableChangeEvent, as the following example shows:

package myEvents 
{ 
    //createcomps_events/myEvents/EnableChangeEvent.as 
    import flash.events.Event; 
 
    public class EnableChangeEvent extends Event 
    { 
 
        // Public constructor. 
        public function EnableChangeEvent(type:String, 
            isEnabled:Boolean=false) { 
                // Call the constructor of the superclass. 
                super(type); 
    
                // Set the new property. 
                this.isEnabled = isEnabled; 
        } 
 
        // Define static constant. 
        public static const ENABLE_CHANGE:String = "enableChange"; 
 
        // Define a public variable to hold the state of the enable property. 
        public var isEnabled:Boolean; 
 
        // Override the inherited clone() method. 
        override public function clone():Event { 
            return new EnableChangeEvent(type, isEnabled); 
        } 
    } 
}

In this example, your custom class defines a public constructor that takes two arguments:

  • A String value that contains the value of the type property of the Event object.

  • An optional Boolean value that contains the state of the component’s isEnabled property. By convention, all constructor arguments for class properties, except for the type argument, are optional.

    From within the body of your constructor, you call the super() method to initialize the base class properties.

Using the Event metadata tag

You use the [Event] metadata tag to define events dispatched by a component so that the Flex compiler can recognize them as MXML tag attributes in an MXML file. You add the [Event] metadata tag in one of the following locations:

  • ActionScript components

    Above the class definition, but within the package definition, so that the events are bound to the class and not a particular member of the class.

  • MXML components

    In the <fx:Metadata> tag of an MXML file.

The Event metadata keyword has the following syntax:

[Event(name="eventName", type="package.eventType")]

The eventName argument specifies the name of the event. The eventType argument specifies the class name, including the package, that defines the event object.

The following example identifies the enableChange event as an event that an ActionScript component can dispatch:

[Event(name="enableChange", type="myEvents.EnableChangeEvent")] 
public class MyComponent extends TextArea 
{ 
    ... 
}

The following example shows the [Event] metadata tag within the <fx:Metadata> tag of an MXML file:

<?xml version="1.0"?> 
<!-- createcomps_events\myComponents\MyButton.mxml --> 
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    click="dispatchEvent(new EnableChangeEvent('enableChange'));"> 
 
    <fx:Script> 
        <![CDATA[ 
            import myEvents.EnableChangeEvent; 
        ]]> 
    </fx:Script> 
 
    <fx:Metadata> 
        [Event(name="enableChange", type="myEvents.EnableChangeEvent")] 
    </fx:Metadata> 
</s:Button>

Once you define the event using the [Event] metadata tag, you can refer to the event in an MXML file, as the following example shows:

<?xml version="1.0"?> 
<!-- createcomps_events/MainEventApp.mxml --> 
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myComponents.*" > 
    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout> 
 
    <fx:Script> 
        <![CDATA[ 
            import myEvents.EnableChangeEvent; 
 
            public function 
                enableChangeListener(eventObj:EnableChangeEvent):void { 
                    // Handle event. 
                    myTA2.text='got event'; 
            } 
        ]]> 
    </fx:Script> 
 
    <MyComp:MyButton enableChange="myTA.text='got event';" /> 
    <mx:TextArea id="myTA" /> 
 
    <MyComp:MyButton enableChange="enableChangeListener(event);" /> 
    <mx:TextArea id="myTA2" /> 
</s:Application>

If you do not identify an event with the [Event] metadata tag, the compiler generates an error if you try to use the event name in MXML. The metadata for events is inherited from the superclass, however, so you do not need to tag events that are already defined with the [Event] metadata tag in the superclass.

Dispatching an event

You use the dispatchEvent() method to dispatch an event. The dispatchEvent() method has the following signature:

public dispatchEvent(event:Event):Boolean

This method requires an argument of the Event type, which is the event object. The dispatchEvent() method initializes the target property of the event object with a reference to the component dispatching the event.

You can create an event object and dispatch the event in a single statement, as the following example shows:

dispatchEvent(new Event("click")); 

You can also create an event object, initialize it, and then dispatch it, as the following example shows:

var eventObj:EnableChangeEvent = new EnableChangeEvent("enableChange"); 
eventObj.isEnabled=true; 
dispatchEvent(eventObj);

For complete examples that create and dispatch custom events, see Advanced MXML Components and Simple Visual Components in ActionScript.

Creating static constants for the Event.type property

The constructor of an event class typically takes a single required argument that specifies the value of the event object’s type property. In the previous section, you passed the string enableChange to the constructor, as the following example shows:

// Define event object, initialize it, then dispatch it.  
var eventObj:EnableChangeEvent = new EnableChangeEvent("enableChange"); 
dispatchEvent(eventObj);

The Flex compiler does not examine the string passed to the constructor to determine if it is valid. Therefore, the following code compiles, even though enableChangeAgain might not be a valid value for the type property:

var eventObj:EnableChangeEvent =  
    new EnableChangeEvent("enableChangeAgain");

Because the compiler does not check the value of the type property, the only time that your application can determine if enableChangeAgain is valid is at run time.

However, to ensure that the value of the type property is valid at compile time, Flex event classes define static constants for the possible values for the type property. For example, the Flex EffectEvent class defines the following static constant:

// Define static constant for event type. 
public static const EFFECT_END:String = "effectEnd";

To create an instance of an EffectEvent class, you use the following constructor:

var eventObj:EffectEvent = new EffectEvent(EffectEvent.EFFECT_END);

If you incorrectly reference the constant in the constructor, the compiler generates a syntax error because it cannot locate the associated constant. For example, the following constructor generates a syntax error at compile time because MY_EFFECT_END is not a predefined constant of the EffectEvent class:

var eventObj:EffectEvent = new EffectEvent(EffectEvent.MY_EFFECT_END);

You can use this technique when you define your event classes. The following example modifies the definition of the EnableChangeEventConst class to include a static constant for the type property:

package myEvents 
{ 
    //createcomps_events/myEvents/EnableChangeEventConst.as 
    import flash.events.Event; 
 
    public class EnableChangeEventConst extends Event 
    {   
        // Public constructor. 
        public function EnableChangeEventConst(type:String, 
            isEnabled:Boolean=false) { 
                // Call the constructor of the superclass. 
                super(type); 
                
                // Set the new property. 
                this.isEnabled = isEnabled; 
        } 
 
        // Define static constant. 
        public static const ENABLE_CHANGE:String = "myEnable"; 
            
        // Define a public variable to hold the state of the enable property. 
        public var isEnabled:Boolean; 
 
        // Override the inherited clone() method. 
        override public function clone():Event { 
            return new EnableChangeEvent(type, isEnabled); 
        } 
    } 
}

Now you create an instance of the class by using the static constant, as the following example shows for the MyButtonConst custom component:

<?xml version="1.0"?> 
<!-- createcomps_events\myComponents\MyButtonConst.mxml --> 
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    click="dispatchEvent(new EnableChangeEventConst(EnableChangeEventConst.ENABLE_CHANGE));"> 
 
    <fx:Script> 
        <![CDATA[ 
            import myEvents.EnableChangeEventConst; 
        ]]> 
    </fx:Script> 
 
    <fx:Metadata> 
        [Event(name="myEnable", type="myEvents.EnableChangeEventConst")] 
    </fx:Metadata> 
</s:Button>

This technique does not preclude you from passing a string to the constructor.

Regular expressions

Using regular expressions

A regular expression describes a pattern that is used to find and manipulate matching text in strings. Regular expressions resemble strings, but they can include special codes to describe patterns and repetition. For example, the following regular expression matches a string that starts with the character A followed by one or more sequential digits:

/A\d+/

The following topics describe the basic syntax for constructing regular expressions. However, regular expressions can have many complexities and nuances. You can find detailed resources on regular expressions on the web and in bookstores. Keep in mind that different programming environments implement regular expressions in different ways. ActionScript 3.0 implements regular expressions as defined in the ECMAScript edition 3 language specification (ECMA-262).

Basics of regular expressions

A regular expression describes a pattern of characters. Regular expressions are typically used to verify that a text value conforms to a particular pattern (such as verifying that a user-entered phone number has the proper number of digits) or to replace portions of a text value that matches a particular pattern.

Regular expressions can be simple. For example, suppose you wanted to confirm that a particular string matches “ABC,” or wanted to replace every occurrence of “ABC” in a string with some other text. In that case, you could use the following regular expression, which defines the pattern consisting of the letters A, B, and C in sequence:

/ABC/

Note that the regular expression literal is delineated with the forward slash ( / ) character.

Regular expression patterns can also be complex, and sometimes cryptic in appearance, such as the following expression to match a valid e-mail address:

/([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}/

Most commonly you will use regular expressions to search for patterns in strings and to replace characters. In those cases, you will create a regular expression object and use it as a parameter for one of several String class methods. The following methods of the String class take regular expressions as parameters: match() , replace() , search() , and split() . For more information on these methods, see Finding patterns in strings and replacing substrings.

The RegExp class includes the following methods: test() and exec() . For more information, see Methods for using regular expressions with strings.

Important concepts and terms

The following reference list contains important terms that are relevant to this feature:

Escape character
A character indicating that the character that follows should be treated as a metacharacter rather than a literal character. In regular expression syntax, the backslash character (\) is the escape character, so a backslash followed by another character is a special code rather than just the character itself.

Flag
A character that specifies some option about how the regular expression pattern should be used, such as whether to distinguish between uppercase and lowercase characters.

Metacharacter
A character that has special meaning in a regular expression pattern, as opposed to literally representing that character in the pattern.

Quantifier
A character (or several characters) indicating how many times a part of the pattern should repeat. For example, a quantifier would be used to designate that a United States postal code should contain five or nine numbers.

Regular expression
A program statement defining a pattern of characters that can be used to confirm whether other strings match that pattern or to replace portions of a string.

Regular expression syntax

This section describes all of the elements of ActionScript regular expression syntax. As you’ll see, regular expressions can have many complexities and nuances. You can find detailed resources on regular expressions on the web and in bookstores. Keep in mind that different programming environments implement regular expressions in different ways. ActionScript 3.0 implements regular expressions as defined in the ECMAScript edition 3 language specification (ECMA-262).

Generally, you use regular expressions that match more complicated patterns than a simple string of characters. For example, the following regular expression defines the pattern consisting of the letters A, B, and C in sequence followed by any digit:

/ABC\d/

The \d code represents “any digit.” The backslash ( \ ) character is called the escape character, and combined with the character that follows it (in this case the letter d), it has special meaning in the regular expression.

The following regular expression defines the pattern of the letters ABC followed by any number of digits (note the asterisk):

/ABC\d*/

The asterisk character ( * ) is a metacharacter . A metacharacter is a character that has special meaning in regular expressions. The asterisk is a specific type of metacharacter called a quantifier, which is used to quantify the amount of repetition of a character or group of characters. For more information, see Quantifiers.

In addition to its pattern, a regular expression can contain flags, which specify how the regular expression is to be matched. For example, the following regular expression uses the i flag, which specifies that the regular expression ignores case sensitivity in matching strings:

/ABC\d*/i

For more information, see Flags and properties.

You can use regular expressions with the following methods of the String class: match() , replace() , and search() . For more information on these methods, see Finding patterns in strings and replacing substrings.

Creating an instance of a regular expression

There are two ways to create a regular expression instance. One way uses forward slash characters ( / ) to delineate the regular expression; the other uses the new constructor. For example, the following regular expressions are equivalent:

var pattern1:RegExp = /bob/i; 
var pattern2:RegExp = new RegExp("bob", "i");

Forward slashes delineate a regular expression literal in the same way as quotation marks delineate a string literal. The part of the regular expression within the forward slashes defines the pattern. The regular expression can also include flags after the final delineating slash. These flags are considered to be part of the regular expression, but they are separate from its pattern.

When using the new constructor, you use two strings to define the regular expression. The first string defines the pattern, and the second string defines the flags, as in the following example:

var pattern2:RegExp = new RegExp("bob", "i");

When including a forward slash within a regular expression that is defined by using the forward slash delineators, you must precede the forward slash with the backslash ( \ ) escape character. For example, the following regular expression matches the pattern 1/2 :

var pattern:RegExp = /1\/2/;

To include quotation marks within a regular expression that is defined with the new constructor, you must add backslash ( \ ) escape character before the quotation marks (just as you would when defining any String literal). For example, the following regular expressions match the pattern eat at "joe's" :

var pattern1:RegExp = new RegExp("eat at \"joe's\"", ""); 
var pattern2:RegExp = new RegExp('eat at "joe\'s"', "");

Do not use the backslash escape character with quotation marks in regular expressions that are defined by using the forward slash delineators. Similarly, do not use the escape character with forward slashes in regular expressions that are defined with the new constructor. The following regular expressions are equivalent, and they define the pattern 1/2 "joe's" :

var pattern1:RegExp = /1\/2 "joe's"/; 
var pattern2:RegExp = new RegExp("1/2 \"joe's\"", ""); 
var pattern3:RegExp = new RegExp('1/2 "joe\'s"', '');

Also, in a regular expression that is defined with the new constructor, to use a metasequence that begins with the backslash ( \ ) character, such as \d (which matches any digit), type the backslash character twice:

var pattern:RegExp = new RegExp("\\d+", ""); // matches one or more digits

You must type the backlash character twice in this case, because the first parameter of the RegExp() constructor method is a string, and in a string literal you must type a backslash character twice to have it recognized as a single backslash character.

The sections that follow describe syntax for defining regular expression patterns.

For more information on flags, see Flags and properties.

Characters, metacharacters, and metasequences

The simplest regular expression is one that matches a sequence of characters, as in the following example:

var pattern:RegExp = /hello/;

However, the following characters, known as metacharacters , have special meanings in regular expressions:

^ $ \ . * + ? ( ) [ ] { } |

For example, the following regular expression matches the letter A followed by zero or more instances of the letter B (the asterisk metacharacter indicates this repetition), followed by the letter C:

/AB*C/

To include a metacharacter without its special meaning in a regular expression pattern, you must use the backslash ( \ ) escape character. For example, the following regular expression matches the letter A followed by the letter B, followed by an asterisk, followed by the letter C:

var pattern:RegExp = /AB\*C/;

A metasequence, like a metacharacter, has special meaning in a regular expression. A metasequence is made up of more than one character. The following sections provide details on using metacharacters and metasequences.

About metacharacters

The following table summarizes the metacharacters that you can use in regular expressions:

Metacharacter

Description

^ (caret)

Matches at the start of the string. With the m ( multiline ) flag set, the caret matches the start of a line as well (see Flags and properties). Note that when used at the start of a character class, the caret indicates negation, not the start of a string. For more information, see Character classes.

$ (dollar sign)

Matches at the end of the string. With the m ( multiline ) flag set, $ matches the position before a newline ( \n ) character as well. For more information, see Flags and properties.

\ (backslash)

Escapes the special metacharacter meaning of special characters.

Also, use the backslash character if you want to use a forward slash character in a regular expression literal, as in /1\/2/ (to match the character 1, followed by the forward slash character, followed by the character 2).

. (dot)

Matches any single character.

A dot matches a newline character ( \n ) only if the s ( dotall ) flag is set. For more information, see Flags and properties.

* (star)

Matches the previous item repeated zero or more times.

For more information, see Quantifiers.

+ (plus)

Matches the previous item repeated one or more times.

For more information, see Quantifiers.

? (question mark)

Matches the previous item repeated zero times or one time.

For more information, see Quantifiers.

( and )

Defines groups within the regular expression. Use groups for the following:

  • To confine the scope of the | alternator: /(a|b|c)d/

  • To define the scope of a quantifier: /(walla.){1,2}/

  • In backreferences. For example, the \1 in the following regular expression matches whatever matched the first parenthetical group of the pattern:

  • /(\w*) is repeated: \1/

For more information, see Groups.

[ and ]

Defines a character class, which defines possible matches for a single character:

/[aeiou]/ matches any one of the specified characters.

Within character classes, use the hyphen ( - ) to designate a range of characters:

/[A-Z0-9]/ matches uppercase A through Z or 0 through 9.

Within character classes, insert a backslash to escape the ] and

- characters:

/[+\-]\d+/ matches either + or - before one or more digits.

Within character classes, other characters, which are normally metacharacters, are treated as normal characters (not metacharacters), without the need for a backslash:

/[$]/ £ matches either $ or £.

For more information, see Character classes.

| (pipe)

Used for alternation, to match either the part on the left side or the part on the right side:

/abc|xyz/ matches either abc or xyz .

About metasequences

Metasequences are sequences of characters that have special meaning in a regular expression pattern. The following table describes these metasequences:

Metasequence

Description

{ n }

{ n ,}

and

{ n , n }

Specifies a numeric quantifier or quantifier range for the previous item:

/A{27}/ matches the character A repeated 27 times.

/A{3,}/ matches the character A repeated 3 or more times.

/A{3,5}/ matches the character A repeated 3 to 5 times.

For more information, see Quantifiers.

\b

Matches at the position between a word character and a nonword character. If the first or last character in the string is a word character, also matches the start or end of the string.

\B

Matches at the position between two word characters. Also matches the position between two nonword characters.

\d

Matches a decimal digit.

\D

Matches any character other than a digit.

\f

Matches a form feed character.

\n

Matches the newline character.

\r

Matches the return character.

\s

Matches any white-space character (a space, tab, newline, or return character).

\S

Matches any character other than a white-space character.

\t

Matches the tab character.

\u nnnn

Matches the Unicode character with the character code specified by the hexadecimal number nnnn . For example, \u263a is the smiley character.

\v

Matches a vertical feed character.

\w

Matches a word character ( AZ –, az –, 0-9 , or _ ). Note that \w does not match non-English characters, such as é , ñ , or ç .

\W

Matches any character other than a word character.

\\x nn

Matches the character with the specified ASCII value, as defined by the hexadecimal number nn .

Character classes

You use character classes to specify a list of characters to match one position in the regular expression. You define character classes with square brackets ( [ and ] ). For example, the following regular expression defines a character class that matches bag , beg , big , bog , or bug :

/b[aeiou]g/

Escape sequences in character classes

Most metacharacters and metasequences that normally have special meanings in a regular expression do not have those same meanings inside a character class. For example, in a regular expression, the asterisk is used for repetition, but this is not the case when the asterisk appears in a character class. The following character class matches the asterisk literally, along with any of the other characters listed:

/[abc*123]/

However, the three characters listed in the following table do function as metacharacters, with special meaning, in character classes:

Metacharacter

Meaning in character classes

]

Defines the end of the character class.

-

Defines a range of characters (see the following section “Ranges of characters in character classes”).

\

Defines metasequences and undoes the special meaning of metacharacters.

For any of these characters to be recognized as literal characters (without the special metacharacter meaning), you must precede the character with the backslash escape character. For example, the following regular expression includes a character class that matches any one of four symbols ( $ , \ , ] , or - ):

/[$\\\]\-]/

In addition to the metacharacters that retain their special meanings, the following metasequences function as metasequences within character classes:

Metasequence

Meaning in character classes

\n

Matches a newline character.

\r

Matches a return character.

\t

Matches a tab character.

\u nnnn

Matches the character with the specified Unicode code point value (as defined by the hexadecimal number nnnn ).

\\x nn

Matches the character with the specified ASCII value (as defined by the hexadecimal number nn ).

Other regular expression metasequences and metacharacters are treated as normal characters within a character class.

Ranges of characters in character classes

Use the hyphen to specify a range of characters, such as A-Z , a-z , or 0-9 . These characters must constitute a valid range in the character set. For example, the following character class matches any one of the characters in the range a-z or any digit:

/[a-z0-9]/

You can also use the \\x nn ASCII character code to specify a range by ASCII value. For example, the following character class matches any character from a set of extended ASCII characters (such as é and ê ):

\\x

Negated character classes

When you use a caret ( ^ ) character at the beginning of a character class, it negates that class—any character not listed is considered a match. The following character class matches any character except for a lowercase letter ( az –) or a digit:

/[^a-z0-9]/

You must type the caret ( ^ ) character at the beginning of a character class to indicate negation. Otherwise, you are simply adding the caret character to the characters in the character class. For example, the following character class matches any one of a number of symbol characters, including the caret:

/[!.,#+*%$&^]/
Quantifiers

You use quantifiers to specify repetitions of characters or sequences in patterns, as follows:

Quantifier metacharacter

Description

* (star)

Matches the previous item repeated zero or more times.

+ (plus)

Matches the previous item repeated one or more times.

? (question mark)

Matches the previous item repeated zero times or one time.

{ n }

{ n ,}

and

{ n , n }

Specifies a numeric quantifier or quantifier range for the previous item:

/A{27}/ matches the character A repeated 27 times.

/A{3,}/ matches the character A repeated 3 or more times.

/A{3,5}/ matches the character A repeated 3 to 5 times.

You can apply a quantifier to a single character, to a character class, or to a group:

  • /a+/ matches the character a repeated one or more times.

  • /\d+/ matches one or more digits.

  • /[abc]+/ matches a repetition of one or more character, each of which is either a , b , or c .

  • /(very, )*/ matches the word very followed by a comma and a space repeated zero or more times.

You can use quantifiers within parenthetical groupings that have quantifiers applied to them. For example, the following quantifier matches strings such as word and word-word-word :

/\w+(-\w+)*/

By default, regular expressions perform what is known as greedy matching. Any subpattern in the regular expression (such as .* ) tries to match as many characters in the string as possible before moving forward to the next part of the regular expression. For example, consider the following regular expression and string:

var pattern:RegExp = /<p>.*<\/p>/; 
str:String = "<p>Paragraph 1</p> <p>Paragraph 2</p>";

The regular expression matches the entire string:

<p>Paragraph 1</p> <p>Paragraph 2</p>

Suppose, however, that you want to match only one <p>...</p> grouping. You can do this with the following:

<p>Paragraph 1</p>

Add a question mark ( ? ) after any quantifier to change it to what is known as a lazy quantifier . For example, the following regular expression, which uses the lazy *? quantifier, matches <p> followed by the minimum number of characters possible (lazy), followed by </p> :

/<p>.*?<\/p>/

Keep in mind the following points about quantifiers:

  • The quantifiers {0} and {0,0} do not exclude an item from a match.

  • Do not combine multiple quantifiers, as in /abc+*/ .

  • The dot (.) does not span lines unless the s ( dotall ) flag is set, even if it is followed by a * quantifier. For example, consider the following code:

    var str:String = "<p>Test\n"; 
    str += "Multiline</p>"; 
    var re:RegExp = /<p>.*<\/p>/; 
    trace(str.match(re)); // null; 
     
    re = /<p>.*<\/p>/s; 
    trace(str.match(re)); 
        // output: <p>Test 
        //                    Multiline</p>

For more information, see Flags and properties.

Alternation

Use the | (pipe) character in a regular expression to have the regular expression engine consider alternatives for a match. For example, the following regular expression matches any one of the words cat, dog, pig, rat :

var pattern:RegExp = /cat|dog|pig|rat/;

You can use parentheses to define groups to restrict the scope of the | alternator. The following regular expression matches cat followed by nap or nip :

var pattern:RegExp = /cat(nap|nip)/;

For more information, see Groups.

The following two regular expressions, one using the | alternator, the other using a character class (defined with [ and ] ), are equivalent:

/1|3|5|7|9/ 
/[13579]/

For more information, see Character classes.

Groups

You can specify a group in a regular expression by using parentheses, as follows:

/class-(\d*)/

A group is a subsection of a pattern. You can use groups to do the following things:

  • Apply a quantifier to more than one character.

  • Delineate subpatterns to be applied with alternation (by using the | character).

  • Capture substring matches (for example, by using \1 in a regular expression to match a previously matched group, or by using $1 similarly in the replace() method of the String class).

The following sections provide details on these uses of groups.

Using groups with quantifiers

If you do not use a group, a quantifier applies to the character or character class that precedes it, as the following shows:

var pattern:RegExp = /ab*/ ; 
// matches the character a followed by 
// zero or more occurrences of the character b 
 
pattern = /a\d+/;  
// matches the character a followed by  
// one or more digits 
 
pattern = /a[123]{1,3}/; 
// matches the character a followed by  
// one to three occurrences of either 1, 2, or 3

However, you can use a group to apply a quantifier to more than one character or character class:

var pattern:RegExp = /(ab)*/; 
// matches zero or more occurrences of the character a  
// followed by the character b, such as ababab 
 
pattern = /(a\d)+/; 
// matches one or more occurrences of the character a followed by  
// a digit, such as a1a5a8a3 
 
pattern = /(spam ){1,3}/;  
// matches 1 to 3 occurrences of the word spam followed by a space

For more information on quantifiers, see Quantifiers.

Using groups with the alternator (|) character

You can use groups to define the group of characters to which you want to apply an alternator ( | ) character, as follows:

var pattern:RegExp = /cat|dog/; 
// matches cat or dog 
 
pattern = /ca(t|d)og/; 
// matches catog or cadog

Using groups to capture substring matches

When you define a standard parenthetical group in a pattern, you can later refer to it in the regular expression. This is known as a backreference , and these sorts of groups are known as capturing groups . For example, in the following regular expression, the sequence \1 matches whatever substring matched the capturing parenthetical group:

var pattern:RegExp = /(\d+)-by-\1/; 
// matches the following: 48-by-48

You can specify up to 99 of these backreferences in a regular expression by typing \1 , \2 , ... , \99 .

Similarly, in the replace() method of the String class, you can use $1$99 – to insert captured group substring matches in the replacement string:

var pattern:RegExp = /Hi, (\w+)\./; 
var str:String = "Hi, Bob."; 
trace(str.replace(pattern, "$1, hello.")); 
  // output: Bob, hello.

Also, if you use capturing groups, the exec() method of the RegExp class and the match() method of the String class return substrings that match the capturing groups:

var pattern:RegExp = /(\w+)@(\w+).(\w+)/; 
var str:String = "bob@example.com"; 
trace(pattern.exec(str)); 
  // bob@example.com,bob,example,com

Using noncapturing groups and lookahead groups

A noncapturing group is one that is used for grouping only; it is not “collected,” and it does not match numbered backreferences. Use (?: and ) to define noncapturing groups, as follows:

var pattern = /(?:com|org|net);

For example, note the difference between putting (com|org) in a capturing versus a noncapturing group (the exec() method lists capturing groups after the complete match):

var pattern:RegExp = /(\w+)@(\w+).(com|org)/; 
var str:String = "bob@example.com"; 
trace(pattern.exec(str)); 
// bob@example.com,bob,example,com 
 
//noncapturing: 
var pattern:RegExp = /(\w+)@(\w+).(?:com|org)/; 
var str:String = "bob@example.com"; 
trace(pattern.exec(str)); 
  // bob@example.com,bob,example

A special type of noncapturing group is the lookahead group, of which there are two types: the positive lookahead group and the negative lookahead group.

Use (?= and ) to define a positive lookahead group, which specifies that the subpattern in the group must match at the position. However, the portion of the string that matches the positive lookahead group can match remaining patterns in the regular expression. For example, because (?=e) is a positive lookahead group in the following code, the character e that it matches can be matched by a subsequent part of the regular expression—in this case, the capturing group, \w*) :

var pattern:RegExp = /sh(?=e)(\w*)/i; 
var str:String = "Shelly sells seashells by the seashore"; 
trace(pattern.exec(str)); 
// Shelly,elly

Use (?! and ) to define a negative lookahead group that specifies that the subpattern in the group must not match at the position. For example:

var pattern:RegExp = /sh(?!e)(\w*)/i; 
var str:String = "She sells seashells by the seashore"; 
trace(pattern.exec(str)); 
// shore,ore

Using named groups

A named group is a type of group in a regular expression that is given a named identifier. Use (?P<name> and ) to define the named group. For example, the following regular expression includes a named group with the identifier named digits :

var pattern = /[a-z]+(?P<digits>\d+)[a-z]+/;

When you use the exec() method, a matching named group is added as a property of the result array:

var myPattern:RegExp = /([a-z]+)(?P<digits>\d+)[a-z]+/;  
var str:String = "a123bcd"; 
var result:Array = myPattern.exec(str); 
trace(result.digits); // 123

Here is another example, which uses two named groups, with the identifiers name and dom :

var emailPattern:RegExp =  
    /(?P<name>(\w|[_.\-])+)@(?P<dom>((\w|-)+))+\.\w{2,4}+/;  
var address:String = "bob@example.com"; 
var result:Array = emailPattern.exec(address); 
trace(result.name); // bob 
trace(result.dom); // example
Note: Named groups are not part of the ECMAScript language specification. They are an added feature in ActionScript 3.0.
Flags and properties

The following table lists the five flags that you can set for regular expressions. Each flag can be accessed as a property of the regular expression object.

Flag

Property

Description

g

global

Matches more than one match.

i

ignoreCase

Case-insensitive matching. Applies to the A Z and a z characters, but not to extended characters such as É and é .

m

multiline

With this flag set, $ and ^ can match the beginning of a line and end of a line, respectively.

s

dotall

With this flag set, . (dot) can match the newline character ( \n ).

x

extended

Allows extended regular expressions. You can type spaces in the regular expression, which are ignored as part of the pattern. This lets you type regular expression code more legibly.

Note that these properties are read-only. You can set the flags ( g , i , m , s , x ) when you set a regular expression variable, as follows:

var re:RegExp = /abc/gimsx;

However, you cannot directly set the named properties. For instance, the following code results in an error:

var re:RegExp = /abc/; 
re.global = true; // This generates an error.

By default, unless you specify them in the regular expression declaration, the flags are not set, and the corresponding properties are also set to false .

Additionally, there are two other properties of a regular expression:

  • The lastIndex property specifies the index position in the string to use for the next call to the exec() or test() method of a regular expression.

  • The source property specifies the string that defines the pattern portion of the regular expression.

The g (global) flag

When the g ( global ) flag is not included, a regular expression matches no more than one match. For example, with the g flag not included in the regular expression, the String.match() method returns only one matching substring:

var str:String = "she sells seashells by the seashore."; 
var pattern:RegExp = /sh\w*/; 
trace(str.match(pattern)) // output: she

When the g flag is set, the Sting.match() method returns multiple matches, as follows:

var str:String = "she sells seashells by the seashore."; 
var pattern:RegExp = /sh\w*/g; 
// The same pattern, but this time the g flag IS set. 
trace(str.match(pattern)); // output: she,shells,shore

The i (ignoreCase) flag

By default, regular expression matches are case-sensitive. When you set the i ( ignoreCase ) flag, case sensitivity is ignored. For example, the lowercase s in the regular expression does not match the uppercase letter S , the first character of the string:

var str:String = "She sells seashells by the seashore."; 
trace(str.search(/sh/)); // output: 13 -- Not the first character

With the i flag set, however, the regular expression does match the capital letter S :

var str:String = "She sells seashells by the seashore."; 
trace(str.search(/sh/i)); // output: 0

The i flag ignores case sensitivity only for the A Z and a z characters, but not for extended characters such as É and é .

The m (multiline) flag

If the m ( multiline ) flag is not set, the ^ matches the beginning of the string and the $ matches the end of the string. If the m flag is set, these characters match the beginning of a line and end of a line, respectively. Consider the following string, which includes a newline character:

var str:String = "Test\n"; 
str += "Multiline"; 
trace(str.match(/^\w*/g)); // Match a word at the beginning of the string.

Even though the g ( global ) flag is set in the regular expression, the match() method matches only one substring, since there is only one match for the ^ —the beginning of the string. The output is:

Test

Here is the same code with the m flag set:

var str:String = "Test\n"; 
str += "Multiline"; 
trace(str.match(/^\w*/gm)); // Match a word at the beginning of lines. 

This time, the output includes the words at the beginning of both lines:

Test,Multiline

Note that only the \n character signals the end of a line. The following characters do not:

  • Return ( \r ) character

  • Unicode line-separator ( \u2028 ) character

  • Unicode paragraph-separator ( \u2029 ) character

The s (dotall) flag

If the s ( dotall or “dot all”) flag is not set, a dot ( . ) in a regular expression pattern does not match a newline character ( \n ). So for the following example, there is no match:

var str:String = "<p>Test\n"; 
str += "Multiline</p>"; 
var re:RegExp = /<p>.*?<\/p>/; 
trace(str.match(re)); 

However, if the s flag is set, the dot matches the newline character:

var str:String = "<p>Test\n"; 
str += "Multiline</p>"; 
var re:RegExp = /<p>.*?<\/p>/s; 
trace(str.match(re)); 

In this case, the match is the entire substring within the <p> tags, including the newline character:

<p>Test 
Multiline</p>

The x (extended) flag

Regular expressions can be difficult to read, especially when they include a lot of metasymbols and metasequences. For example:

/<p(>|(\s*[^>]*>)).*?<\/p>/gi

When you use the x ( extended ) flag in a regular expression, any blank spaces that you type in the pattern are ignored. For example, the following regular expression is identical to the previous example:

/     <p    (>  | (\s* [^>]* >))    .*?    <\/p>  /gix

If you have the x flag set and do want to match a blank space character, precede the blank space with a backslash. For example, the following two regular expressions are equivalent:

/foo bar/ 
/foo \ bar/x

The lastIndex property

The lastIndex property specifies the index position in the string at which to start the next search. This property affects the exec() and test() methods called on a regular expression that has the g flag set to true . For example, consider the following code:

var pattern:RegExp = /p\w*/gi; 
var str:String = "Pedro Piper picked a peck of pickled peppers."; 
trace(pattern.lastIndex); 
var result:Object = pattern.exec(str); 
while (result != null) 
{ 
    trace(pattern.lastIndex); 
    result = pattern.exec(str); 
}

The lastIndex property is set to 0 by default (to start searches at the beginning of the string). After each match, it is set to the index position following the match. Therefore, the output for the preceding code is the following:

0 
5 
11 
18 
25 
36 
44

If the global flag is set to false , the exec() and test() methods do not use or set the lastIndex property.

The match() , replace() , and search() methods of the String class start all searches from the beginning of the string, regardless of the setting of the lastIndex property of the regular expression used in the call to the method. (However, the match() method does set lastIndex to 0.)

You can set the lastIndex property to adjust the starting position in the string for regular expression matching.

The source property

The source property specifies the string that defines the pattern portion of a regular expression. For example:

var pattern:RegExp = /foo/gi; 
trace(pattern.source); // foo

Methods for using regular expressions with strings

The RegExp class includes two methods: exec() and test() .

In addition to the exec() and test() methods of the RegExp class, the String class includes the following methods that let you match regular expressions in strings: match() , replace() , search() , and splice() .

The test() method

The test() method of the RegExp class simply checks the supplied string to see if it contains a match for the regular expression, as the following example shows:

var pattern:RegExp = /Class-\w/; 
var str = "Class-A"; 
trace(pattern.test(str)); // output: true
The exec() method

The exec() method of the RegExp class checks the supplied string for a match of the regular expression and returns an array with the following:

  • The matching substring

  • Substring matches for any parenthetical groups in the regular expression

The array also includes an index property, indicating the index position of the start of the substring match.

For example, consider the following code:

var pattern:RegExp = /\d{3}\-\d{3}-\d{4}/; //U.S phone number 
var str:String = "phone: 415-555-1212"; 
var result:Array = pattern.exec(str); 
trace(result.index, " - ", result); 
// 7-415-555-1212

Use the exec() method multiple times to match multiple substrings when the g ( global ) flag is set for the regular expression:

var pattern:RegExp = /\w*sh\w*/gi; 
var str:String = "She sells seashells by the seashore"; 
var result:Array = pattern.exec(str); 
     
while (result != null) 
{ 
    trace(result.index, "\t", pattern.lastIndex, "\t", result); 
    result = pattern.exec(str); 
} 
//output:  
// 0      3      She 
// 10      19      seashells 
// 27      35      seashore
String methods that use RegExp parameters

The following methods of the String class take regular expressions as parameters: match() , replace() , search() , and split() . For more information on these methods, see Finding patterns in strings and replacing substrings.

Regular expressions example: A Wiki parser

This simple Wiki text conversion example illustrates a number of uses for regular expressions:

  • Converting lines of text that match a source Wiki pattern to the appropriate HTML output strings.

  • Using a regular expression to convert URL patterns to HTML <a> hyperlink tags.

  • Using a regular expression to convert U.S. dollar strings (such as "$9.95" ) to euro strings (such as "8.24 €" ).

To get the application files for this sample, see www.adobe.com/go/learn_programmingAS3samples_flash . The WikiEditor application files can be found in the folder Samples/WikiEditor. The application consists of the following files:

File

Description

WikiEditor.mxml

or

WikiEditor.fla

The main application file in Flash (FLA) or Flex (MXML).

com/example/programmingas3/regExpExamples/WikiParser.as

A class that includes methods that use regular expressions to convert Wiki input text patterns to the equivalent HTML output.

com/example/programmingas3/regExpExamples/URLParser.as

A class that includes methods that use regular expressions to convert URL strings to HTML <a> hyperlink tags.

com/example/programmingas3/regExpExamples/CurrencyConverter.as

A class that includes methods that use regular expressions to convert U.S. dollar strings to euro strings.

Defining the WikiParser class

The WikiParser class includes methods that convert Wiki input text into the equivalent HTML output. This is not a very robust Wiki conversion application, but it does illustrate some good uses of regular expressions for pattern matching and string conversion.

The constructor function, along with the setWikiData() method, simply initializes a sample string of Wiki input text, as follows:

public function WikiParser() 
{ 
    wikiData = setWikiData(); 
}

When the user clicks the Test button in the sample application, the application invokes the parseWikiString() method of the WikiParser object. This method calls a number of other methods, which in turn assemble the resulting HTML string.

public function parseWikiString(wikiString:String):String 
{ 
    var result:String = parseBold(wikiString); 
    result = parseItalic(result); 
    result = linesToParagraphs(result); 
    result = parseBullets(result); 
    return result; 
}

Each of the methods called— parseBold() , parseItalic() , linesToParagraphs() , and parseBullets() —uses the replace() method of the string to replace matching patterns, defined by a regular expression, in order to transform the input Wiki text into HTML-formatted text.

Converting boldface and italic patterns

The parseBold() method looks for a Wiki boldface text pattern (such as '''foo''' ) and transforms it into its HTML equivalent (such as <b>foo</b> ), as follows:

private function parseBold(input:String):String 
{ 
    var pattern:RegExp = /'''(.*?)'''/g; 
    return input.replace(pattern, "<b>$1</b>"); 
}

Note that the (.?*) portion of the regular expression matches any number of characters ( * ) between the two defining ''' patterns. The ? quantifier makes the match nongreedy, so that for a string such as '''aaa''' bbb '''ccc''' , the first matched string will be '''aaa''' and not the entire string (which starts and ends with the ''' pattern).

The parentheses in the regular expression define a capturing group, and the replace() method refers to this group by using the $1 code in the replacement string. The g ( global ) flag in the regular expression ensures that the replace() method replaces all matches in the string (not simply the first one).

The parseItalic() method works similarly to the parseBold() method, except that it checks for two apostrophes ( '' ) as the delimiter for italic text (not three):

private function parseItalic(input:String):String 
{ 
    var pattern:RegExp = /''(.*?)''/g; 
    return input.replace(pattern, "<i>$1</i>"); 
}

Converting bullet patterns

As the following example shows, the parseBullet() method looks for the Wiki bullet line pattern (such as * foo ) and transforms it into its HTML equivalent (such as <li>foo</li> ):

private function parseBullets(input:String):String 
{ 
    var pattern:RegExp = /^\*(.*)/gm; 
    return input.replace(pattern, "<li>$1</li>"); 
}

The ^ symbol at the beginning of the regular expression matches the beginning of a line. The m ( multiline ) flag in the regular expression causes the regular expression to match the ^ symbol against the start of a line, not simply the start of the string.

The \* pattern matches an asterisk character (the backslash is used to signal a literal asterisk instead of a * quantifier).

The parentheses in the regular expression define a capturing group, and the replace() method refers to this group by using the $1 code in the replacement string. The g ( global ) flag in the regular expression ensures that the replace() method replaces all matches in the string (not simply the first one).

Converting paragraph Wiki patterns

The linesToParagraphs() method converts each line in the input Wiki string to an HTML <p> paragraph tag. These lines in the method strip out empty lines from the input Wiki string:

var pattern:RegExp = /^$/gm; 
var result:String = input.replace(pattern, "");

The ^ and $ symbols the regular expression match the beginning and end of a line. The m ( multiline ) flag in the regular expression causes the regular expression to match the ^ symbol against the start of a line, not simply the start of the string.

The replace() method replaces all matching substrings (empty lines) with an empty string ( "" ). The g ( global ) flag in the regular expression ensures that the replace() method replaces all matches in the string (not simply the first one).

Converting URLs to HTML <a> tags

When the user clicks the Test button in the sample application, if the user selected the urlToATag check box, the application calls the URLParser.urlToATag() static method to convert URL strings from the input Wiki string into HTML <a> tags.

var protocol:String = "((?:http|ftp)://)"; 
var urlPart:String = "([a-z0-9_-]+\.[a-z0-9_-]+)"; 
var optionalUrlPart:String = "(\.[a-z0-9_-]*)"; 
var urlPattern:RegExp = new RegExp(protocol + urlPart + optionalUrlPart, "ig"); 
var result:String = input.replace(urlPattern, "<a href='$1$2$3'><u>$1$2$3</u></a>");

The RegExp() constructor function is used to assemble a regular expression ( urlPattern ) from a number of constituent parts. These constituent parts are each strings that define part of the regular expression pattern.

The first part of the regular expression pattern, defined by the protocol string, defines an URL protocol: either http:// or ftp:// . The parentheses define a noncapturing group, indicated by the ? symbol. This means that the parentheses are simply used to define a group for the | alternation pattern; the group will not match backreference codes ( $1 , $2 , $3 ) in the replacement string of the replace() method.

The other constituent parts of the regular expression each use capturing groups (indicated by parentheses in the pattern), which are then used in the backreference codes ( $1 , $2 , $3 ) in the replacement string of the replace() method.

The part of the pattern defined by the urlPart string matches at least one of the following characters: a-z , 0-9 , _ , or - . The + quantifier indicates that at least one character is matched. The \. indicates a required dot ( . ) character. And the remainder matches another string of at least one of these characters: a-z , 0-9 , _ , or - .

The part of the pattern defined by the optionalUrlPart string matches zero or more of the following: a dot ( . ) character followed by any number of alphanumeric characters (including _ and - ). The * quantifier indicates that zero or more characters are matched.

The call to the replace() method employs the regular expression and assembles the replacement HTML string, using backreferences.

The urlToATag() method then calls the emailToATag() method, which uses similar techniques to replace e-mail patterns with HTML <a> hyperlink strings. The regular expressions used to match HTTP, FTP, and e-mail URLs in this sample file are fairly simple, for the purposes of exemplification; there are much more complicated regular expressions for matching such URLs more correctly.

Converting U.S. dollar strings to euro strings

When the user clicks the Test button in the sample application, if the user selected the dollarToEuro check box, the application calls the CurrencyConverter.usdToEuro() static method to convert U.S. dollar strings (such as "$9.95" ) to euro strings (such as "8.24 €" ), as follows:

var usdPrice:RegExp = /\$([\d,]+.\d+)+/g; 
return input.replace(usdPrice, usdStrToEuroStr); 

The first line defines a simple pattern for matching U.S. dollar strings. Notice that the $ character is preceded with the backslash ( \ ) escape character.

The replace() method uses the regular expression as the pattern matcher, and it calls the usdStrToEuroStr() function to determine the replacement string (a value in euros).

When a function name is used as the second parameter of the replace() method, the following are passed as parameters to the called function:

  • The matching portion of the string.

  • Any captured parenthetical group matches. The number of arguments passed this way varies depending on the number of captured parenthetical group matches. You can determine the number of captured parenthetical group matches by checking arguments.length - 3 within the function code.

  • The index position in the string where the match begins.

  • The complete string.

The usdStrToEuroStr() method converts U.S. dollar string patterns to euro strings, as follows:

private function usdToEuro(...args):String 
{ 
    var usd:String = args[1]; 
    usd = usd.replace(",", ""); 
    var exchangeRate:Number = 0.828017; 
    var euro:Number = Number(usd) * exchangeRate; 
    trace(usd, Number(usd), euro); 
    const euroSymbol:String = String.fromCharCode(8364); // € 
    return euro.toFixed(2) + " " + euroSymbol;  
}

Note that args[1] represents the captured parenthetical group matched by the usdPrice regular expression. This is the numerical portion of the U.S. dollar string: that is, the dollar amount without the $ sign. The method applies an exchange rate conversion and returns the resulting string (with a trailing € symbol instead of a leading $ symbol).

TOPIC_TITLE

// Ethnio survey code removed