Subscribe to our newsletter:
Events drive and breathe life into Flex applications, so understanding them is crucial to Flex development. In the latest article in the "From Flash to Flex" series, Kris Hadlock explains Flex events and how to incorporate them into object-oriented code.
Everything in Flex occurs based on an event. This means that simply clicking a button or key to moving the mouse or receiving a response from a web service provides developers with the ability to trigger a custom event in their Flex applications. That's a lot of control, and since Flex is not based on the request/response model of a standard web app, the app contains the functionality to perform those custom events without ever leaving the web page. This is because events are client-based - in other words, separated from the request/response model of a web page and do not require the page to refresh with every user interaction.
On the Web a Flex app is completely loaded upfront, which allows the functionality within to respond faster than a standard web request model. This will initially cause the user to wait until the app is fully loaded, but will save time when it counts, which is during usage.
Not having to wait for a page refresh also prevents the user from having problems maintaining context because the screen reacts instantaneously. With these additional benefits you would expect some new issues to arise, but the capabilities of Flex are not limited in any way when comparing them with a standard web app.
In this article you will learn how to leverage the power of events by dispatching them in your own custom classes. The source code for this project can be downloaded here.
If you feel you need some background on Flex development before diving into events, take a look at the previous articles in the From Flash to Flex series.
Event Dispatching
Dispatching your own events starts by extending the UIComponent. In the last article of the Flash to Flex series, "Creating ActionScript Components for Flex," I explained how to create a Flex component by extending the UIComponent.This article will pick up where that article left off by adding the additional functionality to dispatch your own custom events when a headline is selected. As a quick recap, the headline component that we built ran from XML, which defined a URL and display text for different headlines. When the app loaded, the component would cycle through each of the headlines for a predetermined interval that we passed to the constructor. Each headline would display at the top of the page waiting for someone to click it and visit the corresponding URL.
Since the UIComponent extends the EventDispatcher, all subclasses of the UIComponent have access to the dispatchEvent() method.
Relying on the href to link us to the URL of a headline works great, but if we wanted to add some additional functionality each time a headline is selected, such as logging what headlines were selected and at what time, this functionality would not allow it.
Therefore we will use events to inform a custom handler of the selection and then we will dispatch an event and delegate it to the appropriate class, which will log the data that we define.
First of all, we need to change the way that our headlines are constructed to trigger an event in the href (see Listing 1) instead of just linking to the URL as we did before (see Listing 2).
Listing 1: Triggering an event
<b>this.headlines.push("<a href='event:"+ _headlines[i].attribute("action") +"'>"+ _headlines[i].text() +"</a>");</b>this.headlines.push(’<a href="'+ _headlines[i].attribute("action") +'" target="_blank">'+ _headlines[i].text() +'</a>');Now that we have our event in place we need to add a listener to the textfield that we are creating to display the headlines.
To do this I have added the event listener to the createTextField method from our previous headline class and modified it a bit to handle the text directly as a parameter rather than assigning it after the field has been created (see Listing 3).
Listing 3: Adding an event listener
private function cycle(index:Number):void
{
if(this.currentTextField != null) removeChild(this.currentTextField);
this.currentTextField = this.createTextField(0, 0, 200, 100, this.headlines[index]);
if(index == (this.headlines.length-1)) index = 0;
else index++;
if(this.__cycleTimeout != 0) clearTimeout(this.__cycleTimeout);
this.__cycleTimeout = setTimeout(cycle, (this.delay*1000), index);
}
private function createTextField(x:Number, y:Number, width:Number, height:Number, text:String):TextField
{
var format:TextFormat = new TextFormat();
format.font = "Arial";
format.color = 0x333333;
format.size = 21;
format.underline = true;
var txtField:TextField = new TextField();
txtField.x = x; txtField.y = y;
txtField.width = width; txtField.height = height;
txtField.autoSize = "left";
txtField.defaultTextFormat = format;
txtField.htmlText = text;
txtField.addEventListener(TextEvent.LINK, onHeadlineSelected);
addChild(txtField);
return txtField;
}Listing 4: Importing the TextEvent
import flash.events.TextEvent;Listing 5: Handling the event
private function onHeadlineSelected(e:TextEvent):void
{
var u:URLRequest = new URLRequest(e.text);
navigateToURL(u, "_blank");
e.currentTarget.addEventListener("textlink", Logger.GetInstance().Log);
var tev:TextEvent = new TextEvent("textlink", false, false);
var date:Date = new Date();
tev.text = date.toString() +"::"+ e.text;
e.currentTarget.dispatchEvent(tev);
}The next line assigns an event listener to a method called Log in a new class called Logger, which we will create in a moment (see Listing 6).
You'll also notice that we are providing the listener with a custom type called textlink, which will prevent any recursion issues when our other events are fired.
Once we have the listener in place we need to create a new event, which in this case is a TextEvent, set the values that we want to pass the new method and finally dispatch the event to whomever is listening.
Now that we are finally dispatching events, let's take a look at how to handle them from other classes.
Event Dispatching
When creating a new class we need to determine where we will place it in our class structure. In this case the Logger class is a utility, so we will add it to a new package called util.We only want one instance of the Logger class, so we will make it a Singleton to prevent multiple instances from being created.
Listing 6: Logging custom events
package com.studiosedition.util
{
import flash.events.TextEvent;
public class Logger
{
private static var INSTANCE:Logger;
public static function GetInstance():Logger
{
if(Logger.INSTANCE == null)
{
Logger.INSTANCE = new Logger();
}
return Logger.INSTANCE;
}
public function Log(e:TextEvent):void
{
var logText:Array = e.text.split("::");
var date:String = logText[0];
var url:String = logText[1];
// Log the date and url that were clicked
e.currentTarget.removeEventListener("textlink", Log);
}
}
}We can simply split them by our delimiter and handle logging however we deem appropriate. Once we have completed logging the user selection we will remove the listener to prevent any recursion from future textLink events.





help
and feedback
latest
news
latest
forum entries