Monday, June 9, 2008

ActionScript 3.0 in Adobe Flash CS3




A Brief History of ActionScript in Flash


Early syntax of ActionScript 1 with Flash 3 was simple and verbose and
functionality was based mainly around frame navigation and basic mouse
interaction. This remained consistent until about Flash 5 where ActionScript
assumed a form more similar to JavaScript. This provided a great deal more
functionality and a "dot-syntax" for variable and method access. ActionScript
also became a prototyped language allowing for simple OOP functionality similar
to that available in JavaScript. This was enhanced in the following release of
Flash, Flash MX (6).


Flash MX 2004 (7) introduced ActionScript 2.0. There were two major
improvements that came with ActionScript 2: variable data typing and a new class
syntax.  Variable data typing allowed you to specify what kind of value
your variables contained, whether it be a number, a string, or any other kind of
object or value. This typing association was strictly for compile-time
debugging.  What that meant was that any type you associated with a
variable would only be used to check for errors when you compiled or published. 
If no conflict was found during the compilation process your SWF would be
created with all the typing information stripped from it and the ActionScript
inside would run without any understanding of the types you assigned to them in
your original code.  Though this provided no advantage to the Flash Player
during playback, it did provide Flash authors a helpful tool for debugging
larger, more complicated applications.


The new class syntax was used to define classes in ActionScript 2 similar to
those defined for languages like Java.  Though Flash still didn't really
support classes beyond that in the form of prototypes (in the end, ActionScript
2 still basically gets compiled to ActionScript 1), this new syntax provided a
familiar style that was helpful for people migrating from other languages and
provided a more concrete way to organize class definitions within separate AS
files and packages. 


That brings us to Flash CS3 (9; not much in terms of advances in ActionScript
happened with Flash 8) with ActionScript 3.0.  Here we have a new
ActionScript language that not only received a new version number but also a new
virtual machine – the underlying software within the Flash Player that executes
ActionScript during playback.


Both ActionScript 1 and ActionScript 2 use AVM1 (ActionScript Virtual Machine
1) as they are essentially the same in terms of needs for playback. Remember,
ActionScript 2 mostly only added compile-time type checking and a new syntax
which essentially became ActionScript 1 when compiled. ActionScript 3 runs in a
completely new virtual machine called AVM2 (or sometimes AVM+) designed
specifically, from the ground up. to execute ActionScript 3 and only
ActionScript 3 code.  As a result not only can ActionScript 3 movies not
directly communicate with ActionScript 1 or ActionScript 2 movies, but you may
find that the changes in ActionScript 3 to be much more profound than the jump
even from ActionScript 1 to ActionScript 2.


How different is ActionScript 3?


ActionScript 3 is different.  Very different.  So different, in
fact, that it requires a completely new virtual machine to run it.  But at
its core, its still ActionScript and as ActionScript you'll notice that many of
the commands and programming concepts that applied to ActionScript 1 and
ActionScript 2 still pretty much apply to ActionScript 3.  Very little, at
least syntactically, has changed.  And sometimes the ActionScript 3
equivalent of ActionScript 2 code will look very similar, if not exactly the
same. However, this is not always the case.  And in the end, there are
enough changes to make a direct conversion between the two often very difficult.


These changes were necessary, though.  ActionScript 3 was built with
efficiency and productivity in mind.  Not just efficiency in development
(and this point can be argued for smaller projects but larger projects do
benefit), but also playback performance where code in ActionScript 3 can be
played back in the Flash Player up to 10 times (if not more) faster than
ActionScript 2 code. Yes, you will find that many of the same menial tasks in
ActionScript 1 and ActionScript 2 now seem to take twice as long to code in
ActionScript 3, but in the end the extra speed and functionality.  The
casual coder may look to the sky shaking a fist, cursing, but the advanced
programmer will jump with glee in rejoice.


Lets take a look at some of the new features ActionScript 3 brings to the
table:



  • Runtime exceptions – errors that are thrown at runtime (during SWF
    playback) to help debug your project

  • Runtime variable typing – typing which goes beyond compilation and
    persists during playback

  • Sealed classes – classes based on a static definition for additional
    robustness and performance

  • Method closures – methods are now bound to their respective class
    instance so 'this' in methods will never change

  • E4X – a new, easy to work with implementation of XML

  • Regular expressions – native support for regular expressions

  • Namespaces – support for namespaces not only in XML but in class
    definitions to set custom access to class members

  • int and uint data types – new data types for Number values allowing
    ActionScript to use faster integer-based math for certain calculations

  • New display list model – a new, flexible approach to managing display
    objects to be viewed on the screen

  • New event model – a new, listener-based event model with support for
    event propagation


Variables


Variables are words in code that represent or contain different values or
data.  When you create a variable in ActionScript 3, you must use the
var
keyword.


var myVariableName; // var required

The var keyword has been available in ActionScript 1 since Flash
5 but only now, in ActionScript 3 is it required. The only exception is when
defining a new variable value in a dynamic object instance (one whose variable
definitions are not predefined) using an explicit reference to that object.


aDynamicObject.newVar = value; // only time var not used

In the above example, newVar is a new variable being defined in
the aDynamicObject object without the use of var
In fact, var can never be used with complex references, that is,
any reference that requires a dot (.) or bracket access ([])
to reference the variable.


When defining a variable you must only use numbers, letters, dollar signs ($)
and underscores (_) and a variable cannot start with a number. 
Whereas bits32, _bits32, and $bits32 are
valid, 32bits is not valid for a variable name since it starts with
a number. These are the same restrictions that applied to ActionScript 2.


You will also have to be sure not to create naming conflicts with your
variable names and any internal variable names already defined in the current
scope of your script.  For example, when writing code in any timeline, you
are writing code that is being defined for a MovieClip instance – the MovieClip
instance that is represented by that timeline.  If you try to define a
variable with a name that is the same as a predefined MovieClip variable (or
function) you will get an error.


// Any timeline script

var name:String = "Joe"; // Error: A conflict exists with inherited definition (name)

Similarly, you should not name variables after top-level objects or functions
like Array, XML, or trace or those definitions will no longer be accessible to
you.



Note: Case sensitivity


Since Flash Player 7, ActionScript is case sensitive, so the variables
Name and name are not the same.  This still applies to ActionScript 3.



The Flash CS3 Actions panel can sometimes be helpful in identifying conflicts
since recognized keywords are highlighted as blue. If you are unsure if a
variable name you are using is a conflict, check the documentation for MovieClip
and see what properties and methods already exist for MovieClip (be sure to
include inherited properties and methods)


New to ActionScript 3 is the restriction that you can only declare a variable
with var once in any one scope or timeline in code.  In other
words, if you declare the variable x at the top of your script and
want to use it again at the bottom of your script, you should not use the
var
keyword for that variable again


var x = value; // ok


var x = differentValue; // error; you can only use var once

When defining variables on the timeline in Flash, this also applies to all
frames in the same timeline, not just the current frame. So if you define or
declare variable x in frame 1 using var, you cannot
use var with that variable again even in a different frame.


When declaring variables with the var keyword (and only with the
var [or const] keyword) you have the option of
specifying a variable type.  A variable's type describes the kind of value
it will be holding.  This was a new feature in ActionScript 2 and continues
to exist in ActionScript 3 in the same format.  So, for example, if you
wanted the variable x to hold a number value, you would specify it
as being of the type Number by using a colon and the term Number
directly following the variable name:


var x:Number; // variable x contains number values

In both versions of ActionScript, typing like is optional.  ActionScript
3, however, is different in that it will also retain type information during
movie playback, unlike ActionScript 2 which used it strictly for compile-time
(during publishing) error checking.  This means that you will have to be
much more respective of your type decisions, especially since you cannot
redefine a variable with var a second time in ActionScript 3 (doing this in
ActionScript 2 would let you use different types for one variable). You will
also find that this behavior can be a little troublesome as you start working
with type conflicts further down the road.


By not typing a variable at all, you can use any type you want for that
variable.  ActionScript 3 also provides a special "untyped" type that
represents just that – no type. It is represented by an asterisk (*).


var anyValue:*; // variable can have any type

It's always good to specify some type for your variable as it can lead to
better error checking and performance.  By using the untyped type, you can
specifically indicate that the variable can have any value without reading
others reading the code to guess.


If you do not supply a variable with a default value, it will be assigned one
based on its type.  If no type was supplied, it will be given a value of
undefined.  The following list details the default values of
different data types in ActionScript 3:


var untyped:*; // (or no typing) undefined

var boolean:Boolean; // false
var number:Number; // NaN
var integer:int; // 0
var unsignedInteger:uint; // 0
var string:String; // null
var object:Object; // null

Any other Object type results in default value of null. It
should be noted that values of the type object (any kind of object including
arrays and objects created from custom classes) have a default value of
null
, not undefined.  In fact objects in ActionScript 3
cannot be undefined.  If they have no value, then they are
null.  Only with untyped variables or attempting to access
variables that do not exist will get a value of undefined.


Number types are now unique in that they can no longer be undefined
or null.  If they have no value, they are seen as NaN
("Not a Number").  NaN is a tricky value, however.  You
can't really compare NaN with another NaN with the
equality operator (==) because they probably won't be the same. 
If you ever need to check to see if a number is NaN, you should
always use isNaN().


if (isNaN(myNumber))  // checks to see if Number is defined

The int and uint variables types are new in ActionScript 3.  These are
special kinds of Numbers that represent 32-bit integers or whole numbers. 
The int type is a normal integer and uint is an unsigned integer, or a whole
number whose value cannot be negative.  These kinds of numbers can only
have whole number values.  They cannot be null, undefined., or even NaN
like the Number type on which they are based.  Being that they are based on
the Number type, however, you'll notice that they're type identities ("int" and
"uint") are not capitalized.  This indicates that there is no specific
object type or class definition associated with that type.  Instead, these
types essentially share the Number definition with Number types (with the
exception of the MIN_VALUE and MAX_VALUE constants
which have different values for each type).
























Number, int and uint Values
Numeric Type Values
Number 4.9406564584124654e-324 to 1.79769313486231e+308
int -2147483648 to 2147483647 (whole numbers only)
uint 0 to 4294967295 (whole numbers only)

There is one other type that is also not capitalized.  This is the
special void type.  This was capitalized in ActionScript 2 but
is no longer in ActionScript 3 since, like with int and uint, there is no
specific definition associated with it.  This type has not been seen so far
as it only applies to functions.




























New Basic ActionScritpt 3 Data Types
ActionScript 3.0 ActionScript 2.0
* (not typed)
int Number (loosely)
uint Number (loosely)
void Void

Also new to ActionScript 3 is the behavior of the delete
keyword. The delete keyword is used to delete variables from an
object. Variables defined with var, however, cannot be deleted in
ActionScript 3. Only dynamic variables defined within dynamic objects can be
deleted with delete. For other variables, the equivalent of
deleting would be to set those variables to have a value of null.


As seen above, not all variables can have null values. Variables defined as
int, uint, and Number, can only have numeric values (Number also being able to
have a value of NaN) which does not include null - the
same applying to Boolean values which can be either true or false. For such
cases, there is no equivalent to delete. Variables typed as Number could be set
to NaN, but int and uint variables have to be numeric at all times
and Booleans just either true or false.


// Create a dynamic object with dynamic property

var obj:Object = new Object();
obj.prop = "value";

// delete dynamic property on obj using delete
delete obj.prop

// cannot delete obj, only able to set to null
obj = null;

// int, unit, Number and Boolean
// types cannot be deleted
var intNum:int = 0;
var uintNum:uint = 0;
var numNum:Number = NaN;
var bool:Boolean = false;

Functions


Functions define reusable chunks of code, or custom operations in
ActionScript.  By creating a function you can perform the same operation
multiple times without having to write the same code over again for each time
you want to use it. Instead, all you do is call the function using
its function name.


There are two ways to define functions in ActionScript.  You can create
a named function using the form function [functionName] ([parameters]) {
[code] }
or you can define an anonymous function using var
[functionName] = function ([parameters]) { [code] }
.  Named
functions create function or method definitions while anonymous functions keep
variables which reference a "free floating" function definition.


// Named function

function doubleNumber(num) {
return num*2;
}

// Same function defined as an anonymous function

// defined within the variable doubleNumber
var doubleNumber = function(num) {
return num*2;
}

The above examples create a function with the name doubleNumber
which accepts a single number value and returns that value multiplied by two. 
To use the function, you call it using parentheses (()).


var x:Number = 10;

trace(doubleNumber(x)); // traces 20

As with variables, named functions cannot be defined more than once for any
one given timeline in ActionScript 3. Anonymous functions can reference multiple
functions over time, but cannot be redefined with var as they are
essentially variables. ActionScript 2 allowed you to change any function's
definition anytime. In ActionScript 3, you can only change an anonymous
function's definition.


When assigning type to functions, define typing information for both the
parameter list (the comma separated list of values you can supply the function)
as well as the return value, or the value that the function supplies after it's
executed.  When using an anonymous function definition, the variable the
function is being assigned to would also be typed to Function.


// Named function

function doubleNumber(num:Number):Number {
return num*2;
}

// Same function defined as an anonymous function

var doubleNumber:Function = function(num:Number):Number {
return num*2;
}

If a function does not return a value, then its return type should be
void
.  When a function typed as void is executed, or
simply fails to return a value with the return statement, its
return value becomes undefined.


function returnsNothing():void {

// do nothing
}
trace(returnsNothing()); // traces undefined

The returnsNothing function above not only returns nothing, but
also accepts no values – it has no parameter list.  If you try to pass
values into the function when it has no parameter list defined for it in
ActionScript 3, you will get an error.


returnsNothing(3); // Error: Incorrect number of arguments

In ActionScript 2, the Void type was used as the parameter list
in a function definition to indicate no parameters.  In ActionScript 3, you
just leave the list empty. Using Void in the parameter list in ActionScript 3
will actually make Flash think that a variable named Void is defined for the
parameter list of that function.



Note: Parameters vs. arguments


The difference between parameters and arguments is that parameters are
the value used to define the function.  Arguments are the actual values
provided to the function during use.  You can see arguments as being
parameter values.



With ActionScript 3, you can also now define default values for your
functions. 


// Here, message parameter is optional

function usesDefault(message:String = "hello"):void {
trace(message);
}
usesDefault("test"); // traces "test"
usesDefault(); // traces "hello"

By using defaults you not only get to specify values for parameters not used
by the function caller, but it also lets you define functions with optional
parameters, or parameters that aren't required to be used.  Those
parameters that do not have default values must be provided when the function is
called in ActionScript 3.  Because of this, all optional parameters must be
defined at the end of a parameter list.  You cannot have a required
parameter defined after an optional.


// Error: Required parameters are not

// permitted after optional parameters
function usesDefault(message:String = "hello", num:Number):void {
// code
}

// Correct; usesDefault needs at 

// least 1 argument, accepts 2 at max
function usesDefault(num:Number, message:String = "hello"):void {
// code
}

What if you wanted to allow a function to be called with any number of
arguments?  In ActionScript 2, you could do this simply by omitting any
parameter list and referencing the arguments using the arguments
object in the function.   In ActionScript 3, having no parameter list
means the function cannot be called with any arguments.  Instead, you have
to use a new parameter type known as …(rest).  This parameter
goes at the end of your parameter list (or it can represent your entire
parameter list) and indicates that any number of arguments can be used when
calling the function.  The …(rest) parameter is written as …argumentsArrayName
where argumentsArrayName is the name of the array that will contain the
arguments passed.


// Using the ...(rest) parameter

function passAnything(...statements):void {
trace(statements.length +": "+ statements);
}
passAnything(); // traces 0:
passAnything(1); // traces 1: 1
passAnything("a", true, 0); // traces 3: a,true,0


Note: Access to caller and callee


When using …(rest) parameter, the arguments
object is not available to the function call.  Instead, the
…(rest)
parameter is to be used to obtain the arguments passed. 
Unlike arguments, however, …(rest) does not have
the caller property used to reference the current function. 
In ActionScript 3, neither arguments nor …(rest)
have the callee property used to reference the function calling
the current function (callee was available in the arguments
object in ActionScript 2 but was removed in ActionScript 3).



Objects, Properties, Methods, and Classes


Objects are complex values that contain, or can contain,
additional values or variables known as properties.  The most basic
kind of object is an Object object and is created using new Object().


// Creating a new object instance

var myObject:Object = new Object();

There are other kinds of objects in ActionScript that behave similarly. 
Every timeline in Flash, for instance, represents the timeline of a movie clip
symbol which in ActionScript is represented by a MovieClip object or
instance
. The name variable of a timeline or MovieClip is a property of
that MovieClip instance.


// Main timeline

trace(name); // traces "root1"

Functions defined in objects are known as methods. Together,
properties and methods make up an object's members. All of the
"publically" availablemembers (those to which you have access to) of an object
represent its interface. Methods unique to MovieClip instances
include methods like gotoAndPlay() and gotoAndStop().


Primitive values like Boolean (true or false), Number (numeric values), and
String (text characters) are not objects in the true sense as they represent
basic values and do not act as containers for other values. Flash does, however,
associate these primitives with certain object kinds (Boolean, Number, and
String), or classes, which grants them certain object-like
functionality.  So, for instance, you can extract a certain chunk of text
from a String primitive using the String.slice() method of the
String class.


Classes are what define objects.  They also act as an object type. 
The Array class, for instance, defines what properties and methods exist in
Array instances (whose type is Array). When you look through the documentation
available for Arrays, you're looking at a reference to the Array class. 


var arrayInstance:Array = new Array(); // instance of Array class

Since ActionScript 2, some classes in ActionScript were specified as being
sealed (not dynamic). When a class is sealed, it means that instances
of that class cannot have any additional variables or properties defined for
them outside of those specified in the class's definition.  The Object and
Array classes in ActionScript are dynamic.  You can define what ever
variable values you want those objects.  The Sound class, on the other
hand, is an example of a sealed class since you cannot dynamically create any
variable value you want within a Sound instance.


// ActionScript 2 and 3

var array:Array = new Array();
array.customValue = 1; // OK

var sound:Sound = new Sound();
sound.customValue = 2; // Error: Access of possibly undefined property

In ActionScript 2, enforcement of dynamic or sealed classes was handled by
the compiler.  Because of this, you could work around the restriction of
sealed classes using the array access operator to reference variables


// ActionScript 2 workaround

