blob: 3bdb27ea47be9aa55cf89f0864dedf1fb4911429 [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="Events"/>
<meta name="DC.Format" content="XHTML"/>
<meta name="DC.Identifier" content="WS2db454920e96a9e51e63e3d11c0bf69084-7ee9_verapache"/>
<title>Events</title>
</head>
<body id="WS2db454920e96a9e51e63e3d11c0bf69084-7ee9_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ee9_verapache"><!-- --></a>
<div>
<p>One of the most important parts of your Flex application
is handling events by using controls and ActionScript.</p>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fff_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fff_verapache"><!-- --></a>
<h2 class="topictitle2">About Flex events</h2>
<div>
<p>Events
let a developer know when something happens within an application. They
can be generated by user devices, such as the mouse and keyboard,
or other external input, such as the return of a web service call.
Events are also triggered when changes happen in the appearance
or life cycle of a component, such as the creation or destruction
of a component or when the component is resized.</p>
<p>Any user interaction with your application can generate events.
Events can also occur without any direct user interaction, such
as when data finishes loading from a server or when an attached
camera becomes active. You can "handle" these events in your code
by adding an event handler. <em>Event handlers</em> are the functions
or methods that you write to respond to specific events. They are
also sometimes referred to as <em>event listeners</em>. </p>
<p>The Flex event model is based on the Document Object Model (DOM)
Level 3 events model. Although Flex does not adhere specifically
to the DOM standard, the implementations are very similar. The event
model in Flex comprises the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html" target="_blank">Event</a> object
and its subclasses, and the event dispatching model. For a quick start
in using events in Flex, see the sample code in <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cdf_verapache">Using
events</a>.</p>
<p>Components generate and dispatch events and <em>consume</em> (listen
to) other events. An object that requires information about another
object's events registers a listener with that object. When an event
occurs, the object dispatches the event to all registered listeners
by calling a function that was requested during registration. To
receive multiple events from the same object, you must register
your listener for each event.</p>
<p>Components have built-in events that you can handle in ActionScript
blocks in your MXML applications. You can also take advantage of
the Flex event system's dispatcher-listener model to define your
own event listeners outside of your applications, and define which
methods of your custom listeners will listen to certain events.
You can register listeners with the target object so that when the target
object dispatches an event, the listeners get called.</p>
<p>All visual objects, including Flex controls and containers, are
subclasses of the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html" target="_blank">DisplayObject</a> class.
They are in a tree of visible objects that make up your application.
The root of the tree is the Stage. Below that is the SystemManager
object, and then the Application object. Child containers and components
are leaf nodes of the tree. That tree is known as the <em>display list</em>.
An object on the display list is analogous to a node in the DOM
hierarchical structure. The terms <em>display list object</em> and <em>node</em> are
used interchangeably. </p>
<p>For information about each component's events, see the component's description
in <a href="flx_controls_ctr.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ff8_verapache">UI
Controls</a> or the control's entry in <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>. </p>
<p>For a detailed description of a component's startup life cycle,
including major events in that life cycle, see <a href="flx_ascomponents_advanced_asa.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cdd_verapache">Create
advanced MX visual components in ActionScript</a>.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache"><!-- --></a>
<h3 class="topictitle3">About the event flow</h3>
<div>
<p>You can instruct any container or control to listen for
events dispatched by another container or control. When Adobe<sup>®</sup> Flash<sup>®</sup> Player
dispatches an Event object, that Event object makes a roundtrip
journey from the root of the display list to the target node, checking
each node for registered listeners. The <em>target node</em> is the
node in the display list where the event occurred. For example,
if a user clicks a Button control named Child1, Flash Player dispatches
an Event object with Child1 defined as the target node.</p>
<p>The event flow
is conceptually divided into three parts: the capturing phase, the targeting
phase, and the bubbling phase, as briefly described next. For more information
about the event flow, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cdb_verapache">Event
propagation</a>.</p>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fdd_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fdd_verapache"><!-- --></a><h4 class="sectiontitle">About
the capturing phase</h4>
<p>The
first part of the event flow is called the <em>capturing phase</em>.
This phase comprises all of the nodes from the root node to the
parent of the target node. During this phase, Flash Player examines
each node, starting with the root, to see if it has a listener registered
to handle the event. If it does, Flash Player sets the appropriate values
of the Event object and then calls that listener. Flash Player stops
after it reaches the target node's parent and calls any listeners
registered on the parent. For more information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cde_verapache">Capturing
phase</a>.</p>
</div>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7ff1_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7ff1_verapache"><!-- --></a><h4 class="sectiontitle">About
the targeting phase</h4>
<p>The
second part of the event flow, the <em>targeting phase</em>, consists
solely of the target node. Flash Player sets the appropriate values
on the Event object, checks the target node for registered event
listeners, and then calls those listeners. For more information,
see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ccf_verapache">Targeting
phase</a>.</p>
</div>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fee_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe1_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fee_verapache"><!-- --></a><h4 class="sectiontitle">About
the bubbling phase</h4>
<p>The
third part of the event flow, the <em>bubbling phase</em>, comprises
all of the nodes from the target node's parent to the root node.
Starting with the target node's parent, Flash Player sets the appropriate
values on the Event object and then calls event listeners on each
of these nodes. Flash Player stops after calling any listeners on
the root node. For more information about the bubbling phase, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cce_verapache">Bubbling
phase</a>.</p>
</div>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffe_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffe_verapache"><!-- --></a>
<h3 class="topictitle3">About the Event class</h3>
<div>
<p>The <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html" target="_blank">Event</a>
class
is an ActionScript class with properties that contain information about
the event that occurred. An Event object is an implicitly created
object, similar to the request and response objects in a JavaServer
Page (JSP) that are implicitly created by the application server.</p>
<p>Flex creates an Event object each time an event is dispatched.
You can use the Event object inside an event listener to access
details about the event that was dispatched, or about the component
that dispatched the event. Passing an Event object to, and using
it in, an event listener is optional. However, if you want to access
the Event object's properties inside your event listeners, you must
pass the Event object to the listener. </p>
<p>Flex creates only one Event object when an event is dispatched.
During the bubbling and capturing phases, Flex changes the values
on the Event object as it moves up or down the display list, rather
than creating a new Event object for each node.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe4_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe4_verapache"><!-- --></a>
<h3 class="topictitle3">About event subclasses</h3>
<div>
<p>There are many classes that extend the flash.events.Event
class. These classes are defined mostly in the following packages:</p>
<ul>
<li>
<p>spark.events.*</p>
</li>
<li>
<p>mx.events.*</p>
</li>
<li>
<p>flash.events.*</p>
</li>
</ul>
<p>The mx.events package defines event classes that are specific
to most Flex controls, including the DataGridEvent, DragEvent, and
ColorPickerEvent. The spark.events package defines event classes
that are specific to a few Spark controls, including the TextOperationEvent
and VideoEvent. The flash.events package describes events that are
not unique to Flex but are instead defined by Flash Player. These
event classes include <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html" target="_blank">MouseEvent</a>, <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/DataEvent.html" target="_blank">DataEvent</a>,
and <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/TextEvent.html" target="_blank">TextEvent</a>. All
of these events are commonly used in applications.</p>
<p>In addition to these packages, some packages also define their
own event objects: for example, mx.messaging.events.ChannelEvent
and mx.logging.LogEvent.</p>
<p>Child classes of the Event class have additional properties and
methods that may be unique to them. In some cases, you will want
to use a more specific event type rather than the generic Event
object so that you can access these unique properties or methods.
For example, the LogEvent class has a <samp class="codeph">getLevelString()</samp> method
that the Event class does not.</p>
<p>For information on using Event subclasses, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ce0_verapache">Using
event subclasses</a>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe5_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe5_verapache"><!-- --></a>
<h3 class="topictitle3">About the EventDispatcher class</h3>
<div>
<p>Every object in the display list can trace its class inheritance
back to the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html" target="_blank">DisplayObject</a> class.
The DisplayObject class, in turn, inherits from the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html" target="_blank">EventDispatcher</a> class.
The EventDispatcher class is a base class that provides important
event model functionality for every object on the display list.
Because the DisplayObject class inherits from the EventDispatcher
class, any object on the display list has access to the methods
of the EventDispatcher class.</p>
<p>This is significant because every item on the display list can
participate fully in the event model. Every object on the display
list can use its <samp class="codeph">addEventListener()</samp> method—inherited
from the EventDispatcher class—to listen for a particular event,
but only if the listening object is part of the event flow for that
event.</p>
<p>Although the name EventDispatcher seems to imply that this class's
main purpose is to send (or dispatch) Event objects, the methods
of this class are used much more frequently to register event listeners,
check for event listeners, and remove event listeners.</p>
<p>The EventDispatcher class implements the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/IEventDispatcher.html" target="_blank">IEventDispatcher</a> interface.
This allows developers who create custom classes that cannot inherit
from EventDispatcher or one of its subclasses to implement the IEventDispatcher
interface to gain access to its methods. </p>
<p>The <samp class="codeph">addEventListener()</samp> method is the most commonly
used method of this class. You use it to register your event listeners.
For information on using the <samp class="codeph">addEventListener()</samp> method,
see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache">Using
the addEventListener() method</a>.</p>
<p>Advanced programmers use the <samp class="codeph">dispatchEvent()</samp> method
to manually dispatch an event or to send a custom Event object into
the event flow. For more information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ce1_verapache">Manually
dispatching events</a>.</p>
<p>Several other methods of the EventDispatcher class provide useful
information about the existence of event listeners. The <samp class="codeph">hasEventListener()</samp> method returns <samp class="codeph">true</samp> if
an event listener is found for that specific event type on a particular
display list object. The <samp class="codeph">willTrigger()</samp> method checks
for event listeners on a particular display list object, but it
also checks for listeners on all of that display list object's ancestors
for all phases of the event flow. The method returns <samp class="codeph">true</samp> if
it finds one.</p>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cdf_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cdf_verapache"><!-- --></a>
<h2 class="topictitle2">Using events</h2>
<div>
<p>Using events in Flex is a two-step process. First, you
write a function or class method, known as an <em>event listener</em> or <em>event handler</em>, that
responds to events. The function often accesses the properties of
the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html" target="_blank">Event</a> object
or some other settings of the application state. The signature of
this function usually includes an argument that specifies the event
type being passed in.</p>
<p>The
following example shows a simple event listener function that reports
when a control triggers the event that it is listening for:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SimpleEventHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function initApp():void {
b1.addEventListener(MouseEvent.CLICK, myEventHandler);
}
private function myEventHandler(event:Event):void {
Alert.show("An event occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>As you can see in this example, you also register that function
or class method with a display list object by using the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()" target="_blank">addEventListener()</a> method.</p>
<p>Most Flex controls simplify listener registration by letting
you specify the listener inside the MXML tag. For example, instead
of using the <samp class="codeph">addEventListener()</samp> method to specify
a listener function for the Button control's <samp class="codeph">click</samp> event,
you specify it in the <samp class="codeph">click</samp> attribute of the <samp class="codeph">&lt;mx:Button&gt;</samp> tag:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SimplerEventHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(event:Event):void {
Alert.show("An event occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>This is equivalent to the <samp class="codeph">addEventListener()</samp> method
in the previous code example. However, it is best practice to use
the <samp class="codeph">addEventListener()</samp> method. This method gives
you greater control over the event by letting you configure the
priority and capturing settings, and use event constants. In addition,
if you use <samp class="codeph">addEventListener()</samp> to add an event handler,
you can use <samp class="codeph">removeEventListener()</samp> to remove the
handler when you no longer need it. If you add an event handler
inline, you cannot call <samp class="codeph">removeEventListener()</samp> on
that handler.</p>
<p>Each time a control generates an event, Flex creates an Event
object that contains information about that event, including the
type of event and a reference to the dispatching control. To use
the Event object, you specify it as a parameter in the event handler
function, as the following example shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/EventTypeHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(e:Event):void {
Alert.show("An event of type '" + e.type + "' occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>If you want to access the Event object in an event handler that
was triggered by an inline event, you must add the <samp class="codeph">event</samp> keyword
inside the MXML tag so that Flex explicitly passes it to the handler,
as in the following:</p>
<pre class="codeblock"> &lt;mx:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;</pre>
<p>You are not required to use the Event object in a handler function.
The following example creates two event handler functions and registers
them with the events of a ComboBox control. The first event handler, <samp class="codeph">openEvt()</samp>,
takes no arguments. The second event handler, <samp class="codeph">changeEvt()</samp>,
takes the Event object as an argument and uses this object to access
the <samp class="codeph">value</samp> and <samp class="codeph">selectedIndex</samp> of the
ComboBox control that triggered the event.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/MultipleEventHandlers.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 openEvt():void {
forChange.text="";
}
private function changeEvt(e:Event):void {
forChange.text =
"Value: " + e.currentTarget.selectedItem + "\n" +
"Index: " + e.currentTarget.selectedIndex;
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:ComboBox open="openEvt()" change="changeEvt(event)"&gt;
&lt;s:dataProvider&gt;
&lt;s:ArrayList&gt;
&lt;fx:String&gt;AK&lt;/fx:String&gt;
&lt;fx:String&gt;AL&lt;/fx:String&gt;
&lt;fx:String&gt;AR&lt;/fx:String&gt;
&lt;/s:ArrayList&gt;
&lt;/s:dataProvider&gt;
&lt;/s:ComboBox&gt;
&lt;s:TextArea id="forChange" width="150" height="100"/&gt;
&lt;/s:Application&gt;</pre>
<p>This example shows accessing the <samp class="codeph">target</samp> property
of the Event object. For more information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd1_verapache">Accessing
the currentTarget property</a>.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff0_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff0_verapache"><!-- --></a>
<h3 class="topictitle3">Specifying the Event object</h3>
<div>
<p>You specify the object in a listener function's signature
as type Event, as the following example shows:</p>
<pre class="codeblock"> function myEventListener(e:Event):void { ... }</pre>
<p>However, if you want to access properties that are specific to
the type of event that was dispatched, you must instead specify
a more specific event type, such as ToolTipEvent or KeyboardEvent,
as the following example shows:</p>
<pre class="codeblock"> import mx.events.ToolTip
 function myEventListener(e:ToolTipEvent):void { ... }</pre>
<p>In some cases, you must import the event's class in your ActionScript
block.</p>
<p>Most objects have specific events that are associated with them,
and most of them can dispatch more than one type of event. </p>
<p>If you declare an event of type Event, you can cast it to a more
specific type to access its event-specific properties. For more
information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ce0_verapache">Using
event subclasses</a>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd1_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd1_verapache"><!-- --></a>
<h3 class="topictitle3">Accessing the currentTarget property</h3>
<div>
<p>Event objects include a reference to the
instance of the dispatching component (or <em>target</em>), which
means that you can access all the properties and methods of that
instance in an event listener. The following example accesses the <samp class="codeph">id</samp> of
the Button control that triggered the event:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/AccessingCurrentTarget.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(e:Event):void {
Alert.show("The button '" + e.currentTarget.id + "' was clicked.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can access members of the <samp class="codeph">currentTarget</samp>.
If you do not cast the current target to a specific type, the compiler
assumes that it is of type Object. Objects can have any property
or method because the Object type is dynamic in ActionScript. Therefore,
when accessing methods and properties of the <samp class="codeph">currentTarget</samp>,
it is best practice to cast <samp class="codeph">currentTarget</samp> to whatever
class you anticipate will dispatch that event. This gives you strong
type checking at compile time, and helps avoid the risk of throwing
a run-time error.</p>
<p>The following example casts the current target to a TextInput
class before calling the <samp class="codeph">selectRange()</samp> method,
but does not cast it before trying to set the <samp class="codeph">tmesis</samp> property.
The <samp class="codeph">tmesis</samp> property does not exist on the TextInput
class. This illustrates that you will get a run-time error but not
a compile-time error when you try to access members that don't exist,
unless you cast <samp class="codeph">currentTarget</samp> to a specific type
so that type checking can occur:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/InvokingOnCurrentTarget.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="500"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.core.UIComponent;
private function tiHandler(e:Event):void {
/*
The following enforces type checking:
*/
TextInput(e.currentTarget).selectRange(0,3);
/*
The following throws a run-time error but not a compile-time error:
e.currentTarget.tmesis = 4;
*/
/*
... unless you cast it to the expected type like the following. Then
the compiler throws an error.
TextInput(e.currentTarget).tmesis = 4;
*/
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:TextInput id="ti1" click="tiHandler(event)"
text="When you click on this control, the first three characters are selected."
width="400"/&gt;
&lt;/s:Application&gt;</pre>
<p>You could also cast <samp class="codeph">currentTarget</samp> to UIComponent
or some other more general class that still has methods of display
objects. That way, if you don't know exactly which control will
dispatch an event, at least you can ensure there is some type checking.</p>
<p>You can also access methods and properties of the <samp class="codeph">target</samp> property,
which contains a reference to the current node in the display list.
For more information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd3_verapache">About
the target and currentTarget properties</a>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffb_verapache"><!-- --></a>
<h3 class="topictitle3">Registering event handlers</h3>
<div>
<p>There
are several strategies that you can employ when you register event handlers
with your Flex controls:</p>
<ol>
<li>
<p>Define an event handler inline. This binds a call to
the handler function to the control that triggers the event.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SimplerEventHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(event:Event):void {
Alert.show("An event occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>In this example, whenever the
user clicks the Button control, Flex calls the <samp class="codeph">myClickHandler()</samp> function.</p>
<p>For
more information on defining event handlers inline, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd5_verapache">Defining
event listeners inline</a>.</p>
</li>
<li>
<p>Use the <samp class="codeph">addEventListener()</samp> method, as follows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SimpleEventHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function initApp():void {
b1.addEventListener(MouseEvent.CLICK, myEventHandler);
}
private function myEventHandler(event:Event):void {
Alert.show("An event occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>As with the previous example,
whenever the user clicks the Button control, Flex calls the <samp class="codeph">myClickHandler()</samp> handler
function. However, registering your event handlers using this method
provides more flexibility. You can register multiple components
with this event handler, add multiple handlers to a single component,
or remove the handler. For more information, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache">Using
the addEventListener() method</a>.</p>
</li>
<li>
<p>Create an event handler class and register components to
use the class for event handling. This approach to event handling
promotes code reuse and lets you centralize event handling outside
your MXML files. For more information on creating custom event handler
classes, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cd2_verapache">Creating
event handler classes</a>.</p>
</li>
</ol>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd5_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd5_verapache"><!-- --></a>
<h4 class="topictitle4">Defining event listeners inline</h4>
<div>
<p>The
simplest method of defining event handlers in applications is to
point to a handler function in the component's MXML tag. To do this,
you add any of the component's events as a tag attribute followed
by an ActionScript statement or function call.</p>
<p>You add an event handler inline using the following syntax:</p>
<pre class="codeblock"> &lt;s:<em>tag_name</em> <em>event_name</em>="<em>handler_function</em>"/&gt;</pre>
<p>For example, to listen for a Button control's <samp class="codeph">click</samp> event,
you add a statement in the <samp class="codeph">&lt;mx:Button&gt;</samp> tag's <samp class="codeph">click</samp> attribute.
If you add a function, you define that function in an ActionScript
block. The following example defines the <samp class="codeph">submitForm()</samp> function
as the handler for the Button control's <samp class="codeph">click</samp> event:</p>
<pre class="codeblock"> &lt;fx:Script&gt;&lt;![CDATA[
  function submitForm():void {
  // Do something.
  }
 ]]&gt;&lt;/fx:Script&gt;
 &lt;s:Button label="Submit" click="submitForm();"/&gt;</pre>
<p>Event handlers can include any valid ActionScript code, including
code that calls global functions or sets a component property to
the return value. The following example calls the <samp class="codeph">trace()</samp> global
function:</p>
<pre class="codeblock"> &lt;s:Button label="Get Ver" click="trace('The button was clicked');"/&gt;</pre>
<p>There is one special parameter that you can pass in an inline
event handler definition: the <samp class="codeph">event</samp> parameter.
If you add the <samp class="codeph">event</samp> keyword as a parameter, Flex
passes the Event object and inside the handler function, you can
then access all the properties of the Event object. </p>
<p>The following example passes the Event object to the <samp class="codeph">submitForm()</samp> handler function
and specifies it as type MouseEvent:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/MouseEventHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(event:MouseEvent):void {
// Do something with the MouseEvent object.
Alert.show("An event of type '" + event.type + "' occurred.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>It is best practice to include the <samp class="codeph">event</samp> keyword
when you define all inline event listeners and to specify the most
stringent Event object type in the resulting listener function (for
example, specify MouseEvent instead of Event).</p>
<p>You can use the Event object to access a reference to the target
object (the object that dispatched the event), the type of event
(for example, <samp class="codeph">click</samp>), or other relevant properties,
such as the row number and value in a list-based control. You can
also use the Event object to access methods and properties of the
target component, or the component that dispatched the event.</p>
<p>Although you will most often pass the entire Event object to
an event listener, you can just pass individual properties, as the
following example shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/PropertyHandler.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myEventHandler(s:String):void {
Alert.show("Current Target: " + s);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="myEventHandler(event.currentTarget.id)"/&gt;
&lt;/s:Application&gt;</pre>
<p>Registering an event listener inline provides less flexibility
than using the <samp class="codeph">addEventListener()</samp> method to register
event listeners. The drawbacks are that you cannot set the <samp class="codeph">useCapture</samp> or <samp class="codeph">priority</samp> properties
on the Event object and that you cannot remove the listener once
you add it.</p>
</div>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache"><!-- --></a>
<h4 class="topictitle4">Using the addEventListener() method</h4>
<div>
<p>The <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()" target="_blank">addEventListener()</a> method
lets you register event listener functions with the specified control
or object. The following example adds the <samp class="codeph">myClickListener()</samp> function
to the b1 instance of a Button control. When the user clicks b1,
Flex calls the <samp class="codeph">myClickListener()</samp> method:</p>
<pre class="codeblock"> b1.addEventListener(MouseEvent.CLICK, myClickListener);</pre>
<p>The <samp class="codeph">addEventListener()</samp> method has the following
signature:</p>
<pre class="codeblock"><em>componentInstance</em>.addEventListener(
<em>event_type</em>:String,
<em>event_listener</em>:Function,
<em>use_capture</em>:Boolean,
<em>priority</em>:int,
<em>weakRef</em>:Boolean
)</pre>
<p>The <samp class="codeph">
<em>event_type</em>
</samp> argument is the kind of
event that this component dispatches. This can be either the event
type String (for example, "click" or "mouseOut") or the event type
static constant (such as <samp class="codeph">MouseEvent.CLICK</samp> or <samp class="codeph">MouseEvent.MOUSE_OUT</samp>).
This argument is required.</p>
<p>The constants provide an easy way to refer to specific event
types. You should use these constants instead of the strings that
they represent. If you misspell a constant name in your code, the
compiler catches the mistake. If you instead use strings and make
a typographical error, it can be harder to debug and could lead to
unexpected behavior.</p>
<p>You should use the constants wherever possible. For example,
when you are testing to see whether an Event object is of a certain
type, use the following code:</p>
<pre class="codeblock"> if (myEventObject.type == MouseEvent.CLICK) {/* your code here */}</pre>
<p>Do not use the following code:</p>
<pre class="codeblock"> if (myEventObject.type == "click") {/* your code here */}</pre>
<p>The <em>event_listener</em> argument is the function that handles
the event. This argument is required.</p>
<p>The <samp class="codeph">
<em>use_capture</em>
</samp> parameter of the <samp class="codeph">addEventListener()</samp> method
lets you control the phase in the event flow in which your listener
will be active. It sets the value of the <samp class="codeph">useCapture</samp> property
of the Event object. If <samp class="codeph">useCapture</samp> is set to <samp class="codeph">true</samp>,
your listener is active during the capturing phase of the event
flow. If <samp class="codeph">useCapture</samp> is set to <samp class="codeph">false</samp>,
your listener is active during the targeting and bubbling phases
of the event flow, but not during the capturing phase. The default
value is determined by the type of event, but is <samp class="codeph">false</samp> in
most cases. </p>
<p>To listen for an event during all phases of the event flow, you
must call <samp class="codeph">addEventListener()</samp> twice, once with the <samp class="codeph">useCapture</samp> parameter
set to <samp class="codeph">true</samp>, and again with <samp class="codeph">
<em>use_capture</em>
</samp> set
to <samp class="codeph">false</samp>. This argument is optional. For more information,
see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cde_verapache">Capturing
phase</a>.</p>
<p>The <em>priority</em> parameter sets the priority for that event
listener. The higher the number, the sooner that event handler executes
relative to other event listeners for the same event. Event listeners
with the same priority are executed in the order that they were
added. This parameter sets the <samp class="codeph">priority</samp> property
of the Event object. The default value is 0, but you can set it
to negative or positive integer values. If several event listeners
are added without priorities, the earlier a listener is added, the
sooner it is executed. For more information on setting priorities,
see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cda_verapache">Event
priorities</a>.</p>
<p>The <em>weakRef</em> parameter provides you with some control over
memory resources for listeners. A strong reference (when <samp class="codeph">weakRef</samp> is <samp class="codeph">false</samp>)
prevents the listener from being garbage collected. A weak reference
(when <samp class="codeph">weakRef</samp> is <samp class="codeph">true</samp>) does not.
The default value is <samp class="codeph">false</samp>.</p>
<p>When you add a listener function and that function is invoked,
Flex implicitly creates an Event object for you and passes it to
the listener function. You must declare the Event object in the
signature of your listener function. </p>
<p>If you add an event listener by using the <samp class="codeph">addEventListener()</samp> method,
you are required to declare an event object as a parameter of the <samp class="codeph">
<em>listener_function</em>
</samp>,
as the following example shows:</p>
<pre class="codeblock"> b1.addEventListener(MouseEvent.CLICK, performAction);</pre>
<p>In the listener function, you declare the Event object as a parameter,
as follows:</p>
<pre class="codeblock"> public function performAction(e:MouseEvent):void {
  ...
 }</pre>
<p>The following example defines a new handler function <samp class="codeph">myClickListener()</samp>. It
then registers the <samp class="codeph">click</samp> event of the Button control
with that handler. When the user clicks the button, Flex calls the <samp class="codeph">myClickHandler()</samp> function.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/AddEventListenerExample.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"
initialize="createListener()"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function createListener():void {
b1.addEventListener(MouseEvent.CLICK, myClickHandler, false, 0);
}
private function myClickHandler(e:MouseEvent):void {
Alert.show("The button was clicked.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="Click Me" id="b1"/&gt;
&lt;/s:Application&gt;</pre>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7feb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7feb_verapache"><!-- --></a><h5 class="sectiontitle">Using
addEventListener() inside an MXML tag</h5>
<p>You can add event listeners with
the <samp class="codeph">addEventListener()</samp> method inline with the component
definition. The following Button control definition adds the call
to the <samp class="codeph">addEventListener()</samp> method inline with the
Button control's <samp class="codeph">initialize</samp> property:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/CallingAddEventListenerInline.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function myClickHandler(event:Event):void {
Alert.show("The button was clicked.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id='b1'
label="Click Me"
initialize='b1.addEventListener(MouseEvent.CLICK, myClickHandler, false, 1);'
/&gt;
&lt;/s:Application&gt;</pre>
<p>This is the equivalent of defining
the event handler inline. However, defining a handler by using the <samp class="codeph">addEventListener()</samp> method
rather than setting <samp class="codeph">click="</samp>
<em>
<samp class="codeph">handler_function</samp>
</em>
<samp class="codeph">"</samp> lets
you set the value of the <samp class="codeph">useCapture</samp> and <samp class="codeph">priority</samp> properties
of the Event object. Furthermore, you cannot remove a handler added
inline, but when you use the <samp class="codeph">addEventListener()</samp> method to
add a handler, you can call the <samp class="codeph">removeEventListener()</samp> method
to remove that handler.</p>
</div>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fdc_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fdc_verapache"><!-- --></a><h5 class="sectiontitle">Using
nested inner functions as event listeners</h5>
<p>Rather
than passing the name of an event listener function to the <samp class="codeph">addEventListener()</samp> method,
you can define an inner function (also known as a closure). </p>
<p>In
the following example, the nested inner function is called when
the button is clicked:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/AddingInnerFunctionListener.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;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function initApp():void {
b1.addEventListener("click",
function(e:Event):void {
Alert.show("The button was clicked.");
}
);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id='b1' label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>Function closures are created
any time a function is executed apart from an object or a class.
They retain the scope in which they were defined. This creates interesting
results when a function is passed as an argument or a return value into
a different scope. </p>
<p>For example, the following code creates
two functions: <samp class="codeph">foo()</samp>, which returns a nested function
named <samp class="codeph">rectArea()</samp> that calculates the area of a
rectangle, and <samp class="codeph">bar()</samp>, which calls <samp class="codeph">foo()</samp> and
stores the returned function closure in a variable named <samp class="codeph">myProduct</samp>.
Even though the <samp class="codeph">bar()</samp> function defines its own
local variable <samp class="codeph">x</samp> (with a value of 2), when the
function closure <samp class="codeph">myProduct()</samp> is called, it retains
the variable <samp class="codeph">x</samp> (with a value of 40) defined in
function <samp class="codeph">foo()</samp>. The <samp class="codeph">bar()</samp> function
therefore returns the product of the numbers in the TextInput controls,
rather than 8.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/FunctionReturnsFunction.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="foo()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
[Bindable]
private var answer:String;
private function foo():Function {
var x:int = int(ti1.text);
function rectArea(y:int):int { // function closure defined
return x * y;
}
return rectArea;
}
private function bar():void {
var x:int = 2; // ignored
var y:int = 4; // ignored
var myProduct:Function = foo();
answer = myProduct(int(ti2.text)); // function closure called
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Form width="107"&gt;
&lt;s:FormItem label="X"&gt;
&lt;s:TextInput id="ti1" text="10" width="37" textAlign="right"/&gt;
&lt;/s:FormItem&gt;
&lt;s:FormItem label="Y" width="71"&gt;
&lt;s:TextInput id="ti2" text="20" width="38" textAlign="right"/&gt;
&lt;/s:FormItem&gt;
&lt;s:Label id="label1" text="{answer}" width="71" textAlign="right"/&gt;
&lt;/s:Form&gt;
&lt;s:Button id='b1' label="Compute Product" click="bar()"/&gt;
&lt;/s:Application&gt;</pre>
<p>If the listener that you pass
to <samp class="codeph">addEventListener()</samp> method is a nested inner
function, you should not pass <samp class="codeph">true</samp> for the <samp class="codeph">useWeakReference</samp> argument.
For example:</p>
<pre class="codeblock"> addEventListener("anyEvent",
  function(e:Event) { /* My listener function. */ },
  false, 0, true);</pre>
<p>In this example, passing <samp class="codeph">true</samp> as
the last argument can lead to unexpected results. To Flex, an inner
function is actually an object, and can be freed by the garbage
collector. If you set the value of the <samp class="codeph">useWeakReference</samp> argument
to <samp class="codeph">true</samp>, as shown in the previous example, there
are no persistent references at all to the inner function. The next
time the garbage collector runs, it might free the function, and
the function will not be called when the event is triggered.</p>
<p>If
there are other references to the inner function (for example, if
you saved it in another variable), the garbage collector will not
free it.</p>
<p>Regular class-level member functions are not subject
to garbage collection; as a result, you can set the value of the <samp class="codeph">useWeakReference</samp> argument
to <samp class="codeph">true</samp> and they will not be garbage collected.</p>
</div>
<div class="section" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fe2_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd9_verapache__WS2db454920e96a9e51e63e3d11c0bf64a29-7fe2_verapache"><!-- --></a><h5 class="sectiontitle">Removing
event handlers</h5>
<p>It
is a good idea to remove any handlers that will no longer be used.
This removes references to objects so that they can be targeted
for garbage collection. You can use the <samp class="codeph">removeEventListener()</samp> method
to remove an event handler that you no longer need. All components
that can call <samp class="codeph">addEventListener()</samp> can also call
the <samp class="codeph">removeEventListener()</samp> method. The syntax for
the <samp class="codeph">removeEventListener()</samp> method is as follows:</p>
<pre class="codeblock"><em>componentInstance</em>.removeEventListener(<em>event_type</em>:String, <em>listener_function</em>:Function, <em>use_capture</em>:Boolean)</pre>
<p>For
example, consider the following code:</p>
<pre class="codeblock"> myButton.removeEventListener(MouseEvent.CLICK, myClickHandler);</pre>
<p>The <em>event_type</em> and <em>listener_function</em> parameters
are required. These are the same as the required parameters for
the <samp class="codeph">addEventListener()</samp> method.</p>
<p>The <em>use_capture</em> parameter
is also identical to the parameter used in the <samp class="codeph">addEventListener()</samp> method.
Recall that you can listen for events during all event phases by
calling <samp class="codeph">addEventListener()</samp> twice: once with <em>use_capture</em> set
to <samp class="codeph">true</samp>, and again with it set to <samp class="codeph">false</samp>.
To remove both event listeners, you must call <samp class="codeph">removeEventListener()</samp> twice:
once with <em>use_capture</em> set to <samp class="codeph">true</samp>, and again
with it set to <samp class="codeph">false</samp>.</p>
<p>You can remove only
event listeners that you added with the <samp class="codeph">addEventListener()</samp> method
in an ActionScript block. You cannot remove an event listener that
was defined in the MXML tag, even if it was registered using a call
to the <samp class="codeph">addEventListener()</samp> method that was made
inside a tag attribute. </p>
<p>The following sample application
shows what type of handler can be removed and what type cannot:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/RemoveEventListenerExample.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"
initialize="createHandler(event)"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function createHandler(e:Event):void {
b1.addEventListener(MouseEvent.CLICK, myClickHandler);
}
private function removeMyHandlers(e:Event):void {
/* Remove listener for b1's click event because it was added
with the addEventListener() method. */
b1.removeEventListener(MouseEvent.CLICK, myClickHandler);
/* Does NOT remove the listener for b2's click event because it
was added inline in an MXML tag. */
b2.removeEventListener(MouseEvent.CLICK, myClickHandler);
}
private function myClickHandler(e:Event):void {
Alert.show("The button was clicked.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;s:Button label="Click Me Too" id="b2" click="myClickHandler(event)"/&gt;
&lt;s:Button label="Remove Event Listeners" id="b3" click="removeMyHandlers(event)"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
</div>
<div class="nested3" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd2_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd2_verapache"><!-- --></a>
<h4 class="topictitle4">Creating event handler classes</h4>
<div>
<p>You
can create an external class file and use the methods of this class
as event handlers. Objects themselves cannot be event handlers,
but methods of an object can be. By defining one class that handles
all your event handlers, you can use the same event handling logic
across applications, which can make your MXML applications more
readable and maintainable.</p>
<p>To create a class that handles events, you usually import the
flash.events.Event class. You also usually write an empty constructor.
The following ActionScript class file calls the Alert control's <samp class="codeph">show()</samp> method
whenever it handles an event with the <samp class="codeph">handleAllEvents()</samp> method:</p>
<pre class="codeblock">// events/MyEventHandler.as
package { // Empty package.
import flash.events.Event;
import mx.controls.Alert;
public class MyEventHandler {
public function MyEventHandler() {
// Empty constructor.
}
public function handleAllEvents(event:Event):void {
Alert.show("Some event happened.");
}
}
}</pre>
<p>In your MXML file, you declare a new instance of MyEventHandler
and use the <samp class="codeph">addEventListener()</samp> method to register
its <samp class="codeph">handleAllEvents()</samp> method as a handler to the
Button control's <samp class="codeph">click</samp> event, as the following example
shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/CustomHandler.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"
initialize="createHandler()"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private var myListener:MyEventHandler = new MyEventHandler();
private function createHandler():void {
b1.addEventListener(MouseEvent.CLICK, myListener.handleAllEvents);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="Submit" id="b1"/&gt;
&lt;/s:Application&gt;</pre>
<p>The best approach is to define the event handler's method as
static. When you make the event handler method static, you are not
required to instantiate the class inside your MXML application.
The following <samp class="codeph">createHandler()</samp> function registers
the <samp class="codeph">handleAllEvents()</samp> method as an event handler without
instantiating the MyStaticEventHandler class:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/CustomHandlerStatic.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"
initialize="createHandler()"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private function createHandler():void {
b1.addEventListener(MouseEvent.CLICK, MyStaticEventHandler.handleAllEvents);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="Submit" id="b1"/&gt;
&lt;/s:Application&gt;</pre>
<p>In the class file, you just add the <samp class="codeph">static</samp> keyword
to the method signature:</p>
<pre class="codeblock">// events/MyStaticEventHandler.as
package { // Empty package.
import flash.events.Event;
import mx.controls.Alert;
public class MyStaticEventHandler {
public function MyStaticEventHandler() {
// Empty constructor.
}
public static function handleAllEvents(event:Event):void {
Alert.show("Some event happened.");
}
}
}</pre>
<p>Store your event listener class in a directory in your source
path. You can also store your ActionScript class in the same directory
as your MXML file, although it is not recommended.</p>
</div>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fdf_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fdf_verapache"><!-- --></a>
<h3 class="topictitle3">Defining multiple listeners for
a single event</h3>
<div>
<p>You can define multiple event handler functions for a single
event in two ways. When defining events inside MXML tags, you separate
each new handler function with a semicolon. The following example
adds the <samp class="codeph">submitForm()</samp> and <samp class="codeph">debugMessage()</samp> functions
as handlers of the <samp class="codeph">click</samp> event:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/MultipleEventHandlersInline.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[
[Bindable]
private var s:String = "";
private function submitForm(e:Event):void {
// Handle event here.
s += "The submitForm() method was called. ";
}
private function debugMessage(e:Event):void {
// Handle event here.
s += "The debugMessage() method was called. ";
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:Button id="b1"
label="Do Both Actions"
click='submitForm(event); debugMessage(event);'
/&gt;
&lt;s:Label id="l1" text="{s}"/&gt;
&lt;s:Button id="b2" label="Reset" click="s='';"/&gt;
&lt;/s:Application&gt;</pre>
<p>For events added with the <samp class="codeph">addEventListener()</samp> method,
you can add any number of handlers with additional calls to the <samp class="codeph">addEventListener()</samp> method.
Each call adds a handler function that you want to register to the specified
object. The following example registers the <samp class="codeph">submitForm()</samp> and <samp class="codeph">debugMessage()</samp> handler
functions with b1's <samp class="codeph">click</samp> event:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/MultipleEventHandlersAS.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="createHandlers(event)"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
[Bindable]
private var s:String = "";
public function createHandlers(e:Event):void {
b1.addEventListener(MouseEvent.CLICK, submitForm);
b1.addEventListener(MouseEvent.CLICK, debugMessage);
}
private function submitForm(e:Event):void {
// Handle event here.
s += "The submitForm() method was called. ";
}
private function debugMessage(e:Event):void {
// Handle event here.
s += "The debugMessage() method was called. ";
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Do Both Actions"/&gt;
&lt;s:Label id="l1" text="{s}"/&gt;
&lt;s:Button id="b2" label="Reset" click="s='';"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can mix the methods of adding event handlers to any component;
alternatively, you can add handlers inline and with the <samp class="codeph">addEventListener()</samp> method.
The following example adds a <samp class="codeph">click</samp> event handler
inline for the Button control, which calls the <samp class="codeph">performAction()</samp> method.
It then conditionally adds a second <samp class="codeph">click</samp> handler
to call the <samp class="codeph">logAction()</samp> method, depending on the
state of the CheckBox control.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/ConditionalHandlers.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"
initialize="initApp(event)"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function initApp(e:Event):void {
cb1.addEventListener(MouseEvent.CLICK, handleCheckBoxChange);
b1.addEventListener(MouseEvent.CLICK, logAction);
}
private function handleCheckBoxChange(e:Event):void {
if (cb1.selected) {
b1.addEventListener(MouseEvent.CLICK, logAction);
ta1.text += "Added log listener." + "\n";
} else {
b1.removeEventListener(MouseEvent.CLICK, logAction);
ta1.text += "Removed log listener." + "\n";
}
}
private function performAction(e:Event):void {
Alert.show("You performed the action.");
}
private function logAction(e:Event):void {
ta1.text += "Action performed: " + e.type + ".\n";
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="Perform Action" id="b1" click="performAction(event)"/&gt;
&lt;s:CheckBox id="cb1" label="Log?" selected="true"/&gt;
&lt;s:TextArea id="ta1" height="200" width="300"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can set the order in which event listeners are called by
using the <samp class="codeph">priority</samp> parameter of the <samp class="codeph">addEventListener()</samp> method.
You cannot set a priority for a listener function if you added the
event listener using MXML inline. For more information on setting
priorities, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cda_verapache">Event
priorities</a>.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fde_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fde_verapache"><!-- --></a>
<h3 class="topictitle3">Registering a single listener with
multiple components</h3>
<div>
<p>You can register the same listener function with any number
of events of the same component, or events of different components.
The following example registers a single listener function, <samp class="codeph">submitForm()</samp>,
with two different buttons:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/OneHandlerTwoComponentsInline.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 mx.controls.Alert;
private function submitForm(e:Event):void {
// Handle event here.
Alert.show("Current Target: " + e.currentTarget.id);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1"
label="Click Me"
click="submitForm(event)"/&gt;
&lt;s:Button id="b2"
label="Click Me, Too"
click="submitForm(event)"/&gt;
&lt;/s:Application&gt;</pre>
<p>When
you use the <samp class="codeph">addEventListener()</samp> method to register
a single listener to handle the events of multiple components, you
must use a separate call to the <samp class="codeph">addEventListener()</samp> method
for each instance, as the following example shows: </p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/OneHandlerTwoComponentsAS.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="createHandlers(event)"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
public function createHandlers(e:Event):void {
b1.addEventListener(MouseEvent.CLICK, submitForm);
b2.addEventListener(MouseEvent.CLICK, submitForm);
}
private function submitForm(e:Event):void {
// Handle event here.
Alert.show("Current Target: " + e.currentTarget.id);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;s:Button id="b2" label="Click Me, Too"/&gt;
&lt;/s:Application&gt;</pre>
<p>When doing this, you should add logic to the event listener that
processes the type of event. The event target (or object that dispatched
the event) is added to the Event object for you. No matter what
triggered the event, you can conditionalize the event processing
based on the <samp class="codeph">target</samp> or <samp class="codeph">type</samp> properties
of the Event object. Flex adds these two properties to all Event
objects.</p>
<p>The following example registers a single listener function (<samp class="codeph">myEventHandler()</samp>)
to the <samp class="codeph">click</samp> event of a Button control and the <samp class="codeph">click</samp> event
of a CheckBox control. To detect what type of object called the
event listener, the listener checks the <samp class="codeph">className</samp> property
of the target in the Event object in a <samp class="codeph">case</samp> statement.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/ConditionalTargetHandler.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.controls.Alert;
public function initApp():void {
button1.addEventListener(MouseEvent.CLICK, myEventHandler);
cb1.addEventListener(MouseEvent.CLICK, myEventHandler);
}
public function myEventHandler(event:Event):void {
switch (event.currentTarget.className) {
case "Button":
// Process Button click.
Alert.show("You clicked the Button control.");
break;
case "CheckBox":
// Process CheckBox click.
Alert.show("You clicked the CheckBox control.");
break;
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button label="Click Me" id="button1"/&gt;
&lt;s:CheckBox label="Select Me" id="cb1"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff7_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff7_verapache"><!-- --></a>
<h3 class="topictitle3">Passing additional parameters to
listener functions</h3>
<div>
<p>You can pass additional parameters to listener functions
depending on how you add the listeners. If you add a listener with
the <samp class="codeph">addEventListener()</samp> method, you cannot pass
any additional parameters to the listener function by arbitrarily
adding new parameters to the function signature. The default listener function
can declare only a single argument, the Event object (or one of
its subclasses).</p>
<p>For example, the following code throws an error because the <samp class="codeph">clickListener()</samp> method
expects two arguments:</p>
<pre class="codeblock"> &lt;fx:Script&gt;
  public function addListeners():void {
  b1.addEventListener(MouseEvent.CLICK,clickListener);
  }
  public function clickListener(e:MouseEvent, a:String):void { ... }
 &lt;/fx:Script&gt;
 &lt;mx:Button id="b1"/&gt;</pre>
<p>Because the second parameter of the <samp class="codeph">addEventListener()</samp> method
is a function, you can define that function and pass the event object
plus any additional parameters through to a different handler. The
following example creates a new function in the <samp class="codeph">addEventListener()</samp> method,
add two parameters to the new handler's call, and then handles all
of the parameters in the <samp class="codeph">myClickListener()</samp> method.</p>
<pre class="codeblock">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!-- events/CustomListenerFunction.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(event)"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private var specialParam1:String;
private var specialParam2:String = "42";
private function initApp(e:Event):void {
assignSpecialParam(e);
/* Change the value of specialParam whenever the user changes it
in the TextInput and clicks the button. */
ti1.addEventListener("focusOut", assignSpecialParam);
/* Define the pass-through method in the addEventListener() method call.
You can add any number of parameters, as long as teh target method's
signature agrees. */
myButton.addEventListener(MouseEvent.CLICK, function (e:MouseEvent):void {
myClickListener(e, specialParam1, specialParam2);
}
);
}
private function assignSpecialParam(e:Event):void {
specialParam1 = ti1.text;
}
/* This method acts as the event listener, and it has any
number of parameters that we defined in the addEventListener() call. */
private function myClickListener(e:MouseEvent, s1:String, s2:String) : void {
myButton.label = s1 + " " + s2;
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="myButton" label="Click Me"/&gt;
&lt;s:TextInput id="ti1" text="Enter a custom String here." width="250"/&gt;
&lt;/s:Application&gt;</pre>
<p>Another approach to passing additional parameters to the listener
function is to define them in the listener function and then call
the final method with those parameters. If you define an event listener
inline (inside the MXML tag), you can add any number of parameters
as long as the listener function's signature agrees with that number
of parameters. </p>
<p>The following example passes a string and the Event object to
the <samp class="codeph">runMove()</samp> method:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/MultipleHandlerParametersInline.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 runMove(dir:String, e:Event):void {
if (dir == "up") {
moveableButton.y = moveableButton.y - 5;
} else if (dir == "down") {
moveableButton.y = moveableButton.y + 5;
} else if (dir == "left") {
moveableButton.x = moveableButton.x - 5;
} else if (dir == "right") {
moveableButton.x = moveableButton.x + 5;
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;mx:Canvas height="100%" width="100%"&gt;
&lt;s:Button id="moveableButton"
label="{moveableButton.x.toString()},{moveableButton.y.toString()}"
x="75"
y="100"
width="80"
/&gt;
&lt;/mx:Canvas&gt;
&lt;s:VGroup horizontalAlign="center"&gt;
&lt;s:Button id="b1"
label="Up"
click='runMove("up",event);'
width="75"/&gt;
&lt;s:HGroup horizontalAlign="center"&gt;
&lt;mx:Button id="b2"
label="Left"
click='runMove("left",event);'
width="75"/&gt;
&lt;s:Button id="b3"
label="Right"
click='runMove("right",event);'
width="75"/&gt;
&lt;/s:HGroup&gt;
&lt;s:Button id="b4"
label="Down"
click='runMove("down",event);'
width="75"/&gt;
&lt;/s:VGroup&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7ce1_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ce1_verapache"><!-- --></a>
<h2 class="topictitle2">Manually dispatching events</h2>
<div>
<p>You can manually dispatch events using a component instance's <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#dispatchEvent()" target="_blank">dispatchEvent()</a> method.
All components that extend <a href="https://flex.apache.org/asdoc/mx/core/UIComponent.html" target="_blank">UIComponent</a> have
this method. The method is inherited from the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html" target="_blank">EventDispatcher</a> class,
which UIComponent extends.</p>
<p>The syntax for the <samp class="codeph">dispatchEvent()</samp> method
is as follows:</p>
<pre class="codeblock"> objectInstance.dispatchEvent(event:Event):Boolean</pre>
<p>When dispatching an event, you must create a new Event object.
The syntax for the Event object constructor is as follows:</p>
<pre class="codeblock"> Event(<em>event_type</em>:String, <em>bubbles</em>:Boolean, <em>cancelable</em>:Boolean)</pre>
<p>The <em>event_type</em> parameter is the <samp class="codeph">type</samp> property
of the Event object. The <em>bubbles</em> and <em>cancelable</em> parameters
are optional and both default to <samp class="codeph">false</samp>. For information
on bubbling and capturing, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7cdb_verapache">Event
propagation</a>.</p>
<p>You can use the <samp class="codeph">dispatchEvent()</samp> method to dispatch
any event you want, not just a custom event. You can dispatch a
Button control's <samp class="codeph">click</samp> event, even though the user
did not click a Button control, as in the following example:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/DispatchEventExample.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"
initialize="createListener(event);"&gt;
&lt;fx:Script&gt;&lt;![CDATA[
import mx.controls.Alert;
private function createListener(e:Event):void {
b1.addEventListener(MouseEvent.MOUSE_OVER, myEventHandler);
b1.addEventListener(MouseEvent.CLICK, myClickHandler);
}
private function myEventHandler(e:Event):void {
var result:Boolean = b1.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, false));
}
private function myClickHandler(e:Event):void {
Alert.show("The event dispatched by the MOUSE_OVER was of type '" + e.type + "'.");
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can also manually dispatch an event in an MXML tag. In the
following example, moving the mouse pointer over the button triggers
the button's <samp class="codeph">click</samp> event:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/DispatchEventExampleInline.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"
initialize="createListener(event);"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function createListener(e:Event):void {
b1.addEventListener(MouseEvent.CLICK, myClickHandler);
}
private function myClickHandler(e:Event):void {
Alert.show("The event dispatched by the MOUSE_OVER was of type '" + e.type + "'.");
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1"
label="Click Me"
mouseOver="b1.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, false));"
/&gt;
&lt;/s:Application&gt;</pre>
<p>Your application is not required to handle the newly dispatched
event. If you trigger an event that has no listeners, Flex ignores
the event.</p>
<p>You can set properties of the Event object in ActionScript, but
you cannot add new properties because the object is not dynamic.
The following example intercepts a <samp class="codeph">click</samp> event.
It then creates a new MouseEvent object and dispatches it as a <samp class="codeph">doubleClick</samp> event.
In addition, it sets the value of the <samp class="codeph">shiftKey</samp> property
of the MouseEvent object to <samp class="codeph">true</samp>, to simulate a
Shift-click on the keyboard. </p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/DispatchCustomizedEvent.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="addListeners()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
private function customLogEvent(e:MouseEvent):void {
l1.text = String(e.currentTarget.id);
l2.text = String(e.type);
l3.text = String(e.shiftKey);
// Remove current listener to avoid recursion.
e.currentTarget.removeEventListener("doubleClick", customLogEvent);
}
private function handleEvent(e:MouseEvent):void {
// Add new handler for custom event about to be dispatched.
e.currentTarget.addEventListener("doubleClick", customLogEvent);
// Create new event object.
var mev:MouseEvent = new MouseEvent("doubleClick");
// Customize event object.
mev.shiftKey = true;
// Dispatch custom event.
e.currentTarget.dispatchEvent(mev);
}
private function addListeners():void {
b1.addEventListener("click",handleEvent);
b2.addEventListener("click",handleEvent);
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me (b1)"/&gt;
&lt;s:Button id="b2" label="Click Me (b2)"/&gt;
&lt;s:Form&gt;
&lt;s:FormItem label="Current Target:"&gt;
&lt;s:Label id="l1"/&gt;
&lt;/s:FormItem&gt;
&lt;s:FormItem label="Event Type:"&gt;
&lt;s:Label id="l2"/&gt;
&lt;/s:FormItem&gt;
&lt;s:FormItem label="Shift Key Pressed:"&gt;
&lt;s:Label id="l3"/&gt;
&lt;/s:FormItem&gt;
&lt;/s:Form&gt;
&lt;/s:Application&gt;</pre>
<p>If you want to add custom properties to an Event object, you
must extend the Event object and define the new properties in your
own custom class. You can then manually dispatch your custom events
with the <samp class="codeph">dispatchEvent()</samp> method, as you would any
event.</p>
<p>If you create a custom ActionScript class that dispatches its
own events but does not extend UIComponent, you can extend the flash.events.EventDispatcher
class to get access to the <samp class="codeph">addEventListener()</samp>, <samp class="codeph">removeEventListener()</samp>, and <samp class="codeph">dispatchEvent()</samp> methods.</p>
<p>To make your code more efficient, you can check to see if the
intended target of a dispatched event is listening for the event.
If it is not, then there is no reason to dispatch the event. This
is especially true if the event bubbles because that means many
calls will be made by the system while it searches for a target.
You can check by using the <samp class="codeph">hasEventListner()</samp> and <samp class="codeph">willTrigger()</samp> methods.</p>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cdb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cdb_verapache"><!-- --></a>
<h2 class="topictitle2">Event propagation</h2>
<div>
<p>When events are triggered, there are three phases in which
Flex checks whether there are event listeners. These phases occur
in the following order: </p>
<ul>
<li>
<p>Capturing</p>
</li>
<li>
<p>Targeting</p>
</li>
<li>
<p>Bubbling</p>
</li>
</ul>
<p>During each of these phases, the nodes have a chance to react
to the event. For example, assume the user clicks a Button control
that is inside a VBox container. During the capturing phase, Flex
checks the Application object and the VBox for listeners to handle
the event. Flex then triggers the Button's listeners in the target phase.
In the bubbling phase, the VBox and then the Application are again
given a chance to handle the event but now in the reverse order
from the order in which they were checked in the capturing phase.</p>
<p>In ActionScript 3.0, you can register event listeners on a target
node and on any node along the event flow. Not all events, however,
participate in all three phases of the event flow. Some types of
events are dispatched directly to the target node and participate
in neither the capturing nor the bubbling phases. All events can be
captured unless they are dispatched from the top node.</p>
<p>Other events may target objects that are not on the display list,
such as events dispatched to an instance of the Socket class. These
event objects flow directly to the target node, without participating
in the capturing or bubbling phases. You can also cancel an event
as it flows through the event model so that even though it was supposed
to continue to the other phases, you stopped it from doing so. You
can do this only if the <samp class="codeph">cancelable</samp> property is
set to <samp class="codeph">true</samp>.</p>
<p>Capturing and bubbling happen as the Event object moves from
node to node in the display list: parent-to-child for capturing
and child-to-parent for bubbling. This process has nothing to do
with the inheritance hierarchy. Only <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html" target="_blank">DisplayObject</a> objects
(visual objects such as containers and controls) can have a capturing
phase and a bubbling phase in addition to the targeting phase. </p>
<p>Mouse events and keyboard events are among those that bubble.
Any event can be captured, but no DisplayObject objects listen during
the capturing phase unless you explicitly instruct them to do so.
In other words, capturing is disabled by default.</p>
<p>When a faceless event dispatcher, such as a Validator, dispatches
an event, there is only a targeting phase, because there is no visual
display list for the Event object to capture or bubble through.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cd3_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cd3_verapache"><!-- --></a>
<h3 class="topictitle3">About the target and currentTarget
properties</h3>
<div>
<p>Every <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html" target="_blank">Event</a> object
has a <samp class="codeph">target</samp> and a <samp class="codeph">currentTarget</samp> property
that help you to keep track of where it is in the process of propagation.
The <samp class="codeph">target</samp> property refers to the dispatcher of
the event. The <samp class="codeph">currentTarget</samp> property refers to
the current node that is being examined for event listeners.</p>
<p>When you handle a mouse event such as <samp class="codeph">MouseEvent.CLICK</samp> by
writing a listener on some component, the <samp class="codeph">event.target</samp> property
does not necessarily refer to that component; it is often a subcomponent,
such as the Button control's UITextField, that defines the label.</p>
<p>When Flash Player or Adobe<sup>®</sup> AIR™ dispatches an event, it dispatches the
event from the frontmost object under the mouse. Because children
are in front of parents, that means the player or AIR might dispatch
the event from an internal subcomponent, such as the UITextField
of a Button.</p>
<p>The <samp class="codeph">event.target</samp> property is set to the object
that dispatched the event (in this case, UITextField), not the object
that is being listened to (in most cases, you have a Button control
listen for a <samp class="codeph">click</samp> event). </p>
<p>MouseEvent events bubble up the parent chain, and can be handled
on any ancestor. As the event bubbles, the value of the <samp class="codeph">event.target</samp> property
stays the same (UITextField), but the value of the <samp class="codeph">event.currentTarget</samp> property is
set at each level to be the ancestor that is handling the event.
Eventually, the <samp class="codeph">currentTarget</samp> will be Button, at
which time the Button control's event listener will handle the event.
For this reason, you should use the <samp class="codeph">event.currentTarget</samp> property
rather than the <samp class="codeph">event.target</samp> property; for example:</p>
<pre class="codeblock"> &lt;mx:Button label="OK" click="trace(event.currentTarget.label)"/&gt;</pre>
<p>In this case, in the Button event's click event listener, the <samp class="codeph">event.currentTarget</samp> property
always refers to the Button, while <samp class="codeph">event.target</samp> might
be either the Button or its UITextField, depending on where on the
Button control the user clicked.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cde_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cde_verapache"><!-- --></a>
<h3 class="topictitle3">Capturing phase</h3>
<div>
<p>In the capturing phase, Flex examines an event target's
ancestors in the display list to see which ones are registered as
a listener for the event. Flex starts with the root ancestor and
continues down the display list to the direct ancestor of the target.
In most cases, the root ancestors are the Stage, then the SystemManager, and
then the Application object.</p>
<p>For example, if you have an application with a Panel container
that contains a TitleWindow container, which in turn contains a
Button control, the structure appears as follows:</p>
<pre class="codeblock"> Application
  Panel
  TitleWindow
  Button</pre>
<p>If your listener is on the <samp class="codeph">click</samp> event of the
Button control, the following steps occur during the capturing phase
if capturing is enabled:</p>
<ol>
<li>
<p>Check the Application container for click event listeners.</p>
</li>
<li>
<p>Check the Panel container for click event listeners.</p>
</li>
<li>
<p>Check the TitleWindow container for click event listeners.</p>
</li>
</ol>
<p>During the capturing phase, Flex changes the value of the <samp class="codeph">currentTarget</samp> property
on the Event object to match the current node whose listener is
being called. The <samp class="codeph">target</samp> property continues to
refer to the dispatcher of the event.</p>
<p>By default, no container listens during the capturing phase.
The default value of the <em>use_capture</em> argument is <samp class="codeph">false</samp>.
The only way to add a listener during this phase is to pass <samp class="codeph">true</samp> for
the <em>use_capture</em> argument when calling the <samp class="codeph">addEventListener()</samp> method,
as the following example shows:</p>
<pre class="codeblock"> myPanel.addEventListener(MouseEvent.MOUSE_DOWN, clickHandler, true);</pre>
<p>If you add an event listener inline with MXML, Flex sets this
argument to <samp class="codeph">false</samp>; you cannot override it.</p>
<p>If you set the <em>use_capture</em> argument to <samp class="codeph">true</samp>—in
other words, if an event is propagated through the capturing phase—the
event can still bubble, but capture phase listeners will not react
to it. If you want your event to traverse both the capturing and
bubbling phases, you must call <samp class="codeph">addEventListener()</samp> twice:
once with <em>use_capture</em> set to <samp class="codeph">true</samp>, and then
again with <em>use_capture</em> set to <samp class="codeph">false</samp>. </p>
<p>The capturing phase is very rarely used, and it can also be computationally intensive.
By contrast, bubbling is much more common.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7ccf_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ccf_verapache"><!-- --></a>
<h3 class="topictitle3">Targeting phase</h3>
<div>
<p>In the targeting phase, Flex invokes the event dispatcher's
listeners. No other nodes on the display list are examined for event
listeners. The values of the <samp class="codeph">currentTarget</samp> and
the <samp class="codeph">target</samp> properties on the Event object during
the targeting phase are the same.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cce_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cce_verapache"><!-- --></a>
<h3 class="topictitle3">Bubbling phase</h3>
<div>
<p>In the bubbling phase, Flex examines an event's ancestors
for event listeners. Flex starts with the dispatcher's immediate
ancestor and continues up the display list to the root ancestor.
This is the reverse of the capturing phase.</p>
<p>For example, if you have an application with a Panel container
that contains a TitleWindow container that contains a Button control,
the structure appears as follows:</p>
<pre class="codeblock"> Application
  Panel
  TitleWindow
  Button</pre>
<p>If your listener is on the <samp class="codeph">click</samp> event of the
Button control, the following steps occur during the bubble phase
if bubbling is enabled:</p>
<ol>
<li>
<p>Check the TitleWindow container for click event listeners.</p>
</li>
<li>
<p>Check the Panel container for click event listeners.</p>
</li>
<li>
<p>Check the Application container for click event listeners.</p>
</li>
</ol>
<p>An event only bubbles if its <samp class="codeph">bubbles</samp> property
is set to <samp class="codeph">true</samp>. Mouse events and keyboard events
are among those that bubble; it is less common for higher-level events
that are dispatched by Flex to bubble. Events that can be bubbled
include <samp class="codeph">change</samp>, <samp class="codeph">click</samp>, <samp class="codeph">doubleClick</samp>, <samp class="codeph">keyDown</samp>, <samp class="codeph">keyUp</samp>, <samp class="codeph">mouseDown</samp>,
and <samp class="codeph">mouseUp</samp>. To determine whether an event bubbles,
see the event's entry in the <em>
<a href="https://flex.apache.org/asdoc/" target="_blank">ActionScript 3.0 Reference for Apache Flex</a></em>.</p>
<p>During the bubbling phase, Flex changes the value of the <samp class="codeph">currentTarget</samp> property
on the Event object to match the current node whose listener is
being called. The <samp class="codeph">target</samp> property continues to
refer to the dispatcher of the event.</p>
<p>When Flex invokes an event listener, the Event object might have
actually been dispatched by an object deeper in the display list.
The object that originally dispatched the event is the <samp class="codeph">target</samp>.
The object that the event is currently bubbling through is the <samp class="codeph">currentTarget</samp>.
So, you should generally use the <samp class="codeph">currentTarget</samp> property
instead of the <samp class="codeph">target</samp> property when referring to the
current object in your event listeners.</p>
<p>If you set the <samp class="codeph">useCapture</samp> property to <samp class="codeph">true</samp>—in
other words, if an event is propagated through the capturing phase—then
it does not bubble, regardless of its default bubbling behavior.
If you want your event to traverse both the capturing and bubbling
phases, you must call <samp class="codeph">addEventListener()</samp> twice: once
with <samp class="codeph">useCapture</samp> set to <samp class="codeph">true</samp>, and
then again with <samp class="codeph">useCapture</samp> set to <samp class="codeph">false</samp>.</p>
<p>An event only bubbles up the parent's chain of ancestors in the
display list. Siblings, such as two Button controls inside the same
container, do not intercept each other's events. </p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe9_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe9_verapache"><!-- --></a>
<h3 class="topictitle3">Detecting the event phase</h3>
<div>
<p>You can determine what phase you are in by using the Event
object's <samp class="codeph">eventPhase</samp> property. This property contains
an integer that represents one of the following constants:</p>
<ul>
<li>
<p>1 — Capturing phase (<samp class="codeph">CAPTURING_PHASE</samp>)</p>
</li>
<li>
<p>2 — Targeting phase (<samp class="codeph">AT_TARGET</samp>)</p>
</li>
<li>
<p>3 — Bubbling phase (<samp class="codeph">BUBBLING_PHASE</samp>)</p>
</li>
</ul>
<p>The following example displays the current phase and information
about the current target:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/DisplayCurrentTargetInfo.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;fx:Script&gt;&lt;![CDATA[
import mx.controls.Alert;
private function showInfo(e:MouseEvent):void {
Alert.show("Phase: " + e.eventPhase + "\n" +
"ID: " + e.currentTarget.id + "\n" +
"Label: " + e.currentTarget.label + "\n" +
"Font Size: " + e.currentTarget.getStyle("fontSize"), "Current Target Info");
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me" click="showInfo(event)"/&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffa_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ffa_verapache"><!-- --></a>
<h3 class="topictitle3">Stopping propagation</h3>
<div>
<p>During any phase, you can stop the traversal of the display
list by calling one of the following methods on the Event object:</p>
<ul>
<li>
<p>
<a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html#stopPropagation()" target="_blank">stopPropagation()</a>
</p>
</li>
<li>
<p>
<a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html#stopImmediatePropagation()" target="_blank">stopImmediatePropagation()</a>
</p>
</li>
</ul>
<p>You can call either the event's <samp class="codeph">stopPropagation()</samp> method
or the <samp class="codeph">stopImmediatePropagation()</samp> 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 remaining event listeners are allowed to execute.
The <samp class="codeph">stopPropagation()</samp> 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. </p>
<p>The <samp class="codeph">stopImmediatePropagation()</samp> method also prevents
the Event objects from moving on to the next node, but it does not
allow any other event listeners on the current node to execute. </p>
<p>The following example creates a <a href="https://flex.apache.org/asdoc/mx/containers/TitleWindow.html" target="_blank">TitleWindow</a> container
inside a Panel container. Both containers are registered to listen
for a <samp class="codeph">mouseDown</samp> event. As a result, if you click
on the TitleWindow container, the <samp class="codeph">showAlert()</samp> method
is called twice unless you add a call to the <samp class="codeph">stopImmediatePropagation()</samp> method,
as the following example shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/StoppingPropagation.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"
initialize="init(event);"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
import flash.events.MouseEvent;
import flash.events.Event;
public function init(e:Event):void {
p1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(Event.CLOSE, closeWindow);
p2.addEventListener(MouseEvent.MOUSE_DOWN, showAlertWithoutStoppingPropagation);
tw2.addEventListener(MouseEvent.MOUSE_DOWN, showAlertWithoutStoppingPropagation);
tw2.addEventListener(Event.CLOSE, closeWindow);
}
public function showAlert(e:Event):void {
Alert.show("Alert!\n" + "Current Target: " + e.currentTarget + "\n" +
"Phase: " + e.eventPhase);
e.stopImmediatePropagation();
}
public function showAlertWithoutStoppingPropagation(e:Event):void {
Alert.show("Alert!\n" + "Current Target: " + e.currentTarget + "\n" +
"Phase: " + e.eventPhase);
}
public function closeWindow(e:Event):void {
p1.removeChild(tw1);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Panel id="p1" title="Stops Propagation"&gt;
&lt;mx:TitleWindow id="tw1"
width="300"
height="100"
showCloseButton="true"
title="Title Window 1"&gt;
&lt;s:Button label="Click Me"/&gt;
&lt;s:TextArea id="ta1"/&gt;
&lt;/mx:TitleWindow&gt;
&lt;/s:Panel&gt;
&lt;s:Panel id="p2" title="Does Not Stop Propagation"&gt;
&lt;mx:TitleWindow id="tw2"
width="300"
height="100"
showCloseButton="true"
title="Title Window 2"&gt;
&lt;s:Button label="Click Me"/&gt;
&lt;s:TextArea id="ta2"/&gt;
&lt;/mx:TitleWindow&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
<div class="note"><span class="notetitle">Note:</span> A call to either the <samp class="codeph">Event.stopPropogation()</samp> or
the <samp class="codeph"> Event.stopImmediatePropogation()</samp> methods does
not prevent default behavior from occurring.</div>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff2_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff2_verapache"><!-- --></a>
<h3 class="topictitle3">Event examples</h3>
<div>
<p>In the following example, the parent container's click
handler disables the target control after the target handles the
event. It shows that you can reuse the logic of a single listener
(click the HGroup container) for multiple events (all the clicks).</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/NestedHandlers.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 disableControl(event:MouseEvent):void {
// Use this same logic for all events.
event.currentTarget.enabled = false;
}
public function doSomething(event:MouseEvent):void {
b1.label = "clicked";
ta1.text += "Something happened.";
}
public function doSomethingElse(event:MouseEvent):void {
b2.label = "clicked";
ta1.text += "Something happened again.";
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:HGroup id="hb1" height="200" click="disableControl(event)"&gt;
&lt;s:Button id='b1' label="Click Me" click="doSomething(event)"/&gt;
&lt;s:Button id='b2' label="Click Me" click="doSomethingElse(event)"/&gt;
&lt;s:TextArea id="ta1"/&gt;
&lt;/s:HGroup&gt;
&lt;s:Button id="resetButton"
label="Reset"
click="hb1.enabled=true;b1.enabled=true;b2.enabled=true;b1.label='Click Me';b2.label='Click Me';"/&gt;
&lt;/s:Application&gt;</pre>
<p>By having a single listener on a parent control instead of many
listeners (one on each child control), you can reduce your code
size and make your applications more efficient. Reducing the number
of calls to the <samp class="codeph">addEventListener()</samp> method potentially
reduces application startup time and memory usage.</p>
<p>The following example registers an event handler for the Panel
container, rather than registering a listener for each link. All
children of the Panel container inherit this event handler. Since
Flex invokes the handler on a bubbled event, you use the <samp class="codeph">target</samp> property
rather than the <samp class="codeph">currentTarget</samp> property. In this handler,
the <samp class="codeph">currentTarget</samp> property would refer to the Panel
control, whereas the <samp class="codeph">target</samp> property refers to
the LinkButton control, which has the label that you want.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SingleRegisterHandler.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="createLinkHandler();"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
private function linkHandler(event:MouseEvent):void {
try {
var url:URLRequest = new URLRequest("http://finance.google.com/finance?q=" +
event.target.label);
navigateToURL(url);
} catch (e:Error) {
/**
* Do nothing; just want to catch the error that occurs when a user clicks on
* the Panel and not one of the LinkButtons.
**/
}
}
private function createLinkHandler():void {
p1.addEventListener(MouseEvent.CLICK,linkHandler);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Panel id="p1" title="Click on a stock ticker symbol"&gt;
&lt;s:layout&gt;
&lt;s:HorizontalLayout/&gt;
&lt;/s:layout&gt;
&lt;mx:LinkButton label="ADBE"/&gt;
&lt;mx:LinkButton label="GE"/&gt;
&lt;mx:LinkButton label="IBM"/&gt;
&lt;mx:LinkButton label="INTC"/&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
</div>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7cda_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7cda_verapache"><!-- --></a>
<h2 class="topictitle2">Event priorities</h2>
<div>
<p>You can
register any number of event listeners with a single event. Flex
registers event listeners in the order in which the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()" target="_blank">addEventListener()</a> methods
are called. Flex then typically calls the listener functions when
the event occurs in the order in which they were registered. However,
if you register some event listeners inline and some with the <samp class="codeph">addEventListener()</samp> method,
the order in which the listeners are called for a single event can
be unpredictable.</p>
<p>You can change the order in which Flex calls event listeners
by using the <em>priority</em> parameter of the <samp class="codeph">addEventListener()</samp> method.
It is the fourth argument of the <samp class="codeph">addEventListener()</samp> method. </p>
<p>Flex calls event listeners in priority order, from highest to
lowest. The highest priority event is called first. In the following
example, Flex calls the <samp class="codeph">verifyInputData()</samp> method
before the <samp class="codeph">saveInputData()</samp> function. The <samp class="codeph">verifyInputData()</samp> method
has the highest priority. The last method to be called is <samp class="codeph">returnResult()</samp> because
the value of its <samp class="codeph">priority</samp> parameter is lowest.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/ShowEventPriorities.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 function returnResult(e:Event):void {
ta1.text += "returnResult() method called last (priority 1)\n";
}
private function verifyInputData(e:Event):void {
ta1.text += "verifyInputData() method called first (priority 3)\n";
}
private function saveInputData(e:Event):void {
ta1.text += "saveInputData() method called second (priority 2)\n";
}
private function initApp():void {
b1.addEventListener(MouseEvent.CLICK, returnResult, false, 1);
b1.addEventListener(MouseEvent.CLICK, saveInputData, false, 2);
b1.addEventListener(MouseEvent.CLICK, verifyInputData, false, 3);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;s:TextArea id="ta1" height="200" width="300"/&gt;
&lt;/s:Application&gt;</pre>
<p>You can set the event priority to any valid integer, positive
or negative. The default value is 0. If multiple listeners have
the same priority, Flex typically calls them in the order in which
they were registered, although the order is not guaranteed.</p>
<p>If you want to change the priority of an event listener once
the event listener has already been defined, you must remove the
listener by calling the <samp class="codeph">removeEventListener()</samp> method.
You add the event again with the new priority.</p>
<p>The <em>priority</em> parameter of the <samp class="codeph">addEventListener()</samp> method
is not an official part of the DOM Level 3 events model. ActionScript
3.0 provides it so that programmers can be more flexible when organizing
their event listeners. </p>
<p>If your listeners rely on a specific order of execution, you
can call one listener function from within another, or dispatch
a new event from within the first event listener. For more information
on manually dispatching events, see <a href="flx_events_ev.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ce1_verapache">Manually dispatching
events</a>.</p>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf69084-7ce0_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf69084-7ce0_verapache"><!-- --></a>
<h2 class="topictitle2">Using event subclasses</h2>
<div>
<p>Depending
on the event type, the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html" target="_blank">Event</a> object
can have a wide range of properties. These properties are based
on those defined in the W3C specification <a href="https://www.w3.org/TR/DOM-Level-3-Events/" target="_blank">http://www.w3.org/TR/DOM-Level-3-Events/</a>),
but Flex does not implement all of these.</p>
<p>When you declare an Event object in a listener function, you
can declare it of type Event, or you can specify a subclass of the
Event object. In the following example, you specify the event object
as type <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html" target="_blank">MouseEvent</a>:</p>
<pre class="codeblock"> public function performAction(e:MouseEvent):void {
  ...
 }</pre>
<p>Most controls generate an object that is of a specific event
type; for example, a mouse click generates an object of type MouseEvent.
By specifying a more specific event type, you can access specific
properties without having to cast the Event object to something
else. In addition, some subclasses of the Event object have methods
that are unique to them. For example, the LogEvent has a <samp class="codeph">getLevelString()</samp> method,
which returns the log level as a String. The generic Event object
does not have this method.</p>
<p>An event object that you define at run time can be a subclass
of the compile-time type. You can access the event-specific properties
inside an event listener even if you did not declare the specific
event type, as long as you cast the Event object to a specific type.
In the following example, the function defines the object type as
Event. However, inside the function, in order to access the <samp class="codeph">localX</samp> and <samp class="codeph">localY</samp> properties,
which are specific to the MouseEvent class, you must cast the Event
object to be of type MouseEvent.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/AccessEventSpecificProperties.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"
initialize="addListeners()"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function customLogEvent(e:Event):void {
var a:MouseEvent = MouseEvent(e);
Alert.show("Y: " + a.localY + "\n" + "X: " + a.localX);
}
private function addListeners():void {
b1.addEventListener(MouseEvent.CLICK, customLogEvent);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>If you declare the Event object as a specific type, you are not
required to cast that object in the handler, as the following example
shows:</p>
<pre class="codeblock"> private function customLogEvent(e:MouseEvent):void { ... }</pre>
<p>In the previous example, you can also cast the Event object for
only the property access, using the syntax shown in the following
example:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/SinglePropertyAccess.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"
initialize="addListeners()"&gt;
&lt;fx:Script&gt;
&lt;![CDATA[
import mx.controls.Alert;
private function customLogEvent(e:Event):void {
Alert.show("Y: " + MouseEvent(e).localY + "\n" + "X: " + MouseEvent(e).localX);
}
private function addListeners():void {
b1.addEventListener(MouseEvent.CLICK, customLogEvent);
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:Button id="b1" label="Click Me"/&gt;
&lt;/s:Application&gt;</pre>
<p>This approach can use less memory and system resources, but it
is best to declare the event's type as specifically as possible.</p>
<p>Each of the Event object's subclasses provides additional properties
and event types that are unique to that category of events. The
MouseEvent class defines several event types related to that input
device, including the <samp class="codeph">CLICK</samp>, <samp class="codeph">DOUBLE_CLICK</samp>, <samp class="codeph">MOUSE_DOWN</samp>,
and <samp class="codeph">MOUSE_UP</samp> event types. </p>
<p>For a list of types for each Event subclass, see the subclass's
entry in <em>
<a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/" target="_blank">ActionScript 3.0 Reference for the Adobe
Flash Platform</a>
</em>.</p>
</div>
</div>
<div class="nested1" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fdb_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fdb_verapache"><!-- --></a>
<h2 class="topictitle2">About keyboard events</h2>
<div>
<p>It
is common for applications to respond to a key or series of keys
and perform some action—for example, Control+q to quit the application.
While Flash Player supports all the basic functionality of key combinations
from the underlying operating system, it also lets you override
or trap any key or combination of keys to perform a custom action.</p>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fef_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fef_verapache"><!-- --></a>
<h3 class="topictitle3">Handling keyboard events</h3>
<div>
<p>In some cases, you want to trap keys globally, meaning
no matter where the user is in the application, their keystrokes
are recognized by the application and the action is performed. Flex
recognizes global keyboard events whether the user is hovering over
a button or the focus is inside a TextInput control. </p>
<p>A common way to handle global key presses is to create a listener
for the <samp class="codeph">KeyboardEvent.KEY_DOWN</samp> or <samp class="codeph">KeyboardEvent.KEY_UP</samp> event
on the application. Listeners on the application container are triggered
every time a key is pressed, regardless of where the focus is (as
long as the focus is in the application on not in the browser controls
or outside of the browser). Inside the handler, you can examine
the key code or the character code using the <samp class="codeph">charCode</samp> and <samp class="codeph">keyCode</samp> properties
of the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/KeyboardEvent.html" target="_blank">KeyboardEvent</a> class,
as the following example shows:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/TrapAllKeys.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.core.FlexGlobals;
private function initApp():void {
FlexGlobals.topLevelApplication.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
}
private function keyHandler(event:KeyboardEvent):void {
t1.text = event.keyCode + "/" + event.charCode;
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:TextInput id="myTextInput"/&gt;
&lt;s:Label id="t1"/&gt;
&lt;/s:Application&gt;</pre>
<p>To run this example, you must first set the focus to something
inside the application, such as the TextInput control, by clicking
on it.</p>
<p>Because any class that extends UIComponent dispatches the <samp class="codeph">keyUp</samp> and <samp class="codeph">keyDown</samp> events,
you can also trap keys pressed when the focus is on an individual
component.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fed_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fed_verapache"><!-- --></a>
<h3 class="topictitle3">Understanding the keyCode and charCode
properties</h3>
<div>
<p>You
can access the <samp class="codeph">keyCode</samp> and <samp class="codeph">charCode</samp> properties
to determine what key was pressed and trigger other actions as a
result. The <samp class="codeph">keyCode</samp> property is a numeric value
that corresponds to the value of a key on the keyboard. The <samp class="codeph">charCode</samp> property
is the numeric value of that key in the current character set (the
default character set is UTF-8, which supports ASCII). The primary
difference between the key code and character values is that a key
code value represents a particular key on the keyboard (the 1 on
a keypad is different than the 1 in the top row, but the 1 on the
keyboard and the key that generates the ! are the same key), and
the character value represents a particular character (the <em>R</em> and <em>r</em> characters are
different).</p>
<p>The mappings between keys and key codes are device and operating
system dependent. ASCII values, on the other hand, are available
in the ActionScript documentation.</p>
<p>The following example shows the character and key code values
for the keys you press. When you run this example, you must be sure
to put the focus in the application before beginning.</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- charts/ShowCharAndKeyCodes.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="init()"
width="650"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
import flash.events.KeyboardEvent;
private function init():void {
ti1.setFocus();
this.addEventListener(KeyboardEvent.KEY_DOWN, trapKeys);
}
private function trapKeys(e:KeyboardEvent):void {
ta1.text = String(e.toString());
l1.text = numToChar(e.charCode) + " (" + String(e.charCode) + ")";
l2.text = numToChar(e.keyCode) + " (" + String(e.keyCode) + ")";
}
private function numToChar(num:int):String {
if (num &gt; 47 &amp;&amp; num &lt; 58) {
var strNums:String = "0123456789";
return strNums.charAt(num - 48);
} else if (num &gt; 64 &amp;&amp; num &lt; 91) {
var strCaps:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return strCaps.charAt(num - 65);
} else if (num &gt; 96 &amp;&amp; num &lt; 123) {
var strLow:String = "abcdefghijklmnopqrstuvwxyz";
return strLow.charAt(num - 97);
} else {
return num.toString();
}
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:TextInput width="50%" id="ti1"/&gt;
&lt;s:Panel id="mainPanel" width="100%" height="100%"&gt;
&lt;s:Form&gt;
&lt;s:FormItem label="Char (Code)"&gt;
&lt;s:Label id="l1"/&gt;
&lt;/s:FormItem&gt;
&lt;s:FormItem label="Key (Code)"&gt;
&lt;s:Label id="l2"/&gt;
&lt;/s:FormItem&gt;
&lt;s:FormItem label="Key Event"&gt;
&lt;s:TextArea id="ta1" width="500" height="200" editable="false"/&gt;
&lt;/s:FormItem&gt;
&lt;/s:Form&gt;
&lt;/s:Panel&gt;
&lt;/s:Application&gt;</pre>
<p>You can listen for specific keys or combinations of keys by using
a conditional operator in the KeyboardEvent handler. The following
example listens for the combination of the Shift key plus the q
key and prompts the user to close the browser window if they press
those keys at the same time:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/TrapQKey.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.core.FlexGlobals;
private function initApp():void {
FlexGlobals.topLevelApplication.addEventListener(KeyboardEvent.KEY_UP,keyHandler);
// Set the focus somewhere inside the application.
ta1.setFocus();
}
//This function quits the application if the user presses Shift+Q.
private function keyHandler(event:KeyboardEvent):void {
var bShiftPressed:Boolean = event.shiftKey;
if (bShiftPressed) {
var curKeyCode:int = event.keyCode;
if (curKeyCode == 81) { // 81 is the keycode value for the Q key
/* Quit the application by closing the browser using JavaScript.
This may not work in all browsers. */
var url:URLRequest = new
URLRequest("javascript:window.close()");
navigateToURL(url,"_self");
}
}
}
]]&gt;
&lt;/fx:Script&gt;
&lt;s:TextArea id="ta1" text="Focus here so that Shift+Q will quit the browser."/&gt;
&lt;/s:Application&gt;</pre>
<p>Notice that this application must have focus when you run it
in a browser so that the application can capture keyboard events.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe8_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7fe8_verapache"><!-- --></a>
<h3 class="topictitle3">Understanding KeyboardEvent precedence</h3>
<div>
<p>If you define <samp class="codeph">keyUp</samp> or <samp class="codeph">keyDown</samp> event
listeners for both a control and its parent, you will notice that
the keyboard event is dispatched for each component because the
event bubbles. The only difference is that the <samp class="codeph">currentTarget</samp> property
of the KeyboardEvent object is changed.</p>
<p>In the following example, the application, the <samp class="codeph">my_vgroup</samp> container,
and the <samp class="codeph">my_textinput</samp> control all dispatch <samp class="codeph">keyUp</samp> events
to the <samp class="codeph">keyHandler()</samp> event listener function:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/KeyboardEventPrecedence.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();"
width="650"&gt;
&lt;s:layout&gt;
&lt;s:VerticalLayout/&gt;
&lt;/s:layout&gt;
&lt;fx:Script&gt;&lt;![CDATA[
import mx.core.FlexGlobals;
private function initApp():void {
FlexGlobals.topLevelApplication.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
my_vgroup.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
my_textinput.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
// Set the focus somewhere inside the application.
my_textinput.setFocus();
}
private function keyHandler(event:KeyboardEvent):void {
ta1.text += event.target + "(" + event.currentTarget + "): " +
event.keyCode + "/" + event.charCode + "\n";
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:VGroup id="my_vgroup"&gt;
&lt;s:TextInput id="my_textinput"/&gt;
&lt;/s:VGroup&gt;
&lt;s:TextArea id="ta1" height="300" width="550"/&gt;
&lt;/s:Application&gt;</pre>
<p>When you examine the output, you will notice that the <samp class="codeph">target</samp> property
of the <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/KeyboardEvent.html" target="_blank">KeyboardEvent</a> object
stays the same because it refers to the original dispatcher of the
event (in this case, my_textinput). But the <samp class="codeph">currentTarget</samp> property changes
depending on what the current node is during the bubbling (in this case,
it changes from my_textinput to my_vgroup to the application itself).</p>
<p>The order of calls to the event listener is determined by the
object hierarchy and not the order in which the <samp class="codeph">addEventListener()</samp> methods
were called. Child controls dispatch events before their parents.
In this example, for each key pressed, the TextInput control dispatches
the event first, the VGroup container next, and finally the application.</p>
<p>When handling a key or key combination that the underlying operating
system or browser recognizes, the operating system or browser generally
processes the event first. For example, in Microsoft Internet Explorer,
pressing Control+w closes the browser window. If you trap that combination
in your application, Internet Explorer users never know it, because
the browser closes before the ActiveX Flash Player has a chance
to react to the event.</p>
</div>
</div>
<div class="nested2" id="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff8_verapache"><a name="WS2db454920e96a9e51e63e3d11c0bf64a29-7ff8_verapache"><!-- --></a>
<h3 class="topictitle3">Handling keyboard-related mouse
events</h3>
<div>
<p>The <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html" target="_blank">MouseEvent</a> class
and all MouseEvent subclasses (such as ChartItemEvent, DragEvent,
and LegendMouseEvent) have the following properties that you can use
to determine if a specific key was held down when the event occurred:</p>
<div class="tablenoborder"><table cellpadding="4" cellspacing="0" summary="" frame="border" border="1" rules="all">
<thead align="left">
<tr>
<th class="cellrowborder" valign="top" width="NaN%" id="d206409e2827">
<p>Property</p>
</th>
<th class="cellrowborder" valign="top" width="NaN%" id="d206409e2833">
<p>Description</p>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2827 ">
<p>
<samp class="codeph">altKey</samp>
</p>
</td>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2833 ">
<p>Is set to <samp class="codeph">true</samp> if the Alt
key was held down when the user pressed the mouse button; otherwise, <samp class="codeph">false</samp>.</p>
</td>
</tr>
<tr>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2827 ">
<p>
<samp class="codeph">ctrlKey</samp>
</p>
</td>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2833 ">
<p>Is set to <samp class="codeph">true</samp> if the Control
key was held down when the user pressed mouse button; otherwise, <samp class="codeph">false</samp>.</p>
</td>
</tr>
<tr>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2827 ">
<p>
<samp class="codeph">shiftKey</samp>
</p>
</td>
<td class="cellrowborder" valign="top" width="NaN%" headers="d206409e2833 ">
<p>Is set to <samp class="codeph">true</samp> if the Shift
key was held down when the user pressed mouse button; otherwise, <samp class="codeph">false</samp>.</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>The following example deletes Button controls, based on whether
the user holds down the Shift key while pressing the mouse button:</p>
<pre class="codeblock">&lt;?xml version="1.0"?&gt;
&lt;!-- events/DetectingShiftClicks.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 spark.components.Button;
private function initApp():void {
var b1:Button = new Button();
b1.label = "Button 1";
var b2:Button = new Button();
b2.label = "Button 2";
b1.addEventListener(MouseEvent.CLICK, removeButtons);
b2.addEventListener(MouseEvent.CLICK, removeButtons);
vg1.addElement(b1);
vg1.addElement(b2);
}
private function removeButtons(event:MouseEvent):void {
if (event.shiftKey) {
vg1.removeElement(Button(event.currentTarget));
} else {
event.currentTarget.toolTip = "Shift+click to remove this button.";
}
}
]]&gt;&lt;/fx:Script&gt;
&lt;s:VGroup id="vg1"/&gt;
&lt;s:Button id="resetButton" label="Reset" click="initApp();"/&gt;
&lt;/s:Application&gt;</pre>
<p/>
</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 and Adobe Flash Player 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>