-
Programming ActionScript 3.
-
© 2006 Adobe Systems Incorporated. All rights reserved. Flex 2 Programming ActionScript 3.0 If this guide is distributed with software that includes an end-user agreement, this guide, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license.
-
Contents PART 1: OVERVIEW OF ACTIONSCRIPT PROGRAMMING About This Manual. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 Using this manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Accessing ActionScript documentation . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Developer Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Chapter 1: Introduction to ActionScript 3.
-
Advanced topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Example: GeometricShapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Chapter 5: Display Programming . . . . . . . . . . . . . . . . . . . . . . . . . 159 Understanding the display architecture . . . . . . . . . . . . . . . . . . . . . . . . . 160 Working with display objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
Handling synchronous errors in an application . . . . . . . . . . . . . . . . . . .261 Creating custom error classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Responding to error events and status . . . . . . . . . . . . . . . . . . . . . . . . . 267 Comparing the Error classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Example: CustomErrors application. . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Chapter 10: Using Regular Expressions .
-
flash.text package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .342 flash.ui package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .342 flash.utils package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .343 flash.xml package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .343 Chapter 13: Handling Events . . . . . . . . . . . . . . . . . . . . .
-
Loading content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467 Cross-scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 Accessing loaded media as data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 Loading data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 Loading embedded content from SWF files imported into a security domain . . . . .
-
Contents
-
PART 1 Overview of ActionScript Programming 1 This part describes fundamental programming concepts in ActionScript 3.0. The following chapters are included: About This Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Chapter 1: Introduction to ActionScript 3.0 . . . . . . . . . . . . . . . . . . . 15 Chapter 2: Getting Started with ActionScript . . . . . . . . . . . . . . . . .23 Chapter 3: ActionScript Language and Syntax. . . . . . . . . . . . . . . .
-
-
About This Manual This manual provides a foundation for developing applications in ActionScript 3.0. To best understand the ideas and techniques described, you should already be familiar with general programming concepts such as data types, variables, loops, and functions. You should also understand basic object-oriented programming concepts like classes and inheritance. Prior knowledge of ActionScript 1.0 or ActionScript 2.0 is helpful but not necessary. Contents Using this manual . . . . . . . . . . . .
-
Using this manual This manual is divided into the following parts: Part Description Part 1, “Overview of ActionScript Programming” Discusses core ActionScript 3.0 concepts, including language syntax, statements and operators, the ECMAScript edition 4 draft language specification, object-oriented ActionScript programming, and the new approach to managing display objects on the Adobe® Flash® Player 9 display list. Part 2, “Core ActionScript 3.
-
To understand the code samples in this manual, you don’t need to have prior experience using integrated development environments for ActionScript, such as Flex Builder or the Flash authoring tool. You will, however, want to refer to the documentation for those tools to learn how to use them to write and compile ActionScript 3.0 code. For more information, see “Accessing ActionScript documentation” on page 13. Accessing ActionScript documentation Because this manual focuses on describing ActionScript 3.
-
Flex documentation If you use the Flex development environment, you may want to consult these manuals: Book Description Flex 2 Developer’s Guide Describes how to develop your dynamic web applications. Getting Started with Flex 2 Contains an overview of Flex features and application development procedures. Building and Deploying Flex 2 Applications Describes how to build and deploy Flex applications. Creating and Extending Flex 2 Components Describes how to create and extend Flex components.
-
CHAPTER 1 1 Introduction to ActionScript 3.0 This chapter provides an overview of ActionScript 3.0, the newest and most revolutionary version of ActionScript. Contents About ActionScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Advantages of ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 What’s new in ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
■ A core language based on the upcoming ECMAScript (ECMA-262) edition 4 draft language specification ■ An XML API based on ECMAScript for XML (E4X), as specified in ECMA-357 edition 2 specification. E4X is a language extension to ECMAScript that adds XML as a native data type of the language. ■ An event model based on the Document Object Model (DOM) Level 3 Events Specification Advantages of ActionScript 3.0 ActionScript 3.0 goes beyond the scripting capabilities of previous versions of ActionScript.
-
Run-time exceptions ActionScript 3.0 reports more error conditions than previous versions of ActionScript. Runtime exceptions are used for common error conditions, improving the debugging experience and enabling you to develop applications that handle errors robustly. Run-time errors can provide stack traces annotated with source file and line number information, helping you quickly pinpoint errors. Run-time types In ActionScript 2.
-
ECMAScript for XML (E4X) ActionScript 3.0 implements ECMAScript for XML (E4X), recently standardized as ECMA357. E4X offers a natural, fluent set of language constructs for manipulating XML. In contrast to traditional XML-parsing APIs, XML with E4X performs like a native data type of the language. E4X streamlines the development of applications that manipulate XML by drastically reducing the amount of code needed. For more information about the ActionScript 3.
-
DOM3 event model Document Object Model Level 3 event model (DOM3) provides a standard way of generating and handling event messages so that objects within applications can interact and communicate, maintaining their state and responding to change. Patterned after the World Wide Web Consortium DOM Level 3 Events Specification, this model provides a clearer and more efficient mechanism than the event systems available in previous versions of ActionScript. Events and error events are located in the flash.
-
Low-level data access Various APIs provide low-level access to data that was never before available in ActionScript. For data that is being downloaded, the URLStream class, which is implemented by URLLoader, provides access to data as raw binary data while it is being downloaded. The ByteArray class lets you optimize reading, writing, and working with binary data. The new Sound API provides detailed control of sound through the SoundChannel and SoundMixer classes.
-
The only exception to this rule is that an ActionScript 2.0 SWF file can replace itself with an ActionScript 3.0 SWF file, as long as the ActionScript 2.0 SWF file hasn't previously loaded anything into any of its levels. An ActionScript 2.0 SWF file can do this through a call to loadMovieNum(), passing a value of 0 to the level parameter. ■ In general, SWF files written in ActionScript 1.0 or 2.0 must be migrated if they are to work together with SWF files written in ActionScript 3.0.
-
Introduction to ActionScript 3.
-
CHAPTER 2 2 Getting Started with ActionScript This chapter provides a no-frills, step-by-step approach to building a simple ActionScript 3.0 application. The ActionScript 3.0 programming language can be used from within a number of different development environments, including Macromedia Flash from Adobe and Adobe Flex Builder 2. This chapter will show how to create modular ActionScript code that can be used from within either of these application development environments.
-
3. Create a Flash or Flex application file to run your code. In the Flash authoring tool, this involves creating a new FLA file, setting up the publish settings, adding user interface components to the application, and referencing the ActionScript code. In the Flex development environment, creating a new application file involves defining the application and adding user interface components using MXML, and referencing the ActionScript code. 4. Publish and test your ActionScript application.
-
Many developers simplify the organization of their ActionScript code in the Flash authoring tool by placing code only in the first frame of a timeline, or on a specific layer in the Flash document. This makes it easier to locate and maintain the code in your Flash FLA files. However, in order to use the same code in another Flash or Flex project, you must copy and paste the code into the new file.
-
■ ActionScript class definition: a definition of an ActionScript class, including its method and property definitions. When you define a class, you can access the ActionScript code in the class by creating an instance of the class and using its properties, methods, and events, just as you would with any of the built-in ActionScript classes. This requires two parts: ■ Use the import statement to specify the full name of the class, so the ActionScript compiler knows where to find it.
-
Designing your ActionScript application You should have some idea about the application you want to build before you start building it. The representation of your design can be as simple as the name of the application and a brief statement of its purpose, or as complicated as a set of requirements documents containing numerous Unified Modeling Language (UML) diagrams.
-
5. In the New ActionScript File dialog box, select HelloWorld as the parent folder, type Greeter.as the filename, and then click Finish. A new ActionScript editing window is displayed. Continue with “Adding code to the Greeter class” on page 28. Adding code to the Greeter class The Greeter class defines an object, Greeter, that you will be able to use in your HelloWorld application. To add code to the Greeter class: 1.
-
To create an ActionScript application using Flex Builder: 1. Open the HelloWorld.mxml file, and type the following code:
-
Publishing and testing your ActionScript application Software development is an iterative process. You write some code, try to compile it, and edit the code until it compiles cleanly. You run the compiled application, test it to see if it fulfills the intended design, and if it doesn’t, you edit the code again until it does. The Flash and Flex Builder development environments offer a number of ways to publish, test, and debug your applications.
-
2. Change the contents of the file to the following (new and changed lines are shown in boldface): package { public class Greeter { /** * Defines the names that should receive a proper greeting. */ public static var validNames:Array = ["Sammy", "Frank", "Dean"]; /** * Builds a greeting string using the given name. */ public function sayHello(userName:String = ""):String { var greeting:String; if (userName == "") { greeting = "Hello. Please type your user name, and then press the Enter key.
-
The Greeter class now has a number of new features: ■ The validNames array lists valid user names. The array is initialized to a list of three names when the Greeter class is loaded. ■ The sayHello() method now accepts a user name and changes the greeting based on some conditions. If the userName is an empty string (""), the greeting property is set to prompt the user for a name. If the user name is valid, the greeting becomes "Hello, userName.
-
private var myGreeter:Greeter = new Greeter(); public function initApp():void { // says hello at the start, and asks for the user's name mainTxt.text = myGreeter.sayHello(); } ]]> 4. Save the edited HelloWorld.mxml file.
-
Getting Started with ActionScript
-
CHAPTER 3 3 ActionScript Language and Syntax ActionScript 3.0 comprises both the core ActionScript language and the Flash Player Application Programming Interface (API). The core language is the part of ActionScript that implements the draft ECMAScript (ECMA-262), Edition 4 draft language specification. The Flash Player API provides programmatic access to Flash Player. This chapter provides a brief introduction to the core ActionScript language and syntax.
-
Programmers familiar with object-oriented programming (OOP) in Java or C++ may think of objects as modules that contain two kinds of members: data stored in member variables or properties, and behavior accessible through methods. The ECMAScript edition 4 draft, the standard upon which ActionScript 3.0 is based, defines objects in a similar but slightly different way. In the ECMAScript draft, objects are simply collections of properties.
-
Objects and classes In ActionScript 3.0, every object is defined by a class. A class can be thought of as a template or a blueprint for a type of object. Class definitions can include variables and constants, which hold data values, and methods, which are functions that encapsulate behavior bound to the class. The values stored in properties can be primitive values or other objects. Primitive values are numbers, strings, or Boolean values.
-
Packages and namespaces Packages and namespaces are related concepts. Packages allow you to bundle class definitions together in a way that facilitates code sharing and minimizes naming conflicts. Namespaces allow you to control the visibility of identifiers, such as property and method names, and can be applied to code whether it resides inside or outside a package. Packages let you organize your class files, and namespaces let you manage the visibility of individual properties and methods.
-
Many developers, especially those with Java programming backgrounds, may choose to place only classes at the top level of a package. ActionScript 3.0, however, supports not only classes at the top level of a package, but also variables, functions, and even statements. One advanced use of this feature is to define a namespace at the top level of a package so that it will be available to all classes in that package.
-
Most of the Flash Player API is organized under the flash package. For example, the flash.display package contains the display list API, and the flash.events package contains the new event model. A detailed discussion of the Flash Player API packages can be found in Part 3 of this book. For more information, see “Flash Player APIs” on page 335. Creating packages ActionScript 3.0 provides significant flexibility in the way you organize your packages, classes, and source files.
-
Importing packages If you want to use a class that is inside a package, you must import either the package or the specific class. This differs from ActionScript 2.0, where importing classes was optional. For example, consider the SampleCode class example from earlier in this chapter. If the class resides in a package named samples, you must use one of the following import statements before using the SampleCode class: import samples.*; or import samples.
-
When a package is created, the default access specifier for all members of that package is internal, which means that, by default, package members are only visible to other members of that package. If you want a class to be available to code outside the package, you must declare that class to be public. For example, the following package contains two classes, SampleCode and CodeFormatter: // SampleCode.as file package samples { public class SampleCode {} } // CodeFormatter.
-
The compiler has no way of knowing which SampleCode class to use. To resolve this conflict, you must use the fully qualified name of each class, as follows: var sample1:samples.SampleCode = new samples.SampleCode(); var sample2:langref.samples.SampleCode = new langref.samples.SampleCode(); NO TE Programmers with a C++ background often confuse the import statement with #include.
-
There are three basic steps to follow when using namespaces. First, you must define the namespace using the namespace keyword. For example, the following code defines the version1 namespace: namespace version1; Second, you apply your namespace by using it instead of an access control specifier in a property or method declaration.
-
If a namespace is defined within a package or a class, the namespace may not be visible to code outside that package or class unless the appropriate access control specifier is used. For example, the following code shows the flash_proxy namespace defined within the flash.utils package. In the following example, the lack of an access control specifier means that the flash_proxy namespace would be visible only to code within the flash.
-
You should bear in mind the following when applying namespaces: ■ You can apply only one namespace to each declaration. ■ There is no way to apply a namespace attribute to more than one definition at a time. In other words, if you want to apply your namespace to ten different functions, you must add your namespace as an attribute to each of the ten function definitions.
-
Using namespaces You can find a real-world example of a namespace that is used to prevent name conflicts in the flash.utils.Proxy class that is part of the Flash Player API. The Proxy class, which is the replacement for the Object.__resolve property from ActionScript 2.0, allows you to intercept references to undefined properties or methods before an error occurs. All of the methods of the Proxy class reside in the flash_proxy namespace in order to prevent name conflicts.
-
import flash.utils.Proxy; import flash.utils.flash_proxy; dynamic class MyProxy extends Proxy { flash_proxy override function callProperty(name:*, ...rest):* { trace("method call intercepted: " + name); } } } If you create an instance of the MyProxy class and call an undefined method, such as the testing() method called in the following example, your Proxy object intercepts the method call and executes the statements inside the overridden callProperty() method (in this case, a simple trace() statement).
-
The following example uses a user-defined namespace to group together two functions that reside in different packages. By grouping them into the same namespace, you can make both functions visible to a class or package through a single use namespace statement. This example uses four files to demonstrate the technique. All of the files must be within your classpath. The first file, myInternal.as, is used to define the myInternal namespace.
-
import example.myInternal; use namespace myInternal; public class Helper { private static var _timeStamp:Date; public static function someTask() { _timeStamp = new Date(); } myInternal static function get lastCalled():Date { return _timeStamp; } } } The fourth file, NamespaceUseCase.as, is the main application class, and should be a sibling to the example folder. The NamespaceUseCase class will also import the myInternal namespace and use it to call the two static methods that reside in the other packages.
-
Variables Variables allow you to store values that you use in your program. To declare a variable, you must use the var statement with the variable name. In ActionScript 2.0, use of the var statement is only required if you use type annotations. In ActionScript 3.0, use of the var statement is always required.
-
If you have more than one variable to declare, you can declare them all on one line of code by using the comma operator (,) to separate the variables. For example, the following code declares three variables on one line of code: var a:int, b:int, c:int; You can also assign values to each of the variables on the same line of code.
-
If the variable name you use for your local variable is already declared as a global variable, the local definition hides (or shadows) the global definition while the local variable is in scope. The global variable will still exist outside of the function. For example, the following code creates a global string variable named str1, and then creates a local variable of the same name inside the scopeTest() function.
-
An interesting implication of the lack of block-level scope is that you can read or write to a variable before it is declared, as long as it is declared before the function ends. This is because of a technique called hoisting, which means that the compiler moves all variable declarations to the top of the function.
-
If you declare a variable, but do not declare its data type, the default data type * will apply, which actually means that the variable is untyped. If you also do not initialize an untyped variable with a value, its default value is undefined. For data types other than Boolean, Number, int, and uint, the default value of any uninitialized variable is null. This applies to all the classes defined by the Flash Player API, as well as any custom classes that you create.
-
Many programming languages distinguish between primitive values and their wrapper objects. Java, for example, has an int primitive and the java.lang.Integer class that wraps it. Java primitives are not objects, but their wrappers are, which makes primitives useful for some operations and wrapper objects better suited for other operations. In ActionScript 3.0, primitive values and their wrapper objects are, for practical purposes, indistinguishable. All values, even primitive values, are objects.
-
In order to provide compile-time type checking, the compiler needs to know the data type information for the variables or expressions in your code. To explicitly declare a data type for a variable, add the colon operator (:) followed by the data type as a suffix to the variable name. To associate a data type with a parameter, you use the colon operator followed by the data type.
-
trace("Number: " + myNum); } } dynamicTest(100) dynamicTest("one hundred"); Run-time type checking Run-time type checking occurs in ActionScript 3.0 whether you compile in strict mode or standard mode. Consider a situation in which the value 3 is passed as an argument to a function that expects an array. In strict mode, the compiler will generate an error because the value 3 is not compatible with the data type Array.
-
Run-time type checking also allows more flexible use of inheritance than does compile-time checking. By deferring type checking to run time, standard mode allows you to reference properties of a subclass even if you upcast. An upcast occurs when you use a base class to declare the type of a class instance, but a subclass to instantiate it.
-
The is operator examines the proper inheritance hierarchy and can be used to check not only whether an object is an instance of a particular class, but also whether an object is an instance of a class that implements a particular interface.
-
Dynamic classes A dynamic class defines an object that can be altered at run time by adding or changing properties and methods. A class that is not dynamic, such as the String class, is a sealed class. You cannot add properties or methods to a sealed class at run time. You create dynamic classes by using the dynamic attribute when you declare a class.
-
Methods created in this way, however, do not have access to any private properties or methods of the Protean class. Moreover, even references to public properties or methods of the Protean class must be qualified with either the this keyword or the class name. The following example shows the traceProtean() method attempting to access the private and public variables of the Protean class. myProtean.traceProtean = function () { trace(myProtean.privateGreeting); // undefined trace(myProtean.
-
Null data type The Null data type contains only one value, null. This is the default value for the String data type and all classes that define complex data types, including the Object class. None of the other primitive data types, such as Boolean, Number, int and uint, contain the value null. Flash Player will convert the value null to the appropriate default value if you attempt to assign null to variables of type Boolean, Number, int, or uint. You cannot use this data type as a type annotation.
-
When you store integer values with the Number data type, only the 52 bits of the significand are used. The Number data type uses these 52 bits and a special hidden bit to represent integers from -9,007,199,254,740,992 (-253) to 9,007,199,254,740,992 (253). Flash Player uses the NaN value not only as the default value for variables of type Number, but also as the result of any operation that should return a number but does not.
-
Object data type The Object data type is defined by the Object class. The Object class serves as the base class for all class definitions in ActionScript. The ActionScript 3.0 version of the Object data type differs from that of previous versions in three ways. First, the Object data type is no longer the default data type assigned to variables with no type annotation. Second, the Object data type no longer includes the value undefined, which used to be the default value of Object instances.
-
Implicit conversions Implicit conversions happen at run time in a number of contexts: ■ In assignment statements ■ When values are passed as function arguments ■ When values are returned from functions ■ In expressions using certain operators, such as the addition (+) operator For user-defined types, implicit conversions succeed when the value to be converted is an instance of the destination class or a class that derives from the destination class.
-
Casting to int, uint, and Number You can cast any data type into one of the three number types: int, uint, and Number. If Flash Player is unable to convert the number for some reason, the default value of 0 is assigned for the int and uint data types, and the default value of NaN is assigned for the Number data type. If you convert a Boolean value to a number, true becomes the value 1 and false becomes the value 0.
-
In ActionScript 3.0, the Number() function no longer supports octal, or base 8, numbers. If you supply a string with a leading zero to the ActionScript 2.0 Number() function, the number is interpreted as an octal number, and converted to its decimal equivalent. This is not true with the Number() function in ActionScript 3.0, which instead ignores the leading zero.
-
Casting to Boolean Casting to Boolean from any of the numeric data types (uint, int, and Number) results in false if the numeric value is 0, and true otherwise. For the Number data type, the value NaN also results in false.
-
Boolean variables get special treatment in strict mode in that you can assign values of any data type to a Boolean variable without casting. Implicit coercion from all data types to the Boolean data type occurs even in strict mode. In other words, unlike almost all other data types, casting to Boolean is not necessary to avoid strict mode errors.
-
Casting to String from an instance of the Date class returns a string representation of the date that the instance contains. For example, the following example returns a string representation of the Date class instance (the output shows result for Pacific Daylight Time): var myDate:Date = new Date(2005,6,1); trace(String(myDate)); // Fri Jul 1 00:00:00 GMT-0700 2005 The following table summarizes the results of casting to the String data type from other data types.
-
public function method1():void {} } Using dot syntax, you can access the prop1 property and the method1() method using the instance name created in the following code: var myDotEx:DotExample = new DotExample(); myDotEx.prop1 = “hello”; myDotEx.method1(); You can use dot syntax when you define packages. You use the dot operator to refer to nested packages. For example, the EventDispatcher class resides in a package named events that is nested within the package named flash.
-
An array literal can be used to initialize an array. The following examples show two arrays that are initialized using array literals. You can use the new statement and pass the compound literal as a parameter to the Array class constructor, but you can also assign literal values directly when instantiating instances of the following ActionScript core classes: Object, Array, String, Number, int, uint, XML, XMLList and Boolean. // Use new statement.
-
Parentheses You can use parentheses (()) in three ways in ActionScript 3.0. First, you can use parentheses to change the order of operations in an expression. Operations that are grouped inside parentheses are always executed first.
-
Keywords and reserved words Reserved words are words that you cannot use as identifiers in your code because the words are reserved for use by ActionScript. Reserved words include lexical keywords, which are removed from the program namespace by the compiler. The compiler will report an error if you use a lexical keyword as an identifier. The following table lists ActionScript 3.0 lexical keywords.
-
There are also several identifiers that are sometimes referred to as future reserved words. These identifiers are not reserved by ActionScript 3.0, though some of them may be treated as keywords by products that incorporate ActionScript 3.0. You might be able to use many of these identifiers in your code, but Adobe recommends that you do not use them because they may appear as keywords in a subsequent version of the language.
-
An error results if you attempt to assign an initial value to a constant in any other way. For example, if you attempt to set the initial value of MAXIMUM outside the class, a run-time error will occur. class A { public const MINIMUM:int = 0; public const MAXIMUM:int; } var a:A = new A(); a["MAXIMUM"] = 10; // run-time error The Flash Player API defines a wide range of constants for your use.
-
Some operators are overloaded, which means that they behave differently depending on the type or quantity of operands passed to them. The addition (+) operator is an example of an overloaded operator that behaves differently depending on the data type of the operands. If both operands are numbers, the addition operator returns the sum of the values. If both operands are strings, the addition operator returns the concatenation of the two operands.
-
For example, consider the less-than (<) and greater-than (>) operators, which have the same precedence. If both operators are used in the same expression, the operator on the left is processed first because both operators are left-associative. This means that the following two statements produce the same output: trace(3 > 2 < 1); // false trace((3 > 2) < 1); // false The greater-than operator is processed first, which results in a value of true because the operand 3 is greater than the operand 2.
-
Group Operators Additive + - Bitwise shift << >> >>> Relational < > <= >= as in instanceof is Equality == != === !== Bitwise AND & Bitwise XOR ^ Bitwise OR | Logical AND && Logical OR || Conditional ?: Assignment = *= /= %= += -= <<= >>= >>>= &= ^= |= Comma , Primary operators The primary operators include those used for creating Array and Object literals, grouping expressions, calling functions, instantiating class instances, and accessing properties.
-
Postfix operators The postfix operators take one operator and either increment or decrement the value. Although these operators are unary operators, they are classified separately from the rest of the unary operators because of their higher precedence and special behavior. When a postfix operator is used as part of a larger expression, the expression’s value is returned before the postfix operator is processed.
-
Operator Operation performed delete Deletes a property typeof Returns type information void Returns undefined value Multiplicative operators The multiplicative operators take two operands and perform multiplication, division, or modulo calculations.
-
Relational operators The relational operators take two operands, compare their values, and return a Boolean value.
-
Logical operators The logical operators take two operands and return a Boolean result. The logical operators differ in precedence and are listed in the following table in order of decreasing precedence: Operator Operation performed && Logical AND || Logical OR Conditional operator The conditional operator is a ternary operator, which means that it takes three operands. The conditional operator is a shorthand method of applying the if..else conditional statement.
-
Conditionals ActionScript 3.0 provides three basic conditional statements that you can use to control program flow. if..else The if..else conditional statement allows you to test a condition and execute a block of code if that condition exists, or execute an alternative block of code if the condition does not exist.
-
if..else if You can test for more than one condition using the if..else if conditional statement. For example, the following code not only tests whether the value of x exceeds 20, but also tests whether the value of x is negative: if (x > 20) { trace("x is > 20"); } else if (x < 0) { trace("x is negative"); } If an if or else statement is followed by only one statement, the statement does not need to be enclosed in braces. For example, the following code does not use braces.
-
switch The switch statement is useful if you have several execution paths that depend on the same condition expression. It provides functionality similar to a long series of if..else if statements, but is somewhat easier to read. Instead of testing a condition for a Boolean value, the switch statement evaluates an expression and uses the result to determine which block of code to execute. Blocks of code begin with a case statement, and end with a break statement.
-
Looping Looping statements allow you to perform a specific block of code repeatedly using a series of values or variables. Adobe recommends that you always enclose the block of code in braces ({}). Although you can omit the braces if the block of code contains only one statement, this practice is not recommended for the same reason that it is not recommended for conditionals: it increases the likelihood that statements added later will be inadvertently excluded from the block of code.
-
{ trace(myArray[i]); } // // // // output: one two three What you cannot do is iterate through the properties of an object if it is an instance of a userdefined class, unless the class is a dynamic class. Even with instances of dynamic classes, you will be able to iterate only through properties that are added dynamically. for each..in The for each..
-
You can also iterate through the elements of an array, as this example shows: var myArray:Array = ["one", "two", "three"]; for each (var item in myArray) { trace(item); } // output: // one // two // three You cannot iterate through the properties of an object if the object is an instance of a sealed class. Even for instances of dynamic classes, you cannot iterate through any fixed properties, which are properties defined as part of the class definition.
-
} while (i < 5); // output: 5 Functions Functions are blocks of code that carry out specific tasks and can be reused in your program. There are two types of functions in ActionScript 3.0: methods and function closures. Whether a function is a called a method or a function closure depends on the context in which the function is defined. A function is called a method if you define it as part of a class definition or attach it to an instance of an object.
-
Defining your own functions There are two ways to define a function in ActionScript 3.0: you can use a function statement or a function expression. The technique you choose depends on whether you prefer a more static or dynamic programming style. Define your functions with function statements if you prefer static, or strict mode, programming. Define your functions with function expressions if you have a specific need to do so.
-
An assignment statement with a function expression begins with the var keyword, followed by: ■ The function name ■ The colon operator (:) ■ The Function class to indicate the data type ■ The assignment operator (=) ■ The function keyword ■ The parameters, in a comma-delimited list enclosed in parentheses ■ The function body—that is, the ActionScript code to be executed when the function is invoked, enclosed in curly braces For example, the following code declares the traceParameter function us
-
Function statements provide a more consistent experience between the two compiler modes in that you can use dot syntax in both strict and standard mode to invoke a method declared using a function statement. This is not necessarily true for methods declared with a function expression. For example, the following code defines a class named Example with two methods: methodExpression(), which is declared with a function expression, and methodStatement(), which is declared with a function statement.
-
There are two subtle differences between function statements and function expressions that you should take into account when choosing which technique to use. The first difference is that function expressions do not exist independently as objects with regard to memory management and garbage collection. In other words, when you assign a function expression to another object, such as an array element or an object property, you create the only reference to that function expression in your code.
-
The second difference between function statements and function expressions is that function statements exist throughout the scope in which they are defined, including in statements that appear before the function statement. Function expressions, by contrast, are defined only for subsequent statements.
-
Nested functions You can nest functions, which means that functions can be declared within other functions. A nested function is available only within its parent function unless a reference to the function is passed to external code.
-
In ActionScript 3.0, all arguments are passed by reference because all values are stored as objects. However, objects that belong to the primitive data types, which includes Boolean, Number, int, uint, and String, have special operators that make them behave as if they were passed by value. For example, the following code creates a function named passPrimitives() that defines two parameters named xParam and yParam, both of type int.
-
trace(objParam.x, objParam.y); } var objVar:Object = {x:10, y:15}; trace(objVar.x, objVar.y); // 10 15 passByRef(objVar); // 11 16 trace(objVar.x, objVar.y); // 11 16 The objParam parameter references the same object as the global objVar variable. As you can see from the trace statements in the example, changes to the x and y properties of the objParam object are reflected in objVar object. Default parameter values New in ActionScript 3.0 is the ability to declare default parameter values for a function.
-
ActionScript 3.0 allows function calls to include more parameters than those defined in the function definition, but will generate a compiler error in strict mode if the number of parameters is less than the number of required parameters. You can use the array aspect of the arguments object to access any parameter passed to the function, whether or not that parameter is defined in the function definition. The following example uses the arguments array along with the arguments.
-
You should also be careful to avoid using the string “arguments” as a parameter name because it will shadow the arguments object. For example, if the function traceArgArray() is rewritten so that an arguments parameter is added, the references to arguments in the function body refer to the parameter rather than the arguments object. The following code produces no output: function traceArgArray(x:int, arguments:int):void { for (var i:uint = 0; i < arguments.
-
// // // // output: 1 2 3 The ... (rest) parameter can also be used with other parameters, as long as it is the last parameter listed. The following example modifies the traceArgArray() function so that its first parameter, x, is of type int, and the second parameter uses the ... (rest) parameter. The output skips the first value because the first parameter is no longer part of the array created by the ... (rest) parameter. function traceArgArray(x: int, ... args) { for (var i:uint = 0; i < args.
-
Although it may seem strange to programmers new to ActionScript, functions can have properties and methods, just as any other object can. In fact, every function has a read-only property named length that stores the number of parameters defined for the function. This is different from the arguments.length property, which reports the number of arguments sent to the function. Recall that in ActionScript, the number of arguments sent to a function can exceed the number of parameters defined for that function.
-
Function scope A function’s scope determines not only where in a program that function can be called, but also what definitions the function can access. The same scope rules that apply to variable identifiers apply to function identifiers. A function declared in the global scope is available throughout your code. For example, ActionScript 3.0 contains global functions, such as isNaN() and parseInt(), that are available anywhere in your code.
-
function rectArea(y:int):int // function closure defined { return x * y } return rectArea; } function bar():void { var x:int = 2; var y:int = 4; var myProduct:Function = foo(); trace( myProduct(4) ); // function closure called } bar(); // 160 Methods behave similarly in that they also retain information about the lexical environment in which they were created. This characteristic is most noticeable when a method is extracted from its instance, which creates a bound method.
-
ActionScript Language and Syntax
-
CHAPTER 4 4 Object-Oriented Programming in ActionScript This chapter assumes a basic understanding of object-oriented programming (OOP) principles such as abstraction, encapsulation, inheritance, and polymorphism. The chapter focuses on how to apply these principles using ActionScript 3.0. Because of ActionScript’s roots as a scripting language, ActionScript 3.0 OOP support is optional. This affords programmers flexibility in choosing the best approach for projects of varying scope and complexity.
-
As far back as ActionScript 1.0, ActionScript programmers could use Function objects to create constructs that resembled classes. ActionScript 2.0 added formal support for classes with keywords such as class and extends. ActionScript 3.0 not only continues to support the keywords introduced in ActionScript 2.0, but also adds some new capabilities, such as enhanced access control with the protected and internal attributes, and better control over inheritance with the final and override keywords.
-
public class BitmapData {} } Class attributes ActionScript 3.0 allows you to modify class definitions using one of the following four attributes: Attribute Definition dynamic Allow properties to be added to instances at run time. final Must not be extended by another class. internal (default) Visible to references inside the current package. public Visible to references everywhere.
-
Class body The class body, which is enclosed by curly braces, is used to define the variables, constants, and methods of your class. The following example shows the declaration for the Accessibility class in the Flash Player API: public final class Accessibility { public static function get active():Boolean; public static function updateProperties():void; } You can also define a namespace inside a class body.
-
} // In your script var myST:StaticTest = new StaticTest(); trace(StaticTest.message); // static variable trace(myST.message); // instance variable Class property attributes In discussions of the ActionScript object model, the term property means anything that can be a member of a class, including variables, constants, and methods. This differs from the way the term is used in the ActionScript 3.
-
For example, the following code creates a simple class named PrivateExample with one private variable, and then attempts to access the private variable from outside the class. In ActionScript 2.0, compile-time access was prohibited, but the prohibition was easily circumvented by using the property access operator ([]), which does the property lookup at run time rather than at compile time.
-
Dynamic classes generally return the value undefined instead of generating an error when code external to a class attempts to access a private property. The following table shows that an error is generated only when the dot operator is used to access a private property in strict mode: Strict mode Standard mode dot operator (.) compile-time error undefined bracket operator ([]) undefined undefined The protected attribute, which is new for ActionScript 3.
-
Static properties are not inherited by subclasses, but the properties are part of a subclass’s scope chain. This means that within the body of a subclass, a static variable or method can be used without referencing the class in which it was defined. For more information, see “Static properties not inherited” on page 136. User-defined namespace attributes As an alternative to the predefined access control attributes, you can create a custom namespace for use as an attribute.
-
Code that is external to the StaticVars class and any of its subclasses can reference the totalCount and MAX_NUM properties only through the class itself. For example, the following code works: trace(StaticVars.totalCount); // 0 trace(StaticVars.MAX_NUM); // 16 You cannot access static variables through an instance of the class, so the following code returns errors: var myStaticVars:StaticVars = new StaticVars(); trace(myStaticVars.totalCount); // error trace(myStaticVars.
-
Methods are defined using the function keyword. You can use a function statement, such as the following: public function sampleFunction():String {} Or you can use a variable to which you assign a function expression, as follows: public var sampleFunction:Function = function () {} In most cases you will want to use a function statement instead of a function expression for the following reasons: ■ Function statements are more concise and easier to read.
-
Constructor methods can only be public, but the use of the public attribute is optional. You cannot use any of the other access control specifiers, including private, protected, or internal, on a constructor. You also cannot use a user-defined namespace with a constructor method. A constructor can make an explicit call to the constructor of its direct superclass using the statement.
-
Static methods Static methods, also called class methods, are methods that are declared with the static keyword. Static methods, which are attached to a class rather than to an instance of a class, are useful for encapsulating functionality that affects something other than the state of an individual instance. Because static methods are attached to a class as a whole, static methods can be accessed only through a class and not through an instance of the class.
-
Within the body of an instance method, both static and instance variables are in scope, which means that variables defined in the same class can be referenced using a simple identifier. For example, the following class, CustomArray, extends the Array class.
-
{ return this; } } var myTest:ThisTest = new ThisTest(); trace(myTest.thisValue() == myTest); // true Inheritance of instance methods can be controlled with the keywords override and final. You can use the override attribute to redefine an inherited method, and the final attribute to prevent subclasses from overriding a method. For more information, see “Overriding methods” on page 134.
-
Instead, a user of the GetSet class will use something that appears to be a property named publicAccess, but that is really a pair of get and set accessor functions that operate on the private property named privateProperty. The following example instantiates the GetSet class, and then sets the value of the privateProperty using the public accessor named publicAccess: var myGetSet:GetSet = new GetSet(); trace(myGetSet.publicAccess); // null myGetSet.publicAccess = "hello"; trace(myGetSet.
-
The following code defines a class named ThisTest, which contains a method named foo() that defines the bound method, and a method named bar() that returns the bound method. Code external to the class creates an instance of the ThisTest class, calls the bar() method, and stores the return value in a variable named myFunc.
-
Enumerations with classes Enumerations are custom data types that you create to encapsulate a small set of values. ActionScript 3.0 does not support a specific enumeration facility, unlike C++ with its enum keyword or Java with its Enumeration interface. You can, however, create enumerations using classes and static constants.
-
A second technique for creating enumerations also involves creating a separate class with static properties for the enumeration. This technique differs, however, in that each of the static properties contains an instance of the class instead of a string or integer value.
-
} return retDay; } var dayOfWeek:Day = getDay(); You can also enhance the Day class so that it associates an integer with each day of the week, and provides a toString() method that returns a string representation of the day. You might want to enhance the Day class in this manner as an exercise. Embedded asset classes ActionScript 3.0 uses special classes, called embedded asset classes, to represent embedded assets.
-
var sndChannel:SoundChannel = mySound.play(); } } } TIP To use the [Embed] metadata tag in an Adobe Flex Builder 2 ActionScript project, you must import any necessary classes from the Flex framework. For example, to embed sounds, you must import the mx.core.SoundAsset class. To use the Flex framework, include the file framework.swc in your ActionScript build path. This will increase the size of your SWF file. Alternatively, you can embed an asset with the @Embed() directive in an MXML tag definition.
-
In the Flash Player API, the EventDispatcher class implements the IEventDispatcher interface by defining all of the IEventDispatcher interface methods and adding method bodies to each of the methods. The following code is an excerpt from the EventDispatcher class definition: public class EventDispatcher implements IEventDispatcher { function dispatchEvent(event:Event):Boolean { /* implementation statements */ } ...
-
The Flash Player API follows a convention in which interface names begin with an uppercase I, but you can use any legal identifier as an interface name. Interface definitions are often placed at the top level of a package. Interface definitions cannot be placed inside a class definition or inside another interface definition. Interfaces can extend one or more other interfaces.
-
You do have some flexibility, however, in how you name the parameters of methods that you implement. Although the number of parameters and the data type of each parameter in the implemented method must match that of the interface method, the parameter names do not need to match. For example, in the previous example the parameter of the Alpha.foo() method is named param: public function foo(param:String):String {} But the parameter is named str in the IAlpha.
-
Inheritance Inheritance is a form of code reuse that allows programmers to develop new classes that are based on existing classes. The existing classes are often referred to as base classes or superclasses, while the new classes are usually called subclasses. A key advantage of inheritance is that it allows you to reuse code from a base class yet leave the existing code unmodified. Moreover, inheritance requires no changes to the way that other classes interact with the base class.
-
} var cir:Circle = new Circle(); trace(cir.area()); // 3.141592653589793 var sq:Square = new Square(); trace(sq.area()); // 1 Because each class defines a data type, the use of inheritance creates a special relationship between a base class and a class that extends it. A subclass is guaranteed to possess all the properties of its base class, which means that an instance of a subclass can always be substituted for an instance of the base class.
-
... } Other types of events require unique properties not available in the Event class. These events are defined using subclasses of the Event class so that new properties can be added to the properties defined in the Event class. An example of such a subclass is the MouseEvent class, which adds properties unique to events associated with mouse movement or mouse clicks, such as the mouseMove and click events.
-
You can use the following example to see how each of the access control specifiers affects inheritance across package boundaries. The following code defines a main application class named AccessControl and two other classes named Base and Extender. The Base class is in a package named foo and the Extender class, which is a subclass of the Base class, is in a package named bar.
-
To see how the other access control specifiers affect compilation and execution of the preceding example, change the str variable’s access control specifier to private, protected, or internal after deleting or commenting out the following line from the AccessControl class: trace (myExt.testString); // error if str is not public Overriding variables not permitted Properties that are declared with the var or const keywords are inherited, but cannot be overridden.
-
The names of the parameters in the override method, however, do not have to match the names of the parameters in the base class, as long as the number of parameters and the data type of each parameter matches. The super statement When overriding a method, programmers often want to add to the behavior of the superclass method they are overriding instead of completely replacing the behavior. This requires a mechanism that allows a method in a subclass to call the superclass version of itself.
-
package { import flash.display.MovieClip; public class OverrideExample extends MovieClip { public function OverrideExample() { trace(currentLabel) } override public function get currentLabel():String { var str:String = "Override: "; str += super.currentLabel; return str; } } } The output of the trace() statement in the OverrideExample class constructor is Override: null, which shows that the example was able to override the inherited currentLabel property.
-
The only way to access the static variable test is through the class object, as shown in the following code: Base.test; It is permissible, however, to define an instance property using the same name as a static property. Such an instance property can be defined in the same class as the static property or in a subclass. For example, the Base class in the preceding example could have an instance property named test.
-
import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); } } } class Base { public static var test:String = "static"; } class Extender extends Base { public function Extender() { trace(test); // output: static } } If an instance property is defined that uses the same name as a static property in the same class or a superclass, the instance property has higher precedence in the scope chain.
-
public function Extender() { trace(test); // output: instance } } Advanced topics This section begins with a brief history of ActionScript and OOP and continues with a discussion of the ActionScript 3.0 object model and how it enables the new ActionScript Virtual Machine (AVM2) to perform significantly faster than previous versions of Flash Player that contain the old ActionScript Virtual Machine (AVM1). History of ActionScript OOP support Because ActionScript 3.
-
To create a class in ActionScript 1.0, you define a constructor function for that class. In ActionScript, functions are actual objects, not just abstract definitions. The constructor function that you create serves as the prototypical object for instances of that class. The following code creates a class named Shape and defines one property named visible that is set to true by default: // base class function Shape() {} // Create a property named visible. Shape.prototype.
-
The Shape class and the Circle class are now linked together in an inheritance relationship that is commonly known as the prototype chain. The diagram illustrates the relationships in a prototype chain: Object.prototype Shape.prototype Circle.prototype The base class at the end of every prototype chain is the Object class. The Object class contains a static property named Object.prototype that points to the base prototype object for all objects created in ActionScript 1.0.
-
ActionScript 2.0 ActionScript 2.0 introduced new keywords such as class, extends, public, and private, that allowed you to define classes in a way that is familiar to anyone who works with classbased languages like Java and C++. It’s important to understand that the underlying inheritance mechanism did not change between ActionScript 1.0 and ActionScript 2.0. ActionScript 2.0 merely added a new syntax for defining classes. The prototype chain works the same way in both versions of the language.
-
The ActionScript 3.0 class object A common object-oriented programming paradigm, most commonly associated with Java and C++, uses classes to define types of objects. Programming languages that adopt this paradigm also tend to use classes to construct instances of the data type that the class defines. ActionScript uses classes for both of these purposes, but its roots as a prototype-based language add an interesting characteristic.
-
The traits object The traits object, which is new in ActionScript 3.0, was implemented with performance in mind. In previous versions of ActionScript, name lookup could be a time-consuming process as Flash Player walked the prototype chain. In ActionScript 3.0, name lookup is much more efficient and less time consuming because inherited properties are copied down from superclasses into the traits object of subclasses.
-
The prototype chain, which was the only inheritance mechanism in previous versions of ActionScript, serves only a secondary role in ActionScript 3.0. The primary inheritance mechanism, fixed property inheritance, is handled internally by the traits object. A fixed property is a variable or method that is defined as part of a class definition.
-
Unlike fixed property inheritance, however, prototype inheritance does not require the override keyword if you want to redefine a method in a subclass. For example. if you want to redefine the valueOf() method in a subclass of the Object class, you have three options. First, you can define a valueOf() method on the subclass’s prototype object inside the class definition.
-
The AS3 namespace The existence of two separate inheritance mechanisms, fixed property inheritance and prototype inheritance, creates an interesting compatibility challenge with respect to the properties and methods of the core classes. Compatibility with the ECMAScript, Edition 4 draft language specification requires the use of prototype inheritance, which means that the properties and methods of a core class are defined on the prototype object of that class.
-
ActionScript 3.0 also provides compiler options for each set of properties so that you can apply the AS3 namespace to your entire program. The -as3 compiler option represents the AS3 namespace, and the -es compiler option represents the prototype inheritance option (es stands for ECMAScript). To open the AS3 namespace for your entire program, set the -as3 compiler option to true, and the -es compiler option to false. To use the prototype versions, set the compiler options to the opposite values.
-
File Description com/example/programmingas3/ geometricshapes/RegularPolygon.as A type of geometric shape that has sides of equal length postioned symmetrically around the shape’s center. com/example/programmingas3/ geometricshapes/Circle.as A type of geometric shape that defines a circle. com/example/programmingas3/ geometricshapes/EquilateralTriangle.as A subclass of RegularPolygon that defines a triangle with all sides the same length. com/example/programmingas3/ geometricshapes/Square.
-
The classes and interfaces that define the geometric shapes in this example are shown in the following diagram using Unified Modeling Language (UML) notation: GeometricShapes Example Classes << interface>> << interface>> IGeometricShape IPolygon +getArea (): Number +getPerimeter (): Number +describe(): String +getSumOfAngles (): Number Circle RegularPolygon +diameter : Number +numSides : int +sideLength : Number +Circle (): Circle +getArea (): Number +RegularPolygon ():RegularPolygon +describ
-
} } The interface defines two methods: the getArea() method, which calculates and returns the area of the shape, and the describe() method, which assembles a text description of the shape’s properties. We also want to know the distance around the perimeter of each shape. However, the perimeter of a circle is called the circumference and it’s calculated in a unique way, so the behavior diverges from that of a triangle or a square.
-
{ // The formula is Pi * radius^2. return Math.PI * ((diameter / 2)^2); } public function getCircumference():Number { // The formula is Pi * radius * 2. return Math.PI * diameter; } public function describe():String { var desc:String = "This shape is a Circle.\n"; desc += "Its diameter is " + diameter + " pixels.\n"; desc += "Its area is " + getArea() + ".\n"; desc += "Its circumference is " + getCircumference() + ".
-
public function getArea():Number { // This method should be overridden in subclasses. return 0; } public function getPerimeter():Number { return sideLength * numSides; } public function getSumOfAngles():Number { if (numSides >= 3) { return ((numSides - 2) * 180); } else { return 0; } } public function describe():String { var desc:String = "Each side is " + sideLength + " pixels long.\n"; desc += "Its area is " + getArea() + " pixels square.\n"; desc += "Its perimeter is " + getPerimeter() + " pixels long.
-
The following code for the EquilateralTriangle class show how the getArea() method is overridden: package com.example.programmingas3.geometricshapes { public class EquilateralTriangle extends RegularPolygon { public function EquilateralTriangle(len:Number = 100):void { super(len, 3); } public override function getArea():Number { // The formula is ((sideLength squared) * (square root of 3)) / 4. return ( (this.sideLength * this.sideLength) * Math.
-
The describe() method also uses the super() statement, but in a different way—to invoke the RegularPolygon superclass’ version of the describe() method. The EquilateralTriangle.describe() method first sets the desc string variable to a statement about the type of shape. Then it gets the results of the RegularPolygon.describe() method by calling super.describe(), and it appends that result to the desc string.
-
{ switch (shapeName) { case "Triangle": return new EquilateralTriangle(len); case "Square": return new Square(len); case "Circle": return new Circle(len); } return null; } public static function describeShape(shapeType:String, shapeSize:Number):String { GeometricShapeFactory.currentShape = GeometricShapeFactory.createShape(shapeType, shapeSize); return GeometricShapeFactory.currentShape.
-
Say that you wanted to add a new shape, a pentagon, to this example application. You would create a new Pentagon class that extends the RegularPolygon class and defines its own versions of the getArea() and describe() methods. Then you would add a new Pentagon option to the combo box in the application’s user interface. But that’s it. The Pentagon class would automatically get the functionality of the getPerimeter() method and the getSumOfAngles() method from the RegularPolygon class by inheritance.
-
Object-Oriented Programming in ActionScript
-
5 CHAPTER 5 Display Programming Display programming in ActionScript 3.0 allows you to work with elements that appear on the Stage of Adobe Flash Player 9. This chapter describes the basic concepts for working with onscreen elements. You’ll learn the details about programmatically organizing visual elements. You’ll also learn about creating your own custom classes for display objects. Contents Understanding the display architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
Understanding the display architecture Each application built with ActionScript 3.0 has a hierarchy of displayed objects known as the display list. The display list contains all the visible elements in the application. Display elements fall into one or more of the following groups: ■ The Stage The Stage is the base container of display objects. Each application has one Stage object, which contains all onscreen display objects.
-
You can access the Stage through the stage property of any DisplayObject instance. For more information, see “Setting Stage properties” on page 173. ■ Display objects In ActionScript 3.0, all elements that appear on screen in an application are types of display objects. The flash.display package includes a DisplayObject class, which is a base class extended by a number of other classes.
-
Core display classes The ActionScript 3.0 flash.display package includes classes for visual objects that can appear in Flash Player. The following illustration shows the subclass relationships of these core display object classes. AVM1Movie Bitmap DisplayObjectContainer Loader Sprite InteractiveObject MorphShape SimpleButton TextField Shape StaticText Stage MovieClip The illustration shows the class inheritance of display object classes.
-
■ Sprite—A Sprite object can contain graphics of its own, and it can contain child display objects. (The Sprite class extends the DisplayObjectContainer class). For more information, see “Working with display object containers” on page 168 and “Drawing vector graphics” on page 176. ■ MovieClip—A MovieClip object is similar to a Sprite object, except that it also has a timeline. For more information, see “Controlling ActionScript 3.0 movie clips” on page 183.
-
Advantages of the ActionScript 3.0 display list approach In ActionScript 3.0, there are separate classes for different types of display objects. In ActionScript 1.0 and 2.0, many of the same types of objects are all included in one class: the MovieClip class.
-
In ActionScript 3.0, when you move a display object to a new position in the child list of a DisplayObjectContainer instance, the other children in the display object container are repositioned automatically and assigned appropriate child index positions in the display object container. Also, in ActionScript 3.0 it is always possible to discover all of the child objects of any display object container.
-
You can use off-list display objects to assemble complex display objects, such as those that have multiple display object containers containing multiple display objects. By keeping display objects off-list, you can assemble complicated objects without using the processing time to render these display objects. You can then add an off-list display object to the display list when it is needed.
-
Working with display objects Now that you understand the basic concepts of the Stage, display objects, display object containers, and the display list, this section provides you with some more specific information about working with display objects in ActionScript 3.0. Properties and methods of the DisplayObject class All display objects are subclasses of the DisplayObject class, and as such they inherit the properties and methods of the DisplayObject class.
-
Any display objects that you create without using ActionScript—for example, by adding an MXML tag in Adobe Flex Builder 2 or by using a drawing tool in Flash—are added to the display list. Although you do not add these display objects through ActionScript, you can access them through ActionScript. For example, the following code adjusts the width of an object named button1 that was added in the authoring tool (not through ActionScript): button1.
-
myTextField.text = "hello"; this.root.addChild(myTextField); In this code sample, this.root points to the MovieClip display object container that contains the code. In your actual code, you may specify a different container. Use the addChildAt() method to add the child to a specific position in the child list of the display object container. These zero-based index positions in the child list relate to the layering (the front-to-back order) of the display objects.
-
You can use the getChildAt() method to verify the layer order of the display objects. The getChildAt() method returns child objects of a container based on the index number you pass it. For example, the following code reveals names of display objects at different positions in the child list of the container DisplayObjectContainer object: trace(container.getChildAt(0).name); // ball_A trace(container.getChildAt(1).name); // ball_C trace(container.getChildAt(2).
-
Recall that a display object that is off the display list—one that is not included in a display object container that is a child of the Stage—is known as an off-list display object. Traversing the display list As you’ve seen, the display list is a tree structure. At the top of the tree is the Stage, which can contain multiple display objects. Those display objects that are themselves display object containers can contain other display objects, or display object containers.
-
var url:URLRequest = new URLRequest("banana.jpg"); pict.load(url); pict.name = "banana loader"; container.addChild(title); container.addChild(pict); The getChildAt() method returns the child of the display list at a specific index position: trace(container.getChildAt(0) is TextField); // true You can also access child objects by name. Each display object has a name property, and if you don’t assign it, Flash Player assigns a default value, such as "instance1".
-
If you use Flex, you should know that Flex defines many component display object classes, and these classes override the display list access methods of the DisplayObjectContainer class. For example, the Container class of the mx.core package overrides the addChild() method and other methods of the DisplayObjectContainer class (which the Container class extends).
-
In addition, a user can choose to leave full-screen mode by switching focus to a different window or by pressing one of several key combinations: the escape key (all platforms), ctrl-w (Windows), cmd-w (Mac), or alt-F4 (Windows). Stage scaling behavior for full-screen mode is the same as under normal mode; the scaling is controlled by the Stage class’s scaleMode property. As always, if the scaleMode property is set to StageScaleMode.
-
If you are using JavaScript in a web page to generate the SWF-embedding tags, you must alter the JavaScript to add the allowFullScreen param tag/attribute. For example, if your HTML page uses the AC_FL_RunContent() function (which is used by both Flex Builder- and Flash-generated HTML pages) you should add the allowFullScreen parameter to that function call as follows: AC_FL_RunContent( ...
-
When Flash Player dispatches an event object, that event object makes a round-trip journey from the Stage to the display object where the event occurred. For example, if a user clicks on a display object named child1, Flash Player dispatches an event object from the Stage through the display list hierarchy down to the child1 display object.
-
The Graphics class includes the following methods for easily drawing simple shapes: drawCircle(), drawEllipse(), drawRect(), drawRoundRect(), and drawRoundRectComplex(). Before calling drawing methods, define the line style, fill, or both by calling the linestyle(), lineGradientStyle(), beginFill(), beginGradientFill(), or beginBitmapFill() method.
-
Working with text The TextField class, which is in the flash.text package, lets you work with dynamic and input text fields. Note that there is also a StaticText class in the flash.text package. However, you cannot instantiate StaticText objects in ActionScript; these are created in the Flash authoring tool. As the following example shows, you can use a TextFormat object to set formatting for an entire TextField or for a range of text: var tf:TextField = new TextField(); tf.
-
Loading content dynamically You can load any of the following external display assets into an ActionScript 3.0 application: ■ A SWF file authored in ActionScript 3.0—This file can be a Sprite, MovieClip, or any class that extends Sprite. ■ An image file—This includes JPG, PNG, and GIF files. ■ An AVM1 SWF file—This is a SWF file written in ActionScript 1.0 or 2.0. You load these assets by using the Loader class.
-
The LoaderInfo class Once the file has loaded, a LoaderInfo object is created. This object is a property of both the Loader object and the loaded display object. The LoaderInfo object is a property of the Loader object through the contentLoaderInfo property of the Loader object. It is a property of the loaded display object through the display object’s loaderInfo property.
-
The following diagram shows the different uses of the LoaderInfo object—for the instance of the main class of the SWF file, for a Loader object, and for an object loaded by the Loader object: Stage LoaderInfo object loaderInfo property Instance of the main class of the SWF file Loader object contentLoaderInfo property LoaderInfo object content loaderInfo property The LoaderContext class When you load an external file into Flash Player through the load() or loadBytes() method of the Loader class, you
-
■ securityDomain—Use this property only when loading a SWF file (not an image). Specify this for a SWF file from a domain other than that of the file containing the Loader object. When you specify this option, Flash Player checks for the existence of a crossdomain policy file, and if one exists, SWF files from the domains permitted in the crosspolicy file can cross-script the loaded SWF content. You can specify flash.system.SecurityDomain.currentDomain as this parameter.
-
Controlling ActionScript 3.0 movie clips Each MovieClip object has a timeline, and also includes properties and methods for controlling the playhead and working with frames and scenes. Many properties and methods of the ActionScript 1.0 and 2.0 MovieClip class are present as properties or methods of the ActionScript 3.0 MovieClip class. Some are inherited from a superclass.
-
Creating and manipulating bitmaps The BitmapData class lets you manipulate the pixels of a Bitmap object. This can be a bitmap that you loaded from a file, or one that you draw exclusively through one of the BitmapData methods. Each Bitmap object has a bitmapData property that is a BitmapData object. A BitmapData object represents a rectangular array of pixels. You can create a new bitmap programmatically.
-
{ upState = new TextButtonState(0xFFFFFF, txt); downState = new TextButtonState(0xCCCCCC, txt); hitTestState = upState; overState = upState; addEventListener(MouseEvent.CLICK, buttonClicked); } public function buttonClicked(e:Event) { trace("Button clicked."); } } The hitTestState property of a SimpleButton object is a DisplayObject instance that responds to the mouse events for the button.
-
Working with video The Video class is not in the flash.display package, but it is a subclass of the DisplayObject class. To have a video attached to the Video object, you must use the attachNetStream() method or the attachCamera() method. Here is a simple example that attaches a net stream to a video and adds the video to the Sprite display object container: import flash.display.Sprite; import flash.net.*; import flash.media.
-
Example: SpriteArranger The SpriteArranger example application builds upon the Geometric Shapes example application described in Chapter 4 (see “Example: GeometricShapes” on page 148).
-
File Description com/example/programmingas3/ A subclass of RegularPolygon that defines a triangle geometricshapes/EquilateralTriangle.as with all sides the same length. com/example/programmingas3/ geometricshapes/Square.as A subclass of RegularPolygon defining a rectangle with all four sides the same length. com/example/programmingas3/ geometricshapes/ GeometricShapeFactory.as A class containing a “factory method” for creating shapes given a shape type and size.
-
AS the following example shows, the initCanvas() method defines various properties of the DrawingCanvas object, which were passed as arguments to the constructor function: this.lineColor = lineColor; this.fillColor = fillColor; this.width = 500; this.height = 200; The initCanvas() method then calls the drawBounds() method, which draws the canvas using the DrawingCanvas class’s graphics property. The graphics property is inherited from the Shape class. this.graphics.clear(); this.graphics.lineStyle(1.
-
The GeometricSprite class and its subclasses Each display object the user can add to the canvas is an instance of one of the following subclasses of the GeometricSprite class: ■ CircleSprite ■ SquareSprite ■ TriangleSprite The GeometricSprite class extends the flash.display.Sprite class: public class GeometricSprite extends Sprite The GeometricSprite class includes a number of properties common to all GeometricSprite objects.
-
Adding display objects to the canvas When the user clicks the Add Shape button, the application calls the addShape() method of the DrawingCanvas class.
-
The interface for the application includes two text fields, selectedSpriteTxt and outputTxt. The text properties of these text fields are updated with information about the GeometricSprite objects that have been added to the canvas or selected by the user. The GeometricSprite class handles this information-reporting task by overriding the toString() method, as follows: public override function toString():String { return this.shapeType + “ of size “ + this.size + " at " + this.x + ", " + this.
-
this.selectionIndicator.graphics.drawRect(-1, -1, this.size + 1, this.size + 1); this.addChild(this.selectionIndicator); If this is not the first time the onMouseDown() method is called, the method simply sets the selectionIndicator shape’s visible property (inherited from the DisplayObject class), as follows: this.selectionIndicator.visible = true; The hideSelected() method hides the selectionIndicator shape of the previously selected object by setting its visible property to false.
-
Rearranging display object layering The user interface for the application includes buttons labeled Move Back, Move Down, Move Up, and Move to Front. When the user clicks one of these buttons, the application calls the corresponding method of the DrawingCanvas class: moveToBack(), moveDown(), moveUp(), or moveToFront(). For example, the moveToBack() method includes the following code: public function moveToBack(shape:GeometricSprite):void { var index:int = this.getChildIndex(shape); if (index > 0) { this.
-
PART 2 Core ActionScript 3.0 Data Types and Classes 2 This part describes the implementation of key ActionScript 3.0 classes and data types, and provides strategies for using them. The following chapters are included: Chapter 6: Working with Dates and Times . . . . . . . . . . . . . . . . . . . 197 Chapter 7: Working with Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Chapter 8: Working with Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Chapter 9: Handling Errors . .
-
-
CHAPTER 6 6 Working with Dates and Times Timing might not be everything, but it's usually a key factor in software applications. ActionScript 3.0 provides powerful ways to manage calendar dates, times, and time intervals. Two main classes provide most of this timing functionality: the Date class and the new Timer class in the flash.utils package. Contents Managing calendar dates and times . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Controlling time intervals . . . .
-
Second, if given a single numeric parameter, the Date() constructor treats that as the number of milliseconds since January 1, 1970, and returns a corresponding Date object. Note that the millisecond value you pass in is treated as milliseconds since January 1, 1970, in UTC. However, the Date object shows values in your local time zone, unless you use the UTCspecific methods to retrieve and display them.
-
■ The day property, which is the day of the week in numeric format, with 0 standing for Sunday ■ The hours property, in the range of 0 to 23 ■ The minutes property ■ The seconds property ■ The milliseconds property In fact, the Date class gives you a number of ways to get each of these values.
-
Now it is easy to perform date arithmetic using standard time units. The following code sets a date value to one hour from the current time using the getTime() and setTime() methods: var oneHourFromNow:Date = new Date(); oneHourFromNow.setTime(oneHourFromNow.getTime() + millisecondsPerHour); Another way to set a date value is to create a new Date object using a single milliseconds parameter.
-
Controlling time intervals When you develop applications using the Flash authoring tool, you have access to the timeline, which provides a steady, frame-by-frame progression through your application. In pure ActionScript projects, however, you must rely on other timing mechanisms. Loops versus timers In some programming languages, you must devise your own timing schemes using loop statements like for or do..while.
-
Here is a small sample application showing the Timer class in action: package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; public class ShortTimer extends Sprite { public function ShortTimer() { // creates a new five-second Timer var minuteTimer:Timer = new Timer(1000, 5); // designates listeners for the interval and completion events minuteTimer.addEventListener(TimerEvent.TIMER, onTick); minuteTimer.addEventListener(TimerEvent.
-
When you run this sample, you should see the following lines appear in your console or trace window at the rate of one line per second: tick 1 tick 2 tick 3 tick 4 tick 5 Time's Up! Timing functions in the flash.utils package ActionScript 3.0 contains a number of timing functions similar to those that were available in ActionScript 2.0. These functions are provided as package-level functions in the flash.utils package, and they operate just as they did in ActionScript 2.0.
-
Example: Simple analog clock A simple analog clock example illustrates two of the date and time concepts discussed in this chapter: ■ Getting the current date and time and extracting values for the hours, minutes, and seconds ■ Using a Timer to set the pace of an application The SimpleClock application files can be found in the folder Samples/SimpleClock. The application consists of the following files: File Description SimpleClockApp.mxml The main application file in MXML for Flex. SimpleClockApp.
-
The class has two important properties: property, which is an instance of the AnalogClockFace class ■ The face ■ The ticker property, which is an instance of the Timer class The SimpleClock class uses a default constructor. The initClock() method takes care of the real setup work, creating the clock face and starting the Timer instance ticking. Creating the clock face The next lines in the SimpleClock code create the clock face that is used to display the time: /** * Sets up a SimpleClock instance.
-
Starting the timer After creating the clock face, the initClock() method sets up a timer: // creates a Timer that fires an event once per second ticker = new Timer(1000); // designates the onTick() method to handle Timer events ticker.addEventListener(TimerEvent.TIMER, onTick); // starts the clock ticking ticker.start(); First this method instantiates a Timer instance that will dispatch an event once per second (every 1000 milliseconds).
-
This method saves the current time in a variable, so the time can’t change in the middle of drawing the clock hands. Then it calls the showTime() method to display the hands, as the following shows: /** * Displays the given Date/Time in that good old analog clock style. */ public function showTime(time:Date):void { // gets the time values var seconds:uint = time.getSeconds(); var minutes:uint = time.getMinutes(); var hours:uint = time.getHours(); // multiplies by 6 to get degrees this.secondHand.
-
Working with Dates and Times
-
7 CHAPTER 7 Working with Strings The String class contains methods that let you work with text strings. Strings are important in working with many objects. The methods described in this chapter are useful in working with strings used in objects such as TextField, StaticText, XML, ContextMenu, and FileReference objects. Strings are sequences of characters. ActionScript 3.0 supports ASCII and Unicode characters. Contents Creating strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
var str2:String = new String(str1); var str3:String = new String(); // str3 == null The following two strings are equivalent: var str1:String = "hello"; var str2:String = new String("hello"); To use single quotation marks (') within a string literal defined with single quotation mark (') delimiters, use the backslash escape character (\). Similarly, to use double quotation marks (") within a string literal defined with double quotation marks (") delimiters, use the backslash escape character (\).
-
The length property Every string has a length property, which is equal to the number of characters in the string: var str:String = "macromedia"; trace(str.length); // 10 An empty string and a null string both have a length of 0, as the following example shows: var str1:String = new String(); trace(str1.length); // 0 str2:String = ''; trace(str2.length); // 0 Working with characters in strings Every character in a string has an index position in the string (an integer).
-
You can also use character codes to define a string using the fromCharCode() method, as the following example shows: var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33); // Sets myStr to "hello world!" Comparing strings You can use the following operators to compare strings: <, <=, !=, ==, =>, and >.
-
Obtaining string representations of other objects You can obtain a String representation for any kind of object. All objects have a toString() method for this purpose: var n:Number = 99.47; var str:String = n.toString(); // str == "99.47" When using the + concatenation operator with a combination of String objects and objects that are not strings, you do not need to use the toString() method. For details on concatenation, see the next section.
-
str = str + area; // str == "Area = 28.274333882308138" However, you can use parentheses for grouping to provide context for the + operator, as the following example shows: trace("Total: //"Total: trace("Total: //"Total: $" + 4.55 + 1.45); $4.551.45" $" + (4.55 + 1.45)); $6" Finding substrings and patterns in strings Substrings are sequential characters within a string. For example, the string "abc" has the following substrings: "", "a", "ab", "abc", "b", "bc", "c".
-
The slice() method functions similarly to the substring() method. When given two nonnegative integers as parameters, it works exactly the same. However, the slice() method can take negative integers as parameters, in which case the character position is taken from the end of the string, as shown in the following example: var str:String = "Hello from Paris, Texas!!!"; trace(str.slice(11,15)); // Pari trace(str.slice(-3,-1)); // !! trace(str.slice(-3,26)); // !!! trace(str.slice(-3,str.
-
Creating an array of substrings segmented by a delimiter You can use the split() method to create an array of substrings, which is divided based on a delimiter. For example, you can segment a comma-delimited or tab-delimited string into multiple strings. The following example shows how to split an array into substrings with the ampersand (&) character as the delimiter: var queryStr:String = "first=joe&last=cheng&title=manager&StartDate=3/6/ 65"; var params:Array = queryStr.
-
Finding matching substrings The search() method returns the index position of the first substring that matches a given pattern, as shown in this example: var str:String = "The more the merrier."; trace(str.search("the")); // output: 9 // (This search is case-sensitive.) You can also use regular expressions to define the pattern to match, as this example shows: var pattern:RegExp = /the/i; var str:String = "The more the merrier."; trace(str.
-
Replacing matched substrings You can use the replace() method to search for a specified pattern in a string and replace matches with the specified replacement string, as the following example shows: var str:String = "She sells seashells by the seashore."; var pattern:RegExp = /sh/gi; trace(str.replace(pattern, "sch")); //sche sells seaschells by the seaschore.
-
function usdToEuro(matchedSubstring:String, capturedMatch1:String, index:int, str:String):String { var usd:String = capturedMatch1; usd = usd.replace(",", ""); var exchangeRate:Number = 0.853690; var euro:Number = usd * exchangeRate; const euroSymbol:String = String.fromCharCode(8364); return euro.toFixed(2) + " " + euroSymbol; } When you use a function as the second parameter of the replace() method, the following arguments are passed to the function: ■ The matching portion of the string.
-
Example: ASCII Art This ASCII Art example shows a number of features of working with the String class in ActionScript 3.0, including the following: ■ The split() method of the String class is used to extract values from a characterdelimited string (image information in a tab-delimited text file).
-
The ASCIIArt application files can be found in the folder Samples/AsciiArt. The application consists of the following files: File Description AsciiArtApp.mxml The user interface for the application in MXML for Flex. com/example/programmingas3/asciiArt/ AsciiArtBuilder.as The class that provides the main functionality of the application, including extracting image metadata from a text file, loading the images, and managing the image-to-text conversion process.
-
The file uses a specific tab-delimited format. The first line (row) is a heading row. The remaining lines contain the following data for each bitmap to be loaded: ■ The filename of the bitmap. ■ The display name of the bitmap. ■ The white-threshold and black-threshold values for the bitmaps. These are hex values above which and below which a pixel is to be considered completely white or completely black.
-
Using String methods to normalize image titles One of the design decisions for this application is that all the image titles are displayed using a standard format, with the first letter of each word capitalized (except for a few words which are commonly not capitalized in English titles). Rather than assume that the text file contains properly formatted titles, the application formats the titles while they’re being extracted from the text file.
-
As its name suggests, the capitalizeFirstLetter() method actually does the work of capitalizing the first letter of each word: /** * Capitalizes the first letter of a single word, unless it's one of * a set of words that are normally not capitalized in English. */ private function capitalizeFirstLetter(word:String):String { switch (word) { case "and": case "the": case "in": case "an": case "or": case "at": case "of": case "a": // Don't do anything to these words.
-
3. The remaining characters of the original word are extracted using substring(1), which extracts a substring starting at index 1 (the second letter) through the end of the string (indicated by leaving off the second parameter of the substring() method). 4. The final word is created by combining the newly capitalized first letter with the remaining letters using string concatenation: firstLetter + otherLetters.
-
This code first defines a String instance named result that will be used to build up the ASCII art version of the bitmap image. Next, it loops through individual pixels of the source bitmap image. Using several color-manipulation techniques (omitted here for brevity), it converts the red, green, and blue color values of an individual pixel to a single grayscale value (a number from 0 to 255).
-
8 CHAPTER 8 Working with Arrays Arrays allow you to store multiple values in a single data structure. You can use simple indexed arrays that store values using fixed ordinal integer indexes or complex associative arrays that store values using arbitrary keys. Arrays can also be multidimensional, containing elements that are themselves arrays. This chapter discusses how to create and manipulate various types of arrays. Contents Indexed arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
var myArray:Array = ["one", "two", "three"]; trace(myArray); // output: one,two,three The Array class also contains properties and methods that allow you to modify indexed arrays. These properties and methods apply almost exclusively to indexed arrays rather than associative arrays. Indexed arrays use an unsigned 32-bit integer for the index number. The maximum size of an indexed array is 232-1 or 4,294,967,295. An attempt to create an array that is larger than the maximum size results in a run-time error.
-
Third, if you call the constructor and pass a list of elements as parameters, an array is created with elements corresponding to each of the parameters. The following code passes three arguments to the Array constructor: var names:Array = new Array("John", "Jane", "David"); trace(names.length); // output: 3 trace(names[0]); // output: John trace(names[1]); // output: Jane trace(names[2]); // output: David You can also create arrays with array literals or object literals.
-
Removing array elements Three methods of the Array class—pop(), shift(), and splice()—allow you to remove elements from an array. The pop() method removes an element from the end of the array. In other words, it removes the element at the highest index number. The shift() method removes an element from the beginning of the array, which means that it always removes the element at index number 0.
-
trace(oceans[2]); // output: undefined trace(oceans.length); // output: 5 You can truncate an array using an array’s length property. If you set the length property of an array to a length that is less than the current length of the array, the array is truncated, removing any elements stored at index numbers higher than the new value of length minus 1.
-
You may find that you need to sort your array without regard to case, or in descending order, or perhaps your array contains numbers that you want to sort numerically instead of alphabetically. The sort() method has an options parameter that allows you to alter each characteristic of the default sort order. The options are defined by a set of static constants in the Array class, as shown in the following list: ■ ■ Array.CASEINSENSITIVE: This option makes the sort disregard case.
-
{ return 1; } else { return 0; } } trace(names); // output: John Q. Smith,Jane Doe,Mike Jones names.sort(orderLastName); trace(names); // output: Jane Doe,Mike Jones,John Q. Smith The custom sort function orderLastName() uses a regular expression to extract the last name from each element to use for the comparison operation. The function identifier orderLastName is used as the sole parameter when calling the sort() method on the names array.
-
{ trace(poets[i].name, poets[i].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */ Generally, the sort() and sortOn() methods modify an array. If you wish to sort an array without modifying the existing array, pass the Array.RETURNINDEXEDARRAY constant as part of the options parameter. This option directs the methods to return a new array that reflects the sort and to leave the original array unmodified.
-
Querying an array The remaining four methods of the Array class—concat(), join(), slice(), toString()—all query the array for information, but do not modify the array. The concat() and slice() methods both return new arrays, while the join() and toString() methods both return strings. The concat() method takes a new array or list of elements as arguments and combines it with the existing array to create a new array.
-
One issue to be aware of with the join() method is that any nested arrays are always returned with comma-separated values, no matter what separator you specify for the main array elements, as the following example shows: var nested:Array = ["b","c","d"]; var letters:Array = ["a",nested,"e"]; var joined:String = letters.
-
After the array is created using either an object literal or the Object class constructor, you can add new values to the array using either the bracket operator ([]) or the dot operator (.). The following example adds two new values to monitorArray: monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces monitorInfo.colors = "16.7 million"; trace (monitorInfo["aspect ratio"], monitorInfo.colors); // output: 16:10 16.7 million Note that the key named aspect ratio contains a space character.
-
The following code creates three instances of the Sprite class that serve as keys for the Dictionary object. Each key is assigned a value of either GroupA or GroupB. The values can be of any data type, but in this example both GroupA and GroupB are instances of the Object class. Subsequently, you can access the value associated with each key with the property access ([]) operator, as shown in the following code: import flash.display.Sprite; import flash.utils.
-
Use the for..in loop for direct access to the object keys of a Dictionary object. You can also access the values of the Dictionary object with the property access ([]) operator. The following code uses the previous example of the groupMap dictionary to show how to iterate through a Dictionary object with the for..
-
If you use myObject as a key in a Dictionary object, you are creating another reference to the original object. For example, the following code creates two references to an object—the myObject variable, and the key in the myMap object: import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(); myMap[myObject] = "foo"; To make the object referenced by myObject eligible for garbage collection, you must remove all references to it.
-
Two indexed arrays When you use two indexed arrays, you can visualize the result as a table or spreadsheet. The elements of the first array represent the rows of the table, while the elements of the second array represent the columns. For example, the following multidimensional array uses two indexed arrays to track task lists for each day of the week. The first array, masterTaskList, is created using the Array class constructor.
-
Associative array with an indexed array To make the individual arrays easier to access, you can use an associative array for the days of the week and an indexed array for the task lists. Using an associative array allows you to use dot syntax when referring to a particular day of the week, but at the cost of extra run time processing to access each element of the associative array.
-
Cloning arrays The Array class has no built-in method for making copies of arrays. You can create a shallow copy of an array by calling either the concat() or slice() methods with no arguments. In a shallow copy, if the original array has elements that are objects, only the references to the objects are copied rather than the objects themselves. The copy points to the same objects as the original does. Any changes made to the objects are reflected in both arrays.
-
As mentioned previously, arrays in ActionScript are not typed, but you can create a subclass of Array that accepts elements of only a specific data type. The example in the following sections defines an Array subclass named TypedArray that limits its elements to values of the data type specified in the first parameter. The TypedArray class is presented merely as an example of how to extend the Array class and may not be suitable for production purposes for several reasons.
-
The four overridden methods all use the AS3 namespace instead of the public attribute because this example assumes that the compiler option -as3 is set to true and the compiler option -es is set to false. These are the default settings for Adobe Flex Builder 2 and for Adobe Flash CS3 Professional. For more information, see “The AS3 namespace” on page 147.
-
{ this[i] = args[i] } } } } The TypedArray constructor shares most of the code from the Array constructor, with only four changes to the code. First, the parameter list includes a new required parameter of type Class that allows specification of the array’s data type. Second, the data type passed to the constructor is assigned to the dataType variable.
-
TypedArray overridden methods The TypedArray class overrides the four methods of the Array class that are capable of adding elements to an array. In each case, the overridden method adds a type check that prevents the addition of elements that are not the correct data type. Subsequently, each method calls the superclass version of itself. The push() method iterates through the list of arguments with a for..in loop and does a type check on each argument.
-
The splice() method takes an arbitrary list of arguments, but the first two arguments always refer to an index number and the number of elements to delete. This is why the overridden splice() method does type checking only for args array elements in index positions 2 or higher. One point of interest in the code is that there appears to be a recursive call to splice() inside the for loop, but this is not a recursive call because args is of type Array rather than TypedArray, which means that the call to args.
-
Example: PlayList The PlayList example demonstrates techniques for working with arrays, in the context of a music playlist application that manages a list of songs. These techniques are: ■ Creating an indexed array ■ Adding items to an indexed array ■ Sorting an array of objects by different properties, using different sorting options ■ Converting an array to a character-delimited string The PlayList application files can be found in the Samples/PlayList folder.
-
As with all objects, declaring an Array instance is only half the job of creating an Array. Before accessing an Array instance’s properties or methods, it must be instantiated, which is done in the PlayList class’s constructor. public function PlayList() { this._songs = new Array(); // Set the initial sorting. this.sortList(SortProperty.TITLE); } The first line of the constructor instantiates the _songs variable, so that it is ready to be used.
-
Sorting the list of songs Because the Song instances that are managed by the playlist are complex objects, users of the application may wish to sort the playlist according to different properties, such as song title or year of publication. In the PlayList application, the task of sorting the list of songs has three parts: identifying the property by which the list should be sorted, indicating what sorting options need to be used when sorting by that property, and performing the actual sort operation.
-
Sorting by property and specifying sort options The work of actually sorting the list of songs is performed by the PlayList class in the sortList() method, as follows: /** * Sorts the list of songs according to the specified property. */ public function sortList(sortProperty:SortProperty):void { ... var sortOptions:uint; switch (sortProperty) { case SortProperty.TITLE: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.ARTIST: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.
-
Combining array elements into a character-delimited string In addition to using an array to maintain the song list in the PlayList class, in this example arrays are also used in the Song class to help manage the list of genres to which a given song belongs. Consider this snippet from the Song class’s definition: private var _genres:String; public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) { ...
-
Working with Arrays
-
9 CHAPTER 9 Handling Errors To “handle” an error means you build logic into your application that responds to, or fixes, an error, generated either when an application is compiled or when a compiled application is running. When your application handles errors, something occurs as a response when the error is encountered, as opposed to no response and whatever process created the error failing silently.
-
Types of errors When you develop and run applications, you encounter different types of errors and error terminology. The following list introduces the major error types and terms: ■ Compile-time errors are raised by the ActionScript compiler during code compilation. Compile-time errors occur when syntactical problems in your code prevent your application from being built. ■ Run-time errors occur when you run your application after you compile it.
-
■ Asynchronous errors are run-time errors that occur at various points during run time; they generate events and are caught by event listeners. An asynchronous operation is one in which a function initiates an operation, but doesn’t wait for it to complete. You can create an error event listener to wait for the application or user to try some operation, and if the operation fails, you catch the error with an event listener and respond to the error event.
-
■ Uncaught exceptions are errors thrown with no corresponding logic (like a catch statement) to respond to them. If your application throws an error, and no appropriate catch statement or event handler can be found at the current or higher level to handle the error, the error is considered an uncaught exception.
-
ActionScript 3.0 error handling elements ActionScript 3.0 includes many tools for error handling, including: ■ Error classes. In compliance with the ECMAScript (ECMA-262) edition 4 draft language specification, ActionScript 3.0 includes a broad range of Error classes to expand the scope of situations that may produce error objects.
-
Error handling strategies As long as your application doesn’t encounter a problematic condition, it may still run successfully if you don’t build error handling logic into your code. However, if you don’t actively handle errors and your application does encounter a problem, your users will never know why your application fails when it does. There are different ways you can approach error handling in your application. The following list summarizes the three major options for handling errors: ■ Use try..
-
{ tf.text = error.toString(); } If the readBoolean() method threw an EOFError in the debugger version of Flash Player, the following message would be displayed in the tf text field: “EOFError: Error #2030: End of file was encountered.” The same code in a release version of Flash Player would display the following text: “EOFError: Error #2030.” In order to keep Flash Player’s resources and size to a minimum in the release version, error message strings are not present.
-
The finally statement encloses statements that will execute whether or not an error occurs in the try block. If there is no error, the statements within the finally block execute after the try block statements complete. If there is an error, the appropriate catch statement executes first, followed by the statements in the finally block. The following code demonstrates the syntax for using the try..catch..
-
throw new ArgumentError("I am an ArgumentError"); } catch (error:ArgumentError) { trace(" " + error.message); } catch (error:Error) { trace(" " + error.message); } Several methods and properties in the Flash Player API throw run-time errors if they encounter errors while they execute.
-
catch (error:uint) { throw MyError; // Catch unsigned integer errors. } catch (error:int) { throw MyError; // Catch integer errors. } catch (error:Number) { throw MyError; // Catch number errors. } catch (error:*) { throw MyError; // Catch any other error. } finally { myFunction(); // Perform any necessary cleanup here. } Notice that the catch statements are ordered so that the most specific data types are listed first.
-
1-234 ; public function SimpleError() { try { if (employee.costCenter.length() != 1) { throw new Error("Error, employee must have exactly one cost center assigned."); } } catch (error:Error) { var errorMessage:TextField = new TextField(); errorMessage.autoSize = TextFieldAutoSize.LEFT; errorMessage.textColor = 0xFF0000; errorMessage.text = error.message; addChild(errorMessage); } } } } Using a wider range of error classes and built-in compiler errors, ActionScript 3.
-
} catch (error:Error) { trace("<< Error >> " + error); } } catch (error:ApplicationError) { trace("<< catch >> " + error); } The output from the previous snippet would be the following: << << << << try >> catch >> ApplicationError: some error which will be rethrown throw >> catch >> ApplicationError: some error which will be rethrown The nested try block throws a custom ApplicationError error that is caught by the subsequent catch block.
-
The following shows an example of using AppError in your project: try { throw new AppError("Encountered Custom AppError", 29); } catch (error:AppError) { trace(error.errorID + ": " + error.message) } NO T E If you want to override the Error.toString() method in your subclass, you need to give it one ...(rest) parameter. The ECMAScript (ECMA-262) edition 3 language specification defines the Error.toString() method that way, and ActionScript 3.
-
■ Status-based error events The status-based error events are related to the netStatus and status properties of the networking and communication classes. If Flash Player encounters a problem when reading or writing data, the value of the netStatus.info.level or status.level properties (depending on the class object you’re using) is set to the value "error". You respond to this error by checking if the level property contains the value "error" in your event handler function.
-
{ myMP3.load(new URLRequest(mp3)); myMP3.play(); } catch(err:Error) { trace(err.message); // your error handling code here } myMP3.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); } private function linkHandler(linkEvent:TextEvent):void { playMP3(linkEvent.text); // your error handling code here } private function errorHandler(errorEvent:IOErrorEvent):void { trace(errorEvent.
-
public class VideoExample extends Sprite { private var videoUrl:String = "Video.flv"; private var connection:NetConnection; private var stream:NetStream; public function VideoExample() { connection = new NetConnection(); connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); connection.connect(null); } private function netStatusHandler(event:NetStatusEvent):void { if (event.info.
-
Comparing the Error classes ActionScript provides a number of predefined Error classes. Many of these classes are used by Flash Player, but you can also use the same Error classes in your own code. There are two main types of Error classes in ActionScript 3.0: ActionScript core Error classes and flash.error package Error classes. The core Error classes are prescribed by the ECMAScript (ECMA-262) edition 4 draft language specification. The flash.
-
Class name Description Notes ReferenceError A ReferenceError exception is thrown when a reference to an undefined property is attempted on a sealed (nondynamic) object. Versions of the ActionScript compiler before ActionScript 3.0 did not throw an error when access was attempted to a property that was undefined. However, because the new ECMAScript specification specifies that an error should be thrown in this condition, ActionScript 3.0 throws the ReferenceError exception.
-
Class name Description Notes TypeError The TypeError exception is thrown when the actual type of an operand is different from the expected type. For more information, see Section 15.11.6.5 of the ECMAScript specification at www.ecma-international.org/ publications/standards/Ecma262.htm, as well as Section 10.3 of the E4X specification at www.ecma-international.org/ publications/standards/Ecma357.htm.
-
ActionScript core Error classes In addition to the core ECMAScript Error classes, ActionScript adds several classes of its own for ActionScript-specific error conditions and error handling functionality. Because these classes are ActionScript language extensions to ECMAScript edition 4 draft language specification that could potentially be interesting additions to the draft specification, they are kept at the top level instead of being placed in a package like flash.error.
-
flash.error package Error classes The flash.error package contains Error classes that are considered part of the Flash Player API. In contrast to the Error classes just described, the flash.error package communicates errors events that are specific to Flash Player. Class name Description Notes EOFError An EOFError exception is thrown For example, an EOFError is thrown when one of the read methods in the when you attempt to read past IDataInput interface is called and the end of the available data.
-
Class name Description Notes MemoryError A MemoryError exception is thrown when a memory allocation request fails. By default, ActionScript Virtual Machine 2 does not impose a limit on how much memory an ActionScript program may allocate. On a desktop PC, memory allocation failures are infrequent. You see an error thrown when the system is unable to allocate the memory required for an operation.
-
Example: CustomErrors application The CustomErrors application demonstrates techniques for working with custom errors when building an application. These techniques are: ■ Validating an XML packet ■ Writing a custom error ■ Throwing custom errors ■ Notifying users when an error is thrown The CustomErrors application files can be found in the Samples/CustomError folder. The application consists of the following files: File Description CustomErrors.
-
; } The XML packet is later displayed in a TextArea component instance on the Stage. This allows you to modify the XML packet before attempting to revalidate it. When the user clicks the Validate button, the validateData() method is called. This method validates the employee XML packet using the validateEmployeeXML() method in the Validator class. The following code shows the validateData() method: public function validateData():void { try { var tempXML:XML = XML(xmlText.text); Validator.
-
If a fatal error occurs during an attempt to validate the employee XML packet, the error message is displayed in an Alert component, and the xmlText TextArea component instance and validateBtn Button component instance are disabled, as the following code shows: public function showFatalError(error:FatalError):void { var message:String = error.message + "\n\n" + "Click OK to end."; var title:String = error.getTitle(); Alert.show(message, title); status.text = "This application has ended."; this.xmlText.
-
Building a custom validator The custom Validator class contains a single method, validateEmployeeXML(). The validateEmployeeXML() method takes a single argument, employee, which is the XML packet that you wish to validate. The validateEmployeeXML() method is as follows: public static function validateEmployeeXML(employee:XML):void { // checks for the integrity of items in the XML if (employee.costCenter.length() < 1) { throw new FatalError(9000); } if (employee.costCenter.
-
The ApplicationError class’s constructor method is as follows: public function ApplicationError() { messages =
-
The final method in the ApplicationError class is toString(). This method overrides the function defined in the Error class so that you can customize the presentation of the error message. The method returns a string that identifies the specific error number and message that occurred.
-
Defining the WarningError class The WarningError class extends the ApplicationError class and is nearly identical to the FatalError class, except for a couple minor string changes and sets the error severity to ApplicationError.WARNING instead of ApplicationError.FATAL, as seen in the following code: public function WarningError(errorID:int) { id = errorID; severity = ApplicationError.WARNING; message = super.
-
Handling Errors
-
10 CHAPTER 10 Using Regular Expressions A regular expression describes a pattern that is used to find and manipulate matching text in strings. Regular expressions resemble strings, but they can include special codes to describe patterns and repetition.
-
Introduction to Regular Expressions A regular expression describes a pattern of characters. Regular expressions are typically used to verify that a text value conforms to a particular pattern (such as verifying that a user-entered phone number has the proper number of digits) or to replace portions of a text value which match a particular pattern.
-
trace(str.match(pattern)); // 337,4, 57, 33 The following methods of the String class take regular expressions as parameters: match(), replace(), search(), and split(). For more information on these methods, see “Finding patterns in strings and replacing substrings” on page 216. The RegExp class includes the following methods: test() and exec(). For more information, see “Methods for using regular expressions with strings” on page 303.
-
Do not use the backslash escape character with quotation marks in regular expressions that are defined by using the forward slash delineators. Similarly, do not use the escape character with forward slashes in regular expressions that are defined with the new constructor.
-
A metasequence, like a metacharacter, has special meaning in a regular expression. A metasequence is made up of more than one character. The following sections provide details on using metacharacters and metasequences. About metacharacters The following table summarizes the metacharacters that you can use in regular expressions: Metacharacter Description ^ (caret) Matches at the start of the string.
-
Metacharacter Description [ and ] Defines a character class, which defines possible matches for a single character: /[aeiou]/ matches any one of the specified characters. Within character classes, use the hyphen (-) to designate a range of characters: /[A-Z0-9]/ matches uppercase A through Z or 0 through 9. Within character classes, insert a backslash to escape the ] and - characters: /[+\-]\d+/ matches either + or - before one or more digits.
-
Metasequence Description \s Matches any white-space character (a space, tab, newline, or return character). \S Matches any character other than a white-space character. \t Matches the tab character. \unnnn Matches the Unicode character with the character code specified by the hexidecimal number nnnn. For example, \u263a is the smiley character. \v Matches a vertical feed character. \w Matches a word character (A–Z, a–z, 0-9, or _).
-
However, the three characters listed in the following table do function as metacharacters, with special meaning, in character classes: Metacharacter Meaning in character classes ] Defines the end of the character class. - Defines a range of characters (see “Ranges of characters in character classes” on page 292). \ Defines metasequences and undoes the special meaning of metacharacters.
-
You can also use the \xnn ASCII character code to specify a range by ASCII value. For example, the following character class matches any character from a set of extended ASCII characters (such as é and ê): /[\x80-\x9A]/ Negated character classes When you use a caret (^) character at the beginning of a character class, it negates that class— any character not listed is considered a match.
-
You can use quantifiers within parenthetical groupings that have quantifiers applied to them. For example, the following quantifier matches strings such as word and word-word-word: /\w+(-\w+)*/ By default, regular expressions perform what is known as greedy matching. Any subpattern in the regular expression (such as .*) tries to match as many characters in the string as possible before moving forward to the next part of the regular expression.
-
Alternation Use the | (bar) character in a regular expression to have the regular expression engine consider alternatives for a match. For example, the following regular expression matches any one of the words cat, dog, pig, rat: var pattern:RegExp = /cat|dog|pig|rat/; You can use parentheses to define groups to restrict the scope of the | alternator. The following regular expression matches cat followed by nap or nip: var pattern:RegExp = /cat(nap|nip)/; For more information, see “Groups” on page 295.
-
Using groups with quantifiers If you do not use a group, a quantifier applies to the character or character class that precedes it, as the following shows: var pattern:RegExp = /ab*/ ; // matches the character a followed by // zero or more occurrences of the character b pattern = /a\d+/; // matches the character a followed by // one or more digits pattern = /a[123]{1,3}/; // matches the character a followed by // one to three occurrences of either 1, 2, or 3 However, you can use a group to apply a quantifi
-
Using groups to capture substring matches When you define a standard parenthetical group in a pattern, you can later refer to it in the regular expression. This is known as a backreference, and these sorts of groups are known as capturing groups.
-
A special type of noncapturing group is the lookahead group, of which there are two types: the positive lookahead group and the negative lookahead group. Use (?= and ) to define a positive lookahead group, which specifies that the subpattern in the group must match at the position. However, the portion of the string that matches the positive lookahead group can match remaining patterns in the regular expression.
-
Flags and properties The following table lists the five flags that you can set for regular expressions. Each flag can be accessed as a property of the regular expression object. Flag Property Description g global Matches more than one match. i ignoreCase Case-insensitive matching. Applies to the A—Z and a—z characters, but not to extended characters such as É and é. m multiline With this flag set, $ and ^ can match the beginning of a line and end of a line, respectively.
-
When the g flag is set, the Sting.match() method returns multiple matches, as follows: var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/g; // The same pattern, but this time the g flag IS set. trace(str.match(pattern)); // output: she,shells,shore The i (ignoreCase) flag By default, regular expression matches are case-sensitive. When you set the i (ignoreCase) flag, case sensitivity is ignored.
-
Note that only the \n character signals the end of a line. The following characters do not: ■ Return (\r) character ■ Unicode line-separator (\u2028) character ■ Unicode paragraph-separator (\u2029) character The s (dotall) flag If the s (dotall or “dot all”) flag is not set, a dot (.) in a regular expression pattern does not match a newline character (\n). So for the following example, there is no match: var str:String = "
Test\n"; str += "Multiline
"; var re:RegExp = /.*?<\/p>/; trace(str.
-
The lastIndex property The lastIndex property specifies the index position in the string at which to start the next search. This property affects the exec() and test() methods called on a regular expression that has the g flag set to true. For example, consider the following code: var pattern:RegExp = /p\w*/gi; var str:String = "Pedro Piper picked a peck of pickled peppers."; trace(pattern.lastIndex); var result:Object = pattern.exec(str); while (result != null) { trace(pattern.lastIndex); result = pattern.
-
Methods for using regular expressions with strings The RegExp class includes two methods: exec() and test(). In addition to the exec() and test() methods of the RegExp class, the String class includes the following methods that let you match regular expressions in strings: match(), replace(), search(), and splice().
-
trace(result.index, "\t", pattern.lastIndex, "\t", result); result = pattern.exec(str); } //output: // 0 3 She // 10 19 seashells // 27 35 seashore String methods that use RegExp parameters The following methods of the String class take regular expressions as parameters: match(), replace(), search(), and split(). For more information on these methods, see “Finding patterns in strings and replacing substrings” on page 216.
-
Defining the WikiParser class The WikiParser class includes methods that convert Wiki input text into the equivalent HTML output. This is not a very robust Wiki conversion application, but it does illustrate some good uses of regular expressions for pattern matching and string conversion.
-
The parentheses in the regular expression define a capturing group, and the replace() method refers to this group by using the $1 code in the replacement string. The g (global) flag in the regular expression ensures that the replace() method replaces all matches in the string (not simply the first one).
-
The ^ and $ symbols the regular expression match the beginning and end of a line. The m (multiline) flag in the regular expression causes the regular expression to match the ^ symbol against the start of a line, not simply the start of the string. The replace() method replaces all matching substrings (empty lines) with an empty string (""). The g (global) flag in the regular expression ensures that the replace() method replaces all matches in the string (not simply the first one).
-
The call to the replace() method employs the regular expression and assembles the replacement HTML string, using backreferences. The urlToATag() method then calls the emailToATag() method, which uses similar techniques to replace e-mail patterns with HTML hyperlink strings. The regular expressions used to match HTTP, FTP, and e-mail URLs in this sample file are fairly simple, for the purposes of exemplification; there are much more complicated regular expressions for matching such URLs more correctly.
-
const euroSymbol:String = String.fromCharCode(8364); // € return euro.toFixed(2) + " " + euroSymbol; } Note that args[1] represents the captured parenthetical group matched by the usdPrice regular expression. This is the numerical portion of the U.S. dollar string: that is, the dollar amount without the $ sign. The method applies an exchange rate conversion and returns the resulting string (with a trailing € symbol instead of a leading $ symbol).
-
Using Regular Expressions
-
11 CHAPTER 11 Working with XML ActionScript 3.0 includes a group of classes based on the ECMAScript for XML (E4X) specification (ECMA-357 edition 2). These classes include powerful and easy-to-use functionality for working with XML data. Using E4X, you will be able to develop code with XML data faster than was possible with previous programming techniques. As an added benefit, the code you produce will be easier to read. This chapter describes how to use E4X to process XML data.
-
A quick introduction to XML This chapter assumes that you are familiar with basic XML concepts. However, even if you are new to XML, you may be able to get started working with basic XML methods by using the information in this chapter. As a basic introduction, consider the following XML document: PAGE 313
Since many server-side applications use XML to structure data, you can use the XML classes in ActionScript to create sophisticated rich Internet applications, such as those that connect to web services. A web service is a means to connect applications—for example, an Adobe Flash Player 9 application and an application on a web server)—through a common standard such as the Simple Object Access Protocol (SOAP).
-
Often, your application will load XML data from an external source, such as a web service or a RSS feed. However, for clarity, the examples in this chapter assign XML data as literals. As the following code shows, E4X includes some intuitive operators, such as the dot (.) and attribute identifier (@) operators, for accessing properties and attributes in the XML: trace(myXML.item[0].menuName); // Output: burger trace(myXML.item.(@id==2).menuName); // Output: fries trace(myXML.item.(menuName=="burger").
-
XML objects An XML object may represent an XML element, attribute, comment, processing instruction, or text element. An XML object is classified as having either simple content or complex content. An XML object that has child nodes is classified as having complex content. An XML object is said to have simple content if it is any one of the following: an attribute, a comment, a processing instruction, or a text node.
-
For details on these properties, see the ActionScript 3.0 Language Reference.
-
The following methods are for working with and determining certain types of XML content: ■ comments() ■ hasComplexContent() ■ hasSimpleContent() ■ nodeKind() ■ processingInstructions() ■ text() The following methods are for conversion to strings and for formatting XML objects: ■ defaultSettings() ■ setSettings() ■ settings() ■ normalize() ■ toString() ■ toXMLString() There are a few additional methods: ■ contains() ■ copy() ■ valueOf() ■ length() For details on these methods,
-
The following methods allow you to work with XMLList object attributes: ■ attribute() ■ attributes() The following methods allow you to you work with XMLList properties: ■ hasOwnProperty() ■ propertyIsEnumerable() The following methods are for working with and determining certain types of XML content: ■ comments() ■ hasComplexContent() ■ hasSimpleContent() ■ processingInstructions() ■ text() The following are for conversion to strings and for formatting the XMLList object: ■ normalize()
-
Initializing XML variables You can assign an XML literal to an XML object, as follows: var myXML:XML = - burger 3.95
- fries 1.45
As the following snippet shows, you can also use the new constructor to create an instance of an XML object from a string that contains XML data: var str:String = "- burger" + "3.
-
var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); trace(externalXML.toXMLString()); } else { trace("loader is not a URLLoader!"); } } To read XML data from a socket connection, use the XMLSocket class. For more information, see the XMLSocket entry in the ActionScript 3.0 Language Reference.
-
As the following example shows, you can also use curly brace operators ( { and } ) to pass data by reference (from other variables) when constructing XML objects: var ids:Array = [121, 122, 123]; var names:Array = [["Murphy","Pat"], ["Thibaut","Jean"], ["Smith","Vijay"]] var x:XML = new XML(""); for (var i:int = 0; i < 3; i++) { var newnode:XML = new XML(); newnode = {names[i][0]} {names[i][1]} ; x = x.
-
Traversing XML structures One of the powerful features of XML is its ability to provide complex, nested data via a linear string of text characters. When you load data into an XML object, ActionScript parses the data and loads its hierarchical structure into memory (or it sends a run-time error if the XML data is not well formed). The operators and methods of the XML and XMLList objects make it easy to traverse the structure of XML data. Use the dot (.) operator and the descendent accessor (..
-
Accessing parent and child nodes The parent() method returns the parent of an XML object. You can use the ordinal index values of a child list to access specific child objects. For example, consider an XML object myXML that has two child properties named book. Each child property named book has an index number associated with it: myXML.book[0] myXML.book[1] To access a specific grandchild, you can specify index numbers for both the child and grandchild names: myXML.book[0].
-
Accessing attributes Use the @ symbol (the attribute identifier operator) to access attributes in an XML or XMLList object, as shown in the following code: var employee:XML = Wu Erin ; trace(employee.
-
Filtering by attribute or element value You can use the parentheses operators— ( and ) —to filter elements with a specific element name or attribute value. Consider the following XML object: var x:XML = Zmed Sue Data analyst McGee Chuck Jr.
-
Similarly, the final line of following code generates an error because there is no b property of the second p element: var doc:XML =
Hello, Bob.
Hello.
; trace(doc.p.(b == 'Bob')); To avoid these errors, you can identify the properties that have the matching attributes or elements by using the attribute() and elements() methods, as in the following code: var doc:XML = Hello, Bob.
Hello.
; trace(doc.p.
-
The for..in statement lets you iterate over a set of property names in an XMLList: var total:Number = 0; for (var pname:String in myXML.item) { total += myXML.item.@quantity[pname] * myXML.item.price[pname]; } The for each..in statement lets you iterate through the properties in the XMLList: var total2:Number = 0; for each (var prop:XML in myXML.item) { total2 += prop.@quantity * prop.
-
The XML class includes the following methods for working with namespaces: addNamespace(), inScopeNamespaces(), localName(), name(), namespace(), namespaceDeclarations(), removeNamespace(), setLocalName(), setName(), and setNamespace(). The default xml namespace directive lets you assign a default namespace for XML objects. For example, in the following, both x1 and x2 have the same default namespace: var ns1:Namespace = new Namespace("http://www.example.
-
If you use the trace() method without specifying toString() or toXMLString(), the data is converted using the toString() method by default, as this code shows: var myXML:XML = - burger 3.95
; trace(myXML.item[0].menuName); // burger When using the trace() method to debug code, you will often want to use the toXMLString() method so that the trace() method outputs more complete data.
-
{ myXML.total.children()[0] = Number(myXML.total.children()[0]) + Number(item.price.children()[0]); } trace(myXML.total); // 4.35; If this code did not use the Number() function, the code would interpret the + operator as the string concatenation operator, and the trace() method in the last line would output the following: 01.003.95 Reading external XML documents You can use the URLLoader class to load XML data from a URL.
-
The RSS format is widely used to syndicate news via XML. A simple RSS data file may look like the following: Alaska - Weather http://www.nws.noaa.gov/alerts/ak.html Alaska - Watches, Warnings and Advisories - Short Term Forecast - Taiya Inlet, Klondike Highway (Alaska) http://www.nws.noaa.gov/alerts/ak.html#A18.
-
The RSSViewer application files can be found in the folder Samples/RSSViewer. The application consists of the following files: File Description RSSViewer.mxml The main application file in MXML for Flex. com/example/programmingas3/rssViewer/ A class that contains methods that use E4X to RSSParser.as traverse RSS (XML) data and generate a corresponding HTML representation. RSSData/ak.rss A sample RSS file. The application is set up to read RSS data from the web, at a Flex RSS feed hosted by Adobe.
-
Assembling XMLList data The HTML data (an XMLList object) is of the following form: itemTitle
itemDescription
More...
The first lines of the method clear the default xml namespace: default xml namespace = new Namespace(); The default xml namespace directive has function block-level scope. This means that the scope of this declaration is the buildItemHTML() method.
-
Extracting the title of the RSS feed and sending a custom event The xmlLoaded() method sets a rssTitle string variable, based on information in the source RSS XML data: rssTitle = rssXML.channel.title.
-
3 PART 3 Flash Player APIs This part provides in-depth strategies for working with important features that are implemented in packages and classes specific to Adobe Flash Player 9. The following chapters are included: Chapter 12: Flash Player API Overview . . . . . . . . . . . . . . . . . . . . . 337 Chapter 13: Handling Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 Chapter 14: Networking and Communication . . . . . . . . . . . . . . . . 371 Chapter 15: Working with Geometry . . .
-
-
12 CHAPTER 12 Flash Player API Overview This chapter describes the Adobe Flash Player 9 packages provided with the ActionScript 3.0 language. The Flash Player API refers to all packages, classes, functions, properties, constants, events, and errors that are in the flash package. They are unique to Flash Player, as opposed to the top-level classes, such as Date, Math, and XML, or the language elements, which are based on ECMAScript.
-
Contents flash.accessibility package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .338 flash.display package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .338 flash.errors package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .339 flash.events package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
In ActionScript 2.0, nearly all visual elements were controlled by the MovieClip class or handled “behind the scenes” by Flash Player. Low-level control of objects was not available. In ActionScript 3.0, the API to control visual elements is defined more logically, by functionality and usage. The flash.display package includes the following classes: ■ Basic building blocks that inherit from the DisplayObject class, such as DisplayObjectContainer and Sprite.
-
flash.external package The flash.external package contains only the ExternalInterface class, which was introduced in Flash Player 8 as a replacement for the fscommand() function. ExternalInterface enables communication between ActionScript and the Flash Player container—for example, an HTML page with JavaScript or a desktop application in which Flash Player is embedded. For more information, see “Using the External API” on page 501 and the flash.external package in the ActionScript 3.0 Language Reference.
-
flash.media package The flash.media package contains classes for working with audio and video streams that are either prerecorded or that stream from the client computer that is running Flash Player. The Sound class and its supporting classes let you work with external MP3 files and streaming sound embedded in a SWF file. The Microphone class lets you capture audio from a microphone attached to the computer. The Camera and Video classes let you capture video from a video camera attached to the computer.
-
flash.profiler package This package contains the showRedrawRegions() function, which can be useful for debugging code. For more information, see the flash.profiler package in the ActionScript 3.0 Language Reference. flash.system package The flash.system package contains classes that provide system-level functionality and let you get limited, specified information about the functions of the client computer running Flash Player.
-
flash.utils package This package provides various utility classes, such as ByteArray, which lets you access and work with data on the byte level, and the Timer class, which lets you run code on a specified time sequence. This package also contains a number of package-level functions that can control the time delay or intervals in which ActionScript code is executed. For more information, see the flash.utils package in the ActionScript 3.0 Language Reference. flash.xml package The flash.
-
Flash Player API Overview
-
13 CHAPTER 13 Handling Events An event handling system allows programmers to respond to user input and system events in a convenient way. The new ActionScript 3.0 event model is not only convenient, but also standards-compliant, and well integrated with the new Adobe Flash Player 9 display list.
-
Introduction to Event Handling You can think of events as occurrences of any kind in your SWF file that are of interest to you as a programmer. For example, most SWF files support user interaction of some sort— whether it's something as simple as responding to a mouse click or something more complex, such as accepting and processing data entered into a form. Any such user interaction with your SWF file is considered an event.
-
How ActionScript 3.0 event handling differs from earlier versions The most noticeable difference between event handling in ActionScript 3.0 and event handling in previous versions of ActionScript is that in ActionScript 3.0 there is only one system for event handling, whereas in previous versions of ActionScript there are several different event handling systems.
-
Unfortunately, the syntax used by the various event models overlap in various ways, and differ in others. For example, in ActionScript 2.0, some properties, such as TextField.onChanged, can be used as either a callback function or an event listener. However, the syntax for registering listener objects differs depending on whether you are using one of the six classes that support listeners or the UIEventDispatcher class.
-
Not all default behaviors can be prevented. For example, Flash Player generates a MouseEvent object when a user double-clicks a word in a TextField object. The default behavior, which cannot be prevented, is that the word under the cursor is highlighted. Many types of event objects do not have associated default behaviors. For example, Flash Player dispatches a connect event object when a network connection is established, but there is no default behavior associated with it.
-
The event flow Flash Player dispatches event objects whenever an event occurs. If the event target is not on the display list, Flash Player dispatches the event object directly to the event target. For example, Flash Player dispatches the progress event object directly to a URLStream object. If the event target is on the display list, however, Flash Player dispatches the event object into the display list, and the event object travels through the display list to the event target.
-
If a user clicks on Child1 Node, Flash Player dispatches an event object into the event flow. As the following image shows, the object’s journey starts at Stage, moves down to Parent Node, then moves to Child1 Node, and then “bubbles” back up to Stage, moving through Parent Node again on its journey back to Stage. Stage Capture Phase Bubbling Phase Parent Node Child1 Node Child2 Node Target Phase In this example, the capture phase comprises Stage and Parent Node during the initial downward journey.
-
To find out how a particular event type behaves, you can either check the API documentation or examine the event object's properties. Examining the event object’s properties is described in the following section. Event objects Event objects serve two main purposes in the new event handling system. First, event objects represent actual events by storing information about specific events in a set of properties.
-
Some two dozen event types are associated with the Event class itself and are represented by Event class constants, some of which are shown in the following excerpt from the Event class definition: package flash.events { public class Event { // class constants public static const ACTIVATE:String = "activate"; public static const ADDED:String = "added"; // remaining constants omitted for brevity } } These constants provide an easy way to refer to specific event types.
-
The bubbles property An event is said to bubble if its event object participates in the bubbling phase of the event flow, which means that the event object is passed from the target node back through its ancestors until it reaches the Stage. The Event.bubbles property stores a Boolean value that indicates whether the event object participates in the bubbling phase.
-
For complex SWF files, especially those in which buttons are routinely decorated with smaller child objects, the target property may not be used frequently because it will often point to a button’s child object instead of the button. In these situations, the common practice is to add event listeners to the button and use the currentTarget property because it points to the button, whereas the target property may point to a child of the button.
-
Stopping event flow You can call either the Event.stopPropogation() method or the Event.stopImmediatePropogation() method to prevent an event object from continuing on its way through the event flow. The two methods are nearly identical and differ only in whether the current node's other event listeners are allowed to execute: ■ The Event.stopPropogation() method prevents the event object from moving on to the next node, but only after any other event listeners on the current node are allowed to execute.
-
Subclasses of the Event class For many events, the common set of properties defined in the Event class is sufficient. Other events, however, have unique characteristics that cannot be captured by the properties available in the Event class. For these events, the Flash Player API defines several subclasses of the Event class. Each subclass provides additional properties and event types that are unique to that category of events.
-
In the ActionScript 3.0 event model, there is no distinction between an event listener and a listener function. ActionScript 3.0 does not have an EventListener interface, and listener functions can be defined outside a class or as part of a class. Moreover, listener functions do not have to be named handleEvent()—they can be named with any valid identifier. In ActionScript 3.0, you register the name of the actual listener function.
-
When a user interacts with the resulting SWF file by clicking on the square, Flash Player generates the following trace output: clickHandler detected an event of type: click the this keyword refers to: [object global] Notice that the event object is passed as an argument to clickHandler(). This allows your listener function to examine the event object. In this example, you use the event object's type property to ascertain that the event is a click event.
-
trace("the this keyword refers to: " + this); } } When a user interacts with the resulting SWF file by clicking on the red square, Flash Player generates the following trace output: clickHandler detected an event of type: click the this keyword refers to: [object ChildSprite] Note that the this keyword refers to the ChildSprite instance named child. This is a change in behavior from ActionScript 2.0. If you used components in ActionScript 2.
-
} } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); } } var myListenerObj:Object = new Object(); myListenerObj.clickHandler = function (event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.
-
{ public interface IEventDispatcher { function addEventListener(eventName:String, listener:Object, useCapture:Boolean=false, priority:Integer=0, useWeakReference:Boolean=false):Boolean; function removeEventListener(eventName:String, listener:Object, useCapture:Boolean=false):Boolean; function dispatchEvent(eventObject:Event):Boolean; function hasEventListener(eventName:String):Boolean; function willTrigger(eventName:String):Boolean; } } The Flash Player API implements the IEventDispatcher interface with th
-
The priority parameter of the addEventListener() method is not an official part of the DOM Level 3 event model. It is included in ActionScript 3.0 to provide you with more flexibility in organizing your event listeners. When you call addEventListener(), you can set the priority for that event listener by passing an integer value as the priority parameter. The default value is 0, but you can set it to negative or positive integer values. The higher the number, the sooner that event listener will be executed.
-
Checking for existing event listeners The final two methods of the IEventDispatcher interface provide useful information about the existence of event listeners. The hasEventListener() method returns true if an event listener is found for a specific event type on a particular display list object.
-
Example: Alarm Clock The Alarm Clock example consists of a clock that allows the user to specify a time at which an alarm will go off, as well as a message to be displayed at that time. The Alarm Clock example builds on the SimpleClock application from Chapter 6, “Working with Dates and Times.” Alarm Clock illustrates several aspects of working with events in ActionScript 3.
-
Providing notification when something happens is the job that events are made for. The AlarmClock class exposes the Alarm event, which other objects can listen for in order to perform desired actions. In addition, the AlarmClock class uses an instance of the Timer class to determine when to trigger its alarm. Like the AlarmClock class, the Timer class provides an event to notify other objects (an AlarmClock instance, in this case) when a certain amount of time has passed.
-
The Timer instance defined in the AlarmClock class is named alarmTimer. The initClock() method, which performs necessary setup operations for the AlarmClock instance, does two things with the alarmTimer variable. First, the variable is instantiated with parameters instructing the Timer instance to wait 0 milliseconds and only trigger its timer event one time.
-
This method does several things, including storing the alarm message and creating a Date object (alarmTime) representing the actual moment in time when the alarm is to go off. Of most relevance to the current discussion, in the final several lines of the method, the alarmTimer variable’s timer is set and activated. First, its reset() method is called, stopping the timer and resetting it in case it is already running.
-
Other code can register to be notified of the AlarmClock class’s alarm event by calling the addEventListener() method that AlarmClock inherits from EventDispatcher. When an AlarmClock instance is ready to notify other code that its alarm event has been raised, it does so by calling the dispatchEvent() method, which is also inherited from EventDispatcher. var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); this.
-
* @param message The text to display when the alarm goes off. */ public function AlarmEvent(message:String = "ALARM!") { super(ALARM); this.message = message; } ... } The best way to create a custom event object class is to define a class that extends the Event class, as shown in the preceding example.
-
CHAPTER 14 14 Networking and Communication The flash.net package contains classes to send and receive data across the Internet—for example, to load content from remote URLs, to communicate with other Flash Player instances, and to connect to remote websites. In earlier versions of ActionScript, many of the classes within the flash.net package were top-level classes. In ActionScript 3.0, many of these classes have been moved into the flash.net package. The flash.
-
Working with external data When you build large ActionScript applications, you often need to communicate with serverside scripts, or load data from external XML or text files. This behavior has changed significantly between ActionScript 2.0 and ActionScript 3.0. In earlier versions of ActionScript, you could load remote text files using the LoadVars class and the LoadVars.onData() event handler. In ActionScript 3.0, you can load external files with the URLLoader and URLRequest classes.
-
The URLLoader.load() method (and optionally the URLLoader class’s constructor) takes a single parameter, request, which is a URLRequest class object. A URLRequest object contains all of the information for a single HTTP request, such as the target URL, request method (GET or POST), additional header information, and the MIME type (for example, when you upload XML content). For example, to upload an XML packet to a server-side script, you could use the following ActionScript 3.
-
When you define variables within the URLVariables constructor or within the URLVariables.decode() method, you need to make sure that you URL-encode the ampersand (&) character because it has a special meaning and acts as a delimiter. For example, when you pass an ampersand, you need to URL-encode the ampersand by changing it from & to %26 because the ampersand acts as a delimiter for parameters. Loading data from external documents When you build dynamic applications with ActionScript 3.
-
Once the data has loaded, the Event.COMPLETE event is dispatched, and the contents of the external document are available to use in the URLLoader’s data property, as the following code shows: private function completeHandler(event:Event):void { var loader2:URLLoader = URLLoader(event.target); trace(loader2.
-
The following code demonstrates how setting the URLLoader.dataFormat property to URLLoaderDataFormat.VARIABLES allows you to automatically parse loaded data into a URLVariables object: package { import import import import import flash.display.Sprite; flash.events.*; flash.net.URLLoader; flash.net.URLLoaderDataFormat; flash.net.URLRequest; public class URLLoaderDataFormatExample extends Sprite { public function URLLoaderDataFormatExample() { var request:URLRequest = new URLRequest("http:// www.
-
As the following example shows, Loading XML from an external file is the same as loading URLVariables. You can create a URLRequest instance and a URLLoader instance and use them to download a remote XML document. When the file has completely downloaded, the Event.COMPLETE event is dispatched and the contents of the external file are converted to an XML instance, which you can parse using XML methods and properties. package { import import import import import flash.display.Sprite; flash.errors.*; flash.
-
Communicating with external scripts In addition to loading external data files, you can also use the URLVariables class to send variables to a server-side script and process the server’s response. This is useful, for example, if you are programming a game and want to send the user’s score to a server to calculate whether it should be added to the high scores list, or even send a user’s login information to a server for validation.
-
Connecting to other Flash Player instances The LocalConnection class lets you communicate between different Flash Player instances, such as a SWF in an HTML container or in an embedded or stand-alone player. This allows you to build very versatile applications that can share data between Flash Player instances, such as SWF files running in a web browser or embedded in C# applications.
-
There are three ways to add callback methods to your LocalConnection objects: ■ Subclass the LocalConnection class and add methods. ■ Set the LocalConnection.client property to an object that implements the methods. ■ Create a dynamic class that extends LocalConnection and dynamically attach methods. The first way to add callback methods is to extend the LocalConnection class. You define the methods within the custom class instead of dynamically adding them to the LocalConnection instance.
-
The LocalConnection.client property indicates the object callback methods that should be invoked. In the previous code, the client property was set to a new instance of a custom class, CustomClient. The default value for the client property is the current LocalConnection instance. You can use the client property if you have two data handlers that have the same set of methods but act differently—for example, in an application where a button in one window toggles the view in a second window.
-
The following code defines a local connection object that acts as a server and accepts incoming calls from other Flash Player instances: package { import flash.net.LocalConnection; import flash.display.Sprite; public class ServerLC extends Sprite { public function ServerLC() { var lc:LocalConnection = new LocalConnection(); lc.client = new CustomClient1(); try { lc.
-
} public function closeHandler(event:TimerEvent):void { fscommand("quit"); } } } To create a LocalConnection server, call the LocalConnection.connect() method and provide a unique connection name. If you already have a connection with the specified name, an ArgumentError error is generated, indicating that the connection attempt failed because the object is already connected. The following snippet demonstrates how to create a new socket connection with the name conn1: try { connection.
-
Connecting to SWF documents in different domains To allow communications only from specific domains, you call the allowDomain() or allowInsecureDomain() method of the LocalConnection class and pass a list of one or more domains that are allowed to access this LocalConnection object. In earlier versions of ActionScript, LocalConnection.allowDomain() and were callback methods that had to be implemented by developers and that had to return a Boolean value. In ActionScript 3.0, LocalConnection.
-
If you implement communication between SWF files in different domains, you specify a connectionName parameter that begins with an underscore (_). Specifying the underscore makes the SWF file with the receiving LocalConnection object more portable between domains. Here are the two possible cases: ■ If the string for connectionName does not begin with an underscore (_), Flash Player adds a prefix with the superdomain name and a colon (for example, myDomain:connectionName).
-
Socket class Introduced in ActionScript 3.0, the Socket class enables ActionScript to make socket connections and to read and write raw binary data. It is similar to the XMLSocket class, but does not dictate the format of the received and transmitted data. The Socket class is useful for interoperating with servers that use binary protocols. By using binary socket connections, you can write code that allows interaction with several different Internet protocols, such as POP3, SMTP, IMAP, and NNTP.
-
To create a socket connection, you must create a server-side application to wait for the socket connection request and send a response to the SWF file. This type of server-side application can be written in a programming language such as Java, Python, or Perl. To use the XMLSocket class, the server computer must run a daemon that understands the protocol used by the XMLSocket class. The protocol is described in the following list: ■ XML messages are sent over a full-duplex TCP/IP stream socket connection.
-
When you invoke the XMLSocket.connect() method, Flash Player opens a TCP/IP connection to the server and keeps that connection open until one of the following occurs: ■ The XMLSocket.close() method of the XMLSocket class is called. ■ No more references to the XMLSocket object exist. ■ Flash Player exits. ■ The connection is broken (for example, the modem disconnects).
-
{ socket = new ServerSocket(port); incoming = socket.accept(); readerIn = new BufferedReader(new InputStreamReader(incoming.getInputStream())); printOut = new PrintStream(incoming.getOutputStream()); printOut.println("Enter EXIT to exit.\r"); out("Enter EXIT to exit.\r"); boolean done = false; while (!done) { String str = readerIn.readLine(); if (str == null) { done = true; } else { out("Echo: " + str + "\r"); if(str.trim().equals("EXIT")) { done = true; } } incoming.
-
To connect to the XMLSocket from your ActionScript application, you need to create a new instance of the XMLSocket class, and call the XMLSocket.connect() method while passing a host name and port number, as follows: var xmlsock:XMLSocket = new XMLSocket(); xmlsock.connect("127.0.0.1", 8080); A securityError (flash.events.SecurityErrorEvent) event occurs if a call to XMLSocket.connect() attempts to connect either to a server outside the caller’s security sandbox or to a port lower than 1024.
-
New shared object instances can be created using the static SharedObject.getLocal() or SharedObject.getRemote() methods. The getLocal() method attempts to load a locally persistent shared object that is available only to the current client, whereas the getRemote() method attempts to load a remote shared object that can be shared across multiple clients by means of a server, such as Flash Media Server.
-
} trace(so.data.now); trace("SharedObject is " + so.size + " bytes"); so.flush(); When using the flush() method to write shared objects to a user’s hard drive, you should be careful to check whether the user has explicitly disabled local storage using the Flash Player Settings Manager (http://www.macromedia.com/support/documentation/en/flashplayer/ help/settings_manager07.html), as shown in the following example: var so:SharedObject = SharedObject.
-
{ trace(i + ":\t" + so.data[i]); } Creating a secure SharedObject When you create either a local or remote SharedObject using getLocal() or getRemote(), there is an optional parameter named secure that determines whether access to this shared object is restricted to SWF files that are delivered over an HTTPS connection. If this parameter is set to true and your SWF file is delivered over HTTPS, Flash Player creates a new secure shared object or gets a reference to an existing secure shared object.
-
Working with file upload and download The FileReference class lets you add the ability to upload and download files between a client and a server. Users are prompted to select a file to upload or a location for download from a dialog box (such as the Open dialog box on the Windows operating system). Each FileReference object that you create with ActionScript refers to a single file on the user’s hard disk.
-
FileReference class The FileReference class allows you to upload and download files between a user’s computer and a server. An operating system dialog box prompts the user to select a file to upload or a location for download. Each FileReference object refers to a single file on the user’s disk and has properties that contain information about the file’s size, type, name, creation date, modification date, and creator.
-
------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6 Content-Disposition: form-data; name="Filename" sushi.jpg ------------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6 Content-Disposition: form-data; name="Filedata"; filename="sushi.
-
(actual file data,,,) ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7 Content-Disposition: form-data; name="Upload" Submit Query ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7-- Uploading files to a server To upload files to a server, first call the browse() method to allow a user to select one or more files. Next, when the FileReference.upload() method is called, the selected file will be transferred to the server. If the user selected multiple files using the FileReferenceList.
-
{ var request:URLRequest = new URLRequest("http://www.[yourdomain].com/ fileUploadScript.cfm") try { fileRef.upload(request); } catch (error:Error) { trace("Unable to upload file."); } } function completeHandler(event:Event):void { trace("uploaded"); } TI P You can send data to the server with the FileReference.upload() method by using the URLRequest.method and URLRequest.data properties to send variables using the POST or GET methods. When you attempt to upload a file using the FileReference.
-
■ The url parameter contains an invalid protocol. The FileReference.upload() method must use either HTTP or HTTPS. TIP Flash Player does not offer complete support for servers that require authentication. Only SWF files that are running in a browser using the browser plug-in or ActiveX control can provide a dialog box to prompt the user to enter a user name and password for authentication, and then only for downloads.
-
$files = array(); while ($file = readdir($directory)) { array_push($files, array('./images/'.$file, filectime('./images/ '.
-
} function completeHandler(event:Event):void { trace("uploaded"); } The previous example creates a new URLVariables object that you pass to the remote serverside script. In previous versions of ActionScript, you could pass variables to the server upload script by passing values in the query string. ActionScript 3.
-
To set the default name to currentnews.xml instead of index.xml, specify the defaultFileName parameter, as the following snippet shows: var request:URLRequest = new URLRequest("index.xml"); var fileToDownload:FileReference = new FileReference(); fileToDownload.download(request, "currentnews.xml"); Renaming a file can be very useful if the server filename was not intuitive or was servergenerated.
-
The following code demonstrates the ColdFusion script, download.cfm, that downloads one of two files from the server, depending on the value of a URL variable: PAGE 404
{ var request:URLRequest = new URLRequest("http://www.[yourdomain].com/ fileUploadScript.cfm"); var file:FileReference; var files:FileReferenceList = FileReferenceList(event.target); var selectedFileArray:Array = files.fileList; for (var i:uint = 0; i < selectedFileArray.length; i++) { file = FileReference(selectedFileArray[i]); file.addEventListener(Event.COMPLETE, completeHandler); try { file.upload(request); } catch (error:Error) { trace("Unable to upload files.
-
The Telnet application files can be found in the Samples/Telnet folder. The application consists of the following files: File Description TelnetSocket.mxml The main application file consisting of the MXML user interface. com/example/programmingas3/Telnet/ Telnet.as Provides the Telnet client functionality for the application, such as connecting to a remote server, and sending, receiving, and displaying data. Telnet socket application overview The main TelnetSocket.
-
The first line of code imports the Telnet class from the custom com.example.programmingas.socket package. The second line of code declares an instance of the Telnet class, telnetClient, that will be initialized later by the connect() method. Next, the connect() method is declared and initializes the telnetClient variable declared earlier.
-
public function Telnet(server:String, port:int, output:TextArea) { serverURL = server; portNumber = port; ta = output; socket = new Socket(); socket.addEventListener(Event.CONNECT, connectHandler); socket.addEventListener(Event.CLOSE, closeHandler); socket.addEventListener(ErrorEvent.ERROR, errorHandler); socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); socket.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler); Security.loadPolicyFile("http://" + serverURL + "/crossdomain.
-
Displaying messages from the socket server Whenever a message is received from the socket server, or an event occurs, the custom msg() method is called. This method appends a string to the TextArea on the Stage and calls a custom setScroll() method, which causes the TextArea component to scroll to the very bottom. The msg() method is as follows: private function msg(value:String):void { ta.
-
The FileIO application files are found in the Samples/FileIO folder. The application consists of the following files: File Description FileIO.mxml The main application file consisting of the MXML user interface. com/example/programmingas3/fileio/ FileDownload.as A class that includes methods for downloading files from a server. com/example/programmingas3/fileio/ FileUpload.as A class that includes methods for uploading files to a server.
-
This code places a ProgressBar component instance and two Button component button instances on the Stage. When the user clicks the Upload button (startUpload), an operating system dialog box is launched that allows the user to select a file to upload to a remote server. The other button, cancelUpload, is disabled by default, although when a user begins a file upload, the button becomes enabled and allows the user to abort the file transfer at any time.
-
/** * Define reference to the download ProgressBar component. */ private var pb:ProgressBar; /** * Define reference to the "Cancel" button which will immediately stop * the current download in progress. */ private var btn:Button; The first variable, DOWNLOAD_URL, contains the path to the file, which gets downloaded onto the user’s computer when the user clicks the Download button in the main application file. The second variable, fr, is a FileReference object that gets initialized within the FileDownload.
-
Beginning the file download When the user clicks the Download Button component instance on the Stage, the startDownload() method is to initiate the file download process. The following excerpt shows the startDownload() method: /** * Begin downloading the file specified in the DOWNLOAD_URL constant. */ public function startDownload():void { var request:URLRequest = new URLRequest(); request.url = DOWNLOAD_URL; fr.
-
Monitoring a file’s download progress As a file downloads from a remote server to the user’s computer, the progress event (ProgressEvent.PROGRESS) is dispatched at regular intervals. Whenever the progress event is dispatched, the progressHandler() method is invoked and the ProgressBar component instance on the Stage is updated. The code for the progressHandler() method is as follows: /** * While the file is downloading, update the progress bar's status.
-
pb.label = "DOWNLOAD CANCELLED"; btn.enabled = false; } First, the code stops the file transfer immediately, preventing any further data from downloading. Next, the progress bar’s label property is updated to notify the user that the download has been successfully cancelled. Finally, the Cancel button is disabled, which prevents the user from clicking the button again until they attempt to download the file again.
-
Beginning a file upload The file upload is initiated when the user clicks on the Upload button on the Stage, which invokes the FileUpload.startUpload() method. This method calls the browse() method of the FileReference class which causes the operating system to display a system dialog box prompting the user to select a file to upload to the remote server. The following excerpt shows the code for the startUpload() method: public function startUpload():void { fr.
-
Networking and Communication
-
15 CHAPTER 15 Working with Geometry The flash.geom package contains classes that define geometric objects such as points, rectangles, and transformation matrixes. You use these classes to define the properties of objects that are used in other classes. Contents Using Point objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417 Using Rectangle objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
Finding the distance between two points You can use the distance() method of the Point class to find the distance between two points in a coordinate space. For example, the following code finds the distance between the registration points of two display objects, circle1 and circle2, in the same display object container: import flash.geom.*; var pt1:Point = new Point(circle1.x, circle1.y); var pt2:Point = new Point(circle2.x, circle2.y); var distance:Number = Point.
-
Moving a display object by a specified angle and distance You can use the polar() method of the Point class to move a display object a specific distance by a specific angle. For example, the following code moves the myDisplayObject object 100 pixels by 60 degrees: import flash.geom.*; var distance:Number = 100; var angle:Number = 2 * Math.PI * (90 / 360); var translatePoint:Point = Point.polar(distance, angle); myDisplayObject.x += translatePoint.x; myDisplayObject.y += translatePoint.
-
Using Rectangle objects A Rectangle object defines a rectangular area. A Rectangle object has a position, defined by the x and y coordinates of its top-left corner, a width property, and a height property. You can define these properties for a new Rectangle object by invoking the Rectangle() constructor function, as follows: import flash.geom.
-
Similarly, as the following example shows, if you change the bottom or right property of a Rectangle object, the position of its top-left corner does not change, so it is resized accordingly: import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.right = 60; trect1.
-
Finding unions and intersections of Rectangle objects You use the union() method to find the rectangular region formed by the boundaries of two rectangles: import flash.display.*; import flash.geom.Rectangle; var rect1:Rectangle = new Rectangle(0, 0, 100, 100); trace(rect1); // (x=0, y=0, w=100, h=100) var rect2:Rectangle = new Rectangle(120, 60, 100, 100); trace(rect2); // (x=120, y=60, w=100, h=100) trace(rect1.
-
Other uses of Rectangle objects Rectangle objects are used in the following methods and properties: Class Methods or properties Description BitmapData applyFilter(), colorTransform(), copyChannel(), copyPixels(), draw(), fillRect(), generateFilterRect(), getColorBoundsRect(), getPixels(), merge(), paletteMap(), pixelDissolve(), setPixels(), and threshold() Used as the type for some parameters to define a region of the BitmapData object.
-
Defining Matrix objects Although you could define a matrix by directly adjusting the properties (a, b, c, d, tx, ty) of a Matrix object, it is easier to use the createBox() method. This method includes parameters that let you directly define the scaling, rotation, and translation effects of the resulting matrix. For example, the following code creates a Matrix object that has the effect of scaling an object horizontally by 2.0, scaling it vertically by 3.
-
matrix.rotate(rotation); myDisplayObject.transform.matrix = matrix; The first line sets a Matrix object to the existing transformation matrix used by the myDisplayObject display object (the matrix property of the transformation property of the myDisplayObject display object). This way, the Matrix class methods that you call will have a cumulative effect on the display object’s existing position, scale, and rotation. NO TE The ColorTransform class is also included in the flash.geometry package.
-
The following examples show gradients in which the rotation parameter of the createGradientBox() method differs as indicated, but all other settings stay the same: width = 100; height = 100; rotation = 0; tx = 0; ty = 0; width = 100; height = 100; rotation = Math.PI/4; // 45° tx = 0; ty = 0; width = 100; height = 100; rotation = Math.
-
The following examples show the effects on a green-to-blue linear gradient in which the rotation, tx, and ty parameters of the createGradientBox() method differ as indicated, but all other settings stay the same: width = 50; height = 100; rotation = 0; tx = 0; ty = 0; width = 50; height = 100; rotation = 0 tx = 50; ty = 0; width = 100; height = 50; rotation = Math.PI/2; // 90° tx = 0; ty = 0; width = 100; height = 50; rotation = Math.
-
The following code produces the last radial gradient illustrated: import flash.display.Shape; import flash.display.GradientType; import flash.geom.Matrix; var var var var var var var type:String = GradientType.RADIAL; colors:Array = [0x00FF00, 0x000088]; alphas:Array = [1, 1]; ratios:Array = [0, 255]; spreadMethod:String = SpreadMethod.PAD; interp:String = InterpolationMethod.
-
The application provides an interface for adjusting the parameters of the matrix transformation, as follows: When the user clicks the Transform button, the application applies the appropriate transformation.
-
The DisplayObjectTransformer application files can be found in the folder Samples/ DisplayObjectTransformer. The application consists of the following files: File Description DisplayObjectTransformer.mxml The main application file in MXML for Flex. com/example/programmingas3/geometry/ A class that contains methods for applying MatrixTransformer.as matrix transformations. img/ A directory containing sample image files used by the application.
-
The skew() method The skew() method skews the matrix by adjusting the b and c properties of the matrix. An optional parameter, unit, determines the units used to define the skew angle, and if necessary, the method converts the angle value to radians: if (unit == "degrees") { angle = Math.PI * 2 * angle / 360; } if (unit == "gradients") { angle = Math.PI * 2 * angle / 100; } A skewMatrix Matrix object is created and adjusted to apply the skew transformation.
-
The translate() method The translate() method simply applies the dx and dy translation factors by calling the translate() method of the matrix object, as follows: sourceMatrix.translate(dx, dy); return sourceMatrix; The rotate() method The rotate() method converts the input rotation factor to radians (if it is provided in degrees or gradients), and then calls the rotate() method of the matrix object: if (unit == "degrees") { angle = Math.PI * 2 * angle / 360; } if (unit == "gradients") { angle = Math.
-
16 CHAPTER 16 Client System Environment The client system environment is a collection of classes in the flash.
-
Getting data about the user’s system at runtime By checking the System.totalMemory property, you can determine the amount of memory (in bytes) that Flash Player is currently using. This property allows you to monitor memory usage and optimize your applications based on how the memory level changes. For example, if a particular visual effect causes a large increase in memory usage, you may want to consider modifying the effect or eliminating it altogether. The System.
-
Capabilities class The Capabilities class allows developers to determine the environment in which a SWF file is being run. Using various properties of the Capabilities class, you can find out the resolution of the user’s system, whether the user’s system supports accessibility software, and the language of the user’s operating system, as well as the version of the currently installed Flash Player.
-
ApplicationDomain class The purpose of the ApplicationDomain class is to store a table of ActionScript 3.0 definitions. All code in a SWF file is defined to exist in an application domain. You use application domains to partition classes that are in the same security domain. This allows multiple definitions of the same class to exist and also lets children reuse parent definitions. You can use application domains when loading an external SWF file written in ActionScript 3.0 using the Loader class API.
-
} } } Other things to keep in mind when you work with application domains include the following: ■ All code in a SWF file is defined to exist in an application domain. The current domain is where your main application runs. The system domain contains all application domains, including the current domain, which means that it contains all Flash Player classes. ■ All application domains, except the system domain, have an associated parent domain.
-
The main application file is application1.swf. It contains Loader objects that load content from other SWF files. In this scenario, the current domain is Application domain 1. Usage A, usage B, and usage C illustrate different techniques for setting the appropriate application domain for each SWF file in an application. Usage A: Partition the child SWF file by creating a child of the system domain. In the diagram, application domain 2 is created as a child of the system domain.The application2.
-
The following code creates a new child domain of the current domain: request.url = "module3.swf"; request.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); IME class The IME class lets you manipulate the operating system’s Input Method Editor (IME) within Flash Player. Using ActionScript, you can determine the following: ■ If an IME is installed on the user's computer (Capabilities.hasIME). ■ If the IME is enabled or disabled on the user’s computer (IME.enabled).
-
Checking if an IME is installed and enabled Before you call any of the IME methods or properties, you should always check to see if the user’s computer currently has an IME installed and enabled. The following code illustrates how to check that the user has an IME both installed and active before you call any methods: if (Capabilities.hasIME) { if (IME.enabled) { trace("IME is installed and enabled."); } else { trace("IME is installed but not enabled. Please enable your IME and try again.
-
tf.text = "Current conversion mode is Japananese Hiragana."; break; case IMEConversionMode.JAPANESE_KATAKANA_FULL: tf.text = "Current conversion mode is Japanese Katakana (fullwidth)."; break; case IMEConversionMode.JAPANESE_KATAKANA_HALF: tf.text = "Current conversion mode is Japanese Katakana (halfwidth)."; break; case IMEConversionMode.KOREAN: tf.text = "Current conversion mode is Korean."; break; default: tf.text = "Current conversion mode is " + IME.conversionMode + "."; break; } } else { tf.
-
statusText.text = "Unable to set conversion mode.\n" + error.message; } } The previous code first creates a text field, which is used to display a status message to the user. Next, if the IME is installed, the code enables the IME and sets the conversion mode to Korean. If the user’s computer does not have a Korean IME installed, an error is thrown by Flash Player and is caught by the try..catch block. The try..catch block displays the error message in the previously created text field.
-
{ if (Capabilities.hasIME) { IME.enabled = true; } } This example creates two input text fields, phoneTxt and nameTxt, and then adds two event listeners to the phoneTxt text field. When the user sets focus to the phoneTxt text field, a FocusEvent.FOCUS_IN event is dispatched and the IME is disabled. When the phoneTxt text field loses focus, the FocusEvent.FOCUS_OUT event is dispatched to re-enable the IME.
-
outputTxt.text = "Unable to change IME."; } System.ime.addEventListener(IMEEvent.IME_COMPOSITION, imeCompositionHandler); } else { outputTxt.text = "Please install IME and try again."; } function imeCompositionHandler(event:IMEEvent):void { outputTxt.text = "you typed: " + event.text; } The previous code creates two text fields and adds them to the display list. The first text field, inputTxt, is an input text field that allows the user to enter Japanese text.
-
CapabilitiesExplorer overview The CapabilitiesExplorer.mxml file is responsible for setting up the user interface for the CapabilitiesExplorer application. The user’s Flash Player capabilities will be displayed within a DataGrid component instance on the Stage. Their browser capabilities will also be displayed if they are running the application from an HTML container and if the External API is available. When the main application file’s creationComplete event is dispatched, the initApp() method is invoked.
-
} capDP.sortOn("name", Array.CASEINSENSITIVE); return capDP; } The getBrowserObjects() method returns an array of each of the propreties in the browser’s navigator object. If this array has a length of one or more items, the array of browser capabilities (navArr) is appended to the arrray of Flash Player capabilities (capDP), and the entire array is sorted alphabetically. Finally, the sorted array is returned to the main application file, which then populates the data grid.
-
Communicating with JavaScript The final piece in building the CapabilitiesExplorer application is writing the necessary JavaScript to loop over each of the items in the browser’s navigator object and append a namevalue pair to a temporary array. The code for the JavaScript JS_getBrowserObjects() method in the container.html file is as follows: The code begins by creating a temporary array that will hold all the name-value pairs in the navigator object. Next, the navigator object is looped over using a for..in loop, and the data type of the current value is evaluated to filter out unwanted values. In this application, we are interested only in String or Boolean values, and other data types (such as functions or arrays) are ignored.
-
17 CHAPTER 17 Flash Player Security Security is a key concern of Adobe, users, website owners, and content developers. For this reason, Adobe Flash Player 9 includes a set of security rules and controls to safeguard the user, website owner, and content developer. This chapter discusses how to work with the Flash Player security model when you are developing Flash applications. In this chapter, all SWF files discussed are assumed to be published with ActionScript 3.
-
Flash Player Security overview Much of Flash Player security is based on the domain of origin for loaded SWF files, media, and other assets. A SWF file from a specific Internet domain, such as www.example.com, can always access all data from that domain. These assets are put in the same security grouping, known as a security sandbox. (For more information, see “Security sandboxes” on page 461.) For example, a SWF file can load SWF files, bitmaps, audio, text files, and any other asset from its own domain.
-
In the Flash Player security model, there is a distinction between loading content and accessing or loading data. ■ Loading content—Content is defined as media, including visual media Flash Player can display, audio, video, or a SWF file that includes displayed media. Data is defined as something that is accessible only to ActionScript code. You can load content using classes such as the Loader, Sound, and NetStream classes.
-
Overview of permission controls The Flash Player client run-time security model has been designed around resources, which are objects such as SWF files, local data, and Internet URLs. Stakeholders are the parties who own or use those resources. Stakeholders can exercise controls (security settings) over their own resources, and each resource has four stakeholders.
-
The mms.cfg file On Mac OS X systems, the mms.cfg file is located at /Library/Application Support/ Macromedia/mms.cfg. On Microsoft Windows systems, the file is located in the Macromedia Flash Player folder in the system directory (for example, C:\windows\system32\macromed\flash\mms.cfg on a default Windows XP installation). When Flash Player starts, it reads its security settings from this file, and uses them to limit functionality. The mms.
-
The Global Flash Player Trust directory Administrative users and installer applications can register specified local SWF files as trusted. These SWF files are assigned to the local-trusted sandbox. They can interact with any other SWF files, and they can load data from anywhere, remote or local. Files are designated as trusted in the Global Flash Player Trust directory, which is in the same directory as the mms.
-
The Settings UI and Settings Manager The Settings UI is a quick, interactive mechanism for configuring the settings for a specific domain. The Settings Manager presents a more detailed interface and provides the ability to make global changes that affect permissions for many or all domains. Additionally, when a new permission is requested by a SWF file, requiring run-time decisions concerning security or privacy, dialog boxes are displayed in which users can adjust some Flash Player settings.
-
These settings affect only the current user, not other users who log in to the computer. If a user without administrative rights installs an application in their own portion of the system, the User Flash Player Trust directory lets the installer register the application as trusted for that user.
-
When a SWF file attempts to access data from another domain, Flash Player automatically attempts to load a policy file from that domain. If the domain of the SWF file that is attempting to access the data is included in the policy file, the data is automatically accessible. By default, policy files must be named crossdomain.xml and must reside in the root directory of the server. However, a SWF file can check for a different name or in a different directory location by calling the Security.
-
If data to be loaded is on a HTTPS server, but the SWF file loading it is on an HTTP server, Adobe recommends that you move the loading SWF file to an HTTPS server so that you can keep all copies of your secure data under the protection of HTTPS. However, if you decide that you must keep the loading SWF file on an HTTP server, add the secure="false" attribute to the tag, as shown in the following code: PAGE 459
When policy files were first introduced in Flash Player 6, there was no support for socket policy files. Connections to socket servers were authorized by a policy file from the default location of the cross-domain policy file on an HTTP server on port 80 of the same host as the socket server. To make it possible to preserve existing server arrangements, Flash Player 9 still supports this capability.
-
Author (developer) controls The main ActionScript API used to grant security privileges is the Security.allowDomain() method, which grant privileges to SWF files in the domains that you specify. In the following example, a SWF file grants access to SWF files served from the www.example.com domain: Security.allowDomain("www.example.
-
Another important security-related method is the Security.loadPolicyFile() method, which causes Flash Player to check for a cross-domain policy file at a nonstandard location. For more information, see “Website controls (cross-domain policy files)” on page 456. Security sandboxes Client computers can obtain individual SWF files from a number of sources, such as from external websites or from a local file system.
-
Local sandboxes Local file describes any file that is referenced by using the file: protocol or a Universal Naming Convention (UNC) path. Local SWF files are placed into one of three local sandboxes: ■ The local-with-filesystem sandbox—For security purposes, Flash Player places all local SWF files and assets in the local-with-file-system sandbox, by default.
-
SWF files in the local-with-networking sandbox cannot load SWF files in the local-withfilesystem sandbox. SWF files in the local-with-filesystem sandbox cannot load SWF files in the local-with-networking sandbox. Setting the sandbox type of local SWF files You can configure a SWF file for the local-with-filesystem sandbox or the local-withnetworking sandbox by setting the use-network flag in the Flex compiler.
-
Restricting networking APIs You can control a SWF file’s access to network functionality by setting the allowNetworking parameter in the
-
An addition to those APIs on the previous list, the following APIs are also prevented when allowNetworking is set to "none": ■ sendToURL() ■ FileReference.download() ■ FileReference.upload() ■ Loader.load() ■ LocalConnection.connect() ■ LocalConnection.send() ■ NetConnection.connect() ■ NetStream.play() ■ Security.loadPolicyFile() ■ SharedObject.getLocal() ■ SharedObject.getRemote() ■ Socket.connect() ■ Sound.load() ■ URLLoader.load() ■ URLStream.load() ■ XMLSocket.
-
To enable full-screen mode, in the
-
When you call the load() method of the Loader object, you can specify a context parameter, which is a LoaderContext object. The LoaderContext class includes three properties that let you define the context of how the loaded content can be used: ■ checkPolicyFile—Use this property only when loading an image file (not a SWF file). Specify this for an image file from a domain other than that of the file containing the Loader object.
-
An important property of a Loader object is the contentLoaderInfo property, which is a LoaderInfo object. Unlike most other objects, a LoaderInfo object is shared between the loading SWF file and the loaded content, and it is always accessible to both parties. When the loaded content is a SWF file, it can access the LoaderInfo object through the DisplayObject.loaderInfo property.
-
When you use an
tag in a text field to load an external file (as opposed to using a Bitmap class embedded within your SWF), a Loader object is automatically created as a child of the TextField object, and the external file is loaded into that Loader just as if you had used a Loader object in ActionScript to load the file. In this case, the getImageReference() method returns the Loader that was automatically created.
-
If two SWF files written with ActionScript 3.0 are served from different domains—for example, http://siteA.com/swfA.swf and http://siteB.com/swfB.swf—then, by default, Flash Player does not allow swfA.swf to script swfB.swf, nor swfB.swf to script swfA.swf. A SWF file gives permission to SWF files from other domains by calling Security.allowDomain(). By calling Security.allowDomain("siteA.com"), swfB.swf gives SWF files from siteA.com permission to script it.
-
In addition to protecting SWF files from cross-domain scripting originated by other SWF files, Flash Player protects SWF files from cross-domain scripting originated by HTML files. HTML-to-SWF scripting can occur with callbacks established through the ExternalInterface.addCallback() method. When HTML-to-SWF scripting crosses domains, the SWF file being accessed must call the Security.allowDomain() method, just as when the accessing party is a SWF file, or the operation will fail.
-
There are also restrictions on the removeChildAt() and swapChildrenAt() methods of the Stage object, but these are different from the other restrictions. Rather than needing to be in the same domain as the Stage owner, to call these methods code must be in the same domain as the owner of the affected child object(s), or the child object(s) can call the Security.allowDomain() method. Traversing the display list The ability of one SWF file to access display objects loaded from other sandboxes is restricted.
-
For events that are dispatched from objects other than display objects, there are no security checks or security-related implications. Accessing loaded media as data You access loaded data using methods such as BitmapData.draw() and SoundMixer.computeSpectrum(). By default, a SWF file from one security sandbox cannot obtain pixel data or audio data from graphic or audio objects rendered or played by loaded media in another sandbox.
-
When you load the image using the load() method of the Loader class, you can specify a context parameter, which is a LoaderContext object. If you set the checkPolicyFile property of the LoaderContext object to true, Flash Player checks for a cross-domain policy file on the server from which the image is loaded. If there is a cross-domain policy file, and the file permits the domain of the loading SWF file, the file is allowed to access data in the Bitmap object; otherwise, access is denied.
-
You can use the SoundMixer.areSoundsInaccessible() method to find out whether a call to the SoundMixer.stopAll() method would not stop all sounds because the sandbox of one or more sound owners is inaccessible to the caller. Calling the SoundMixer.stopAll() method stops those sounds whose owner sandbox is the same as that of the caller of stopAll(). It also stops those sounds whose playback was started by SWF files that have called the Security.
-
Loading data SWF files can load data from servers into ActionScript, and send data from ActionScript to servers. Loading data is a different kind of operation from loading media, because the loaded information appears directly in ActionScript, rather than being displayed as media. Generally, SWF files may load data from their own domains. However, they usually require crossdomain policy files in order to load data from other domains.
-
To retrieve a socket policy file from the same port as a main socket connection, simply call the Socket.connect() or XMLSocket.connect() method, and, if the specified domain is not the same as the domain of the calling SWF file, Flash Player automatically attempts to retrieve a policy file from the same port as the main connection you are attempting. To retrieve a socket policy file from a different port on the same server as your main connection, call the Security.
-
Uploading and downloading files The FileReference.upload() method starts the upload of a file selected by a user to a remote server. You must call the FileReference.browse() or FileReferenceList.browse() method before calling the FileReference.upload() method. Calling the FileReference.download() method opens a dialog box in which the user can download a file from a remote server.
-
An alternative way for a SWF file to access classes in loaded SWF files from a different security sandbox is to have the loaded SWF file call the Security.allowDomain() method to grant access to the domain of the calling SWF file. You can add the call to the Security.allowDomain() method to the constructor method of the main class of the loaded SWF file, and then have the loading SWF file add an event listener to respond to the init event dispatched by the contentLoaderInfo property of the Loader object.
-
Setting LocalConnection permissions The LocalConnection class lets you develop SWF files that can send instructions to each other. LocalConnection objects can communicate only among SWF files that are running on the same client computer, but they can be running in different applications—for example, a SWF file running in a browser and a SWF file running in a projector. For every LocalConnection communication, there is a sender SWF file and a listener SWF file.
-
Set this parameter in the HTML code for the web page that hosts a SWF file. You set the parameter in the PARAM or EMBED tag. The AllowScriptAccess parameter can have one of three possible values: "always", "sameDomain", or "never": ■ When AllowScriptAccess is "sameDomain", outbound scripting is allowed only if the SWF file and the web page are in the same domain. This is the default for AVM2 content. ■ When AllowScriptAccess is "never", outbound scripting always fails.
-
Shared objects Flash Player provides the ability to use shared objects, which are ActionScript objects that persist outside of a SWF file, either locally on a user’s file system or remotely on an RTMP server. Shared objects, like other media in Flash Player, are partitioned into security sandboxes. However, the sandbox model for shared objects is somewhat different, because shared objects are not resources that can ever be accessed across domain boundaries.
-
The choice of a shared object store is based on a SWF file’s origin URL. This is true even in the two situations where a SWF file does not originate from a simple URL: import loading and dynamic loading. Import loading refers to the situation where you load a SWF file with the LoaderContext.securityDomain property set to SecurityDomain.currentDomain. In this situation, the loaded SWF file will have a pseudo-URL that begins with its loading SWF file’s domain and then specifies its actual origin URL.
-
The System.setClipboard() method allows a SWF file to replace the contents of the Clipboard with a plain-text string of characters. This poses no security risk. To protect against the risk posed by passwords and other sensitive data being cut or copied to Clipboards, there is no corresponding “getClipboard” (read) method. A Flash application can monitor only keyboard and mouse events that occur within its focus. A Flash application cannot detect keyboard or mouse events in another application.
-
Flash Player Security
-
18 CHAPTER 18 Printing Adobe Flash Player 9 can communicate with an operating system’s printing interface so that you can pass pages to the print spooler. Each page Flash Player sends to the spooler can contain content that is visible, dynamic, or offscreen to the user, including database values and dynamic text. Additionally, Flash Player sets the properties of the flash.printing.PrintJob class based on a user’s printer settings, so that you can format pages appropriately.
-
What’s new for the PrintJob class using ActionScript 3.0 The PrintJob class hasn’t changed dramatically for the ActionScript 3.0 implementation of printing. However, a few critical differences are worth noting: ■ The PrintJob.addPage() method now takes a Sprite and a Rectangle object for the first two parameters. ■ ActionScript 3.0 does not support using the delete (as in delete myPrintJob) operator to remove an entire object. In ActionScript 2.
-
So, for example, a very simple print job script may look like the following (including package, import and class statements for compiling): package { import flash.printing.PrintJob; import flash.display.Sprite; public class BasicPrintExample extends Sprite { var myPrintJob:PrintJob = new PrintJob(); var mySprite:Sprite = new Sprite(); public function BasicPrintExample() { myPrintJob.start(); myPrintJob.addPage(mySprite); myPrintJob.
-
Working with exceptions and returns You should check to see if the PrintJob.start() method returns true before executing addPage() and send() calls, in case the user has cancelled the print job. A simple way to check whether these methods have been cancelled before continuing is to wrap them in an if statement, as follows: if (myPrintJob.start()) { // addPage() and send() statements here } If PrintJob.
-
If Flash Player encounters a problem sending the print job to the printer (for example, if the printer is offline), you can catch that exception, too, and provide the user (or Flash Player) with information or more options (such as displaying message text or providing an alert within the Flash animation). For example, you can assign new text to a text field in an if..else statement, as the following code shows: if (myPrintJob.start()) { try { myPrintJob.
-
Setting vector or bitmap rendering You can manually set the print job to spool each page as vector graphics or a bitmap image. In some cases, vector printing will produce a smaller spool file, and a better image than bitmap printing. However, if your content includes a bitmap image, and you want to preserve any alpha transparency or color effects, you should print the page as a bitmap image. Also, a nonPostScript printer automatically converts any vector graphics to bitmap images.
-
Setting size, scale, and orientation The section “Printing a page” on page 488 details the steps for a basic print job, where the output directly reflects the printed equivalent of the screen size and position of the specified sprite. However, printers use different resolutions for printing, and can have settings that adversely affect the appearance of the printed sprite.
-
Comparing points and pixels A rectangle's width and height are pixel values. A printer uses points as print units of measurement. Points are a fixed physical size (1/72 inch), but the size of a pixel on the screen depends on the resolution of the particular screen. The conversion rate between pixels and points depends on the printer settings and whether the sprite is scaled.
-
Printing for landscape or portrait orientation Because Flash Player can detect the settings for orientation, you can build logic into your ActionScript to adjust the content size or rotation in response to the printer settings, as the following example illustrates: if (myPrintJob.orientation == PrintJobOrientation.LANDSCAPE) { mySprite.
-
import flash.geom.Rectangle; public class PrintMultiplePages extends MovieClip { private var sheet1:Sprite; private var sheet2:Sprite; public function PrintMultiplePages():void { init(); printPages(); } private function init():void { sheet1 = new Sprite(); createSheet(sheet1, "Once upon a time...", {x:10, y:50, width:80, height:130}); sheet2 = new Sprite(); createSheet(sheet2, "There was a great story to tell, and it ended quickly.\n\nThe end.
-
{ var pj:PrintJob = new PrintJob(); var pagesToPrint:uint = 0; if (pj.start()) { if (pj.orientation == PrintJobOrientation.LANDSCAPE) { throw new Error("Page is not set to an orientation of portrait."); } sheet1.height = pj.pageHeight; sheet1.width = pj.pageWidth; sheet2.height = pj.pageHeight; sheet2.width = pj.pageWidth; try { pj.addPage(sheet1); pagesToPrint++; } catch (e:Error) { // Respond to error. } try { pj.addPage(sheet2); pagesToPrint++; } catch (e:Error) { // Respond to error.
-
Example: Scaling, cropping, and responding In some cases, you may want adjust the size (or other properties) of a display object when printing it to accommodate differences between the way it appears on screen and the way it appears printed on paper. When you adjust the properties of a display object before printing (for example, by using the scaleX and scaleY properties), be aware that if the object scales larger than the defined rectangle for the print area, the object will be cropped.
-
trace(">> pj.paperHeight: " + pj.paperHeight); try { pj.addPage(this, new Rectangle(0, 0, 100, 100)); } catch (e:Error) { // Do nothing. } pj.send(); } else { txt.text = } // Reset the txt.scaleX = txt.scaleY = "Print job canceled"; txt scale properties. 1; 1; } private function init():void { bg = new Sprite(); bg.graphics.beginFill(0x00FF00); bg.graphics.drawRect(0, 0, 100, 200); bg.graphics.endFill(); txt = new TextField(); txt.border = true; txt.
-
Printing
-
19 CHAPTER 19 Using the External API The ActionScript 3.0 External API enables straightforward communication between ActionScript and the container application within which Adobe Flash Player 9 is running. There are several situations in which you may want to use the External API—for example, when you create interaction between a SWF document and JavaScript in an HTML page, or when building a desktop application that uses Flash Player to display a SWF file.
-
About the External API The External API is the portion of ActionScript that provides a mechanism for communication between ActionScript and code running in an “external application” that is acting as a container for Flash Player (commonly a web browser or stand-alone projector application). In ActionScript 3.0, the functionality of the External API is provided by the ExternalInterface class.
-
From ActionScript, you can call a JavaScript function on the HTML page. The External API offers the following improved functionality compared with fscommand(): ■ You can use any JavaScript function, not only the functions that you can use with the fscommand() function. ■ You can pass any number of arguments, with any names; you aren't limited to passing a command and a single string argument. This gives the External API much more flexibility than fscommand().
-
Getting information about the external container The ExternalInterface.available property indicates whether the current Flash Player is in a container that offers an external interface. If the external interface is available, this property is true; otherwise, it is false. Before using any of the other functionality in the ExternalInterface class, you should always check to make sure that the current container supports external interface communication, as follows: if (ExternalInterface.
-
If the container is an HTML page, this method invokes the JavaScript function with the specified name, which must be defined in a