var sound:Sound = new Sound();
sound["customValue"] = 2; // Works

This is no longer the case in ActionScript 3.  Sealed classes in
ActionScript 3 are enforced not only at compile time, but also runtime. This,
however, is necessary to ActionScript 3 since it uses the nature of sealed
classes to improve performance.


As you work with different objects in ActionScript, you will need to note
which objects are dynamic and which are not.  Here is a list of commonly
used dynamic classes:



  • Object

  • Array

  • Date

  • Dictionary*

  • Error (and most other Error Classes)

  • MovieClip

  • RegExp*

  • StyleSheet

  • URLVariables*

  • XML* (and XMLList*)


* New to ActionScript 3


The Dictionary Class


The Dictionary class represents a new kind of Object in ActionScript 3. 
Dictionary objects have the special ability of being able to use object
references as its keys, or variable names. Normal Object instances
(and other instances of dynamic classes) use normal variable names which
essentially equates to strings (Arrays also use numbers though they can equate
to strings in terms of how they are treated as keys). Dictionaries can use
actual objects references.


// Only Dictionary instances can have

// object references as keys
var arr:Array = new Array();
arr[0] = "value";

var obj:Object = new Object();
obj["variable"] = "value";

var dict:Dictionary = new Dictionary();
dict[arr] = "value1";
dict[obj] = "value2";

If you attempt to use objects as keys within normal, generic Object
instances, the keys used will actually become the string representation of those
objects, not the actual objects themselves as is the case with the Dictionary
class.


Dictionaries are most often used to keep information about other objects when
those other objects aren't capable of facilitating that information themselves.
For example, if you have a collection of Point instances (where Point is a
sealed class meaning additional values cannot be assigned to instances of that
class) and you need to have a name value to be associated with each one of those
points, what you can do is use a Dictionary instance to contain the names of
each Point using the Point instance as a key.


// Use Dictionary for name association with inatances

// Assuming ptA - ptC are Point instances
var names:Dictionary = new Dictionary();
names[ptA] = "A";
names[ptB] = "B";
names[ptC] = "C";

// Point A properties
ptA.x; // x value
ptA.y; // y value
names[ptA]; // name ("A")

Because Point instances have no name property, and because they are not
dynamic (allowing you to create your own on those instances), the names
Dictionary instance here is used to store Point names using the points
themselves as a key to their respective name value. This would not be possible
with generic Object instances since they can take only variable names as keys
(strings or numbers, not instances).


The Value of this


The this keyword in ActionScript is used to access the current
scope, or the object the code in the current block is being run in the context
of.  Using this on the timeline will reference the MovieClip
instance to which that timeline belongs.


// Main timeline

trace(this); // [object MainTimeline]

In functions, referencing this references the object in which
the current function is defined.  Since the same function can be easily
defined in multiple objects, a single function can make use of the this
reference and perform actions on different objects based on which object it is
being called from.


// The this reference depends on

// the object "owning" the function call
var joe:Object = new Object();
joe.name = "Joe";
joe.showName = function():void {
trace(this.name);
}

var jane:Object = new Object();
jane.name = "Jane";
jane.showName = joe.showName;

joe.showName(); // traces "Joe"
jane.showName(); // traces "Jane"

Here, there was only one function definition for showName (anonymous),
initially defined to the showName variable in the joe object.  That
function was then assigned to the jane object, again using the variable name
showName – one function, two references to it in two different objects. 
The object from which the function is being called determines which object the
this keyword references.


This behavior was consistent for ActionScript 2 for all functions.  Now,
in ActionScript 3, this is only the case for anonymous functions.  Named
functions in ActionScript 3 now support method closures, or are bound
to the object for which they are initially defined.  If the above example
can be written again using a named function.  Watch what happens when the
functions are called from their respective objects.


// In ActionScript 3, this in named functions always reference

// the object of the scope in which they were defined
function showName():void {
trace(this.name);
}

var joe:Object = new Object();
joe.name = "Joe";
joe.showName = showName

var jane:Object = new Object();
jane.name = "Jane";
jane.showName = showName;

joe.showName(); // traces "root1"
jane.showName(); // traces "root1"

It doesn't matter what object the showName function is defined,
it's reference to this will always be the main timeline (root1).  This is
because, as a named function, with method closure in ActionScript 3, this will
always reference the object instance of the original context of the function
definition.  This is especially useful for event handling where, in the
past, workarounds had to be used to maintain a valid reference to the instance
for which a handler as defined (i.e. using Delegate (mx.utils.Delegate)
in ActionScript 2).


Iteration


Iteration is the process of cycling through the various properties defined
within a system or object. In ActionScript 2, inherently all explicit
definitions within an object could be iterated through using for..in.
The only way to prevent iteration for any or all of those properties was to use
an undocumented method called ASSetPropFlags(). In ActionScript 3
iteration with for..in only applies to dynamic definitions in
dynamic objects.  That means class-defined methods or properties will not
be seen through iteration within any object, nor is there a way to make them be
seen. You can hide dynamic definitions from iteration using the ActionScript 3
setPropertyIsEnumerable() function.



The Array class is a dynamic class that has non-dynamic definitions.
Using for..in, you can access only the dynamic definitions
within that class, even though the other defnitions still exist within that
class.


// Create a list array

var list:Array = new Array();
list[0] = "bread";
list[1] = "milk";
list.type = "grocery";

// Iterate through properties in list
var prop:String;
for (prop in list) {
trace(prop + ": " + list[prop]);
}
/* output
0: bread
1: milk
type: grocery
*/


// length is an Array property but not
// enumerable since part of class definition
trace(list.length); // traces 2

// Hide type property from enumeration
list.setPropertyIsEnumerable("type", false);

// length can not be made enumerable
// through setPropertyIsEnumerable
list.setPropertyIsEnumerable("length", true);
for (prop in list) {
trace(prop + ": " + list[prop]);
}
/* output
0: bread
1: milk
*/

Notice that length cannot be found in enumeration even if attempted to be
set visible through setPropertyIsEnumerable. This is because it
is part of that class definition. In fact, any variable declared with
var
is assumed to be part of a class definition. This means that even
variables defined within the timeline will not be enumerable for that
timeline.


// var-declared variables do not enumerate

var a:Number = 1;
var b:Number = 2;

for (var prop:String in this){
trace(prop + ": " + this[prop]);
}
// traces no output

To make timeline variables enumerable, you have to define them as dynamic
properties. To do that, you have to define the variable using this.
Dynamic variables defined in this manner, however, cannot be typed.


// dynamic variables enumerate

this.a = 1;
this.b = 2;

for (var prop:String in this){
trace(prop + ": " + this[prop]);
}
/* output
b: 2
a: 1
*/

 



for each


Statements used for iteration in ActionScript 2 include while,
do..while, for, and for..in. ActionScript
3 still supports all of these but also adds another new statement, for
each..in
.


The for each..in statement is like a simplified for..in
Unlike for..in, for each..in iterates through object
values, not object variable names or keys.  If you don't need to know the
keys for the object values during iteration, you'll probably want to use a
for each..in
instead of a for..in.


// for..each iterates through values (not keys)

var obj:Object = new Object();
obj.a = 1;
obj.b = 2;
obj.c = 3;

for (var key:String in obj) {
trace(key); // key (a, b, c)
trace(obj[key]); // value (1, 2, 3)
}
for each (var value:* in obj) {
trace(value); // value without key (1, 2, 3)
}

The first for..in loop will trace both the keys (a, b, and c) as
well as the values (1, 2, and 3) while the for each will only trace the values
(1, 2, 3) and will have no way of accessing which keys are used to define those
vaules.


Display Objects


One of the more drastic changes (if not the most) in ActionScript 3 probably
has to be working with display objects, or objects visible on the screen. Along
with the well established and popular MovieClip (flash.display.MovieClip),
ActionScript 3 supports additional display object instances including but not
limited to:



Sprites are a new kind of light-weight MovieClip that doesn’t
technically have any frames, at least not in the conventional sense.  In a
more practical, Flash-like sense, you can see a Sprite as having one frame in
which it keeps its content or children, but there is no navigation to any frames
beyond that first. Since MovieClip instances you create dynamically through
ActionScript cannot have frames anyway, chances are you'd want to use a Sprite
in place of a MovieClip for all dynamically created MovieClip instances.


Shapes are like Sprites but are impeded by the fact that they
offer no form of mouse or keyboard interactivity.  In other words, these
display objects cannot receive events like mouseDown or keyUp. 
Additionally, Shape instances cannot contain any other kind of display objects
nor have children of their own.  You can only draw vector shapes within
them using the vector drawing API (beginFill, lineTo,
endFill, etc). This comes as an advatage to Shapes since they use
less memory and are more efficient than MovieClips and Sprites.


Bitmap instances are much like Shapes except instead of being able
to contain vector drawings, they contain bitmap images defined by a BitmapData
instance.  They, too, cannot contain any other display objects or children.
Unlike Shapes, Bitmaps can interact with the mouse and keyboard.


Loader is a Sprite-like display object which, like Sprite, has no
timeline, but is designed specifically to facilitate the loading of external
display content such as external SWFs and bitmap images. When loaded, those
assets displayed in the Loader instance and are accessible through the Loader's
content property.


You can read more in the Flash CS3 documentation about

Core display classes
.


Timeline based symbols


Most elements on the timeline which are not text or symbols from the library
are created as Shapes instances.  These Shapes include not only vector
drawings in Flash, but bitmap images as well; instead of using a Bitmap instance
for the timeline, Flash uses a Shape instance drawn with a bitmap fill.


Shape tweens on the timeline, instead of a Shape instances, are represented
by a new class called MorphShape (flash.display.MorphShape). 
MorphShape instances cannot be created dynamically and offer limited
interactivity through ActionScript.


As with previous versions of Flash, the only available symbol types for your
library are movie clip, button, and graphic.  When on the timeline, movie
clip symbols are represented as MovieClip instances; buttons, instances of a top
level Button class in ActionScript 2, are now instances of a new class called
SimpleButton (flash.display.SimpleButton);
and graphic symbols become, because of their lack of interactivity, Shape
instances.  As a Shape, however, graphic symbols are not allowed to contain
other children like MovieClips.  If you have an instance of a MovieClip in
a graphic symbol, that MovieClip will become a child of the graphic's parent
during playback, escaping from what would be the containing Shape instance..


For text, there are now two classes, TextField (flash.text.TextField)
and StaticText (flash.text.StaticText). 
The TextField class is for dynamic and input text.  As with previous
versions of ActionScript, these kinds of text fields can be created dynamically
through ActionScript.  The StaticText class used to represent static text
on the timeline, however, cannot be created dynamically.  These instances
are only available when a static text field has been placed on a timeline in
Flash.



Note: Text Fields and Var


In older versions of ActionScript, you could assign a variable (Var) to
be associated with a text field on the screen through the Property Inspector
panel. This variable would reference the text value of that field. Like
being able to define scripts on selected objects, this too has been removed
as a feature for ActionScript 3. Instead you would need to use the
text
property of the text field through its instance name.



The most common way to gain access of text and symbol display objects on the
screen through ActionScript is to assign them an instance name.  This name
is added through the instance name field in the property inspector of the
selected instance in Flash. 






Figure: Dynamic text field with instance name "myText"



By assigning an instance name, you are doing two things.  First you are
assigning the name property of that instance to that of the
instance name provided.  Secondly you are creating a variable in the
timeline with the name of the instance name that, when the instance is present
in the timeline, references that instance; otherwise its value is null.



Note: Changes with the name property in ActionScript 3


The name property in ActionScript 3 and the _name
property in previous versions of ActionScript do not behave the same. 
In ActionScript 2, by changing the _name property of a movie
clip in ActionScript you also changed the timeline variable used to access
that movie clip.


// ActionScript 2 changing _name

// Original movie clip instance name: my_mc
trace(my_mc); // traces _level0.my_mc
my_mc._name = "same_mc";
trace(same_mc); // traces _level0.same_mc
trace(my_mc); // traces undefined

With ActionScript 3 you cannot change the name property of a
display object if it was placed on the timeline in Flash (you can if the
object was dynamically created).  Even if you could, it would not
change the variable used to reference that instance as they are not
connected like they were in ActionScript 2.



As with ActionScript before, all display objects have a common set of
properties that describe their presentation on the screen in Flash.  This
includes properties for location, size, and color etc. In ActionScript 3,
however, many of these properties' names have changed.  More specifically,
the underscores used to preceded these properties are no more.  The x and y
positions are no longer represented with _x and _y but
simply x and y.  Similarly, the values to which
some of these properties can be defined has also changed.  The scaleX,
scaleY, and alpha properties, for example, no longer
range from 0-100 but now 0-1 (scale properties still able to go beyond these
bounds).  This may be something to watch for if you are porting code from
older versions of ActionScript to ActionScript 3.  Not only have the
property names changed, but also their potential values.


// ActionScript 2

myMovie._x = 50; // x position of 50
myMovie._xscale = 200; // 200% horizontal scale
myMovie._alpha = 50; // 50% transparent
// ...

// ActionScript 3
myMovie.x = 50; // x position of 50
myMovie.scaleX = 2; // 200% horizontal scale
myMovie.alpha = .5; // 50% transparent
// ...































































Common MovieClip Property Names
ActionScript 2 ActionScript 3
_name name
_x x
_y y
_width width
_height height
_xscale (0-100) scaleX (0-1)
_yscale (0-100) scaleY (0-1)
_rotation rotation
_alpha (0-100) alpha (0-1)
_visible visible
_xmouse mouseX
_ymouse mouseY
_parent parent

Understanding the Class Inheritance Hierarchy


If you look a the documentation for a class like MovieClip (flash.display.MovieClip),
you may notice that there may not be many definitions specific to the MovieClip
class. There are only 9 properties and 10 methods. You won't see definitions for
properties like name, x, y, etc. unless
you click the "Show Inherited Public Properties/Methods" link at the top of
those lists (these links appear as "Hide Inherited Public Properties/Methods" if
the definitions are already visible) since those properties are not unique to
the MovieClip class. Sure, the MovieClip class has those properties, but these
properties are actually defined within another class and MovieClip inherits
them to use as its own.


Since many classes use the same properties and methods in the same way -
MovieClip, Sprite, and Shape, for example, each have x, and y
properties and use them the same way - classes can be defined to reduce
redundancy by having similar members defined in a single location (class) and
then referencing those definitions for their own use. This is handled through
what is known as class inheritance. A single base class (a.k.a.
superclass) has definitions which may derived classes (a.k.a. subclasses) can
use as their own as long as they do what is called extending that
class.


It's an OOP concept, and though you may not be working specifically with OOP
when you're programming ActionScript yourself, this is in particular is helpful
to understand because the documentation is set up to reflect this association.
And the documentation is something you should be very dependant on, especially
when you first start learning ActionScript (or any language for that matter).


Taking a look back at the top of the MovieClip documentation page, you can
see a path that represents the location of MovieClip within its inheritance
hierarchy. For MovieClip this path is:




MovieClip
>

Sprite
>

DisplayObjectContainer
>

InteractiveObject
>

DisplayObject
>

EventDispatcher
>

Object


This shows that MovieClip inherits from Sprite and has all the properties and
methods that Sprite does, which itself, has all the properties and methods that
DisplayObjectContainer has... and so on and so forth until you reach the base
class Object, the class from which all other classes in ActionScript inherit.
This path shows just how similar MovieClips and Sprites really are. They are
practically the same except for the extra frame-related properties and methods
that are uniquely defined for MovieClip. Similarly all other objects that are
visible on the screen will inherit from DisplayObject. And you know all the
properties defined within the DisplayObject class will be within any display
object instance that can be made visible on the stage in Flash. So don't be
surprised when you click on the x link to look up the documentation of the
x
property and find yourself on th DisplayObject documentation page. They
are one in the same.



Note: The Class Hierarchy and Typing


The types that these classes within the MovieClip class hierarchy
represent, and the fact that there are so many within hierarchy (in
ActionScript 2, MovieClip inherited only from the Object class) will become
important later as types are discussed. For now, understand that an instance
can be typed as it's own class type or any of the classes from which it
inherits. A MovieClip, for example, can be correctly typed as DisplayObject.



Example: Referencing Movie Clips in the Timeline


In this example, you will create some display objects in the main timeline
and use ActionScript to change their properties.



  1. Create a new ActionScript 3 document in Flash CS3



The Display List


The display list in ActionScript 3 represents the visual hierarchy
of objects or display objects on screen within the Flash player. This starts
with a top-most, always present display object known as the stage followed by
the main timeline, or root, and all children within the main timeline as well as
their children.






Figure: Example display list starting with stage instance



Usually when referring to the display list, you're referring to the entire
display list within the Flash player. This is also sometimes called the
active display list
. However, you may also see the term display list used
with individual display object containers - display objects of the type
DisplayObjectContainer (flash.display.DisplayObjectContainer)
which can contain other display objects (e.g. Sprite and MovieClip instances) -
where each container is said to have their own display list. The display list of
any container consists of all of that container's child display objects and all
children within those children.


In AVM1 with ActionScript 2, it was not possible for a movie clip instance to
exist without it being attached to some timeline and effectively being a part of
the SWF's display list. AVM2 and ActionScript 3 has changed that. Now it is
possible for display objects to exist within memory but not be associated with
any particular timeline and therefore not be on screen. When this is the case,
these instances are said to be off-list as they are not within the
active display list and can only be referenced through ActionScript.


Also different with ActionScript 3 is how arrangement, or depth, is handled.
Before, all movie clips could be placed in just about any depth where movie
clips on the timeline actually initially existed in negative depths. Now all
depths start at 0 and are contiguous. In other words, if you have 2 display
objects within a container, they will have to exist at depths 0 and 1. You
cannot have one at depth 0 and the other at 10 leaving 9 empty depths. This
ultimately could mean less flexibility, but at the same time there is a more
concise understanding of the arrangement of display objects within the display
list since, if you know there are 5 objects in a display object container, you
know at exactly which depths they occupy.






Figure: Depths in ActionScript 3 are contiguous and cannot be negative



The root and stage


The main timeline of a FLA or SWF is known as the root timeline. In
ActionScript 2, you could access this timeline directly using the _root
property. This reference continues to exist in ActionScript 3, but is now called
root.


