blob: 19d71bc0cd76ea1e665003dc29bbec49acdba09f [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta name="DC.Type" content="topic"/>
<meta name="DC.Title" content="Using ActionScript"/>
<meta name="DC.Format" content="XHTML"/>
<meta name="DC.Identifier" content="WS2db454920e96a9e51e63e3d11c0bf69084-7ffe_verapache"/>
<title>Using ActionScript</title>
</head>
<body id="WS2db454920e96a9e51e63e3d11c0bf69084-7ffe_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ffe_verapache"><!-- --></a>
<div>
<p>Flex
developers can use ActionScript to extend the functionality of their
applications. ActionScript provides flow control and object manipulation
features that are not available in MXML. For a complete introduction
to ActionScript and a reference for using the language, see <em>
<a href="https://help.adobe.com/en_US/as3/dev/index.html" target="_blank">ActionScript 3.0 Developer's Guide</a>
</em> and <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>.</p>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fff_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fff_verapache"><!-- --></a>
<h2 class="topictitle2">Using ActionScript in applications</h2>
<div>
<p>Flex developers can use ActionScript to implement custom
behavior within their applications. You first use MXML tags to declare
things like the containers, controls, effects, formatters, validators,
and web services that your application requires, and to lay out
its user interface. Each of these components provides the standard
behavior you'd expect. For example, a button automatically highlights when
you roll over it, without requiring you to write any ActionScript.
But a declarative language like MXML is not appropriate for coding
what you want to happen when the user clicks a button. For that,
you need to use a procedural language like ActionScript, which offers
executable methods, various types of storage variables, and flow
control such as conditionals and loops. In a general sense, MXML
implements the static aspects of your application, and ActionScript implements
its dynamic aspects.</p>
<p>ActionScript is an
object-oriented procedural programming language, based on the ECMAScript
(ECMA-262) edition 4 draft language specification. You can use a variety
of methods to mix ActionScript and MXML, including the following:</p>
<ul>
<li>
<p>Define event listeners inside MXML event attributes.</p>
</li>
<li>
<p>Add script blocks using the <samp class="codeph">&lt;fx:Script&gt;</samp> tag.</p>
</li>
<li>
<p>Include external ActionScript files.</p>
</li>
<li>
<p>Import
ActionScript classes. </p>
</li>
<li>
<p>Create ActionScript components.</p>
</li>
</ul>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffe_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffe_verapache"><!-- --></a>
<h3 class="topictitle3">ActionScript compilation</h3>
<div>
<p>Although a simple application can be written in a single
MXML or ActionScript (AS) file, most applications will be broken
into multiple files. For example, it is common to move the <samp class="codeph">&lt;fx:Script&gt;</samp> and <samp class="codeph">&lt;fx:Style&gt;</samp> blocks
into separate AS and CSS files that the application then includes. </p>
<p>It is also common for an application to import custom MXML and
ActionScript components. These must be defined in other files, and
MXML components may put their own <samp class="codeph">&lt;fx:Script&gt;</samp> blocks
into yet more AS files that they include. Components may also be
imported from precompiled SWC files rather than source code. Finally,
SWF files containing executable code can also be embedded in an
application. The end result of all these input files is a single
SWF file.</p>
<p>The Flex compiler transforms the main MXML file and other files
it includes into a single ActionScript class. As a result, you cannot
define classes or use statements outside of functions in the MXML
files and the included ActionScript files.</p>
<p>You can reference imported ActionScript classes from your MXML
application files, and those classes are added to the final SWF
file. When the transformation to an ActionScript file is complete,
Flex links all the ActionScript components and includes those classes
in the final SWF file.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffd_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffd_verapache"><!-- --></a>
<h3 class="topictitle3">About generated ActionScript</h3>
<div>
<p>When you write an MXML file and compile it, the Flex compiler
creates a class and generates ActionScript that the class uses.
MXML tags and ActionScript are used by the resulting class in several
ways. This information is useful for understanding what is happening
in the background of the application.</p>
<p>An MXML application (a file that starts with the <samp class="codeph">&lt;s:Application&gt;</samp> tag) defines
a subclass of the Spark Application class. Similarly, an MXML component (a
file that starts with some other component's tag, such as <samp class="codeph">&lt;s:Button&gt;</samp>) defines
a subclass of that component.</p>
<p>The name of the subclass is the name of the file. The base class
is the class of the top-level tag. An MXML application actually
defines the following:</p>
<pre class="codeblock"> class MyApp extends Application</pre>
<p>If MyButton.mxml starts with <samp class="codeph">&lt;s:Button&gt;</samp>,
you are actually defining the following:</p>
<pre class="codeblock"> class MyButton extends Button</pre>
<p>The variable and function declarations in an <samp class="codeph">&lt;fx:Script&gt;</samp> block
define properties and methods of the subclass. </p>
<p>Setting an <samp class="codeph">id</samp> property on a component instance
within a class results in a public variable being autogenerated
in the subclass that contains a reference to that component instance.
For example, if the <samp class="codeph">&lt;s:Button id="myButton"/&gt;</samp> tag is
nested deeply inside several containers, you can still refer to
it as <samp class="codeph">myButton</samp>.</p>
<p>Event attributes become the bodies of autogenerated event listener
methods in the subclass. For example:</p>
<pre class="codeblock"> &lt;s:Button id="myButton" click="foo = 1; doSomething()"&gt;</pre>
<p>becomes</p>
<pre class="codeblock"> private function __myButton_click(event:MouseEvent):void {
  foo = 1;
  doSomething()
 }</pre>
<p>The event attributes become method bodies, so they can access
the other properties and methods of the subclass.</p>
<p>All the ActionScript anywhere in an MXML file, whether in its <samp class="codeph">&lt;fx:Script&gt;</samp> block
or inside tags, executes with the <samp class="codeph">this</samp> keyword
referring to an instance of the subclass.</p>
<p>The public properties and methods of the class are accessible
by ActionScript code in other components, as long as that code "dots
down" (for example, <samp class="codeph">myCheckoutAccordion.myAddressForm.firstNameTextInput.text</samp>)
or reaches up using the <samp class="codeph">parentDocument</samp>, <samp class="codeph">parentApplication</samp>,
or <samp class="codeph">FlexGlobals.topLevelApplication</samp> properties to
specify which component the property or method exists on.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffc_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffc_verapache"><!-- --></a>
<h3 class="topictitle3">Using ActionScript in MXML event
handlers</h3>
<div>
<p>One
way to use ActionScript code in an application is to include it
within the MXML tag's event handler, as the following example shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/HelloWorldAS.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:BasicLayout/&gt;
&lt;/s:layout&gt;
&lt;s:Panel title="My Application" height="128" x="226" y="24"&gt;
&lt;s:TextArea id="textarea1" width="155" x="0" y="0"/&gt;
&lt;s:Button label="Click Me"
click="textarea1.text='Hello World';"
width="92"
x="31.5" y="56"/&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
<p>In this example, you include ActionScript code for the body of
the click event handler of the Button control. The MXML compiler
takes the attribute <samp class="codeph">click="</samp>
<em>...</em>
<samp class="codeph">"</samp> and
generates the following event handler method:</p>
<pre class="codeblock"> public function __myButton_click(event:MouseEvent):void {
<strong>textarea1.text='Hello World';</strong>
 }</pre>
<p>When the user clicks the button, this code sets the value of
the TextArea control's <samp class="codeph">text</samp> property to the String <samp class="codeph">"Hello World</samp>.<samp class="codeph">" </samp> In
most cases, you do not need to look at the generated code, but it
is useful to understand what happens when you write an inline event
handler. </p>
<p>To see the generated code, set the value of the <samp class="codeph">keep-generated-actionscript</samp> compiler
option to <samp class="codeph">true</samp>. The compiler then stores the *.as helper
file in the /generated directory, which is a subdirectory of the
location of the SWF file. </p>
<p>For more information about events, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee9_verapache">Events</a>.
For more information on using the command-line compilers, see <a href="flx_compilers_cpl.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ffd_verapache">Flex
compilers</a>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffb_verapache"><!-- --></a>
<h3 class="topictitle3">Using ActionScript blocks in MXML
files</h3>
<div>
<p>You use the <samp class="codeph">&lt;fx:Script&gt;</samp> tag
to insert an ActionScript block in an MXML file. ActionScript blocks
can contain ActionScript functions and variable declarations used
in MXML applications. Code inside <samp class="codeph">&lt;fx:Script&gt;</samp> tags
can also declare constants (with the <samp class="codeph">const</samp> statement)
and namespaces (with <samp class="codeph">namespace</samp>), include ActionScript
files (with <samp class="codeph">include</samp>), import declarations (with <samp class="codeph">import</samp>), and
use namespaces (with <samp class="codeph">use namespace</samp>).</p>
<p>The <samp class="codeph">&lt;fx:Script&gt;</samp> tag must be a child of
the <samp class="codeph">&lt;s:Application&gt;</samp> or other top-level component
tag. </p>
<p>Statements and expressions are allowed only if they are wrapped
in a function. In addition, you cannot define new classes or interfaces
in <samp class="codeph">&lt;fx:Script&gt;</samp> blocks. Instead, you must
place new classes or interfaces in separate AS files and import them. </p>
<p>All ActionScript in the block is added to the enclosing file's
class when Flex compiles the application. The following example
declares a variable and sets the value of that variable inside a
function:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/StatementSyntax.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="doSomething()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
public var s:Boolean;
public function doSomething():void {
// The following statements must be inside a function.
s = label1.visible;
label1.text = "label1.visible = " + String(s);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Label id="label1"/&gt;
&lt;/s:Application&gt;</pre>
<p>Most ActionScript statements must be inside functions in an <samp class="codeph">&lt;fx:Script&gt;</samp> block.
However, the following statements can be outside functions: </p>
<ul>
<li>
<p>
<samp class="codeph">import</samp>
</p>
</li>
<li>
<p>
<samp class="codeph">var</samp>
</p>
</li>
<li>
<p>
<samp class="codeph">include</samp>
</p>
</li>
<li>
<p>
<samp class="codeph">const</samp>
</p>
</li>
<li>
<p>
<samp class="codeph">namespace</samp>
</p>
</li>
<li>
<p>
<samp class="codeph">use namespace</samp>
</p>
</li>
</ul>
<p>When using an <samp class="codeph">&lt;fx:Script&gt;</samp> block,
you should wrap the contents in a CDATA construct. This prevents
the compiler from interpreting the contents of the script block
as XML, and allows the ActionScript to be properly generated. It's
best to write all your <samp class="codeph">&lt;fx:Script&gt;</samp> open and
close tags as the following example shows:</p>
<pre class="codeblock"> &lt;fx:Script&gt;
  &lt;![CDATA[
  ...
  ]]&gt;
 &lt;/fx:Script&gt;</pre>
<p>Flex does not parse text in a CDATA construct, which means that
you can use XML-parsed characters such as angle brackets (&lt; and
&gt;) and ampersand (&amp;). For example, the following script that
includes a greater-than (&gt;) comparison must be in a CDATA construct:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/UsingCDATA.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="doSomething()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
public var m:Number;
public var n:Number;
public function doSomething():void {
n = 40;
m = 42;
label1.text = "40 &lt; 42 = " + String(n &lt; m);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Label id="label1"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffa_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ffa_verapache"><!-- --></a>
<h3 class="topictitle3">Accessing ActionScript documentation</h3>
<div>
<p>The ActionScript 3.0 programming language can be used from
within several development environments, including Adobe<sup>®</sup> Flash<sup>®</sup> Professional
. </p>
<p>The ActionScript API reference is included as part of the <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>.</p>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff9_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff9_verapache"><!-- --></a>
<h2 class="topictitle2">Working with components</h2>
<div>
<p>The primary use of ActionScript in your applications is
probably going to be for working with the visual cont</p>
<p>rols and containers in your application. Flex provides several
techniques for doing this, including referencing a Flex control
in ActionScript and manipulating properties during the instantiation
of controls and containers.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7ff6_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ff6_verapache"><!-- --></a>
<h3 class="topictitle3">Referring to components</h3>
<div>
<p>To work with a component in ActionScript, you usually define
an <samp class="codeph">id</samp> property for that component in the MXML tag.
For example, the following code sets the <samp class="codeph">id</samp> property
of the Button control to the String <samp class="codeph">"myButton"</samp>:</p>
<pre class="codeblock"> &lt;s:Button id="myButton" label="Click Me"/&gt;</pre>
<p>This property is optional if you do not want to access the component
with ActionScript.</p>
<p>This code causes the MXML compiler to autogenerate a public variable
named <samp class="codeph">myButton</samp> that contains a reference to that
Button instance. This autogenerated variable lets you access the
component instance in ActionScript. You can explicitly refer to
the Button control's instance with its <samp class="codeph">id</samp> instance
reference in any ActionScript class or script block. By referring
to a component's instance, you can modify its properties and call
its methods. </p>
<p>For example, the following ActionScript block changes the value
of the Button control's <samp class="codeph">label</samp> property when the
user clicks the button:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ButtonExample.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private function setLabel():void {
if (myButton.label=="Click Me") {
myButton.label = "Clicked";
} else {
myButton.label = "Click Me";
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="myButton" label="Click Me" click="setLabel();"/&gt;
&lt;/s:Application&gt;</pre>
<p>The IDs for all tags in an MXML component, no matter how deeply
nested they are, generate public variables of the component being
defined. As a result, all <samp class="codeph">id</samp> properties must be
unique within a document. This also means that if you specified
an ID for a component instance, you can access that component from anywhere
in the application: from functions, external class files, imported
ActionScript files, or inline scripts.</p>
<p>You can refer to a component if it does not have an <samp class="codeph">id</samp> property
by using methods of the component's Spark container, such as the <samp class="codeph">getElementAt()</samp> method.
For MX containers, you can use the <samp class="codeph">getChildAt()</samp> method.</p>
<p>You can refer to the current enclosing document or current object
using the <samp class="codeph">this</samp> keyword.</p>
<p>You can also get a reference to a component when you have a String
that matches the name. To access an object on the application, you
use the <samp class="codeph">this</samp> keyword, followed by square brackets,
with the String inside the square brackets. The result is a reference
to the objects whose name matches the String. </p>
<p>The following example changes style properties on each Button
control using a compound String to get a reference to the object:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/FlexComponents.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
private var newFontStyle:String;
private var newFontSize:int;
public function changeLabel(s:String):void {
s = "myButton" + s;
if (this[s].getStyle("fontStyle")=="normal") {
newFontStyle = "italic";
newFontSize = 18;
} else {
newFontStyle = "normal";
newFontSize = 10;
}
this[s].setStyle("fontStyle",newFontStyle);
this[s].setStyle("fontSize",newFontSize);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="myButton1"
click="changeLabel('2')"
label="Change Other Button's Styles"/&gt;
&lt;s:Button id="myButton2"
click="changeLabel('1')"
label="Change Other Button's Styles"/&gt;
&lt;/s:Application&gt;</pre>
<p>This technique is especially useful if you use a Repeater control
or when you create objects in ActionScript and do not necessarily
know the names of the objects you want to refer to prior to run
time. However, when you instantiate an object in ActionScript, to
add that object to the properties array, you must declare the variable
as public and declare it in the class's scope, not inside a function.</p>
<p>The following example uses ActionScript to declare two Label
controls in the application scope. During initialization, the labels
are instantiated and their <samp class="codeph">text</samp> properties are
set. The example then gets a reference to the Label controls by
appending the passed-in variable to the String when the user clicks
the Button controls.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ASLabels.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="initLabels()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Label;
public var label1:Label;
public var label2:Label;
// Objects must be declared in the application scope. Adds the names to
// the application's properties array.
public function initLabels():void {
label1 = new Label();
label1.text = "Change Me";
label2 = new Label();
label2.text = "Change Me";
addElement(label1);
addElement(label2);
}
public function changeLabel(s:String):void {
// Create a String that matches the name of the Label control.
s = "label" + s;
// Get a reference to the label control using the
// application's properties array.
this[s].text = "Changed";
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" click="changeLabel('2')" label="Change Other Label"/&gt;
&lt;s:Button id="b2" click="changeLabel('1')" label="Change Other Label"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff7_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff7_verapache"><!-- --></a>
<h3 class="topictitle3">Calling component methods</h3>
<div>
<p>You
can invoke the public methods of a component instance in your application by
using the following dot-notation syntax:</p>
<pre class="codeblock"> componentInstance.method([<em>parameters</em>]);</pre>
<p>The following example invokes the <samp class="codeph">adjustThumb()</samp> method
when the user clicks the button, which invokes the public <samp class="codeph">setThumbValueAt()</samp> method
of the HSlider control:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ComponentMethods.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
public function adjustThumb(s:HSlider):void {
var randomNumber:int = (Math.floor(Math.random() * 10));
s.setThumbValueAt(0, randomNumber);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;mx:HSlider id="slider1" tickInterval="1"
labels="[1,2,3,4,5,6,7,8,9,10]" width="282"/&gt;
&lt;s:Button id="myButton"
label="Change Thumb Position"
click="adjustThumb(slider1);"/&gt;
&lt;/s:Application&gt;</pre>
<p>To invoke a method from a child document (such as a custom MXML component),
you can use the <samp class="codeph">parentApplication</samp>, <samp class="codeph">parentDocument</samp>,
or <samp class="codeph">FlexGlobals.topLevelApplication</samp> properties.
For more information, see <a href="flx_app_container_apc.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee7_verapache">Application
containers</a>.</p>
<div class="note"><span class="notetitle">Note:</span> Because Flex invokes the <samp class="codeph">initialize</samp> event
before drawing the component, you cannot access size and position
information of that component from within the <samp class="codeph">initialize</samp> event
handler unless you use the <samp class="codeph">creationComplete</samp> event handler.
For more information on the order of initialization events, see <a href="flx_layoutperformance_lp.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee6_verapache">About
startup order</a>.</div>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff6_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff6_verapache"><!-- --></a>
<h3 class="topictitle3">Creating visual components in ActionScript</h3>
<div>
<p>You can use ActionScript to programmatically create visual
components using the <samp class="codeph">new</samp> operator, in the same
way that you create instances of any ActionScript class. The created
component has default values for its properties, but it does not yet
have a parent or any children (including any kind of internal DisplayObjects), and
it is not yet on the display list in Flash Player or Adobe<sup>®</sup> AIR™, so you can't
see it. After creating the component, you should use standard assignment
statements to set any properties whose default values aren't appropriate. </p>
<p>Finally, you must add the new component to a container, by using
the Spark container's <samp class="codeph">addElement()</samp> or <samp class="codeph">addElementAt()</samp> methods,
so that it becomes part of the visual hierarchy of an application.
(For MX containers, you can use the <samp class="codeph">addChild()</samp> or <samp class="codeph">addChildAt()</samp> methods.)
The first time that it is added to a container, a component's children
are created. Children are created late in the component's life cycle
so that you can set properties that can affect children as they
are created.</p>
<p>When creating visual controls, you must import the appropriate
package. In most cases, this is the mx.controls package, although
you should check the <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>.</p>
<p>The following example creates a Button control inside the HGroup
container:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ASVisualComponent.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import spark.components.Button;
public var button2:Button;
public function createObject():void {
button2 = new Button();
button2.label = "Click Me";
hb1.addElement(button2);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:HGroup id="hb1"&gt;
&lt;s:Button label="Create Object" click="createObject()"/&gt;
&lt;/s:HGroup&gt;
&lt;/s:Application&gt;</pre>
<p>Flex creates the new child as the last child in the container.
If you do not want the new child to be the last in the Spark container,
use the <samp class="codeph">addElementAt()</samp> method to change the order.
You can use the <samp class="codeph">setItemIndex()</samp> method after the
call to the <samp class="codeph">addElement()</samp> method, but this is less
efficient. For MX containers, you use the <samp class="codeph">addChildAt()</samp>, <samp class="codeph">setChildIndex()</samp>,
and <samp class="codeph">addChild()</samp> methods.</p>
<p>You should declare an instance variable for each dynamically
created component and store a reference to the newly created component
in it, just as the MXML compiler does when you set an <samp class="codeph">id</samp> property
for a component instance tag. You can then access your dynamically
created components in the same way as those declaratively created
in MXML.</p>
<p>To programmatically remove a control in Spark containers, you
can use the <samp class="codeph">removeElement()</samp>, <samp class="codeph">removeElementAt()</samp>,
and <samp class="codeph">removeAllElements()</samp> methods. For MX containers,
you use the <samp class="codeph">removeChild()</samp> or <samp class="codeph">removeChildAt()</samp> methods.
You can also use the <samp class="codeph">removeAllChildren()</samp> method
to remove all child controls from a container. </p>
<p>Calling the "remove" methods does not actually delete the objects
from memory. If you do not have any other references to the child,
Flash Player includes the object in garbage collection at some future
point. But if you have a reference to that child, the child is not
garbage collected. </p>
<p>In some cases, you declaratively define a component with an MXML
tag. You can set the <samp class="codeph">creationPolicy</samp> property of
the component's container to <samp class="codeph">none</samp> to defer the
creation of the controls inside that container. You can then create
the component programmatically rather than declaratively. For information
on using the <samp class="codeph">creationPolicy</samp> property, see <a href="flx_layoutperformance_lp.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee5_verapache">Improving
startup performance</a>.</p>
<p>The only component you can pass to the <samp class="codeph">addElement()</samp> method
is a class that implements the IVisualElement interface. In other
words, if you create a new object that is not a subclass of mx.core.IVisualElement,
you must wrap it in a class that implments IVisualElement before
you can attach it to a container. The following example creates
a new Sprite object, which is not a subclass of IVisualElement,
and adds it as a child of the UIComponent (which implements IVisualElement)
before adding it to the Panel container:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/AddingChildrenAsUIComponents.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import flash.display.Sprite;
import mx.core.UIComponent;
private var xLoc:int = 20;
private var yLoc:int = 20;
private var circleColor:Number = 0xFFCC00;
private function addChildToPanel():void {
var circle:Sprite = new Sprite();
circle.graphics.beginFill(circleColor);
circle.graphics.drawCircle(xLoc, yLoc, 15);
var c:UIComponent = new UIComponent();
c.addChild(circle);
panel1.addElement(c);
xLoc = xLoc + 5;
yLoc = yLoc + 1;
circleColor = circleColor + 20;
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Panel id="panel1" height="250" width="300"/&gt;
&lt;s:Button id="myButton" label="Click Me" click="addChildToPanel();"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7e3e_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7e3e_verapache"><!-- --></a>
<h3 class="topictitle3">About scope</h3>
<div>
<p>Scoping in ActionScript is largely a description of what
the <samp class="codeph">this</samp> keyword refers to at a particular point.
In your application's core MXML file, you can access the Application
object by using the <samp class="codeph">this</samp> keyword. In a file defining
an MXML component, <samp class="codeph">this</samp> is a reference to the current
instance of that component.</p>
<p>In an ActionScript class file, the <samp class="codeph">this</samp> keyword
refers to the instance of that class. In the following example,
the <samp class="codeph">this</samp> keyword refers to an instance of myClass. Because <samp class="codeph">this</samp> is
implicit, you do not have to include it, but it is shown here to illustrate
its meaning.</p>
<pre class="codeblock"> class myClass {
  var _x:Number = 3;
  function get x():Number {
  return this._x;
  }
  function set x(y:Number):void {
  if (y &gt; 0) {
  this._x = y;
  } else {
  this._x = 0;
  }
  }
 }</pre>
<p>However, in custom ActionScript and MXML components or external
ActionScript class files, Flex executes in the context of those
objects and classes, and the <samp class="codeph">this</samp> keyword refers
to the current scope and not the Application object scope.</p>
<p>Flex includes a <samp class="codeph">FlexGlobals.topLevelApplication</samp> property
that you can use to access the root application. In some cases,
you can also use the <samp class="codeph">parentDocument</samp> property to
access the next level up in the document chain of an application,
or the <samp class="codeph">parentApplication</samp> property to access the
next level up in the application chain when one Application object
loads another Application object.</p>
<p>You cannot use these properties to access the root application
if the loaded application was loaded into a separate ApplicationDomain
or SecurityDomain, as is the case with sandboxed and multi-versioned
applications. For more information, see <a href="flx_loading_applications_la.html#WS2db454920e96a9e51e63e3d11c0bf619ab-7fe5_verapache">Accessing
the main application from sub-applications</a>.</p>
<p>If you write ActionScript in a component's event listener, the
scope is not the component but rather the application. For example,
the following code changes the label of the Button control to <samp class="codeph">"Clicked"</samp> once
the Button control is pressed:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ButtonScope.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:BasicLayout/&gt;
&lt;/s:layout&gt;
&lt;s:Panel width="250" height="100" x="65" y="24"&gt;
&lt;s:Button id="myButton"
label="Click Me"
click="myButton.label='Clicked'"
x="79.5" y="20"/&gt;
&lt;/s:Panel&gt;
&lt;s:Button label="Reset"
x="158" y="149"
click="myButton.label='Click Me'"/&gt;
&lt;/s:Application&gt;</pre>
<p>Contrast the previous example with the following code: </p>
<pre class="noswf">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/AppScope.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;!-- The following throws a compiler error because the app level scope does
not have a label to set. --&gt;
&lt;!-- &lt;s:Button id="myButton" label="Click Me" click="{this.label='Clicked'}"/&gt; --&gt;
&lt;!-- &lt;s:Button label="Reset" click="myButton.label='Click Me'"/&gt; --&gt;
&lt;/s:Application&gt;</pre>
<p>This code does not work because when an event listener executes,
the <samp class="codeph">this</samp> keyword does not refer to the Button instance;
the <samp class="codeph">this</samp> keyword refers to the Application or other
top-level component instance. The second example attempts to set
the <samp class="codeph">label</samp> property of the Application object, not
the <samp class="codeph">label</samp> property of the Button.</p>
<p>Variables declared within a function are locally scoped to that
function. These variables can share the same name as variables in
outer scopes, and they do not affect the outer-scoped variable.
If a variable is just used temporarily by a single method, make
it a local variable of that method rather than an instance variable. Use
instance variables only for storing the state of an instance, because
each instance variable will take up memory for the entire lifetime
of the instance. You can refer to the outer-scoped variable with
the <samp class="codeph">this.</samp> prefix.</p>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff4_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff4_verapache"><!-- --></a>
<h2 class="topictitle2">Including versus importing ActionScript code</h2>
<div>
<p>To make your MXML code more readable,
you can reference ActionScript files in your <samp class="codeph">&lt;fx:Script&gt;</samp> tags,
rather than insert large blocks of script. You can either include
or import ActionScript files. </p>
<p>There is a distinct difference between including and importing
code in ActionScript. <em>Including</em> copies lines of code from
one file into another, as if they had been pasted at the position
of the <samp class="codeph">include</samp> statement. <em>Importing</em> adds
a reference to a class file or package so that you can access objects
and properties defined by external classes. Files that you import
must be found in the source path. Files that you include must be
located relative to the file that uses the <samp class="codeph">include</samp> statement,
or you must use an absolute path.</p>
<p>You use the <samp class="codeph">include</samp> statement or the <samp class="codeph">&lt;fx:Script source="<em>filename</em>"&gt;</samp> tag
to add ActionScript code to your applications.</p>
<p>You use <samp class="codeph">import</samp> statements in an <samp class="codeph">&lt;fx:Script&gt;</samp> block
to define the locations of ActionScript classes and packages that
your applications might use.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff3_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff3_verapache"><!-- --></a>
<h3 class="topictitle3">Including ActionScript files</h3>
<div>
<p>To include ActionScript code, you reference
an external ActionScript file in your <samp class="codeph">&lt;fx:Script&gt;</samp> tags.
At compile time, the compiler copies the entire contents of the
file into your MXML application, as if you had actually typed it.
As with ActionScript in an <samp class="codeph">&lt;fx:Script&gt;</samp> block,
ActionScript statements can only be inside functions. Included files
can also declare constants and namespaces, include other ActionScript
files, import declarations, and use namespaces. You cannot define
classes in included files.</p>
<p>Variables and functions defined in an included ActionScript file
are available to any component in the MXML file. An included ActionScript
file is not the same as an imported ActionScript class. Flex provides
access to the included file's variables and functions, but does
not add a new class, because the MXML file itself is a class.</p>
<p>Included ActionScript files do not need to be in the same directory
as the MXML file. However, you should organize your ActionScript
files in a logical directory structure.</p>
<p>There are two ways to include an external ActionScript file in
your application:</p>
<ul>
<li>
<p>The <samp class="codeph">source</samp> attribute of the <samp class="codeph">&lt;fx:Script&gt;</samp> tag.
This is the preferred method for including external ActionScript
class files.</p>
</li>
<li>
<p>The <samp class="codeph">include</samp> statement inside <samp class="codeph">&lt;fx:Script&gt;</samp> blocks.</p>
</li>
</ul>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff2_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff2_verapache"><!-- --></a>
<h4 class="topictitle4">Using the source attribute to include
ActionScript files</h4>
<div>
<p>You use the <samp class="codeph">source</samp> attribute of the <samp class="codeph">&lt;fx:Script&gt;</samp> tag
to include external ActionScript files in your applications. This
provides a way to make your MXML files less cluttered and promotes
code reuse across different applications. </p>
<p>Do not give the script file the same name as the application
file. This causes a compiler error.</p>
<p>The following example shows the contents of the IncludedFile.as
file:</p>
<pre class="codeblock">// usingas/includes/IncludedFile.as
public function computeSum(a:Number, b:Number):Number {
return a + b;
}</pre>
<p>The following example uses the <samp class="codeph">&lt;fx:Script&gt;</samp> tag
to include the contents of the IncludedFile.as file. This file is
located in the /includes subdirectory.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/SourceInclude.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script source="includes/IncludedFile.as"/&gt;
&lt;s:TextInput id="ta1st" text="3" width="40" x="170" y="24" textAlign="right"/&gt;
&lt;s:TextInput id="ta2nd" text="3" width="40" x="170" y="52" textAlign="right"/&gt;
&lt;s:TextArea id="taMain" height="25" width="78" x="132" y="82" textAlign="right"/&gt;
&lt;s:Button id="b1" label="Compute Sum"
click="taMain.text=String(computeSum(Number(ta1st.text), Number(ta2nd.text)));"
x="105" y="115"/&gt;
&lt;s:Label x="148" y="52" text="+" fontWeight="bold" fontSize="17" width="23"/&gt;
&lt;/s:Application&gt;</pre>
<p>The <samp class="codeph">source</samp> attribute of the <samp class="codeph">&lt;fx:Script&gt;</samp> tag
supports both relative and absolute paths. For more information,
see <a href="flx_usingas_ua.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee4_verapache">Referring
to external files that have been included</a>.</p>
<p>You cannot use the <samp class="codeph">source</samp> attribute of an <samp class="codeph">&lt;fx:Script&gt;</samp> tag
and wrap ActionScript code inside that same <samp class="codeph">&lt;fx:Script&gt;</samp> tag.
To include a file and write ActionScript in the MXML file, use two <samp class="codeph">&lt;fx:Script&gt;</samp> tags.</p>
</div>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff1_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff1_verapache"><!-- --></a>
<h4 class="topictitle4">Using the include directive</h4>
<div>
<p>The <samp class="codeph">include</samp> directive
is an ActionScript statement that copies the contents of the specified
file into your MXML file. The <samp class="codeph">include</samp> directive
uses the following syntax: </p>
<pre class="codeblock"> include "<em>file_name</em>";</pre>
<p>The following example includes the myfunctions.as file:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/IncludeASFile.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
/* The myfunctions.as file defines two methods that
return Strings. */
include "includes/myfunctions.as";
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="myButton"
label="Call Methods in Included File"
click="ta1.text=doSomething();ta1.text+=doSomethingElse()"/&gt;
&lt;s:TextArea width="268" id="ta1"/&gt;
&lt;s:Button label="Clear" click="ta1.text=''"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can specify only a single file for each <samp class="codeph">include</samp> directive,
but you can use any number of <samp class="codeph">include</samp> directives.
You can nest <samp class="codeph">include</samp> directives; files with <samp class="codeph">include</samp> directives
can include files that have <samp class="codeph">include</samp> directives.</p>
<p>The <samp class="codeph">include</samp> directive supports only relative
paths. For more information, see <a href="flx_usingas_ua.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ee4_verapache">Referring
to external files that have been included</a>.</p>
<p>You can use the <samp class="codeph">include</samp> only where multiple
statements are allowed. For example, the following is not allowed:</p>
<pre class="codeblock"> if (expr)
  include "foo.as"; // First statement is guarded by IF, but rest are not.
 ...</pre>
<p>The following is allowed:</p>
<pre class="codeblock"> if (expr) {
  include "foo.as"; // All statements inside { } are guarded by IF.
 }</pre>
<p>The use of curly braces ({ }) allows multiple statements because
you can add multiple statements inside the braces.</p>
<p>It's best that you not use the <samp class="codeph">include</samp> directive
if you use a large number of included ActionScript files. You should
try to break the code into separate class files where appropriate
and store them in logical package structures.</p>
</div>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf69084-7ee4_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ee4_verapache"><!-- --></a>
<h4 class="topictitle4">Referring to external files that
have been included</h4>
<div>
<p>The <samp class="codeph">source</samp> attribute
of the <samp class="codeph">&lt;fx:Script&gt;</samp> tag and the <samp class="codeph">include</samp> directive refer
to files in different ways.</p>
<p>The following are the valid paths to external files that are
referenced in an <samp class="codeph">&lt;fx:Script&gt;</samp> tag's <samp class="codeph">source</samp> attribute:</p>
<ul>
<li>
<p>Absolute
URLs, such as http://www.macromedia.com or file:///C|/site_flashteam/foo.gif.</p>
</li>
<li>
<p>Relative URLs, such as ../myscript.as. A relative URL that
does not start with a slash is resolved relative to the file that
uses it. If the tag <samp class="codeph">&lt;fx:Script source="../IncludedFile.as"&gt;</samp> is
included in "mysite/myfiles/myapp.mxml," the system searches for
"mysite/IncludedFile.as".</p>
</li>
</ul>
<p>For an ActionScript <samp class="codeph">include</samp> directive, you can
reference only relative URLs.</p>
<p>Flex searches the source path for imported classes and packages.
Flex does not search the source path for files that are included
using the <samp class="codeph">include</samp> directive or the <samp class="codeph">source</samp> attribute
of the <samp class="codeph">&lt;fx:Script&gt;</samp> tag. </p>
</div>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fef_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fef_verapache"><!-- --></a>
<h3 class="topictitle3">Importing classes and packages</h3>
<div>
<p>If you create many utility classes or include
multiple ActionScript files to access commonly used functions, you
might want to store them in a set of classes in their own package.
You can import ActionScript classes and packages using the <samp class="codeph">import</samp> statement.
By doing this, you do not have to explicitly enter the fully qualified
class names when accessing classes within ActionScript. </p>
<p>The following example imports the MyClass class in the MyPackage.Util
package:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/AccessingPackagedClasses.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import MyPackage.Util.MyClass;
private var mc:MyClass = new MyClass;
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="myButton" label="Click Me" click="myButton.label=mc.returnAString()"/&gt;
&lt;/s:Application&gt;</pre>
<p>In your ActionScript code, instead of referring to the class
with its fully qualified package name (MyPackage.Util.MyClass),
you refer to it as MyClass.</p>
<p>You can also use the wildcard character (*) to import the entire
package. For example, the following statement imports the entire
MyPackage.Util package:</p>
<pre class="codeblock"> import MyPackage.Util.*;</pre>
<p>Flex searches the source path for imported files and packages,
and includes only those that are used in the final SWF file. </p>
<p>It is not sufficient to simply specify the fully qualified class
name. You should use fully qualified class names only when necessary
to distinguish two classes with the same class name that reside
in different packages.</p>
<p>If you import a class but do not use it in your application,
the class is not included in the resulting SWF file's bytecode.
As a result, importing an entire package with a wildcard does not
create an unnecessarily large SWF file.</p>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fee_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fee_verapache"><!-- --></a>
<h2 class="topictitle2">Techniques for separating ActionScript from
MXML</h2>
<div>
<p>The
following sample application, which calls a single function, shows
several methods of separating ActionScript from the MXML. </p>
<p>The Temperature
application takes input from a single input field and uses a function
to convert the input from Fahrenheit to Celsius. It then displays
the resulting temperature in a Label control.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fed_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fed_verapache"><!-- --></a>
<h3 class="topictitle3">One MXML document (event handling
logic in event attribute)</h3>
<div>
<p>The following code shows the ActionScript event handling
logic inside the MXML tag's <samp class="codeph">click</samp> event:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ASOneFile.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
width="700"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;s:Panel title="Temperature Application" width="90%"&gt;
&lt;s:HGroup&gt;
&lt;s:Label text="Temperature in Fahrenheit:"/&gt;
&lt;s:TextInput id="fahrenheit" width="120"/&gt;
&lt;s:Button label="Convert"
click="celsius.text=String(Math.round((Number(fahrenheit.text)-32)/1.8 * 10)/10);"/&gt;
&lt;s:Label text="Temperature in Celsius:"/&gt;
&lt;s:Label id="celsius" width="120" fontSize="24"/&gt;
&lt;/s:HGroup&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fec_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fec_verapache"><!-- --></a>
<h3 class="topictitle3">One MXML document (event handling
logic in &lt;fx:Script&gt; block)</h3>
<div>
<p>In this example, the logic for the function is inside an <samp class="codeph">&lt;fx:Script&gt;</samp> block
in the MXML document, and is called from the MXML tag's <samp class="codeph">click</samp> event,
as the following code shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ASScriptBlock.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
width="700"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
public function calculate():void {
var n:Number = Number(fahrenheit.text);
var t:Number = Math.round((n-32)/1.8*10)/10;
celsius.text=String(t);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Panel title="Temperature Application" width="90%"&gt;
&lt;s:HGroup&gt;
&lt;s:Label text="Temperature in Fahrenheit:"/&gt;
&lt;s:TextInput id="fahrenheit" width="120"/&gt;
&lt;s:Button label="Convert" click="calculate();" /&gt;
&lt;s:Label text="Temperature in Celsius:"/&gt;
&lt;s:Label id="celsius" width="120" fontSize="24"/&gt;
&lt;/s:HGroup&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7feb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7feb_verapache"><!-- --></a>
<h3 class="topictitle3">One MXML document and one ActionScript
file (event handling logic in separate script file)</h3>
<div>
<p>Here, the function call is in an MXML event attribute,
and the function is defined in a separate ActionScript file, as
the following code shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ASSourceFile.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
width="700"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;!-- Specify the ActionScript file that contains the function. --&gt;
&lt;fx:Script source="includes/Sample3Script.as"/&gt;
&lt;s:Panel title="Temperature Application" width="90%"&gt;
&lt;s:HGroup&gt;
&lt;s:Label text="Temperature in Fahrenheit:"/&gt;
&lt;s:TextInput id="fahrenheit" width="120"/&gt;
&lt;s:Button label="Convert" click="celsius.text=calculate(fahrenheit.text);"/&gt;
&lt;s:Label text="Temperature in Celsius:"/&gt;
&lt;s:Label id="celsius" width="120" fontSize="24"/&gt;
&lt;/s:HGroup&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
<p>The Sample3Script.as ActionScript file contains the following
code:</p>
<pre class="codeblock">// usingas/includes/Sample3Script.as
public function calculate(s:String):String {
var n:Number = Number(s);
var t:Number = Math.round((n-32)/1.8*10)/10;
return String(t);
}</pre>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7fe3_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7fe3_verapache"><!-- --></a>
<h2 class="topictitle2">Creating ActionScript components</h2>
<div>
<p>You
can create reusable components that use ActionScript and reference
these components in your applications as MXML tags. Components created
in ActionScript can contain graphical elements, define custom business
logic, or extend existing components. They can inherit from any
components available in Flex.</p>
<p>Defining your own components in ActionScript has several benefits.
Components let you divide your applications into individual modules
that you can develop and maintain separately. By implementing commonly
used logic within custom components, you can build a suite of reusable
components that you can share among multiple applications. </p>
<p>Also, you can base your custom components on the set of components
by extending from the Flex class hierarchy. You can create custom
versions of Flex visual controls, as well as custom versions on
nonvisual components, such as data validators, formatters, and effects.</p>
<p>For
example, you can define a custom button, derived from the Button
control, in the myControls package, as the following example shows: </p>
<pre class="codeblock"> package myControls {
  import mx.controls.Button;
  public class MyButton extends Button {
  public function MyButton() {
  ...
  }
  ...
  }
 }</pre>
<p>In this example, you write your MyButton control to the MyButton.as
file, and you store the file in the myControls subdirectory of the
root directory of your application. The fully qualified class name
of your component reflects its location. In this example, the component's
fully qualified class name is myControls.MyButton.</p>
<p>You can reference your custom Button control from an application
file, such as MyApp.mxml, as the following example shows:</p>
<pre class="codeblock"> &lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:cmp="myControls.*"&gt;
<strong>&lt;cmp:MyButton label="Jack"/&gt;</strong>
 &lt;/s:Application&gt;</pre>
<p>In this example, you define the <samp class="codeph">cmp</samp> namespace
that defines the location of your custom component in the application's
directory structure. You then reference the component as an MXML
tag using the namespace prefix. </p>
<p>Typically, you put custom ActionScript components in directories
that are in the source path. These include any directory that you
specify in the source path. </p>
<p>You can also create custom components using MXML. For more information,
see <a href="flx_p8a_custom_components.html#WS4bebcd66a74275c35bf45738120d4f86190-8000_verapache">Custom
components</a>.</p>
</div>
<div class="nested2" id="WS02f7d8d4857b1677309f9423126233b4f18-8000_verapache"><a name="WS02f7d8d4857b1677309f9423126233b4f18-8000_verapache"><!-- --></a>
<h3 class="topictitle3">Types of custom components</h3>
<div>
<p>You
can create the following types of components in ActionScript:</p>
<dl>
<dt class="dlterm">User-interface components</dt>
<dd>
<p>
<em>User-interface components</em> contain
both processing logic and visual elements. These components usually
extend the component hierarchy. You can extend from the UIComponent
classes, or any of the components, such as Button, ComboBox, or
DataGrid. Your custom ActionScript component inherits all of the
public methods, along with public and protected properties of its
base class.</p>
</dd>
<dt class="dlterm">Nonvisual components</dt>
<dd>
<p>
<em>Nonvisual components</em> define
no visual elements. A nonvisual component is an ActionScript class
that does not extend the UIComponent class. They can provide greater
efficiency at run time.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe8_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe8_verapache"><!-- --></a>
<h2 class="topictitle2">Performing object introspection</h2>
<div>
<p>
<em>Object introspection</em> is
a technique for determining the elements of a class at run time,
such as its properties and methods. There are two ways to do introspection in
ActionScript: </p>
<ul>
<li>
<p>Using <samp class="codeph">for..in</samp> loops</p>
</li>
<li>
<p>Using the introspection API</p>
</li>
</ul>
<p>You might find object introspection a useful technique when debugging
your application. For example, you might write a method that takes
a generic object of type Object as an argument. You can use introspection
to output all of the properties and methods of the Object to determine
exactly what your application passed to it.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe7_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe7_verapache"><!-- --></a>
<h3 class="topictitle3">Using for..in loops</h3>
<div>
<p>You can use a <samp class="codeph">for..in</samp> loop to iterate
over objects and output their properties and their values. A <samp class="codeph">for..in</samp> loop
enumerates only dynamically added properties. Declared variables
and methods of classes are not enumerated in <samp class="codeph">for..in</samp> loops.
This means that most classes in the ActionScript API will not display
any properties in a <samp class="codeph">for..in</samp> loop. However, the
generic type Object is still a dynamic object and will display properties
in a <samp class="codeph">for..in</samp> loop.</p>
<p>The following example creates a generic Object, adds properties
to that object, and then iterates over that object when you click
the button to inspect its properties:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/IntrospectionForIn.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="initApp()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private var obj:Object = new Object();
private function initApp():void {
// Create the object.
obj.a = "Schotten Totten";
obj.b = "Taj Majal";
obj.c = "Durche die Wuste";
}
public function dumpObj():void {
for (var p:String in obj) {
ta1.text += p + ":" + obj[p] + "\n";
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:TextArea id="ta1" width="400" height="200"/&gt;
&lt;s:Button label="Dump Object" click="dumpObj()"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can also use the <samp class="codeph">mx.utils.ObjectUtil.toString()</samp> method <samp class="codeph"/>to print
all the dynamically added properties of an object, for example:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/ObjectUtilToString.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="initApp()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.utils.ObjectUtil;
private var obj:Object = new Object();
private function initApp():void {
// Create the object.
obj.a = "Schotten Totten";
obj.b = "Taj Majal";
obj.c = "Durche die Wuste";
}
public function dumpObj():void {
ta1.text = ObjectUtil.toString(obj);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:TextArea id="ta1" width="400" height="200"/&gt;
&lt;s:Button label="Dump Object" click="dumpObj()"/&gt;
&lt;/s:Application&gt;</pre>
<p>The mx.utils.ObjectUtil class has other useful methods such as <samp class="codeph">compare()</samp>, <samp class="codeph">copy()</samp>,
and <samp class="codeph">isSimple()</samp>. For more information, see the <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe6_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf61c8a-7fe6_verapache"><!-- --></a>
<h3 class="topictitle3">Using the introspection API</h3>
<div>
<p>If you want to list all the public properties and methods
of a nondynamic (or sealed) class or class instance, use the <samp class="codeph">describeType()</samp> method
and parse the results using the E4X API. The <samp class="codeph">describeType()</samp> method
is in the flash.utils package. The method's only parameter is the
target object that you want to introspect. You can pass it any ActionScript
value, including all available ActionScript types such as object
instances, primitive types such as <samp class="codeph">uint</samp>, and class
objects. The return value of the <samp class="codeph">describeType()</samp> method
is an E4X XML object that contains an XML description of the object's
type. </p>
<p>The <samp class="codeph">describeType()</samp> method returns only public
members. The method does not return private members of the caller's
superclass or any other class where the caller is not an instance.
If you call <samp class="codeph">describeType(this)</samp>, the method returns
information only about nonstatic members of the class. If you call <samp class="codeph">describeType(getDefinitionByName("MyClass"))</samp>,
the method returns information only about the target's static members.</p>
<p>The following example introspects the Button control and prints
the details to TextArea controls:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/IntrospectionAPI.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="getDetails()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import flash.utils.*;
public function getDetails():void {
// Get the Button control's E4X XML object description.
var classInfo:XML = describeType(button1);
// Dump the entire E4X XML object into ta2.
ta2.text = classInfo.toString();
// List the class name.
ta1.text = "Class " + classInfo.@name.toString() + "\n";
// List the object's variables, their values, and their types.
for each (var v:XML in classInfo..variable) {
ta1.text += "Variable " + v.@name + "=" + button1[v.@name] +
" (" + v.@type + ")\n";
}
// List accessors as properties.
for each (var a:XML in classInfo..accessor) {
// Do not get the property value if it is write only.
if (a.@access == 'writeonly') {
ta1.text += "Property " + a.@name + " (" + a.@type +")\n";
}
else {
ta1.text += "Property " + a.@name + "=" +
button1[a.@name] + " (" + a.@type +")\n";
}
}
// List the object's methods.
for each (var m:XML in classInfo..method) {
ta1.text += "Method " + m.@name + "():" + m.@returnType + "\n";
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="This Button Does Nothing" id="button1"/&gt;
&lt;s:TextArea id="ta1" width="400" height="200"/&gt;
&lt;s:TextArea id="ta2" width="400" height="200"/&gt;
&lt;/s:Application&gt;</pre>
<p>The output displays accessors, variables, and methods of the
Button control, and appears similar to the following:</p>
<pre class="codeblock"> Class mx.controls::Button
 ...
 Variable id=button1 (String)
 Variable __width=66 (Number)
 Variable layoutWidth=66 (Number)
 Variable __height=22 (Number)
 Variable layoutHeight=22 (Number)
 ...
 Property label=Submit (String)
 Property enabled=true (Boolean)
 Property numChildren=2 (uint)
 Property enabled=true (Boolean)
 Property visible=true (Boolean)
 Property toolTip=null (String)
 ...
 Method dispatchEvent():Boolean
 Method hasEventListener():Boolean
 Method layoutContents():void
 Method getInheritingStyle():Object
 Method getNonInheritingStyle():Object</pre>
<p>Another useful method is the ObjectUtil's <samp class="codeph">getClassInfo()</samp> method.
This method returns an Object with the name and properties of the
target object. The following example uses the <samp class="codeph">getClassInfo()</samp> and <samp class="codeph">toString()</samp> methods
to show the properties of the Button control:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- usingas/IntrospectionObjectUtil.mxml --&gt;
&lt;s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
height="650"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
private function showProps(b:Button):void {
var o:Object = ObjectUtil.getClassInfo(b);
ta1.text = ObjectUtil.toString(o);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Show Properties" click="showProps(b1)"/&gt;
&lt;s:TextArea id="ta1" width="300" height="500"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div>
<p><strong>Navigation</strong></p>
<p><a href="index.html">Using Flex</a> &raquo; <a href="flx_p1_gettingstarted.html">Getting Started</a></p>
</div>
<p>Adobe, Adobe AIR, Adobe Flash Platform, Adobe Flash Player and Adobe Flash Professional are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries and are used by permission from Adobe. No other license to the Adobe trademarks are granted.</p>
</div>
</body>
</html>