Sunday, December 03, 2006

User Events With Actionscript 3

I came across this problem the other day. I was looking all over for a simple article explaining how to create your own events with the new event system in AS3. I found a few interesting links, such as Darron Schall's blog post, but nothing completely definitive. Along with that article and some digging in the AS3 documentation I managed, amazingly, to successfully create my own custom event.

It's even easier to implement than when using AS2. First you need to create the actual event that will contain your custom event data. If you don't have any custom data you need to pass via the event then this is completely unnecessary to do. In my case I'm sending out the forecast for Miami Beach so one is needed.

The first step is to extend the built in event class.

package classes{

import flash.events.Event;

public class WeatherEvent extends Event{


}
}


Once we have the class definition created we need to define the type of event it will be. In my case I will be calling it update. There also needs to be a variable that will allow the event to contain custom data.

package classes{

import flash.events.Event;

public class WeatherEvent extends Event{

public var _message:String;
public static var UPDATE:String = "update";
}
}


Next the event needs a constructor. Don't forget to allow the ability for the custom data to be passed. The super constructor also needs to be called with the type of our event which is exactly why we defined it earlier.

package classes{

import flash.events.Event;

public class WeatherEvent extends Event{

public static var UPDATE:String = "update";
public var _message:String;

public function WeatherEvent($message:String){

super(UPDATE);
_message = $message;
}
}
}


There is one last piece. There needs to be a clone method that will duplicate the event in the case that it's relayed. Check this link for more information.

Next up is the class that will dispatch the event in the first place. It's rather long and I wish to keep this short so I'm just going to paste it.

package classes{

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest;
import classes.WeatherEvent;


public class WeatherData extends EventDispatcher{

public var forecast:Object;

private var xmlData:XML;
private var loader:URLLoader;
private var rss:String;

static var instance:Object = null;


public function WeatherData($rss:String){

super();
rss = $rss;

updateForecast();

}

public function updateForecast():void{

if(!loader){

loader = new URLLoader(new URLRequest(rss));

loader.addEventListener(Event.COMPLETE, parseData, false, 0, true);
}else{

loader.load(new URLRequest(rss));
}
}

private function parseData(evt:Event):void{

xmlData = new XML(loader.data);

forecast = xmlData..description[1];

dispatchEvent(new WeatherEvent(forecast));
}

public static function getInstance():Object{

if(instance != null){

instance.updateForecast();

return instance;
}else{

instance = new WeatherData("http://www.rssweather.com/rss.php?config=&forecast=zandh&place=miami+beach&state=fl&zipcode=&country=us&county=12086&zone=flz074&alt=rss20a");

return instance;
}
}

}
}


As you can see in the parseData method dispatches a WeatherEvent object. Finally, to add a listener and see if it works! First to import the classes and create a WeatherData object.

import classes.WeatherData;
import classes.WeatherEvent;
import flash.events.Event;

var conditions:WeatherData = WeatherData.getInstance();


Then to create a function callback for the listener.

function checkUpdate(evt:Event):void{

trace("Forecast Updated");
trace(evt._message);
}


Finally all that's left is to add a listener and force the WeatherData class to dispatch an event.

conditions.addEventListener(WeatherEvent.UPDATE, checkUpdate);

WeatherData.getInstance();


Ctrl+enter to test the movie and the output should look something like this.

Forecast Updated
Currently mostly cloudy and 66. Winds from the NNW at 9 mph. Relative Humidity at 73%.