ActionScript 2 also had a class or object called Stage. Using the Stage
object you could determine the size of the Flash player window, check to see
when that size has changed, and specify how content was affected when it did
change, etc. The concept of the stage also exists in ActionScript 3, but now it
has taken a new form; instead of just being just an object or static class, the
stage is an instance that also acts as the top-most display object in the
display list hierarchy. It is the Flash player container for which all other SWF
content on screen. Whereas in ActionScript 2, the main timeline was the top-most
display object in the display list, in ActionScript 3 it is the stage instance
followed by the main timeline (root) as its first child. As with
the root property, you can access the stage instance in
ActionScript 3 using the stage property (note the lowercase "s").


There are 2 very important qualities about root and stage
that you need to come to terms with when working with ActionScript 3:



  1. The root and stage properties in ActionScript
    3 are not global. These properties are instead properties of the
    DisplayObject class, so only display object instances have access to them.
    Other classes, namely custom classes, do not have access unless explicity
    given access by another class that does.

  2. The root and stage properties will be
    null
    unless the display object from which they are being referenced
    is a child of the active display list. Off-list display objects will not be
    able to access the root timeline and the stage through those respective
    properties.


When coding within the main timeline in Flash CS3 and not creating dynamic
display object instances with ActionScript, these qualities normally don't
apply. This is because you're writing ActionScript within a display object's
timeline who gets automatically added to the active display list by Flash making
the root and stage properties immediately available. Creating display objects
dynamically means that you are working with an instance that starts off-list,
and won't have access to root or stage until added to the active display list
through ActionScript


// Main timeline in Flash CS3

// The main timeline always has access to root and stage
trace(root); // traces "[object MainTimeline]"
trace(stage); // traces "[object Stage]"

In the above example you can see that the output of tracing root actually
produces an object instance of the type MainTimeline. This is an automatic
MovieClip-based class that Flash generates to represent the instance used for
the root timeline - It's basically just a MovieClip under a different name. The
stage, similarly, is an instance of the Stage class (flash.display.Stage).
This same output would be seen if this code was placed in the timeline of a
movie clip placed on the main timeline.


Dynamic display objects


When you created dynamic movie clips in ActionScript 2, you had basically 3
options: you could duplicate an existing movie clip on the screen using
duplicateMovieClip()
, you could create an empty movie from scratch with
createEmptyMovieClip(), or you could create an instance of a movie
clip symbol within your library through attachMovie().


In ActionScript 3, it's all much simpler. All you need to do to make a
dynamic movie clip is create a new instance of it like you would any other class
using the new keyword. For new empty MovieClip instances, you just
use new MovieClip(), or better yet, new Sprite() since
empty MovieClip instances cannot be given new frames (and a Sprite is just a
MovieClip with no frames).


// Create a new, dynamic, off-list Sprite

var mySprite:Sprite = new Sprite();

Because display objects in ActionScript 3 can exist off screen (off-list)
creating a new dynamic instance in this manner does not mean that the new
instance is visible on the screen. Before it can be made visible, it has to be
added to the active display list. To do that you use one of two methods:
addChild()
which adds a display object at the end of a display list, or
addChildAt() which adds a display object at a specific location
within a display list.


// Create a new, dynamic, Sprite and add

// it to the current timeline's display list
// (ActionScript 3 equivalent to createEmptyMovieClip)
var mySprite:Sprite = new Sprite();
addChild(mySprite);

New Sprite instances, however, contain no content by default. Even though the
above example places a Sprite on the screen, it cannot be seen because there's
nothing in it to see. It's more likely that in Flash you would want to
dynamically create an instance of a movie clip symbol in your FLA's library.
Before you can create an instance of a movie clip that exists as a symbol in
your library, then you first need to give that symbol a class name within the
Linkage dialog (right or command-click on that symbol and select Linkage...)
for that symbol.


In the Linkage dialog, you have a number of checkboxes providing you with
some options for your symbol. Under Linkage you have two primary options, Export
for ActionScript and Import for runtime sharing. Import for runtime sharing
allows you to load in symbols from external SWFs. For dynamic movie clips, you
need to Export for ActionScript. Additional options related to Export for
ActionScript include Export for runtime sharing which is related to Import for
runtime sharing, and Export in first frame which assures that your SWF will load
this movie clip into the Flash Player prior to any of your frame scripts making
it available for dynamic creation at any time.


Once Export for ActionScript is selected, two text fields within the Linkage
dialog appear, Class and Base class. The Class field is the most important for
creating dynamic movie clip instances from your library. It is needed to
uniquely identify the symbol with a class (which will be automatically generated
for you behind the scenes) so that it can be created with the new
keyword. The Base class identifies the class from which the symbol inherits.
Since you're working with movie clip symbols, this will usually be MovieClip,
the default value. When working with custom classes, you could decide to put
your own class as the Base class.






Figure: Assigning a custom class name to a movie clip in the library



Once a class name is specified for a movie clip symbol, you can create an
instance of it with the new keyword and then add it to the active
display list using addChild or addChildAt. The class
name you defined represents the ActionScript 3 version of the ActionScript 2
linkage ID.


// Create a new, dynamic movie clip from the library

// and add it to the current timeline's display list
// (ActionScript 3 equivalent to attachMovie)
var myMovie:CustomMovieClass = new CustomMovieClass();
addChild(myMovie);

For every movie clip symbol (this also works with button symbols, though the
Base class would be SimpleButton) you wish to add to the screen or create
dynamically, you would need to define a unique class so that those instances can
be created and added to the display list as seen above.


Unfortunately, there is no ActionScript 3 equivalent to
duplicateMovieClip
. Butin reality, it's not a function that the Flash
world has had a whole lot of dependancy on since the introduction of
attachMovie
in Flash 5. ActionScript 3 developers will have to get by
with out it.


Bitmaps


Bitmap images are another form of media that can exist within your Flash
library. They too can be created and added to the screen dynamically with
ActionScript 3. The images as they exist in the library, however, do not
directly translate to on-screen display objects like movie clips do. Instead,
images in the library represent BitmapData (flash.display.BitmapData)
instances in ActionScript. To be visible on the screen, this data needs to be
given to a Bitmap (flash.display.Bitmap)
instance.


As with movie clips in the library, when creating bitmap images dynamically
from your library in Flash, you need to assign it a unique class name through
the Linkage dialog. This is done the same way it is done with movie clips only
the base class for bitmaps will be BitmapData as opposed to MovieClip.


When you create new BitmapData instances with ActionScript, it is required
that both a width and height be supplied for the new instance as it defines the
size for that instance. Since images in your library are based off of the
BitmapData class, they too require that width and height be set for them when
new instances are created. Images in your library, however, already exist with a
set width and height so the values used when creating new instances of your
library bitmap image do nothing. If you know the image size you should use that;
otherwise 0 works fine.


Once you create an instance of your library image, you need to give it to a
Bitmap instance before it can be seen on the screen. This can be done through
the Bitmap constructor or by setting the bitmapData property of the
Bitmap instance. That Bitmap instance would then need to be added to the active
display list before it could be made visible in Flash.


// Create an instance of a library bitmap 

// given the Class name of MyImage
var imageData:MyImage = new MyImage(0, 0);

// Give the instance to a Bitmap through its
// constructor, then add it to the display list
var imageBmp:Bitmap = new Bitmap(imageData);
addChild(imageBmp);

Removing


Once you have a display object on the screen, and it's time for it to be
removed, you can use one of two removal methods, removeChild()
which removes the specified display object from a display list, and
removeChildAt()
which removes the child at a specific location within a
display list.


// Add movie clip from the library to display list

var myMovie:CustomMovieClass = new CustomMovieClass();
addChild(myMovie);

// Remove movie clip from the library from display list
removeChild(myMovie);

There are two important points to display object removal in ActionScript 3:



  • Removal is handled through the parent display object container, not the
    child as was the case with removeMovieClip() in ActionScript 2
    (parentObject.removeChild(childObject) vs.
    childObject.removeMovieClip()
    ).

  • Removing a display object from a display list does not destroy the
    display object or remove it from Flash's memory. As long as you still have a
    reference to a display object, it will still exist off-list even if not as a
    child of any other timeline or container.


The latter is especially important for ActionScript 2 veterns who are used to
having movie clip references become invalid after the object has been removed
from the screen. This is no longer true in ActionScript 3 since the instance
remains valid, just off-list. To truely get rid of the instance, all references
would need to be deleted (if dynamic) or set to null, just like any
other kind of non-display object in ActionScript.


The first point should also not be seen as unimportant. This is a reflection
of how you should be working with ActionScript - starting at the outside looking
in as opposed to being on the inside looking out, which has become a popular
approach for many ActionScript 2 developers, espcially commands like
removeMovieClip
which work from the child removing itself from it's own
parent. What this basically means is that when working with movie clips and
timelines, the best approach when writing script is not to be within a movie
clip referencing data and methods that exist outside that movie clip, but
instead to be looking into child movie clips and letting parent containers look
into that movie clip. The less dependancy any movie clip or timeline has on
objects outside of itself, the better.


Other properties and methods in addition to the add and remove methods that
are useful when working with movie clips include those found in the
DisplayObjectContainer class (flash.display.DisplayObjectContainer).
These include:



  • numChildren

  • getChildAt

  • getChildByName

  • getChildIndex

  • setChildIndex

  • swapChildren

  • swapChildrenAt


Most are pretty self explanitory. For more information consult the
DisplayObjectContainer documentation.



Tip: Reducing Display Object References


Since removeChild does not remove a display object from
memory, only the removal of all references, you can limit your references to
dynamic display objects by not creating any. Instead you can take advantage
of the fact that addChild returns a reference to the added
display object and use it to define a name for the new object added (which
can be created directly within the call to addChild). Then if
you ever need to reference the display object, you can use
getChildByName
.


// Minimize display object references

addChild(new CustomMovieClass()).name = "myMovie";
getChildByName("myMovie").x = 100;

If no other references are made, removing the child from its parent will
remove it from memory (assuming the garbage collector catches it; for more
information on how the garbage collector in Flash works, see Grant Skinners
article

AS3: Resource Management
).








Example: Creating Dynamic Instances from the Library


This example will add symbols and bitmaps from the library randomly to
the document at different locations on the screen. Then, based on their
locations, a script will rearrange the objects so that the lower objects are
positioned above the objects that are higher for the appearance of
perspective.


Steps:



  1. In the source files, open RandomTreesWithArrangement.fla in the
    DisplayObjects directory. This file consists of one empty layer named
    ActionScript and two objects in the library, a tree movie clip symbol,
    and a tree.png bitmap image





Figure: Tree movie clip and bitmap assets


In order to be able to dynamically create the objects in the library with
ActionScript 3, you will need adjust their linkage options and provide a
unique class name by which to reference them.



  1. Right-click (Command-click on Mac) on the tree movie clip symbol in
    the library

  2. Select Linkage... from the context menu






Figure: Setting linkage properties from the library



  1. In the linkage dialog select Export for ActionScript

  2. Type for the Class name: Tree

  3. Repeat the steps fot the tree.png image only for its class use:
    TreeImageData


    Notice that BitmapData is the Base class for the image whereas for the
    movie clip it was MovieClip





Figure: Class name for tree.png bitmap


With the linkage definitions set up, we can now start coding the
ActionScript to create them. First, define some variables that will apply to
the example. In this case, there is only one, treeCount, to
determine how many trees to generate.



  1. Select the first frame in the ActionScript layer and open the
    Actions panel.

  2. Add the following script to the Actions panel


// The number of trees to generate

var treeCount:int = 20;

Next we can define a function to generate the trees. This will rely
heavily on the Math.random() function to



  1. determine if a movie clip or bitmap version of the tree is created
    and

  2. where on the screen (x and y locations) it is placed


A loop will be used to create and place the trees based on the value of
treeCount which will be passed into the function when it is
called.



  1. Add the following script to the Actions panel


// Create a number of trees randomly

// positioned within the document
function createTrees(numberOfTrees:int):void {

// variable to store trees created
// in the loop - the DisplayObject
// type satisfies both MovieClip
// and Bitmap instances
var currTree:DisplayObject;

// loop through the number of trees
while(numberOfTrees--){

// randomly add a tree either
// as a bitmap or a movie clip
if (Math.random() < .5) {

// create a new Tree instance
// Tree is the class name given to
// the tree symbol in the library
currTree = new Tree();

}else{

// create the tree BitmapData instance
// from the library, then add it to a
// new Bitmap instance
var currTreeData:TreeImageData = new TreeImageData(0, 0);
currTree = new Bitmap(currTreeData);
}

// position the new instance randomly on
// the screen based on the stage's size.
// subtracting the tree size from the stage
// size keeps the trees on screen
currTree.x = Math.random() * (stage.stageWidth - currTree.width);
currTree.y = Math.random() * (stage.stageHeight - currTree.height);

// don't forget to add the tree
// to the display list
addChild(currTree);
}
}

As it is now, we can call the createTrees function and trees from the
library will be created and added to the screen dynamically.



  1. Add the following script to the Actions panel


// Create the trees

createTrees(treeCount);


  1. Test your movie. You should see the following





Figure: Dynamic random tree objects


Because these trees were added dynamically and randomly, their
arrangement does not seem quite right. You can see that trees higher on the
screen seem to be overlapping those below them when you would expect the
opposite to be true.


In ActionScript 2, this could easily be fixed during the creation of the
tree objects by setting their depth to equal their y position. This does not
work in ActionScript 3 since you cannot have and gaps in the display list -
all depths must be contiguous. A solution for ActionScript 3 would be to put
your objects in an array and sort that array based on the objects y (or
other) value. That array's sorted arrrangement can then be used for the
display list's arrangement. A new function can be created to facilirate
that.



  1. Add the following script to the Actions panel


// Arrange all children in the specified

// container based on their y value
function sortChildrenByY(container:MovieClip):void {
var i:int;
var childList:Array = new Array();

// first put all children in an array
i = container.numChildren;
while(i--){
childList[i] = container.getChildAt(i);
}

// next, sort the array based on the
// elements' y property
childList.sortOn("y", Array.NUMERIC);

// now match the arrangement of the array
// with the arrangement of the display list
i = container.numChildren;
while(i--){

// if the child at position i in the array
// does not match the child at position
// i in the display list, set that child
// to the i position in the display list
if (childList[i] != container.getChildAt(i)){
container.setChildIndex(childList[i], i);
}
}
}

This function takes any container MovieClip and arranges its children so
that the higher they are on the screen the lower they are in the display
list using array-based sorting.


All that remains is calling this new function using the current timeline
so that the trees created earlier will be properly arranged.



  1. Add the following script to the Actions panel


// Arrange the trees

sortChildrenByY(this);


  1. When you've completed adding the code, test your movie. You should
    see the following





Figure: Dynamic tree objects with arrangement


The similarities of the display list to an array makes it easy to use
arrays for sorting display lists like this. Similarly, you could implement
your own sorting algorithm using just the display list and methods like
getChildAt() and setChildIndex() without the aide
of arrays.



Dynamic graphics


Since Flash MX, ActionScript has had a drawing API for creating dynamic
vector graphics in Flash. This API consists of methods like beginFill(),
moveTo(), lineTo(), and curveTo() used
within MovieClip instances. ActionScript 3 continues to make these methods
available but they are no longer used with MovieClip instances, or even
DisplayObject instances for that matter. Instead, they are used with Graphics (flash.display.Graphics)
instances.


The Graphics class is now used to facilitate all dynamic drawings. Instances
of this class are available as graphics properties within the
classes that allow you to draw in them dynamically. These classes include:



  • Shape

  • Sprite

  • MovieClip


// Create a blue triangle with a red

// outline within the current timeline

graphics.lineStyle(2, 0xFF0000);
graphics.beginFill(0x0000FF);
graphics.moveTo(50, 0);
graphics.lineTo(100, 100);
graphics.lineTo(0, 100);
graphics.endFill();

When drawing methods are used for the Graphics object within these instances,
dynamic drawings are created within a drawing layer within those instances. For
Sprite and MovieClip, this drawing layer exists below child objects within their
display list. There is no way to draw dynamic vectors above children of a Sprite
or MovieClip instance.


In addition to the methods available in ActionScript 2, ActionScript adds
some new methods to make drawing simple shapes like rectangles and circles a lot
easier. These methods include:



  • drawCircle

  • drawEllipse

  • drawRect

  • drawRoundRect

  • drawRoundRectComplex


Example: Dynamic Drawings Created with ActionScript



This example uses the vector drawing API to create a checkerboard with
ActionScript. It will use two of the new API methods, drawRect
and drawCircle.


Checkerboards are a little tricky because they're checkered. This means
that every other space within the checkerboard grid is the opposite color
than the one adjacent to it. With ActionScript, the modulous, or mod,
operator (%) can be used to help determine what color any
location is base on the x and y location within the board. This will be
helpful when creating checkboard and drawing each of the board's spaces.


The general idea here is to generate a checkerboard graphic within the
main timeline and then add on top of that graphic a collection of checkers
that could be played with in a checker game. Though there will be no
interaction assigned to these checkers in this example, there could be some
down the line, so each are placed in their own Sprite instance when added to
the board allowing for each to be interacted with independently.


Steps:



  1. In the source files, open DrawingAPICheckerBoard.fla in the
    DisplayObjects directory. This file consists of one empty layer named
    ActionScript.

  2. Select the first frame in the ActionScript layer and open the
    Actions panel.


The first thing to do is define some variables that can be used to
control the script. For this example, we will want control over the
checkerboard color, the checkerboard space size and the size of the checkers
within those spaces.



  1. Add the following script to the Actions panel


// Set up some variables

var player1Color:uint = 0x000000;
var player2Color:uint = 0xFF0000;
var spaceSize:Number = 40;
var checkerSize:Number = 30;

Next we'll define a function for drawing the board. This will use two for
loops to loop through and draw each space in the board with the drawing API
based on the space size. Using mod with the locations in the board grid (spaceX
and spaceY), the correct color of that location can be
determined.



  1. Add the following script to the Actions panel


// Draws the checkerboard

function drawBoard():void {
var currColor:uint;
var spaceX:int;
var spaceY:int;

// loop through x and y coordinates of board
for (spaceX = 0; spaceX < 8; spaceX++){
for (spaceY = 0; spaceY < 8; spaceY++){

// alternate colors using modulous
currColor = (spaceX%2 != spaceY%2) ? player1Color : player2Color;

// draw square in graphics object

// this will be drawn in the current timeline
graphics.beginFill(currColor);
graphics.drawRect(spaceX*spaceSize, spaceY*spaceSize, spaceSize, spaceSize);
graphics.endFill();
}
}
}

Now the checkers drawing function can be defined. To make it a little
easier to draw a large number of checkers, this function can be used to draw
an entire row at a time. Each checker is drawn in a sprite and that sprite
is added to the active display list (of the current timeline) so it can be
seen on screen.



  1. Add the following script to the Actions panel


// Draws a row of checkers on the checker

// board. Each checker is in it's own Sprite
function drawCheckerRow(rowNumber:int, playerColor:uint):void {
var spaceX:int;
var checkerOffset:Number = spaceSize/2;
var checkerRadius:Number = checkerSize/2;
var checker:Sprite;

// loop through each column in the row
// skipping every other column
for (spaceX = (rowNumber + 1)%2; spaceX < 8; spaceX += 2){

// create a new Sprite for the checker
checker = new Sprite();
checker.x = spaceX*spaceSize + checkerOffset;
checker.y = rowNumber*spaceSize + checkerOffset;

// draw checker in checker sprite's graphics
checker.graphics.lineStyle(2, player2Color);
checker.graphics.beginFill(playerColor);
checker.graphics.drawCircle(0, 0, checkerRadius);
checker.graphics.endFill();

// be sure to add it to the display list
addChild(checker);
}
}

All that remains is calling the functions so the drawings can be made.
For a new checkerboard setup, you need 3 rows of checkers for each player, 6
total.



  1. Add the following script to the Actions panel.


// Call drawing functions drawing

// checkerboard and checkers
drawBoard();
drawCheckerRow(0, player2Color);
drawCheckerRow(1, player2Color);
drawCheckerRow(2, player2Color);
drawCheckerRow(5, player1Color);
drawCheckerRow(6, player1Color);
drawCheckerRow(7, player1Color);


  1. When you've completed adding the code, test your movie. You should
    see the following




Figure: Dynamically drawn checkerboard


The inclusion of the drawRect and drawCircle
methods really made this a lot easier in ActionScript 3. In ActionScript 2,
you would have to draw each line or curve individually or create your own
functions that behaved like drawRect and drawCircle.





Note: Working with Display Objects


This section has only covered the basics in display object usage and
their characteristics. There are many other important topics that relate
to display objects that are covered in more detail in later sections.




Events


Events indicate when something happen.  Clicking on a button indicates a
"click" event.  When an external text file loads into the Flash player,
there's a "complete" event indicating that the contents of that text file have
been completely read into the player.


Virtually all ActionScript is executed based on events.  Whether it's an
event handler used to run code when a button is clicked or just commands written
on the timeline in frames (executed during the event of the Flash player
displaying that frame), you're writing code that reacts to events.


Events then


For non frame-based actions, most events (specifically mouse and keyboard
events) were originally handled within on([event]){} code blocks
placed on button symbols.


// Starting with Flash 2 and available for

// ActionScript 1 and 2, a press event
// placed on a selected button symbol
on(press) {
// play timeline in which this button exists
play();
}

Events used with on (some introduced after Flash 2) include:



  • press

  • release

  • releaseOutside

  • rollout

  • rollover

  • dragOut

  • dragOver

  • keyPress ["whichKey"]


When Flash 5 came around, ActionScript featured a new kind of event handler
that could be added, not to button symbols, but movie clips. This was done using
the onClipEvent([event]{} code block.


// Flash 5; ActionScript 1

// Placed on a selected movie clip symbol
onClipEvent(enterFrame) {
// move this movie clip 5 frames to
// the right every time the Flash player
// draws a frame based on the frame rate
_x += 5;
}

With Flash 5 you could also load XML into the Flash player with the new (at
the time) XML object.  In order for a programmer to know when the XML has
been loaded and parsed, an onLoad event handler would be defined
for the XML object.  This handler was in the form of a dynamic function
definition that could be defined, deleted and changed for the XML object at any
time.


// Flash 5; ActionScript 1

// XML onLoad handler
var myXML = new XML();

// event handler called when
// XML has been loaded into myXML
myXML.onLoad = function(success){
// if XML has been loaded and parsed
// successfully, success is true
if (success){
trace(this); // trace XML
}
}

// load the XML into the XML object when
// loaded and parsed, onLoad will be called
myXML.load("xmlFile.xml");

Flash MX (6) greatly improved event handling. Not only were on
code blocks allowed to be used on both movie clips and buttons (as opposed to
just buttons) but, Flash MX also allowed dynamic event handlers to be created
for buttons and movie clips in the same way the onLoad event
handler was defined for XML objects in Flash 5.  Whereas on
and onClipEvent were static and couldn't be changed during runtime,
using these function-based event handlers meant an event could be deleted or
redefined as the Flash movie was playing, something especially useful for
onEnterFrame events used to handle animation.


// Flash MX; ActionScript 1

// onEnterFrame event handler
// assigned for for a movie clip instance
myBall_mc.onEnterFrame = function(){
// move this movie clip to the right
// by 5 pixels every frame
this._x += 5;

// if the x position of this movie clip
// is greater than 200, delete the event handler
if (this._x > 200){
delete this.onEnterFrame;
}
}

More importantly, Flash MX introduced a new concept to ActionScript called
listeners.  Listeners are objects with methods (and, later, can
include just methods or functions) that listen for and have a handler called as
a result of an event. The key concept behind listeners is that you can have more
than one event handler associated with any one event.  With normal event
handlers, like the onLoad event handler with the XML object, you
can only define one onLoad function. If you define it again, you
will be overwriting the old onLoad and replacing it with the new definition. 
It was very difficult to have more than one event handler associated with a
single event. Listeners solved that problem.


With listeners, instead of defining an event handler for the object receiving
the event, you assigned the event handler to another object – any other object –
and then that object was added as a listener of the object originally receiving
the event.


// Flash MX; ActionScript 1

// Mouse listeners; more than one
// object/handler reacting to the same event
var handler1 = new Object();
handler1.onMouseDown = function(){
trace("Handler 1");
}

var handler2 = new Object();
handler2.onMouseDown = function(){
trace("Handler 2");
}

Mouse.addListener(handler1);
Mouse.addListener(handler2);

// Clicking the mouse once results in the traces:
// Handler 1
// Handler 2

Since both handler1 and handler2 in the example
above were listeners of the Mouse object, their onMouseDown methods
were called as event handlers of the Mouse's onMouseDown event. If you ever
wanted to remove an object from being an event listener, you could use
removeListener()
.


Assigning listeners with addListener was a great concept but was limited to a
few objects. They included:



  • Key

  • Mouse

  • Selection

  • Stage

  • TextField

  • FStyleFormat


Enter ActionScript 2 with Flash MX 2004 (7).  With ActionScript 2 came a
new set of components that used an architecture known as V2 ("Version 2"). 
This architecture used a new kind of listener format which was similar to using
addListener but instead of adding objects as listeners of other
objects, you listened to specific events from other objects.  This used a
new method called addEventListener that was part of a new (V2)
class called EventDispatcher.  The addEventListener method accepted
both an object with event handlers (or just an event handler function) as well
as a name of the event you wanted to listen for.  The inclusion of the
event prevented unnecessary events to be sent to objects that didn't have event
handlers for them (e.g. handler1 and handler2 in the
previous example received onMouseDown and onMouseUp events from the Mouse object
even though they had no event handlers for them). Additionally, an event object
was passed to the event handlers added as listeners when called for an event to
provide information about the event occuring.


// Flash MX 2004; ActionScript 2

// button component event handlers

// Listener object with event handler
var handlerObject:Object = new Object();
handlerObject.click = function(event:Object):Void {
trace(event.type +": "+ this);
}

// Listener function
function handlerFunction(event:Object):Void {
trace(event.type +": "+ this);
}

// assign to be listeners of
// submit_button for the click event
submit_button.addEventListener("click", handlerObject);
submit_button.addEventListener("click", handlerFunction);

// Clicking the submit_button component:
// click: _level0.submit_button
// click: [object Object]

Because this form of event handling was built into the V2 component
architecture (the EventDispatcher class being part of that architecture), you
really didn't see it much anywhere else in ActionScript outside of components. 
The core language objects like Mouse and Key still used the older addListener
method for handling events.  This all changed with ActionScript 3.


Events now


[TODO: fit in that root does not dispatch its own mouse events, event
clean-up (oef running after removal)]


ActionScript 3 completely revamped the way events were handled in
ActionScript.  There are two major themes that define ActionScript 3
events:



  1. Consistent event handling with a new, native EventDispatcher class

  2. Support for event propagation within display objects


Though the EventDispatcher class is not entirely new having existed with the
V2 component architecture present in Flash MX 2004 components, with ActionScript
3 EventDispatcher has been updated and made a native part of the ActionScript
language responsible for essentially all event handling.  What does this
mean for events in ActionScript 3?



  • no on(event){}

  • no onClipEvent(event){}

  • no adding scripts on selected objects. Period.

  • no object.onEvent = function(){} (for native events)

  • no addListener

  • no object-based listeners (now only using methods/functions)


With ActionScript 3 all event handlers are associated with events using
addEventListener
and consist of a single function listener. With Events
in ActionScript 3 you get the flexibility of listeners (more than one handler
for any one event) and the efficiency of the V2 addEventListener
(being able to single out events) plus an increase in performance as a result of
the EventDispatcher class now being native to the Flash player.


Also, in ActionScript 2, when an event handler was called, it received an
Object argument (of the type Object) containing some information about the event
such as the type of event and any properties that might be specific to that
event.  ActionScript 3 formalized this process now having pre-defined Event
classes to be used within events instead of the generic objects used with
ActionScript 2.  These event objects contain the event type, where the
event originated, the current object receiving the event, as well as a few other
properties used to describe the event that occurred.


Different kinds of events have different kinds of Event classes. The most
basic event class is Event, but there are also other Event classes such as
MouseEvent, KeyboardEvent, and many others.  These classes often also
contain the event types as constant properties of the class.  The click
event, for example, has an event type of "click" which is defined in the
MouseEvent class as MouseEvent.CLICK.  The purpose of using
these values instead of their string representations is that the ActionScript
compiler will be able to warn you about spelling mistakes if you make them.


button.addEventListener("clikc", handler); // no error

button.addEventListener(MouseEvent.CLIKC, handler); // Error!

To summarize, event handling in ActionScript 3 means:



  • using addEventListener/removeEventListener

  • listening for event types stored in Event classes

  • using a function (not an object) event handler/listener

  • defining event handler/listeners to receive an argument of the type
    Event


// ActionScript 3 event handler

function clickSubmit(event:MouseEvent):void {
gotoAndStop("submitFrame");
}

// add clickSubmit event handler as listener of the
// click event received by submit_button instance
submit_button.addEventListener(MouseEvent.CLICK, clickSubmit);


Along with how event handlers are defined, you will also changes in how
they work and how they are identified. Many event names have changed while
other events have been added and even some removed. Here is a quick
comparison of some common events between ActionScript 2 and ActionScript 3.









































































Common Interactive Events
ActionScript 2 ActionScript 3 Differences
onPress "mouseDown" (MouseEvent.MOUSE_DOWN)  
onRelease "mouseUp" (MouseEvent.MOUSE_UP), "click" (MouseEvent.CLICK) The click event is most like onRelease since it depends on the
object first receiving a mouseDown event whereas mouseUp can occur
regardless of what was pressed
onReleaseOutside "mouseUp" (MouseEvent.MOUSE_UP) This has been removed, but using the mouseUp event with the
stage (because of propagation) will allow you to detect when the
mouse has been released outside of the object originally pressed
onRollOver "mouseOver" (MouseEvent.MOUSE_OVER), "rollOver"
(MouseEvent.ROLL_OVER)
Two events can now be used for rolling over objects; mouseOver
will propagate, rollOver will not
onRollOut "mouseOut" (MouseEvent.MOUSE_OUT), "rollOut"
(MouseEvent.ROLL_OUT)
Two events can now be used for rolling off of objects; mouseOut
will propagate, rollOut will not
onDragOver "mouseOver" (MouseEvent.MOUSE_OVER), "rollOver"
(MouseEvent.ROLL_OVER)
Detecting a "drag" will have to be done manually in combination
with the mouseDown event.
onDragOut "mouseOut" (MouseEvent.MOUSE_OUT), "rollOut"
(MouseEvent.ROLL_OUT)
Detecting a "drag" will have to be done manually in combination
with the mouseDown event.
mouseDown "mouseDown" (MouseEvent.MOUSE_DOWN) Now only works when the mouse is over the object dispatching the
event (like onPress); normal objects cannot be made listeners of the
Mouse to be able to recieve this event, only InteractiveObject
instances can
mouseUp "mouseUp" (MouseEvent.MOUSE_UP) Now only works when the mouse is over the object dispatching the
event (like onRelease but not requiring that the object be clicked
first); normal objects cannot be made listeners of the Mouse to be
able to recieve this event, only InteractiveObject instances can
mouseMove "mouseMove" (MouseEvent.MOUSE_MOVE) Now only works when the mouse is over the object dispatching the
event; normal objects cannot be made listeners of the Mouse to be
able to recieve this event, only InteractiveObject instances can
onKeyDown "keyDown" (KeyboardEvent.KEY_DOWN) Object must now have focus to receive this event; normal objects
cannot be made listeners of the Key to be able to recieve this
event, only InteractiveObject instances can
onKeyUp "keyUp" (KeyboardEvent.KEY_UP) Object must now have focus to receive this event; normal objects
cannot be made listeners of the Key to be able to recieve this
event, only InteractiveObject instances can

You may notice a theme of reducing the number of events needed to work
with in ActionScript. The older onPress and onMouseDown events have now been
consolidated into one mouseDown event in ActionScript 3. Similarly, you are
seeing events that are less global and more specific to a related object.
The mouseMove event, for example, now only works when the mouse is over the
object handling the event. Similarly, the key events, too, only respond to
the objects which currenly have focus.


Other behaviors regarding mouse events and display objects have also
changed. In ActionScript 2, for example, adding any onPress,
onRelease, or similar "on" mouse event handler to a movie clip
would cause that movie clip to display a hand (or finger) cursor when the
mouse was over that movie clip. This is no longer the case with ActionScript
3. That hand cursor will now not be visible unless the display object's
buttonMode and useHandCursor properties are true (useHandCursor
is true by default but buttonMode is not). Setting
buttonMode
to true will also enable a focused object to receive a
click event if the space bar or the Enter key is pressed on the keyboard.


// Show the hand cursor for myButton

// and allow clicking through Spacebar and Enter
myButton.buttonMode = true;

Similarly, by defining the same event handlers in ActionScript 2 that
provided the hand cursor, you were also indicating to the Flash player that
the movie clip was "mouse enabled" or that it is necessary for that instance
to intercept and handle mouse events. Movie clips without those "on" mouse
event handlers ignored mouse events and let them pass on through to any
mouse enabled movie clip instances beneath them. With ActionScript 3, all
mouse capable display objects (any instance on the screen that inherits from
the InteractiveObject class, including Sprites and MovieClips) will be mouse
enabled by default and prevent events from reaching instances arranged below
them, even if they have no event handlers defined for them. To change this,
you have to set the object's mouseEnabled property to false.


// Allow objects beneath the overlay

// instance to receive mouse events
overlay.mouseEnabled = false;

There's a similar mouseChildren property which relates to
child objects within a display object container instance. When
mouseChildren
is set to false, child objects will not receive mouse
events but the main parent object will (assuming mouseEnabled
is true). This becomes useful when dealing with event propagation.


// Prevent the child objects in the

// window instance from receiving mouse events
window.mouseChildren = false;

[TODO: more about the Event object]


Example: Reacting to the Mouse


Most user interaction with Flash revolves around mouse events. This
example demonstrates how mouse events can be used with the vector drawing
API to make a drawing board application. It will rely on mouse clicking as
well as dragging the mouse around on the screen (mouseMove) to make strokes
on the drawing canvas.


To use this application, a user will first select a color from a
collection of colors on the left side of the screen, then click and drag in
the drawing board box to the right of the screen. As they move their mouse,
lines of the selected color will be drawn on the board. To clear an existing
drawing, the Clear button below the color selections can be clicked.


For the colors, this example will use a little bit of a shortcut. Instead
of defining color variables in each color selection, an array will be used
to contain all the color values being used. Those colors will then be
associated with the selectable color movie clips by matching the movie
clip's position in the display list with the color at that position in the
array. The real benefit here, for all the lazy people out there, is that
this will prevent the need to assign instance names to each of the wells
since each well will be referenced and assigned a color using
getChildAt()
. Their positions within the display list will be used
both to assign colors as well as to retrieve the color when that color is
selected.



Note: Dynamic Creation


The process of creating the color selections could also be done
dynamically which would also, at least in terms of authoring set up,
prevent the need to assign instance names. However, in this example, the
selections are added to the screen manually and using their index within
the display list is used to prevent the need to reference them by name.



Because there are other elements on the screen, these selectable color
movie clips will need their own display list. For that, the
colorCollection
movie clip was created to contain them. Each
selection also contains a colorBlock movie clip (to show their
color) and a border movie clip that will be highlighted when
that color is selected. Each color selection within colorCollection,
however, remains unnamed.





Figure: Color selections within the drawing application


There will be some initialization steps where colors in an array will be
assigned to each selection. That selection, and the color it references,
will be saved to variables for when the user draws to the screen or changes
the selection from the current color to the next.


Steps:



  1. In the source files, open DrawingBoardApplication.fla in the Events
    directory. This file consists of one empty layer named ActionScript and
    an Interface layer with the contents of the drawing application's
    interface.

  2. Select the first frame in the ActionScript layer and open the
    Actions panel.

  3. Add the following script to the Actions panel.


// A variables to contain the

// selected color and color clip
var selectedColor:uint;
var selectedColorClip:MovieClip;
// Colors to be used in the selections
var colors:Array = [
0x000000, 0xFFFFFF,
0xFF0000, 0x00FF00,
0x0000FF, 0xFF00FF,
0xFFFF00, 0x00FFFF,
];

This sets up or current color (to be referenced when drawing), the
currently selected color movie clip, and the colors to be assigned to the
different color selections. Note that the selectedColor
variable has a type of uint. Normal RGB color values such as 0xFFFFFF are
numeric values that can fit into the positive values of the int datatype.
However, when dealing with RGBA, or Red, Green, Blue, and Alpha, you start
seeing color values which exceed the positive range within ints. Unsigned
integers (uint) can account for these values which is why you will often see
colors typed as uint.


Next a function is needed to make the connection between the colors and
the selectable color clips. This function will need to loop through the
children of the colorCollection movie clip and set the
colorBlock
of each of those children to the related color in the
colors array. This function will also set up the interaction
that selects the color when each of these clips are clicked using
addEventListener()
. This function can be called
defineColorSelections().



  1. Add the following script to the Actions panel.


// Adds colors to the color movie clips

// in the colorCollection clip and sets
// them up with click listeners
// for selecting a current color
function defineColorSelections():void {

// set up some variables to be used
var colorClip:*;
var colorForm:ColorTransform;

// loop through all the child
// instances within colorCollection
// using this loop, instance names do
// not have to be given for each child
var i:int = colorCollection.numChildren;
while(i--) {

// get the current child in the loop
colorClip = colorCollection.getChildAt(i);

// set the color of the colorClip's
// colorBlock instance to the color
// specified in the colors array
// at this same position.
colorForm = colorClip.colorBlock.transform.colorTransform;
colorForm.color = colors[i];
colorClip.colorBlock.transform.colorTransform = colorForm;

// set up an event handler so that when
// the colorClip is clicked, it will set
// itself to be the selected color
colorClip.addEventListener(MouseEvent.CLICK, selectColor);
}
}

Notice at the end of this function, addEventListener was
used with colorClip - the current child movie clip of
colorCollection
in the loop - to set up an event handler called
selectColor
with the click event. This means that whenever one of
those child clips is clicked, the selectColor event handler
function is run. The sole purpose of this handler is to call a function
called setCurrentColor which will set the current color based
on the selection clicked


The setCurrentColor function will do a couple of things. For
one, it sets the selectedColor property defined earlier to be
the color related to the clicked movie clip. It will also apply a highlight
to the border of that clip, but not before removing any highlighted border
of the last selection. Here is where the selectedColorClip
comes into play. By keeping the selected clip within that variable, it can
be referred to later when its highlight need to be removed in favor of a
newly selected color movie clip.



  1. Add the following script to the Actions panel.


// Event handler for selecting a color

function selectColor(event:MouseEvent):void {
// the currentTarget property of the event
// object represents the color selection clicked
// or the object from which addEventListener was
// called; pass it to setCurrentColor to select it
setCurrentColor(event.currentTarget);
}

// Sets the passed color selection clip
// as the currently selected color
function setCurrentColor(colorClip:*):void {

// if there is a selected color clip already
// remove the highlight from its border
// be assigning a default ColorTransform
if (selectedColorClip) {
selectedColorClip.border.transform.colorTransform = new ColorTransform();
}

// assign the new selected color clip
selectedColorClip = colorClip;

// get the selected color for the new clip
// by referencing the color in the colors
// array that has the same index as the
// clip in the display list (since they match)
var index:int = colorCollection.getChildIndex(selectedColorClip);
selectedColor = colors[index];

// add a highlight to the border
// of the new selection by adding some
// rgb to the black color using ColorTransform
var lighter:ColorTransform = new ColorTransform(1, 1, 1, 1, 120, 160, 200, 0);
selectedColorClip.border.transform.colorTransform = lighter;
}

The selectColor function here does one thing; calls
setCurrentColor
which is defined with one parameter, colorClip.
That clip needs to be the color selection movie clip clicked. The
selectColor
function is able to access this through the
currentTarget
property of the event object. This
property represents the object on which addEventListener was
used - the object receiving the event, or in this case, one of the children
in colorCollection.


In setCurrentColor you can see where the last
selectedColorClip
has its highlight removed. Then the variable gets
reassigned with the value of colorClip which then get its own
highlight through its colorTransform property. The
selectedColor
property is assigned based on that new clips position
within the colorCollection's display list.


And with that, you have a functioning color selection. At this point,
it's far enough along to test out - setting up and selecting colors at
least, not drawing anything.



  1. Add the following script to the Actions panel


// Set up color selections to have the

// colors defined in the colors array
defineColorSelections();
// Set the current selection to
// be the first clip in colorCollection
setCurrentColor(colorCollection.getChildAt(0));


  1. Test your movie. You should see the following





Figure: Drawing Application with color definitions


The next step is making it possible to draw with these wonderful color
selections. For that we will use the drawingBoard movie clip
along with the mouseDown, mouseMove, and mouseUp (and rollOut) events. When
the mouse is pressed on the drawingBoard instance, a drawing is started.
When this is the case and the mouse moves, drawings are made. When the mouse
is released (or rolls off the drawing board), drawing stops.


The act of drawing happens during the mouseMove event. To make sure that
drawing only occurs then after the mouse has been pressed, that event
handler will only be added as a listener to the mouseMove event during the
mouseDown event. Similarly, when the mouse is released or rolls off the
drawingBoard instance, the event handler would be removed as a
listener to stop additional drawing.


Remember, in ActionScript 3, the mouseMove event only occurs while within
the object receiving the event, unlike ActionScript 2 where the onMouseMove
event occurred for any time the mouse was moved within the player window.
This means no boundaries need to be coded if drawing is restricted to the
mouseMove event of the drawingBoard movie clip.


Along with defining the event handlers for drawing, one additional step
is needed: creating a place to draw. There's two problems with drawing
directly within the drawingBoard instance. The firs is that the
graphics layer of a display object (those that have it) is below all of its
other content. The drawingBoard movie clip already consists of
a white square. Any dynamic drawing created within that instance would be
placed below that square and would not be visible. Secondly, by drawing in
the object you are using as boundaries, its possible that the drawing itself
could create graphics that extend the boundaries beyond their original
extents making it possible to create an ever expanding drawing canvas.


We don't want that, so we can make a dynamic Sprite instance called
canvas
that will contain the drawing's graphics. This will be placed
directly over the drawingBoard instance and all drawings
created from the related events will be drawn in the canvas's
graphics object.



  1. Add the following script to the Actions panel


// Create a shape to draw in and

// position it over the drawingBoard
var canvas:Shape = new Shape();
canvas.x = drawingBoard.x;
canvas.y = drawingBoard.y;
addChild(canvas);

// This starts the drawing process
// for when the user clicks on the
// drawing board on the screen
function startDrawing(event:MouseEvent):void {

// set up the drawing API with that
// color starting at the mouse location
canvas.graphics.lineStyle(1, selectedColor);
canvas.graphics.moveTo(canvas.mouseX, canvas.mouseY);

// create an event listener for the mouse
// moving so that it can draw lines in the canvas
drawingBoard.addEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);
}

// When the user has clicked the drawing
// board, this function will be called when
// the mouse moves to draw lines in canvas
function whileDrawing(event:MouseEvent):void {
// draw a line in the canvas to
// the new mouse location
canvas.graphics.lineTo(canvas.mouseX, canvas.mouseY);
}

// When drawing has stopped, this function
// removes the event calling userDrawing
function stopDrawing(event:MouseEvent):void {
// prevent mouse movements from drawing
// anymore lines until startDrawing
// is called again during mouseDown
drawingBoard.removeEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);
}

These events, or at least start startDrawing and
stopDrawing
, now need to be associated with the necessary events.



  1. Add the following script to the Actions panel


// Define event handlers

// drawingBoard event handlers control drawing
// on the drawing board (to canvas) based
// on the occurrences respective event types
drawingBoard.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
drawingBoard.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
drawingBoard.addEventListener(MouseEvent.ROLL_OUT, stopDrawing);

Now, when the mouse is pressed down on drawingBoard,
startDrawing
makes whileDrawing a listener of the
mouseMove event. The user will move the mouse and cause lines to be added to
the canvas instance (based on selectedColor) until
the mouse is released over drawingBoard or rolls out of
drawingBoard
at which point whileDrawing is removed as a
listener of the mouseMove event and drawing stops.


About all that remains is the clear button, defined with the instancename
clearButton. This button will use a click event to clear the
graphics object in canvas. As a button symbol, the
clear button will inherently have a hand cursor when the mouse is over it.
To make the interface a little more consistent and to help indicate that the
color selections are in fact interactive, they too should have a hand
cursor. That can be added by setting the buttonMode property of
the colorCollection instance to true.



  1. Add the following script to the Actions panel


// Clears the canvas of all drawings

function clearCanvas(event:MouseEvent):void {
// clear the canvas graphics
canvas.graphics.clear();
}

// clearButton handler clears the
// canvas when clicked
clearButton.addEventListener(MouseEvent.CLICK, clearCanvas);

// Give the color selections a finger cursor
colorCollection.buttonMode = true;


  1. When you've completed adding the code, test your movie and start
    drawing. You should see something like the following (though possibly
    more visibly appealing)





Figure: Completed Drawing Application with drawing



Event Propagation


Also new is the support for event propagation for display objects. 
Event propagation
is a process where a single event travels through a
hierarchy of objects as opposed to being constrained to the one originating
object.  For example, in ActionScript 3, if you have a button within a
movie clip and you click the button, that button will dispatch a click event. 
Not only will the clicked button receive the click event, but also the movie
clip in which it exists and that movie clip's parent, and its parent if it
exists, and so on until there are no more parents for the event to reach. 
This is a dramatic change from how events, especially button events like
onPress
, onRelease, onRollOver, etc. worked for
ActionScript 2.  Then, any parent object assigned with an event handler for
those events would prevent those events from reaching the children.






Figure: ActionScript 3 events can now propagate through to parent instances



This behavior may take some time to get used to as those events that do
propagate (not all events do) may fire unexpectedly as children of your target
object dispatch them. If you want to see if an event has originated from the
object you're listening to, one thing you can do is compare the target
and currentTarget properties of the Event object passed to your
event handler.  The target property indicates the object where
the event originated and the currentTarget property references the
object currently receiving the event, or the object you used
addEventListener
with.


// Detecting when an event hasn't been propagated

function handler(event:Event):void {
if (event.target == event.currentTarget) {
// event came from object
// addEventListener was used with and
// is not result of propagation
}
}

You can also use the eventPhase property.  This property
specifies the phase of the current event, or its position within the
hierarchy of objects through which it propagates.


Propagation occurs in 3 phases: capture phase, target phase, and bubbling
phase.  The capture phase is when an event starts at the top of a display
list with the top-most parent and works its way down through the children until
reaching, but not including the event target where the current event originated. 
When at the target, it’s the target phase.  Though the capture phase can
consist of many display objects, the target phase consists of only one. 
Between the capture and target phases, you have all the display objects that are
affected by a propagated event.  After the target, however, the event
doesn't stop and continues to work back up the hierarchy up through all the
parents again until there are no more left in what is known as the bubbling
phase.  This means, each non-target object affected by a propagating event
receives that event twice, once during the capture phase, and once during the
bubbling phase.


When you use addEventListener to assign event handlers to listen
for events, by default, you are listening for events only within the target and
bubbling phases.  This means propagating events with the default
addEventListener
usage will start with the target and then be sent to
each parent of that target.  If you want a handler to listen for events in
the capture phase, for events reaching the parents before reaching the target,
you have to specify to addEventListener that you want to use the
capture phase by passing true for its third parameter, the useCapture
parameter.  If you want to listen for events for all phases, you have to
use addEventListener twice, once using the default useCapture
(false) and again with useCapture set to true.


// Default phases: target and bubbling

object.addEventListener(MouseEvent.CLICK, onClick);
// Also listen for events in capture phase
object.addEventListener(MouseEvent.CLICK, onClick, true);

Note that in setting useCapture for addEventListener
to true, you will not receive events for the target instance, only the events
for its parents.  The target instance's events would be handled through a
listener added with useCapture as false since that usage handles
both the target and bubble phases.






Figure: Event phases through the display list hierarchy



Since the target phase of an event only occurs for the object instance where
the event originated, as with comparing event.target and
event.currentTarget
, the event.eventPhase property can be
used to see if your event handler is being called for the target instance. 
It contains a number representing current phase of the event. These values are
stored in more readable variables located in the EventPhase class as
EventPhase.CAPTURING_PHASE
, EventPhase.AT_TARGET, and
EventPhase.BUBBLING_PHASE
.


function handler(event:Event):void {

if (event.eventPhase == EventPhase.AT_TARGET) {
// event came from object
// addEventListener was used with and
// is not result of propagation
}
}

[TODO: more?]


Example: TBD


[TODO: Buttons, oef]


Stage events


The stage's importance goes beyond just being a container for all display
objects in a movie.  It also serves as the beginning and ending point for
all propagated events.  All mouse clicks, even if the mouse is not over any
object on the screen, will be received by the stage.  The same applies to
keyboard events which would otherwise go to the focused object.  If no
object is focused, however, only the stage will receive keyboard events. 
This makes the stage a key object for global mouse and keyboard event detection.


One event in particular to be careful of is the mouseMove event.  This
has changed in ActionScript 3.  Before the mouseMove event was triggered
for any MovieClip (or Mouse listener) when the mouse moved, no matter where it
was, just so long as it was within the Flash player window.  In
ActionScript 3, the mouseMove event for display objects is only triggered when
the mouse is over the display object.  If you need the mouseMove event to
be more global as it was before, you need to listen to the stage.


// Create a listener for any mouse move 

// event within the Flash player
stage.addEventListener(MouseEvent.MOUSE_MOVE, anyMouseMove);
function anyMouseMove(event:MouseEvent):void {
// mouse moved
}

[TODO: mouse up outside]


Example: Drag and drop


[TODO: drag and drop using stage events]


Keyboard Events


[TODO: complete; no Key.isDown, offer alternative]


Errors


One thing you may notice about ActionScript 3 how error prone it is or,
rather, how error prone it perceives you to be.  You'll see a lot more
errors, not only during compile, but also runtime.  ActionScript 3 is much
less lenient in letting you get away with mistakes or code conflicts. 
Whereas ActionScript 1 and 2 may silently fail or ignore many errors,
ActionScript 3 will be sure to let you know something went wrong.


Synchronous Errors


Normal errors in code which occur as a code block is being executed are
synchronous
errors. When the Flash player encounters one of these errors
in code, an error, or exception, is thrown.  At that
point the Flash player will suspend all code in the current block and prevent it
from continuing unless the exception is taken care of or caught.  To
catch exceptions in ActionScript, you use a try..catch..finally statement. 


The try..catch..finally statement lets you try a block of code possible of
throwing an error and react accordingly if an error occurs.  It consists of
2 or more blocks of code: an initial try block, consisting of the code that
could throw an error, 1 or more catch blocks that catch errors of different
types and run if that type of error is thrown, and an optional finally block
which is run after the try and any catches whether or not an error occurs. Its
format is as follows:


try {

// potential error causing code
} catch (error:Error) {
// error of type Error occurred
// additional catch blocks may follow
} finally {
// optional to follow try and catch blocks
}

If an exception is thrown within a try block, Flash will look through each
catch block until a matching error type is found.  When a match is found,
that code is run followed by the finally block if it exists.  Any
additional code following a try..catch..finally statement will be executed as
normal even if an error occurs because it was caught by the try..catch..finally
statement.


Throw custom errors


Errors are not thrown exclusively by Flash. You also have the ability to
throw errors in your own code if you so desire. To throw errors you would use
the throw statement. The throw statement throws any
value that precedes it (namely an Error object).  When thrown, the error
will act just like any error and would require a try..catch..finally block to be
correctly caught.


// Throwing your own errors in ActionScript

throw new Error("Error message");

Throwing your own errors can be a helpful debugging tool, especially as you
work with more complicated applications.


Asynchronous Errors


Errors can also occur during asynchronous actions, such as loading external
content, and take the form of events.  These errors cannot be caught with
try..catch..finally statements.  Instead you have to create event handlers
to handle and "catch" the error events. If you do not have an event listener
assigned to an error event and that error occurs, the Flash player will inform
you of the unhandled error event.


// creating listeners for error events handles

// asynchronous errors
target.addEventListener(ErrorEvent.TYPE, handler);
function handler(event:ErrorEvent):void {
// handle error
}

Creating Asynchronous Errors


If you want to invoke your own asynchronous errors, all you need to do is
dispatch an event using dispatchEvent that is of the type
ErrorEvent.  When an unhandled ErrorEvent reaches the Flash player when
authoring in Flash, the output window will display the error.


// target object is an event dispatcher

// that needs to dispatch an error event
target.dispatchEvent(new ErrorEvent("type"));

Release and Debug Players


The release of the Flash player is available in two versions, the release and
debug. The release player is the standard, public player. This player is what
you will have installed for your browser(s) when you download and install Flash
player from adobe.com. 


The debug player is an alternate player with additional debug information and
capabilities embedded within it.  This makes the player a little heftier in
file size (which is why its not preferred for distribution) but also provides
popup dialogs for uncaught exceptions and unhandled asynchronous errors –
something the public would rather not see when your Flash movie or application
runs into a snag.  For developers, however, this player provides useful
information when testing your movies.


You can find installers for both the release and debug players in the Players
folder within your Flash CS3 (or older) install directory.


One thing to keep in mind is that just because the release player doesn't
visually show an error when an exception is thrown, it doesn't mean that error
line is simply ignored like with previous versions of ActionScript.  The
code block where that error occurred will be exited and the remaining script
ignored.


Example: Loading external text with error handling


To load text content from an external source into the Flash player, you would
use the URLLoader class (flash.net.URLLoader). 
An instance of URLLoader will load a text file into its data property to be read
as a string.  Because the process of locating, downloading, and reading an
external file into the Flash player takes time, events are used to indicate when
the content has been loaded and is available.  Not only that, events are
used to indicate loading progress and also any errors that occur. 


The URLLoader class uses the load method to start the loading process which
is also capable of throwing exceptions of many different error types.  When
using the URLLoader class to load external content, its always best to listen
for all asynchronous errors as well as call the load method within a
try..catch..finally
statement. This example will show you how to load an
external text file into the Flash Player with all the necessary error checking.


Steps:



  1. In the source files, open LoadTextFile.fla in the Errors directory. This
    file contains two text fields, one which will display the loaded text, and
    one which will display errors if there are any..

  2. Select the first frame in the ActionScript layer and open the Actions
    panel.

  3. Add the following script to the Actions panel.


// Load textfile.txt text into loader instance

var request:URLRequest = new URLRequest("textfile.txt");
var loader:URLLoader = new URLLoader();

// Listen for complete event (and others if desired)
loader.addEventListener(Event.COMPLETE, loadComplete);
// Listen for error events
loader.addEventListener(IOErrorEvent.IO_ERROR, loadIOError);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadSecurityError);

// Complete event handler
function loadComplete(event:Event):void {

// output loaded text to trace
// window and contentText field
trace(loader.data); // textfile.txt contents
contentText.text = loader.data;
}
// Handler for IO error
function loadIOError(event:IOErrorEvent):void {

// output errors to trace
// window and errorText field
trace("IOError: "+event);
errorText.text = "IO Error: "+event;
}
// Handler for security error
function loadSecurityError(event:SecurityErrorEvent):void {

// output errors to trace
// window and errorText field
trace("SecurityError: "+event);
errorText.text = "Security Error: "+event;
}

// Try the load operation and
// catch any thrown exceptions
try {
loader.load(request);
}catch (error:ArgumentError){

// output errors to trace
// window and errorText field
trace("ArgumentError: "+error);
errorText.text = "Argument Error: "+error;
}catch (error:MemoryError){
trace("MemoryError: "+error);
errorText.text = "Memory Error: "+error;
}catch (error:SecurityError){
trace("SecurityError: "+error);
errorText.text = "Security Error: "+error;
}catch (error:TypeError){
trace("TypeError: "+error);
errorText.text = "Type Error: "+error;
}catch (error:Error){
trace("Unknown Error: "+error);
errorText.text = "Unknown Error: "+error;
}

Here, each error event has its own listener tracing the error if an error
occurs during loading.  Additionally, each type of error thrown by the
load operation is being checked within respective catch blocks. 
An ending catch with the type Error (top-level
Error
) is used in case there was an error thrown not within the other
catches.  Then that final block would catch the error no matter what it
was.



  1. When you've completed adding the code, test your movie. You should see
    the following.






Figure: Text file loaded into the Flash player with error checking



As this example stands, you should not get any errors when the content loads.
To see an error get caught, try breaking the file by misspelling the file name.


As an alternate approach, you can use one event handler could be used for all
error events.  In doing this you can still catch and handle all errors but
it would involve less code.


// Load textfile.txt text into loader instance

var request:URLRequest = new URLRequest("textfile.txt");
var loader:URLLoader = new URLLoader();

// Listen for complete event (and others if desired)
loader.addEventListener(Event.COMPLETE, loadComplete);
// Listen for error events using one handler
loader.addEventListener(IOErrorEvent.IO_ERROR, loadError);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadError);

// Complete event handler
function loadComplete(event:Event):void {

// output loaded text to trace
// window and contentText field
trace(loader.data); // textfile.txt contents
contentText.text = loader.data;
}
// Handler for errors
function loadError(event:ErrorEvent):void {

// output errors to trace
// window and errorText field
trace("Asynchronous Error: "+event);
errorText.text = "Asynchronous Error: "+event;
}

// Try the load operation and
// catch any thrown exceptions
try {
loader.load(request);
}catch (error:Error){

// output errors to trace
// window and errorText field
trace("Caught Error: "+error);
errorText.text = "Caught Error: "+error;
}

Here, all errors are still accounted for but less code is involved. One thing
to notice is that the event parameter of the loadError method is
now typed as ErrorEvent (flash.events.ErrorEvent). 
Just like all errors thrown by Flash are also of the type Error as well as their
own type (their classes extend the Error class), the event errors are also of
the type ErrorEvent.  By typing the event parameter as ErrorEvent, you can
be sure that whatever type of error occurs, it will correctly match with the
type of event used in the event handler.


Common errors


The Flex ActionScript 3 documentation has a list of some of the common errors
you may see when working with ActionScript.  To learn more see:



http://livedocs.adobe.com/flex/2/langref/compilerErrors.html


Data Typing and Casting


[TODO: explain types used for both value usage as well as members of that
value; also trace(29) example (error because number vs string conflict)]


Since ActionScript 2, ActionScript has supported strict data typing. 
This allows developers to specify what types of data different variables will
have.  For example, if you attempt to use a variable typed as a String in a
method that expects an argument typed as Number, Flash will create an error.


var str:String = "string";

function doubleNumber(num:Number):Number {
return num*2;
}
doubleNumber(str); // Error: Type mismatch

In ActionScript 2, data typing was used for compile-time error checking only. 
Once compiled, all typing information is stripped and no type-specific errors
would be recognized.  



Note: When type is maintained for ActionScript 2


The only exception in ActionScript 2 where type information is retained
for runtime operations is with try..catch..finally statements.



ActionScript 3, on the other hand, supports not just compile-type type
checking, but runtime type checking as well.  If a conflict exists with
types during runtime in ActionScript 3, a runtime error will be thrown. In
general, this is a good thing. But it can also require that you sometimes
massage your variable typing to prevent unwarranted errors.


One thing about ActionScript 3 is that there are a lot more kinds of object
types, or classes.  Usng the MovieClip class as an example, it now inherits
from Sprite, DisplayObjectContainer, InteractiveObject, DisplayObject,
EventDispatcher, and Object.  In ActionScript 2, MovieClip only inherited
from Object.  What this means is that now MovieClip can be used as a value
for any variable with any one of these types since in addition to being a
MovieClip instance, MovieClip instances are also instances of those type (since
they are inherited types).


var container:DisplayObject = new MovieClip(); // OK

A good example of this is the parent property of DisplayObject.
It is typed as DisplayObjectContainer, but a MovieClip instance can easily be a
parent of another instance because it too is a DisplayObjectContainer through
inheritance. By being typed as a DisplayObjectContainer and not MovieClip, it
also allows other containers, like Sprite or Loader, to be acceptable values.


But here is where there is a problem. Even though assigning values to a
variable typed as an inherited type is OK, and even necessary in many cases, it
also means that Flash doesn't have a complete understanding of that variable's
type.  For all events and purposes Flash can only assume that any value has
properties and methods that are specific to the definition provided by it's
type.  The parent of some display object may be a MovieClip, but if you try
to use the gotoAndPlay() method on that display object's
parent
property, the Flash player will throw an error because
gotoAndPlay()
is not a method of DisplayObjectContainer – the type
associated with the parent property.


parent.gotoAndPlay(5); // Error: Call to a possibly undefined method

To get around this you have to cast parent to be of the correct
type, in this case MovieClip.


// Cast to MovieClip

MovieClip(parent).gotoAndPlay(5);

Casting


To cast a value means to change its type, either by physically changing a
value from one type to another, or just changing the type association provided
for that value. With some primitive values, the actual value will change when
casting.  For example, casting a String value to a Number will create a new
Number primitive from the original string.  For objects, you can only
change the type association provided for a variable that references that object,
and no object can be associated with a type that it is not.  MovieClip
instances can be typed as DisplayObject since MovieClip inherits from
DisplayObject (DisplayObject is a subtype). But MovieClips cannot be typed as
Arrays since the MovieClip class does not inherit from Array (and thus MovieClip
instances are not Array instances as they are DisplayObject
instances). 


Casting is necessary for objects when you have an object cast to one of its
subtypes. Though a subtype will accurately work for an object value, it does not
correctly describe all the properties and methods available to that value. By
casting a value to it lowest-most class type, you will have the most accurate
type information for that value.


The ActionScript 2 method of casting involved wrapping a value around
parenthesis preceded by the class or type you wished that value to be – almost
as if you were calling the class as a function, passing in the original value as
an argument.


// Cast an object typed as Object to MovieClip

var typedAsMovieClip:MovieClip = MovieClip(typedAsObject);

This form of casting is still available in ActionScript 3.  Unlike
ActionScript 2, if this form of cast fails, Flash will throw an error.


// Try to cast an Array to MovieClip

var typedAsMovieClip:MovieClip = MovieClip(typedAsArray);
// Error: Type Coercion failed

ActionScript 3 also provides a new form of casting using a new keyword,
as
.  The as keyword follows a variable which is then
followed by the type.  The resulting value is the newly casted value or
null if the cast failed. 


// Cast an object typed as Object to MovieClip

var typedAsMovieClip:MovieClip = typedAsObject as MovieClip;

Unlike the other form of casting, no error is thrown for failed casts.


// Try to cast an Array to MovieClip

var typedAsMovieClip:MovieClip = typedAsArray as MovieClip;
trace(typedAsMovieClip); // traces null, no error

By using as, you can avoid unwanted errors being thrown. 
Casting with as, however, is slower in terms of performance. 
If you are sure your variable is of the type being cast, it would be a good idea
to avoid as.  Casting with as comes in handy when
you expect the cast to fail sometimes and take possible resulting null
values into consideration.


Casting to Dynamic Classes


Be careful when you are using variables typed as dynamic classes. 
Because a dynamic class instance can have any variable defined for it, errors
related to property access do not occur based on type.  For dynamic
instances, type information only applies to where that value is used, not how
its properties are used.  So, if you attempt to pass a Date instance (Date
is dynamic) into a method that accepts only Numbers, an error will occur.
However, attempting to access the property doesNotExist from the
Date instance will result in no error as the instance is an instance of a
dynamic class.


In terms of casting and accessing custom properties, especially with
MovieClips, this can be an advantage.  Because the MovieClip class is
dynamic, as long as you have an instance that inherits from MovieClip, you can
cast a reference to that instance as MovieClip and access any property from it. 
This is especially helpful for instances of movie clip symbols from the library
that may have variables defined in them but no class defined within the linkage
properties.  Though the actual movie clip symbol instance is not a direct
instance of MovieClip, you could cast a reference to that instance as MovieClip
and access any property you wanted from it.


// myClip is an instance of a movie clip symbol 

// with custom variable definition
MovieClip(myClip).anyProperty; // OK since MovieClip is dynamic

More than likely, the biggest use of casting to MovieClip will be for casting
the parent property since it is typed as a DisplayObjectContainer
and you will more than likely want to reference MovieClip methods from your
MovieClip parents. If you are using a lengthy reference, you would want to cast
to the end of that reference up to the point where the MovieClip property
exists.


// Cast long reference to MovieClip

MovieClip(parent.parent.parent).play();

XML (E4X)


E4X is a new approach (ECMAScript
specification
) for working XML data that has been integrated into
ActionScript 3.  The default XML class now uses this implementation over
that of the older XML classes.  The old XML class in ActionScript 3 has
been renamed to XMLDocument (flash.xml.XMLDocument).
The old XMLNode class is still XMLNode (flash.xml.XMLNode).


E4X provides a simpler, more intuitive method for accessing XML content using
familiar dot syntax.  Instead of looping through all child nodes within
your XML, you can reference elements by name and even filter nodes using simple
conditions.  Additionally, XML can now be written inline in ActionScript.


// XML writtin inline in ActionScript 3

// no quote characters needed
var xml:XML = <inline>
<example />
</inline>;

This makes XML much easier to use when embedded in ActionScript as it no
longer needs to be written as a continuous string.


There are two primary, top level ActionScript classes that Flash uses to work
with E4X XML; XML (XML)
and XMLList (XMLList). 
XML instances contain one root node which can contain any number of child nodes. 
XMLList instances are a collection or list of XML instances or XML nodes.



Note: There is no inline XMLList


Inline XML needs an XML instance with a single root node.  You
cannot create an inline XMLList in ActionScript since the list would not
have a single root node.


// Syntax error: inline XML needs a root node

var list:XMLList =
<item>
<title>Item2</title>
</item>
<item>
<title>Item2</title>
</item>;


For any XML instance, you can reference an XMLList of its children using the
children() method which is similar to the childNodes
property within the older XML model.  E4X provides an additional option
which allows you to reference children by name.  Instead of getting all
children of an XML node, you can get an XMLList of element children with a
specified name simply by using that name as a property of the XML instance with
the XML dot (.) operator (child accessor).


// Child elements accessible as

// properties of XML instance
var sport:XML =
<sport>
<name>Basketball</name>
<players>men</players>
<players>women</players>
<nationalTV>NBC</nationalTV>
<nationalTV>ESPN</nationalTV>
</sport>;

trace(sport.players is XMLList); // true
trace(sport.players);
/* output:
<players>men</players>
<players>women</players>
*/

By referencing players from the sport XML, an XMLList of all child elements
with the name players is returned. If you then want to access the first node of
that list, you would access it through the players XMLList with the array access
operators ([]) and the index of the element as you would an array.


// Child elements accessible as

// properties of XML instance
var sport:XML =
<sport>
<name>Basketball</name>
<players>men</players>
<players>women</players>
<nationalTV>NBC</nationalTV>
<nationalTV>ESPN</nationalTV>
</sport>;

trace(sport.players[0] is XML); // true
trace(sport.players[0]); // traces "men"

Notice that the trace output shows the text node within the first players
node within the XMLList. Even though the players element is the actual reference
for sport.players[0], the default trace output (toString())
is actually the text contents of that element.  If you want to see the full
XML element, you will need to use XML.toXMLString().


// Show XML source string using toXMLString()

// default value (toString()) just shows text
var sport:XML =
<sport>
<name>Basketball</name>
<players>men</players>
<players>women</players>
<nationalTV>NBC</nationalTV>
<nationalTV>ESPN</nationalTV>
</sport>;

trace(sport.players[0].toString()); // traces "men"
trace(sport.players[0].toXMLString()); // traces "<players>men</players>"


Note: XML.text()


The XML.text() returns the text contents of an XML element
and is similar to the default (toString()) string value of that
node.



Similar to the child accessing dot operator, E4X introduces a similar
descendant accessor operator for accessing descendants, or children and all
childrens children. This takes the form of two dot operators used in succession
(..) followed by the name of the descendant element nodes you wish
returned in an XMLList.


// Child (.) vs. descendant (..) access

var channel:XML =
<channel>
<title>Feed Title</title>
<description>Feed description.</description>
<item>
<title>Item 1 Title</title>
<description>Item 1 description.</description>
</item>
<item>
<title>Item 2 Title</title>
<description>Item 2 description.</description>
</item>
</channel>

trace(channel.title.toXMLString()); // traces "<title>Feed Title</title>"
trace(channel..title.toXMLString());
/* output
<title>Feed Title</title>
<title>Item 1 Title</title>
<title>Item 2 Title</title>
*/


You can see that in using child access the elements returned are only those
within the first level of the hierarchy beneath the target element (here being
channel).. The the descendant accessor all of the appropriately
named elements beneath the target element are returned


Attributes in XML are also accessible via dot syntax. To differentiate
element names from attribute names, attributes have an additional attribute
identifier operator
(@) prefixed to the attribute name.


// Access attributes with the @

// attribute identifier operator
var item:XML =
<item name="attribute">
<name>element</name>
</item>;

trace(item.name); // traces "element"
trace(item.@name); // traces "attribute"

Attributes (which are technically also nodes) can also be returned in an
XMLList


// Attributes as an XMLList

var images:XML =
<images>
<img href="image1.jpg" />
<img href="image2.jpg" />
<img href="image3.jpg" />
</images>;

trace(images.img.@href is XMLList); // traces true
trace(images.img.@href); // traces "image1.jpgimage2.jpgimage3.jpg"
trace(images.img.@href[0]); // traces "image1.jpg"

Because you can reference elements (and attributes) by name using dot syntax
with E4X XML, there's a greater likelihood that there will be a conflict between
XML node names and real properties within the XML instance in ActionScript. To
prevent this from happening properties of the XML class are instead methods. 
You may have already noticed that the old childNodes property is
now the children() method. As a method, you wouldn't have a
conflict if you had XML with elements of the name children. Another example is
the name() method which returns the name of the XML element node


// XML node access vs method access

var family:XML =
<family>
<name>Hendersons</name>
</family>;

trace(family.name); // traces "Hendersons"
trace(family.name()); // traces "family"

Sometimes you may find that you have XML whose element names are not valid
ActionScript variable names. If that is the case, you will need to use the
XML.elements()
method allowing you to access elements by name using a
string.  For attributes a similar method XML.attribute()
method exists.


// Reference nodes by name using 

// elements() and attribute()
var values:XML =
<values for-example="see below">
<complex-name>simple value</complex-name>
</values>;

// trace(values.@for-example); // Syntax error
trace(values.attribute("for-example")); // traces "see below"
// trace(values.complex-name); // Syntax error
trace(values.elements("complex-name")); // traces "simple value"

For child elements, using the array access operator ([]) will
also work much in the same way as the elements method.


Conditional Filtering


By referencing child elements from an XML or XMLList instance by name, you're
essentially filtering child nodes by name.  You can also filter an XMLList
using simple conditions.  These conditions follow a node reference with a
dot (.) and a condition within the filtering predicate
operator
(()) where a condition can be used to filter an
XMLList further.



Note: Filtering is not for children


Though a dot is being used to access the filtering predicate operator, it
does not mean you are accessing children of that XMLList being filtered. 
The filtering predicate operator filters the instance on which it is used
much like the slice() method removes elements of an Array
instance.



Consider the following XML


var grades:XML =

<grades>
<student>
<name>Tom</name>
<quiz num="1"><score>60</score></quiz>
<quiz num="2"><score>90</score></quiz>
</student>
<student>
<name>Brett</name>
<quiz num="1"><score>100</score></quiz>
</student>
<student>
<name>Michelle</name>
<quiz num="1"><score>90</score></quiz>
</student>
</grades>;

The following statements use conditional filtering to trace results from this
XML.


// Find students with the name Michelle

trace(grades.student.(name == "Michelle"));
/* output:
<student>
<name>Michelle</name>
<quiz num="1">
<score>90</score>
</quiz>
</student>
*/

Here a filter is used on the XMLList produced by grades.student. This
contains a list of elements with the name student that exist within the grades
XML. Within that list, the filter finds all student nodes where referencing name
from that node results in a value of "Michelle". This results in one student
node where, as you can see, the name element contains the text "Michelle".


// Find quizes whose num attribute equals 1

trace(grades.student.quiz.(@num == "1"));
/* output:
<quiz num="1">
<score>100</score>
</quiz>
<quiz num="1">
<score>60</score>
</quiz>
<quiz num="1">
<score>90</score>
</quiz>
*/

This example instead filters the quiz elements within grades.students. It
looks for the quiz elements with the num attrubute whose value is 1. Since the
filter is used on the quiz reference, only quiz elements are returned.


// Find students who are not Michelle that

// have less than 2 quiz elements
trace(grades.student.(name != "Michelle" && quiz.length() < 2));
/* output:
<student>
<name>Brett</name>
<quiz num="1">
<score>100</score>
</quiz>
</student>
*/

The condition in this filter has two parts, one that makes sure the student's
name is not Michelle and another that requires the student have less than two
quiz elements. This leaves only the student element with the name Brett which is
what the filter returns.


// Find students with a single score

// element having a value of 90
trace(grades.student.(quiz.score == 90));
/* output
<student>
<name>Michelle</name>
<quiz num="1">
<score>90</score>
</quiz>
</student>
*/

You can see here that you can go further down the heirarchy within the scope
of the condition this returns student elements with a quiz.score
value of 90. Though the student element with the name Tom also has a score
element with the score 90, it is not caught in this filter because quiz.score
evaluates as an XMLList with two elements whose value is not comparable to 90.
It works for Michelle because the quiz element in that student has one score
node whose value is 90. When that value is evaluated for the condition it is
seen as the value 90 and the condition can evaluate to true


// Find students with any score

// element that has a value of 90
trace(grades.student.(quiz.(score == 90).length()));
/* output
<student>
<name>Tom</name>
<quiz num="1">
<score>60</score>
</quiz>
<quiz num="2">
<score>90</score>
</quiz>
</student>
<student>
<name>Michelle</name>
<quiz num="1">
<score>90</score>
</quiz>
</student>
*/

This example does what the previous did not; it finds all students that have
any score element with the value 90. This is accomplished by a nested filter.
The first filter is used to make sure that the results returned results in a
collection of student elements. Within that filter you have another filter used
with the quiz XMLList which filters that list by scores whose values equal 90.
If any score exists within that quiz element with a value of 90, the filter will
result in a quiz XMLList with one or more lements meaning length()
will return 1 or greater, which in the original students filter, condition
resolves as true. Both the Tom and Michelle student nodes have a score element
with the value of 90 meaning quiz.(score == 90) creates an XMLList
with a length of 1 for each of them (containing the respective score element).
These nodes then get added to the XMLList resulting from the student filter.


With any filter you have the option of using literal values (used in the
examples far) as well as ActionScript variables just so long as the variable
name does not match the name of an element within the XMLList used in the
filter.


// Find students with a single score

// element having a value of scoreCheck
var scoreCheck:int = 90;
trace(grades.student.(quiz.score == scoreCheck));
/* output
<student>
<name>Michelle</name>
<quiz num="1">
<score>90</score>
</quiz>
</student>
*/

This filter is equivalent to using (quiz.score == 90) assuming
grades.student has no child elements with the name scoreCheck.


Every filter condition essentially boils down to:


var result:XMLList = new XMLList();

for each (var node:XML in target) {
with (node) {
if (condition) {
result += node;
}
}
}
return result;

Where target is the XMLList the filter is used with,
condition
the condition within the filter, and result is the
resulting XMLList from using the filter (result = target.(condition)).
Any non-node reference within the filter condition will resolve to the
respective ActionScript defined variable value (if one exists).


Dynamic XML definitions


You can also use ActionScript variables directly within inline XML to be used
in defining that XML. For that you would use XML braces operator ({}).
Variable values within the braces in XML is evaluated as its ActionScript value
allowing ActionScript variables to be used in place of what would be inline XML
values. The braces can be used to define element names, attribute names,
attribute values, and text element values. An example that does all is as
follows:


// Dynamic XML definition with braces

var elementName:String = "elem";
var attributeName:String = "attr";
var attributeValue:String = "value";
var textNode:String = "text";
var xml:XML =
<{elementName} {attributeName}={attributeValue}>
{textNode}
</{elementName}>;
trace(xml.toXMLString()); // traces "<elem attr="value">text</elem>"

If you need to be more complex in your XML definitions given variables that
might contain data including full tags, you would need to instead create XML
from a string using the XML constructor.


// XML generation with strings

var tagContents:String = "elem att=\"value\"";
var xml:XML = new XML("<" + tagContents + "/>");
trace(xml.toXMLString()); // traces <elem att="value"/>

XML Namespaces


Namespaces are used to separate or identify data. In XML they are used to
associate one or more nodes with a certain URI (Uniform Resource Identifier).
Elements with a namespace can have the same tag name as other tags but still be
separated from them because of their association with a URI.


You will often see namespaces used with RSS feeds. The
Apple iTunes
podcast feed
, for example, uses an itunes namespace to separate
iTunes-specific tags from other normal RSS 2.0 tags.


Namespaces can be defined in XML in two ways. One way is to define an
attribute named xmlns within an element node with the value of a URI. That node
and all of its children then belong to the namespace identified by that URI. URI
values are usually web site addresses. They don't have to be valid addresses,
but since only one body can own any one domain, they make good candidates in
making sure people will not be using the same URI for different purposes. This
is known as setting a default namespace.


<xml>

<parent xmlns="http://www.example.com/uri/">
<child />
</parent>
</xml>

In the above example, both parent and child are in the namespace identified
by the example.com URI (http://www.example.com/uri/).


Namespace URIs can also be associated with a prefix in XML. When defined with
a prefix, only the nodes using that prefix will be considered part of the
namespace. Both element nodes and attributes can use the prefix. To define the
prefix, you make a xmlns node in a parent element with the prefix name as a
suffix of the xmlns attribute.


<xml xmlns:ns="http://www.example.com/uri/">

<parent>
<ns:child />
</parent>
</xml>

In this example, only the child element is in the namespace because only that
node is using the ns prefix.


Looking an an example iTunes podcast XML document, you can see how elements
prefixed with itunes (for the itunes namespace) are mixed with other elements
not within a namespace indicating that they are specific to iTunes.


<?xml version="1.0" encoding="UTF-8"?>

<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>

<title>All About Everything</title>
<link>http://www.example.com/podcasts/everything/index.html</link>
<language>en-us</language>
<copyright>&#x2117; &amp; &#xA9; 2005 John Doe &amp; Family</copyright>
<itunes:subtitle>A show about everything</itunes:subtitle>
<itunes:author>John Doe</itunes:author>
<itunes:summary>All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our Podcast in the iTunes Music Store</itunes:summary>
<description>All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our Podcast in the iTunes Music Store</description>
<itunes:owner>
<itunes:name>John Doe</itunes:name>
<itunes:email>john.doe@example.com</itunes:email>
</itunes:owner>
<itunes:image href="http://example.com/podcasts/everything/AllAboutEverything.jpg" />
<itunes:category text="Technology">
<itunes:category text="Gadgets"/>
</itunes:category>
<itunes:category text="TV &amp; Film"/>

<item>
<title>Shake Shake Shake Your Spices</title>
<itunes:author>John Doe</itunes:author>
<itunes:subtitle>A short primer on table spices</itunes:subtitle>
<itunes:summary>This week we talk about salt and pepper shakers, comparing and contrasting pour rates, construction materials, and overall aesthetics. Come and join the party!</itunes:summary>
<enclosure url="http://example.com/podcasts/everything/AllAboutEverythingEpisode3.m4a" length="8727310" type="audio/x-m4a" />
<guid>http://example.com/podcasts/archive/aae20050615.m4a</guid>
<pubDate>Wed, 15 Jun 2005 19:00:00 GMT</pubDate>
<itunes:duration>7:04</itunes:duration>
<itunes:keywords>salt, pepper, shaker, exciting</itunes:keywords>
</item>

</channel>
</rss>

Any elements within the RSS specification that use the same tags used by
iTunes will not conflict because of the use of the itunes prefix and its
association with the unique iTunes URI.


When working with XML with namespaces in Flash, you will need to make use of
namespaces in code in order to access nodes within the XML that use them. Though
elements with namespaces may have the same local name, or the tag
name not including a namespace prefix (if it exists), their namespace helps
define their true name (URI + local name), so for a element with a namespace to
be referenced by name, the namespace is needed. In Flash, a node within a
namespace is referenced using its namespace and base name in combination with
the name qualifier operator (::).


Namespaces in ActionScript 3 are handled through a new Namespace class (top-level
Namespace
). This class consists of two properties, uri and
prefix which relate to the URI of the namespace and the namespace's
prefix if it has one. The URI is really the more important part a Namespace
instance as the URI is what defines the full node name. The prefix is just a
type of shortcut to associate the URI with a node.


// Create a new Namespace instance

var myNamespace:NameSpace = new Namespace("http://www.example.com/uri");

Once you have a namespace defined, you can use it to reference XML nodes
within the namespace specified by that URI through the use of the name qualifier
operator.


The name qualifier operator in ActionScript works much like the namespace
prefix does within the actual XML. In XML, the prefix comes in front of the node
name separating itself from the name with a colon (:). In ActionScript, you're
now just using two colons (::).


// XML with xpl namespace

var xml:XML =
<xml xmlns:xpl="http://www.example.com/uri/">
<text>Hello World</text>
<xpl:text>Hello Namespace</xpl:text>
</xml>;

// Make a namespace instance based
// on the xpl namespace's URI
var xplNs:Namespace = new Namespace("http://www.example.com/uri/");

// Accessing the text element
trace(xml.text); // traces "Hello World"

// Use the name qualifier operator to
// reference the text tag using the namespace
// and the element's base name
trace(xml.xplNs::text); // traces "Hello Namespace"

Here you can see how the namespace separates the text within the two
text
elements. The xplNs Namespace instance is used to
access the text element in the namespace by using the name qualifier to fully
qualify that element's full name.


If you want to get both text elements, or all elements within a
node with the local name of text, you can use a filter checking those elements'
local name. You can access the local name of an XML node through the QName
instance (top-level
QName
) returned by the XML method name(). QName instances
describe a node's full name including both the local name (localName
property) and URI (uri property). To have the filter work for all
of the XML node's children, you will need to access the node's chilren through
the children() method.


// XML with xpl namespace

var xml:XML =
<xml xmlns:xpl="http://www.example.com/uri/">
<text>Hello World</text>
<xpl:text>Hello Namespace</xpl:text>
</xml>;

// Get all elements with local name of text
trace(xml.children().(name().localName == "text"));
/* output
<text xmlns:xpl="http://www.example.com/uri/">Hello World</text>
<xpl:text xmlns:xpl="http://www.example.com/uri/">Hello Namespace</xpl:text>
*/

Notice that the namespace definition is retained through the results with the
inclusion of the xmlns attribute in the text nodes. This allows the namespaces
to remain valid even when working with portions of the original XML in
ActionScript.


There may be times when you are not able to know the namespace URIs used in
the XML you will need to work with. Without the URI's you may have trouble
accessing nodes because you couldn't access them through theit qualified names
(though you can still easily access them through an index with a parent node's
children() list, etc.). If you do not know what namespaces are used
within the XML, you can retrieve them using the namespace() and
namespaceDeclarations() methods.


The XML namespace() method returns a single Namespace instance
that represents the Namespace of that XML node. The
namespaceDeclarations()
method is similar, but instead provides a list of
all the namespaces defined within the XML element - the default namespace (if
exists) and all namespaces with their defined prefix. If an element node does
not have any xmlns attributes defined for it, namespaceDeclarations()
will return an empty array. Where namespace() will return an
inherited default namespace value if defined in a parent node,
namespaceDeclarations()
will only return definitions set within the
element from which it's used.


The following XML is an XML stylesheet (XSL) used to transform the format of
XML from one format to another. It has two namespaces, one for the the XSL and
the other for the (X)HTML being generated.


var xsl:XML = <xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict">
<xsl:template match="/">
<html>
<head>
<title>Expense Report Summary</title>
</head>
<body>
<p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>;

// Find the namespaces defined in the root node

trace(xsl.namespaceDeclarations());
// traces http://www.w3.org/1999/XSL/Transform,http://www.w3.org/TR/xhtml1/strict

// Define namespace variables from declarations
var namespaces:Array = xsl.namespaceDeclarations();
var xslNs:Namespace = namespaces[0];
var xhtmlNs:Namespace = namespaces[1];

// Get the html element's namespace
trace(xsl.xslNs::template.xhtmlNs::html.namespace());
// traces http://www.w3.org/TR/xhtml1/strict

// Get the value-of element's namespace
trace(xsl.xslNs::template.xhtmlNs::html..xslNs::["value-of"].namespace());
// traces http://www.w3.org/1999/XSL/Transform

Notice that with this XSL file, that the default namespace is the one using
the xhtml URI. This means by default, all XML elements are considered XHTML.
Those that are not are prefixed with the xsl prefix identifying them as being
part of the XSL namespace, including the root xsl node in which the
xsl namespace was defined. To get to the html element both
namespaces were used in the E4X path to reference it.


The above example also shows how the descendant operator (..)
and array access notation ([]) was used to reach the value-of
element. Notice that the the brackets used for referencing value-of
came after the name qualifier operator. The namespace used to qualify your
element name cannot be used inside the brackets. It continues to be separate
from the local name - the local name (as a string) being the only part within
the brackets. This format, however, will not work in conjunction with the
elements()
or descendants() methods. In those cases, you
would have to pass in a QName instance to those methods that specifies both the
local name as well as the namespace URI. To access the element using descendants
instead of the descendant operator, you would use the following


// descendants method with namespace

xsl.xslNs::template.xhtmlNs::html.descendants(new QName(xslNs.uri, "value-of"))

As you start to reference XML nodes in this manner with name spaces, you can
find that references may start to get excessively long, especially if you have
to prefix each node with a namespace qualifier when, for example, your XML
document uses even a single default namespace. To make this process a little
easier, you have the option of defining a default xml namespace in ActionScript
using the default xml namespace directive.


The default xml namespace directive acts sort of like a variable
that you set to specify a type of automatic namespace for XML references. This
would allow you to use E4X references for XML that uses a single namespace
without the need of prefixing each node with the appropriate qualifier.


// Get the title

trace(xsl.xslNs::template.xhtmlNs::html.xhtmlNs::head.xhtmlNs::title);
// traces Expense Report Summary

// set xhtmlNs as the default namespace
default xml namespace = xhtmlNs;

// Get the title now with default namespace
trace(xsl.xslNs::template.html.head.title);
// traces Expense Report Summary

So far the examples have covered only element nodes within namespaces. Don't
forget that attributes too can be associated with a namespace. Just because an
attribute is within an element defined in a namespace doesn't mean that
attribute is also in that namespace (unless part of a default namespace).


// XML with xpl namespace

var xml:XML =
<xml xmlns:xpl="http://www.example.com/uri/">
<xpl:text value="Hello World" xpl:value="Hello Namespace" />
</xml>;

// Define namespace with xpl URI
var xplNs:Namespace = new Namespace("http://www.example.com/uri/");

// Get value of text attribute
// with and without namespace
trace(xml.xplNs::text.@value); // traces Hello World
trace(xml.xplNs::text.@xplNs::value); // traces Hello Namespace

You can see that even though both attributes are part of the text
node in the xpl namespace, they are not inherently also part of that namespace.
The prefix is still required for an attribute of a node to be placed within a
namespace (unless a default namespace is defined and that attribute falls under
the hierarchy of that definition).


Example: RSS Feed Reader



This example will load an RSS feed from an external source and parse its
contents to be displayed, formatted, within a text field in Flash. The
source for this example will be the
Adobe XML News Aggregator
(MXNA) - recent news from the front page (rss).



Note: Loading content sites and crossdomain.xml


When you load text content from an external site outside of the
domain (and subdomain) of the SWF, a crossdomain.xml file is necessary
to grant access of that content to the SWF requesting it. The MXNA feed,
for example, would normally not be accessible from another web site, but
weblogs.macromedia.com has crossdomain.xml policy file located at

weblogs.macromedia.com/crossdomain.xml
allowing access to all Flash
SWFs within other domains.



In this example you will see how external XML can be loaded into the
Flash Player and how its contents can be read when that content uses
multiple namespaces.


Steps:



  1. In the source files, open MXNARssReader.fla in the XML directory.
    This file contains a text field that will display the MXNA feed as HTML
    text.

  2. Select the first frame in the ActionScript layer and open the
    Actions panel.


The variables needed for this example are simply those related to the
loading of the feed XML. This includes a URLLoader instance, the URLRequest
it uses, and the actual URL of the feed.



  1. Add the following script to the Actions panel.


// Set up variables

var mxnaURL:String = "http://weblogs.macromedia.com/mxna/xml/rss.cfm?query=byMostRecent&languages=1";
var mxnaRequest:URLRequest = new URLRequest(mxnaURL);
var mxnaLoader:URLLoader = new URLLoader();


Note: Testing Without Internet Access


In the source files, there is an XML file named mxna_sample.xml that
you can substitute for the above MXNA URL if you want to test this
example without being connected to the internet.


var mxnaURL:String = "mxna_sample.xml";


Next handlers are defined for the URLLoader instance. The most important
handler is the complete event handler letting us know when the XML has
loaded. When that has happened, we can read the XML and display its contents
in Flash. To protect against errors, you should also listen for the io and
security error events.


The error handler can just trace a message if there's an error for now.
Ideally special action should be taken to inform the user that there was an
error or the operation should be tried again. In the complete handler, an
XML object should be created based on the loaded text and the contents of
that XML displayed on the screen (in the text field). For now, that process
will be delegated to a function called renderFeedXML().



  1. Add the following script to the Actions panel.


// Assign listeners for downloading feed

mxnaLoader.addEventListener(Event.COMPLETE, feedDownloadedHandler);
// Error listeners
mxnaLoader.addEventListener(IOErrorEvent.IO_ERROR, feedDownloadError);
mxnaLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, feedDownloadError);

// Event handlers

// Called when feed has completely downloaded
function feedDownloadedHandler(event:Event):void {

// use a try-catch block in case
// xml parsing fails
try {

// convert the loaded text into XML
var mxnaXML:XML = XML(mxnaLoader.data);

// if XML succeeded (no error)
// show it in the text field
renderFeedXML(mxnaXML);

}catch(error:Error){
trace("Error parsing XML: "+error);
}

}
// Called if feed download fails
function feedDownloadError(event:Event):void {
trace("Error during download: "+event);
}

When the XML loads and is successfully converted to an XML instance from
Flash, the renderFeedXML is called. This function is the
function that will need to go through the XML and translate it into HTML
text that will be displayed in the text field on the screen. At this point
it is important to understand the setup of the XML feed.


The MXNA feed is a RSS 1.0 feed.
By looking at the root node you can see what namespaces it has defined for
it.


<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/">

The URI http://purl.org/rss/1.0/ is the URI for the default namespace.
The other namespaces are rdf (http://www.w3.org/1999/02/22-rdf-syntax-ns#)
which stands for Resource Description
Framework
(the R in RSS, though RSS is sometimes also referred to as
"Real Simple Syndication"), and dc (http://purl.org/dc/elements/1.1) which
stands for Dublin Core, an additional
set of metadata added to the feed.


Each post in the feed is stored in an item element that is a direct child
of the root rdf node. An example of one of these items looks like this.


<item rdf:about="http://www.senocular.com/?id=2.4">

<title>New Flash Player 9 Update Posted</title>
<link>http://weblogs.macromedia.com/mxna/controller.cfm?handler=PostHandler&action=click&postId=198719&nextPage=http%3A%2F%2Fwww%2Esenocular%2Ecom%2F%3Fid%3D2%2E4</link>
<description><![CDATA[If you haven't already noticed, there's a new version of the Flash Player posted on the Adobe.com website. This version is 9,0,47,0 (you can check your current version from the About Adobe Flash Player page). For more information, see the release notes.]]></description>
<dc:subject>Fireworks</dc:subject>
<dc:creator>senocular.com</dc:creator>
<dc:date>2007-07-11T16:50:12.0-00:00</dc:date>
<dc:identifier>02DD0C9679274B1F18BFCAE95E2A4009</dc:identifier>
</item>

For this reader we're only going to be interested in the original source
link in the about attribute, the title, the description, the creator and the
date. As you can see, the about attribute is defined in the rdf namespace.
The about attribute is contained within the item tag that has no namespace
specified for it. However, since the root rdf element has a default
namespace defined for it, that puts item in that one
(http://purl.org/rss/1.0/). This also applies to the title and description
elements. The remaining elements, creator and date, are part of the dc
namespace. When referencing these nodes in ActionScript, the proper
namespaces will need to be used. Referencing item, title, and description
can be made a little simpler if the default xml namespace is
set to be the XML's default namespace.


Because there are multiple item elements within the feed, a loop can be
used in renderFeedXML to go through each one and add it to the
text field on the stage. A for each..in loop is usually the
easiest kind of loop to do this, especially for XML where indexes are not
important, just the nodes and their values. The function will call another
function renderFeedItem to actually place the content of an
individual item within the text field.



  1. Add the following script to the Actions panel.


// Functions

// Writes each feed item to the screen
function renderFeedXML(feed:XML):void {

// get default namespace for feed
var defaultNs:Namespace = new Namespace("http://purl.org/rss/1.0/");
// set default namespace to make referencing easier
default xml namespace = defaultNs;

// clear screen text
mxnaText.text = "";

// write each Feed item to the screen
// looping through the XMLList with for each
var items:XMLList = feed.item;
for each (var item:XML in items){
renderFeedItem(item);
}
}

// Writes a single feed item to the screen
function renderFeedItem(item:XML):void {

// namespaces
var rdf:Namespace = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
var dc:Namespace = new Namespace("http://purl.org/dc/elements/1.1/");
var defaultNs:Namespace = new Namespace("http://purl.org/rss/1.0/");

// set default namespace to make referencing easier
default xml namespace = defaultNs;

// parse date string [YYYY-MM-DD]
var date:String = item.dc::date.text().substring(0, 10);

// write other feed content to text using HTML
mxnaText.htmlText += "<u><b><a href=\""+item.@rdf::about+"\">"+item.title+"</a></b></u><br />";
mxnaText.htmlText += "<i>by "+item.dc::creator+" on "+date+"</i><br />";
mxnaText.htmlText += item.description+"<br /><br />";
}

Notice that default xml namespace was set in both
renderFeedXML
and renderFeedItem. When you set
default xml namespace
, it only applies to the current scope. When you
are in another function or exit the current function, you will need to set
it again (assuming you intend to use it again).


The renderFeedXML and renderFeedItem functions
are the functions doing all the work. Once the XML is loaded they will read
through the XML and place its relevant content on the screen. The only thing
left to do is load the XML.



  1. Add the following script to the Actions panel.


// Download XML feed. Once loaded, the

// parsing and displaying process will start
try {
mxnaLoader.load(mxnaRequest);
mxnaText.text = "Loading...";
}catch(error:Error){
trace("Error during load: "+error);
}

Remember, a try..catch block is needed to catch any errors
load() might throw.



  1. When you've completed adding the code, test your movie. You should
    see something similar to the following.





Figure: MXNA RSS Reader in Flash


More attention can certainly be given to design or completeness, but you
can see how easy it can be to get XML content from the web and display it in
Flash.



Editing XML


[TODO: complete; remove xml child is now delete]


Object Oriented Programming


Object Oriented Programming (OOP) is an object-based style of programming
that uses objects to store and work with data. Templates known as classes
are used to define the properties and methods that make up objects in code. OOP
focuses on some of the following concepts:



  • Encapsulation

  • Polymorphism

  • Abstraction

  • Inheritance

  • Composition


Encapsulation is the idea that object implementation as defined by
its class is hidden from and inaccessible to the user of that class. This
basically means, given an object, a user should be able to know how to use that
object (using its interface) but not know how the object does what it does. That
implementation is buried away and cannot (normally) be changed. This idea
facilitates robust, reusable and modular code.


Polymorphism is being able to use more than one kind of object in
the same context. Objects capable of being interchanged in this manner have the
same interface, or the same collection of properties or methods
required to satisfy the context in which they are to be used. Interface
definitions - class like definitions that outline what properties and methods
exist for a certain type of interface - can be implemented by classes to
associate them with a type. Types are defined by class definitions
and interface definitions and indicate the kind of object based on its available
interface.


Abstraction relates to how a single object can be represented as
different types based on context. This relates to polymorphism but instead of
having one context for many different objects, you have one object fitting into
many other contexts. Consider an apple. It is an apple, a fruit, and food -
three different contexts which it satisfies. In programming, you have one object
able to be used in different places with different types as long as that object
represents that type, either through its own class definition, an inherited
definition or an interface definition.


Inheritance describes the process by which one object is based on
the definition of another. The original class definition is known as the
superclass. The definition based off that class is known as the subclass.
Subclasses inherit or extend their superclasses. Interfaces (types)
and non-private properties and methods are inherited by subclasses.


Composition is the means by which one object acquires another
object's functionality by controlling an instance of that object. This is an
alternative to inheritance that, though requires a little more effort, is often
more flexible and does a better job enforcing encapsulation. Unlike with
inheritance, typing through composition can only be made through interfaces
since the composed object's type is not inherited by the object controlling it.


ActionScript 3 relies heavily on OOP, more so than ActionScript 1 or
ActionScript 2.  Having a clear understanding of and the ability to use OOP
in ActionScript will be paramount in being able to lever ActionScript 3 to its
fullest potential.


Classes


Classes are predetermined definitions or templates for object
instances.  They describe properties an object contains and what methods
are used when working with that object.  When you create new objects in
ActionScript, you are creating instances of a class. Most everything in OOP
revolves around classes as they define the Objects in Object Oriented
Programming..


The Flash player has many native ActionScript classes that are defined
internally and always available for use to the Flash developer.  These
include classes like Object, Array, Bitmap, MovieClip, Event, etc.  Any
class within a package starting with flash is most likely native to the Flash
player.


Packages represent collections of classes. Packages not
only categorize classes but are also part of a class's definition. The
ActionScript 3 Tween class available in Flash CS3, for example, is defined
within the fl.transitions package. As a result the Tween class source file
(Tween.as) is saved in a folder named transitions which is contained within the
folder fl.


ActionScript 3 is class-based by nature. An Array object in ActionScript, for
example, has a predefined set of properties and methods associated with it;
properties like length, and methods like push() and
pop().  These are all predetermined by an Array class which is
defined internally by Flash.  Should you want to make your own object
definitions, you could make your own class to describe your own custom object. 
For example, consider the following object created with ActionScript:


// Triangle object represented in code

var rightTriangle:Object = new Object();
rightTriangle.width = 10;
rightTriangle.height = 20;
rightTriangle.area = function():Number {
return this.width * this.height/2;
}

This example creates an object called rightTriangle which has
two variables assigned to it, width and height, as
well as a function called area which determines the area of the
right triangle based on the values of width and height.
In terms of functionality, this does about everything you need it to as far as
basic right triangles go.  But, if you want to make more triangles, it
would require duplicating this code for each of those triangle instances. And
what if you ever wanted to check to see if a certain variable was assigned to
have a triangle value?  In this example, the type of object the
rightTriangle
is, is Object, not something that specifically indicates it
as being a triangle.


A better approach would be to define a right triangle class and create new
triangle objects by creating new instances of that class.  The definition
for rightTriangle as a class could look something like the
following in ActionScript 3:


// Defined in an external ActionScript

// file saved as RightTriangle.as
package {
public class RightTriangle {
public var width:Number;
public var height:Number;
public function RightTriangle(width:Number = 0, height:Number = 0){
this.width = width;
this.height = height;
}
public function area():Number {
return width*height/2;
}
}
}

This definition contains all the same content; width, height, and area; only
it's given a slightly different format and it's defined within a separate
ActionScript file (a text file with an .as extension). Once Flash recognizes
this definition, you can create a new rightTriangle object with the
easily with the following code:


// Code used in Flash

var rightTriangle:RightTriangle = new RightTriangle(10, 20);

Here, not only was creating rightTriangle easier, but it also
has a unique type associated with it that can be used to check to see if a
certain value is in fact of the type (or originating from the class)
RightTriangle and use RightTriangle in oher typing situations like for variables
and parameter lists in functions.



[TODO: do we really want to go this route?]


Breaking down the class we can see what each line represents.


1. package {

This line defines the package block for an ActionScript 3 class. This is
a new block that was not present in ActionScript 2. It defines the package
path for the class. Since there is no package for this definition of
RightTriangle, no path is provided. If the class was defined in the
com.senocular.geom package, the line would look like package
com.senocular.geom {
. In ActionScript 2, the package path would be
part of the class name.


2. public class RightTriangle {

Here the class block is being defined. This consists of the class keyword
along with the class name. The class name should be the same as the file
name of the class file. The public attribute before class indicates that
this class is publically accessible to all other scripts. Access attributes
in ActionScript 3 include



  • public

  • private

  • protected

  • internal


Public Access: All


If no access attribute is provided, internal is assumed. This is
different than ActionScript 2 that used public as the default access
operator.


 



ActionScript has supported these classes in some respect all the way back to
Flash 5 with ActionScript 1, only with ActionScript 3 are you seeing a more true
representation of classes.  And it just isn't a matter of having the option
of creating these things called classes.  In ActionScript 3, everything is
an instance of a class and all the code you right becomes part of a class
definition, even if not written within a separate ActionScript file meant to
define a class.


This is important, especially if you are coming from an ActionScript 1 or
ActionScript 2 background.  Code written for ActionScript 1 and
ActionScript 2 was either timeline based or added to button or movie clip
selections. Even when a class was defined in ActionScript 1 or ActionScript 2 it
was done so on the timeline – where there was code, there was a timeline. 
In ActionScript 3, where there is code, there is a class.


So what does this mean for Flash CS3 and ActionScript 3?  Does all code
have to exist as external class files? Can you still write code on the timeline? 
What if you don't know, or want to know, anything about classes?


The good news is little has changed in terms of writing code for FLA files in
the Flash IDE and you can still write code on the timeline, just as you always
have.  The compiler that creates published SWF from your FLA file will be
able to handle all the technical issues revolving around this new aspect of
ActionScript in the background, much in the same way it handles converting
ActionScript 2 classes into ActionScript 1 code in the background without you,
the user, really knowing. This means you won't have to know anything about
classes nor will you need to mess with external class files if you don't want to
when working with ActionScript 3 in Flash.


ActionScript and the Timeline


Timelines in Flash consist of one or more frames that contain graphics
associated with visual elements displayed on the screen.  A timeline with
multiple frames will run through those frames as a Flash movie is being viewed
showing an animation. 


In addition to graphics, timelines can also contain ActionScript (as well as
anchors and labels).  More specifically, frames within a timeline can
contain ActionScript.  The code placed in each frame of a timeline gets
executed when Flash displays that frame on the screen.  With ActionScript 1 and
ActionScript 2 Flash was working with a paradigm that depended heavily on the
timeline as a foundation for not only animation but also ActionScript.  To
make a long story short, this model was limiting.


ActionScript 3 broke away from the timeline and instead isolates ActionScript
definitions into separate class definitions that have no dependency on the
timeline.  Take the following ActionScript 2 class.


// ActionScript 2 definition in Example.as

class Example {
public var num:Number;
private var str:String = "text";
public function Example(){
num = 1;
}
public function doubleNum():Void {
num *= 2;
}
}

A FLA might use this class in frame 1 of the main timeline with the
following:


// main timeline of ActionScript 2 FLA

var myExample:Example = new Example();

When compiled and published into a SWF, the SWF gets code that is attached to
the timeline and essentially looks like this:


// compiled version

_global.Example = function(){
this.num = 1;
}
Example.prototype.str = "text";
Example.prototype.doubleNum = function(){
this.num *= 2;
}
myExample = new Example();

All ActionScript 2 class definitions, when compiled, end up in the main
timeline as ActionScript 1 definitions.  And, really, to be more specific,
the definitions actually end up in dynamically generated movie clip symbols
placed in the library during compile time.  Within these movie clips'
timelines, however, the definitions are created within an #initclip/#endinitclip
block, which ultimately translates to a main timeline definition.  Either
way, the end result is code placed on a timeline which gets run when that frame
in the timeline is run.


In ActionScript 3, classes become isolated definitions.  They do not end
up in the timeline which requires that the timeline to be executed in order to
be defined.  In fact the opposite happens for code placed on the timeline
in ActionScript 3.  In that instance, timeline code is ripped out of the
timeline and placed in a class definition that is then used to define that
timeline instance.  Consider the following ActionScript 3 code placed on
the main timeline in Flash.


var num:Number = 10;

function isOdd(num:Number):Boolean {
return Boolean(num % 2);
}
trace(isOdd(num));

When compiled, this timeline code is removed from the timeline and is instead
placed in the class definition used to describe the main timeline.


package {

public class MainTimeline extends MovieClip {
public var num:Number;
public function MainTimeline(){
super();
addFrameScript(0, frame1);
}
public function isOdd(num:Number):Boolean {
return Boolean(num % 2);
}
public frame1(){
num = 10;
trace(isOdd(num));
}
}
}

This class is then used when the main timeline is instantiated.  With
this in mind, it might be a little easier to see why you cannot define a
variable or a function more than once anywhere within the same timeline. 
If you did, you would have conflicting definitions in the class that is
generated from the code in the timeline.


[TODO: img visual of ActionScript 3 vs ActionScript 2]


Interfaces


Types are not limited by class definitions.  Types can also take the
form of interfaces.  Interfaces define what properties and
methods are available to a type. 


The term "interface" itself describes the actual collection of accessible
(usually public) properties and methods available to an object.  This is
the same collection of properties and methods you see when you lookup class
definitions in help or an ActionScript language reference.  It's a common
term that is used with most all programming.


var myObj:Object = new Object();

myObj.foo = "foo";
myObj.bar = function():String {
return this.foo;
}

The interface of the above object consists of the property foo,
and the method bar.


ActionScript also supports interface definitions.  Interface
definitions are class-like definitions (usually starting with a capital "I")
 that describe what properties and methods and object has but does not go so far
as to provide an implementation for them (which remains the class's job).  
When a class implements an interface, it is required to supply the
implementation of the properties and methods within the interface(s) being
implemented, either explicitly or through inheritance.


The big idea behind having interfaces is to have more type options. 
Like classes, interfaces are also types.  A type's purpose, after all, is
to describe an object's interface so Flash can recognize when you are using a
typed value correctly.  You will get an error when you attempt to access a
part of an object's interface that is not described in its type, whether that
type is defined by a class type or an interface type.  So why not just use
class types?


There are some situations in ActionScript where a certain property can
contain more than one kind of instance but requires that each share the same
interface (as in properties and methods), even if they are instances of
unrelated classes. One example of this is with the BitmapData.draw()
method.  The signature or definition for draw()
starts off as the following


public function draw(source:IBitmapDrawable, matrix:Matrix = null, …

Notice that the first parameter is typed as IBitmapDrawable. 
IBitmapDrawable is an interface that describes objects that can be used with the
draw() method.  The classes that implement this interface are
BitmapData and DisplayObject so only instances of those classes (or their
subclasses) which are of the type IBitmapDrawable can be used in draw().


A better example might be the IEventDispatcher interface. This interface,
unlike IBitmapDrawable, actually defines methods associated with the interface
itself.  These methods include



  • addEventListener

  • dispatchEvent

  • hasEventListener

  • removeEventListener

  • willTrigger


The EventDispatcher class which implements this interface is required to
define and provide an implementation each one of those methods, and it does. 
Any other class that also implements the IEventDispatcher interface would also
have to do the same.  Currently there are no other native Flash classes
that implement IEventDispatcher other than EventDispatcher, though some Flex
classes (AbstractService and DataService) do.


The reason EventDispatcher has its own interface is because the functionality
of EventDispatcher can be used in classes two ways; one by extending
EventDispatcher or a subclass of EventDispatcher (so its methods are inherited)
or using an instance of EventDispatcher as a property of a class to funnel event
operations through (this is called composition).  If a class is
not able to extend EventDispatcher for some reason (for example if it needs to
extend Proxy instead) then it would need an EventDispatcher instance to manage
events.  In that case, recognizing the class as being the type
EventDispatcher would not be possible even though the same functionality is
there.  Instead, the class would have to implement IEventDispatcher so
values expecting the interface of EventDispatcher can be typed as
IEventDispatcher and still work with that class instance.


// any object extending EventDispatcher or

// using EventDispatcher with composition
var dispatcher:IEventDispatcher;

Whenever you require a variable typed as EventDispatcher, you should always
use the type IEventDispatcher instead.  This will cover all instances that
inherit from EventDispatcher as well as those which use composition to acquire
EventDispatcher functionality.


You may also decide to create your own interface definitions that can be used
to describe a custom type for custom classes.


Components


Components are pre-built assets available in Flash that allow advanced
functionality right "out of the box."  What separates components from other
symbols or libraries is that each instance of a component on the screen in Flash
is customizable through the Flash interface without the need for ActionScript. 


Components were originally introduced in Flash 5.  Then, they were known
simply as smart clips and were limited to simple variable definitions. 
Since Flash 5 components have evolved to support other features such as custom
interfaces and dynamic previews within the Flash drawing area through live
preview.


Different versions of Flash and different versions of ActionScript have
different component sets.





No comments: