Google analytics code

Showing posts with label actionscript. Show all posts
Showing posts with label actionscript. Show all posts

Friday, August 3, 2012

Flex / ActionScript 3 : Problem with ExternalInterface.addCallback

I'm adding some functionality to an existing Flex project that requires cross talk between ActionScript and Javascript. Reaching from ActionScript to Javascript is pretty easy. This can be done with the ExternalInterface.call. Calling from Javascript to ActionScript was a little tricker. Especially with local development.

You can use ExternalInterface.addCallback to create a bridge for Javascript to talk with ActionScript. There are a few more steps to make sure this is set up properly.

1) Make sure the id and name are the same in each AC_FL_RunContent function. Just changing one won't work. This way document.getElementById should always find the object on the page.
2) Make sure allowScriptAccess is set to always in each AC_FL_RunContent function. This updates the security setting so Javascript can access the Flash object.
3) If you're doing local development make sure to check Always allow in Global Security Settings Panel.

I found step 3 after wasting an entire morning looking around the internet. Without this I kept getting this warning.


*** Security Sandbox Violation ***
SecurityDomain 'null' tried to access incompatible context 'file:///foo/bar/project.swf'

Once you're project is finished you might want to change this back. Not sure what thing on the web wants to break your computer.

Tuesday, February 8, 2011

Flex / ActionScript : Eclipse autocomplete stopped working

At some point if you're working with Eclipse autocomplete is going to stop working. I've tried hunting on google for a few hours and finally found a solution that worked from the comments in a blog.

You might have either a path to a SWC folder or have multiple SWC files in your project. Remove either all the SWC files from the folder and add them back one at a time, or remove the SWC files from the project and add them back one at a time. They might be causing a conflict that will result in autocomplete not functioning anymore.

Tuesday, April 13, 2010

Flex / ActionScript: Copy an ArrayCollection

While working with an ArrayCollection I ran into a issue. It seems when you set one ArrayCollection equal to another they share memory space. This can cause issues when you perform any operation that will alter the internal array.

var arrayCollection1:ArrayCollection = new ArrayCollection([1,2,3,4,5]);
var arrayCollection2:ArrayCollection = arrayCollection1;

trace("arrayCollction1: " + arrayCollection1.toString());
trace("arrayCollction2: " + arrayCollection2.toString());

arrayCollection1.removeItemAt(0);

trace("arrayCollction1: " + arrayCollection1.toString());
trace("arrayCollction2: " + arrayCollection2.toString());
Output:
arrayCollection1: 1,2,3,4,5
arrayCollection2: 1,2,3,4,5

arrayCollection1: 2,3,4,5
arrayCollection2: 2,3,4,5

The simple solution for this is to always create a new ArrayCollection for the target using the toArray method from the source.

var arrayCollection1:ArrayCollection = new ArrayCollection([1,2,3,4,5]);
var arrayCollection2:ArrayCollection = new ArrayCollection(arrayCollection1.toArray());

trace("arrayCollection1: " + arrayCollection1.toString());
trace("arrayCollection2: " + arrayCollection2.toString());

arrayCollection1.removeItemAt(0);

trace("arrayCollection1: " + arrayCollection1.toString());
trace("arrayCollection2: " + arrayCollection2.toString());
Output: 
arrayCollection1: 1,2,3,4,5
arrayCollection2: 1,2,3,4,5

arrayCollection1: 2,3,4,5
arrayCollection2: 1,2,3,4,5

Those post is based on findings from this blog post.

Friday, March 19, 2010

Flash / ActionScript 3: Singleton Example

Singletons are a design pattern that allows you to share one instance of a class throughout a application. An example of where a singleton is useful is when you only want one and only one connection to a database. It also allows you to keep memory usage down because there is only one copy in memory.

I've created a sample ActionScript project that shows how a singleton can be used. You can download it here.

Here is what the files look like.
Singleton_Example.as
package {
    import flash.display.Sprite;
    
    import Singleton.ExampleSingleton;
    import classes.ExampleClass;

    public class Singleton_Example extends Sprite
    {
        public function Singleton_Example()
        {
            //init the Singleton by grabbing an instance of it
            var singleton:ExampleSingleton = ExampleSingleton.instance;
            var exampleClass1:ExampleClass;
            
            
            //set the flag
            singleton.flag = ExampleSingleton.FLAG1;
            
            //show the current state of the flag
            trace("flag state: " + singleton.flag);
            
            //creating this class will update the flag in the singleton
            exampleClass1 = new ExampleClass;
            
            //the flag should be updated now
            trace("flag state: " + singleton.flag);
            
            //update the flag here
            singleton.flag = ExampleSingleton.FLAG3;
            
            //make the class display the state
            exampleClass1.displayFlagState();
        }
    }
}


ExampleSingleton.as
package Singleton
{
    public class ExampleSingleton
    {
        //a set of dummy values used to explain how a Singleton is manuplated
        public static const FLAG1:String = "value1";
        public static const FLAG2:String = "value2";
        public static const FLAG3:String = "value3";
        public static const FLAG4:String = "value4";
        
        
        //this is the only instance of the class
        private static const _instance:ExampleSingleton = new ExampleSingleton(SingletonLock);
        
        //list of allowed values that can be set for the flag
        private var _allowedValues:Array = [];
        
        //state of the flag
        private var _flag:String = "";
        
        //this will control wither the Singleton is really to be accessed
        private var _initialized:Boolean = false;
        
        /**
         * Use this to return an instance of the singleton 
         * @return 
         * 
         */
        public static function get instance() : ExampleSingleton {
            return _instance;
        }
        
        /**
         * Query the Singleton to see if it's ready to be accessed 
         * @return 
         * 
         */
        public function get initialized() : Boolean {
            return _initialized;
        }
        
        /**
         * Return the current flag 
         * @return String
         * 
         */
        public function get flag() : String {
            return _flag;
        }
        
        /**
         * Set the flag state 
         * @param value
         * @return Boolean
         * 
         */
        public function set flag(value:String) : void {
            //make sure the Singleton is initialized first
            if(!_initialized) {
                return;
            }
            
            //check to make sure it's an allowed value before setting it
            if(_allowedValues.indexOf(value) == -1) {
                return;
            }
            
            //update the flag
            _instance._flag = value;
        }
        
        /**
         * This will initialize the Singleton. It's never publicly called. Use ExampleSingleton.instance instead 
         * @param lock
         * 
         */
        public function ExampleSingleton(lock:Class) {
            if(lock != SingletonLock) {
                throw new Error("Invalid ExampleSingleton access. Use ExampleSingleton.instance");
            }
            
            initialize();
        }
        
        /**
         * This is where you would set up anything the Singleton needed before it should be accessable to the public 
         * 
         */
        private function initialize() : void {
            //we only need to initialize once. 
            if(_initialized) {
                return;
            }
            //set up what we allow the flag to be
            _allowedValues = [FLAG1, FLAG2, FLAG3, FLAG4];
            
            _initialized = true;
        }
    }
}

//this is used to lock the Singleton
class SingletonLock{}

ExampleClass.as
package classes
{
    import Singleton.ExampleSingleton;
    
    public class ExampleClass
    {
        public function ExampleClass() {
            //update the flag in the Singleton. we don't need to create a var to update it
            ExampleSingleton.instance.flag = ExampleSingleton.FLAG2;
        }
        
        /**
         * This will display the current flag from the Singleton 
         * 
         */
        public function displayFlagState() : void {
            trace("flag state from ExampleClass: " + ExampleSingleton.instance.flag);
        }
    }
}

Lets start with ExampleSinglton.as. The important parts of this class are the _instance member variable, the instance getter method and the ExampleSingleton constructor.

The constructor takes a SingletonLock class argument as a locking precaution. This class is defined at the bottom of the ExampleSingleton package. This allows us to control the way the class is created. The _instance member variable is where we create the instance of the ExampleSingleton. The ExampleSingleton constructor should check to make sure the lock argument is a SingletonLock class and throw an error if it isn't. The error you throw should let the person know how to properly access the singleton.

ExampleSingleton.initialize is where some basic values are set up that are accessed in the rest of the project.

Now lets look at Singleton_Example.as. When we create the singleton variable we access the .instance property of the class. This will return the single instance of ExampleSingleton.

ExampleClass.as also uses the ExampleSingleton class. You'll see how setting a property on ExampleSingleton in Singleton_Example is reflected in ExampleClass and vice versa.

Friday, March 12, 2010

ActionScript: The difference between "FOR IN" and "FOR EACH"

I ran into an issue earlier while looping through a list of objects where I couldn't get the index of the array I was accessing. Turns out there is a BIG difference between FOR and FOR EACH. Coding late at night probably didn't help either.

FOR EACH gives you access to the element in the array. FOR gives you access to the index of the array.

var elements:Array = [{name:'Orange'}, {name:'Apple'},{name:'Banana'},{name:'Pear'}];

for(var i:Object in elements) {
    trace("index: " + i);
}

for each(var e:Object in elements) {
    trace("element: " + e.name);
}

The output from FOR loop looks like this:
index: 0
index: 1
index: 2
index: 3

The output from FOR EACH looks like this:
element: Orange
element: Apple
element: Banana
element: Pear

Hopefully this helps someone from blunt force trauma caused by baning your head against the desk. Probably common knowledge for most, but it never hurts to post it.

Thursday, November 12, 2009

Flash / ActionScript 3: Event Bubbling Example

Previously I wrote an article that showed an example of Event Bubbling with Flex. I wanted to write a similar example for ActionScript 3. The principle is the same, but it works just a little different.

Any class involved in bubbling must extend DisplayObjectContainer. Sprite is the most basic DisplayObjectContainer class and most examples I see use it, so that's what I will use. I gave a brief overview of how event bubbling works in the Flex example that I won't repeat here.

I'm creating three classes that include each other. The primary class includes Level1. Level1 includes Level2. Level2 includes Level3. Level3 triggers an event when it's added to the stage. The event from Level3 will bubble through Level2 and Level1 to the primary class without re-dispatching it.

event_bubbling_as.as
package {
    import flash.display.Sprite;
    import flash.events.Event;
    
    import obj.Level1;
    import obj.Level3;

    public class event_bubbling_as extends Sprite
    {
        private var _level1:Level1
        
        public function event_bubbling_as()
        {
            _level1 = new Level1;
            _level1.addEventListener(Level3.EVENT, onEvent);
            
            addChild(_level1);
        }
        
        private function onEvent(event:Event) : void {
                trace('caught event from level 3');
        }
    }
}

Level1.as
package obj
{
    import flash.display.Sprite;
    
    public class Level1 extends Sprite
    {
        private var _level2:Level2;
        
        public function Level1()
        {
            trace("in level 1");
            _level2 = new Level2;
            
            addChild(_level2);
        }
    }
}
Level2.as
package obj
{
    import flash.display.Sprite;
    
    public class Level2 extends Sprite
    {
        private var _level3:Level3;
        
        public function Level2()
        {
            trace("in level 2");
            _level3 = new Level3;
            
            addChild(_level3);
        }
    }
}
Level3.as
package obj
{
    import flash.display.Sprite;
    import flash.events.Event;
    
    public class Level3 extends Sprite
    {
        public static const EVENT:String = "level3";
        public function Level3(){
            trace("in level 3");
            
            //trigger event when the object is added to the stage
            addEventListener(Event.ADDED_TO_STAGE, launchEvent);
        }
        
        public function launchEvent(event:Event) : void {
         var newEvent:Event = new Event(EVENT, true, true);
         dispatchEvent(newEvent);
        }
    }
}
You can download the Flex Project Archive example here. This can be directly imported into Flex. Run it in debug mode to see how each level is triggered.

Thursday, October 29, 2009

Flex: Problems reusing the HTTPService class

UPDATE: This problem occurred because of a bug in the 3.4 SDK. This bug does not exist in 3.2 or lower. I've opened a bug with adobe on the issue.

UPDATE 2: The issue has been resolved in a new nightly build of the SDK. It should be fixed when 3.6 is release.

I ran into an issue using the HTTPService object that involved removing event listeners that were added inside MXML.

Here is a snippet of code in the project. This will open an xml file and load some data into a List.

//this will fetch all our content.
private var _httpService:HTTPService = new HTTPService; 

private function init() : void {
    _httpService.url = "stub/data/albums.xml";
    _httpService.resultFormat = "e4x";
    
    //set up http call
    _httpService.addEventListener(ResultEvent.RESULT, populateList);
    _httpService.send();
}

private function populateList(event:ResultEvent) : void {
    //set the data provider
    albumsComboBox.dataProvider = event.result.album;
    
    //remove listener
    _httpService.removeEventListener(ResultEvent.RESULT, populateList);
}

This will open another xml file and populate the TileList with images.

private function loadAlbum(event:ListEvent) : void {
    _httpService.url = "stub/data/" + event.currentTarget.selectedItem.@images;
    _httpService.resultFormat = "e4x";
    
    //set up http call
    _httpService.addEventListener(ResultEvent.RESULT, populateTilelist);
    _httpService.send();
}

private function populateTilelist(event:ResultEvent) : void {
    //set the data provider
    imageGrid.dataProvider = event.result.photo;
    
    //remove listener
    _httpService.removeEventListener(ResultEvent.RESULT, populateTilelist);
}

When loadAlbum calls send() it will call populateList first and then goto populateTilelist. removeEventListener didn't work. I posted a question to StackOverflow with the problem and got some great answers.


To get around this problem I created a HTTPService wrapper that can be reused with no issues because it's an ActionScript Class. It's very light weight, doesn't include everything under the sun, but it gets the job done in a pinch. This is the 3rd revision of the class. It's been cleaned up and there are fewer methods now.

package util
{
    import mx.controls.Alert;
    import mx.rpc.AsyncResponder;
    import mx.rpc.AsyncToken;
    import mx.rpc.IResponder;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;
    
    public class HTTPServiceWrapper {
        //reference for connections
        private var _httpService:HTTPService;
        
        private var _alertTitle:String = "HTTPService: An error occured";
        
        // Holds all the tokens and callbacks
        private var _processingQueue : Object = {};
        
        /**
         * Create the HTTPService 
         * 
         */
        public function HTTPServiceWrapper() : void {
            //create the service
            _httpService = new HTTPService;
        }
        
        /**
         * Get content from URL 
         * @param url
         * @param resultFormat
         * @param callBack
         * @param request
         * @param returnErrorEvent
         * 
         */
        public function getContent(url:String,
                                    resultFormat:String,
                                    callBack:Function,
                                    request:Object = null, 
                                    returnErrorEvent:Boolean = false) : void {
            var asyncToken:AsyncToken;
            var internalIResponder:IResponder;
            
            //set the url and result format
            _httpService.url = url;
            _httpService.resultFormat = resultFormat;
            _httpService.request = null;
            
            //check for key/value pairs to be sent in the url
            if(request) {
                _httpService.request = request;
            }
            
            //send the request
            asyncToken = _httpService.send();
            internalIResponder = new AsyncResponder(onGetContentHandler,onFault, asyncToken);
            asyncToken.addResponder(internalIResponder);
            
            //give token unique ID
            asyncToken = tokenID(asyncToken);
            
            _processingQueue[asyncToken.ID] = new QueueObject(callBack,returnErrorEvent);
        }
        
        /**
         * This is the handler event for getContent. The callBack should accept a ResultEvent
         *  
         * @param event
         * @param token
         * 
         */
        private function onGetContentHandler(event:ResultEvent, token:AsyncToken) : void {
            var queueObject:QueueObject = _processingQueue[token.ID];
            
            queueObject.callBack(event);
        }
        
        
        /**
         * This is the fault event for the class. The callBack should accept a null ArrayCollection and a FaultEvent if
         * you want to handle the error.
         *  
         * @param event
         * @param token
         * 
         */
        private function onFault(event:FaultEvent, token:AsyncToken) : void {
            var queueObject:QueueObject = _processingQueue[token.ID];
            
            //handle the fault
            if(queueObject.returnErrorEvent){
                queueObject.callBack(null, event);
            }
            else {
                var displayMessage:String = event.fault.faultString;
                displayError(displayMessage);
                queueObject.callBack(null);
            }
        }
        
        
        /**
         * This will add a unique identifier to a token 
         * @param token
         * @return 
         * 
         */
        private function tokenID(token : AsyncToken) : AsyncToken {
            token.ID = Math.random();
            return token;
        }
        
        /**
         * Displays the error on a fault event in the content service 
         * @param event
         * 
         */
        private function displayError(displayMessage : String) : void {
            Alert.show(displayMessage, _alertTitle, Alert.OK);
        }
    }
}

class QueueObject{
    public var callBack:Function;
    public var returnErrorEvent:Boolean;
    
    public function QueueObject(callBack:Function, returnErrorEvent:Boolean){
        this.callBack = callBack;
        this.returnErrorEvent = returnErrorEvent;
    }
}


Using the class is really simple. Use getContent and pass it the file you want to load, the format it should be loaded in and the call back you want it to call after the file is retrieved. There are two extra properties I'm not using right now, but they will be helpful in the future. The fourth parameter accepts an Object of key/value pairs to be sent with the URL.The fifth parameter lets you capture the result of an error if one occurs. The call back should accept a FaultEvent object if you want to capture the error. If you let HTTPServiceWrapper handle the error an Alert window will pop up showing the error.
//http wrapper
private var _httpServiceWrapper:HTTPServiceWrapper = new HTTPServiceWrapper;

/**
* Runs when the application loads
* */
private function init() : void {
    //get the list of albums
    _httpServiceWrapper.getContent("stub/data/albums.xml", "e4x", populateList);
    
    //set event listeners for app
    albumsComboBox.addEventListener(ListEvent.CHANGE, loadAlbum);
}

/**
* This will populate the album list
* */
private function populateList(event:ResultEvent) : void {
 //if the result is null don't set it
 if(!event) {
  return;
 }
 
 //set the data provider
 albumsComboBox.dataProvider = event.result.album;
}

/**
* This will fetch the selected album
* */
private function loadAlbum(event:ListEvent) : void {
    _httpServiceWrapper.getContent("stub/data/" + event.currentTarget.selectedItem.@images, "e4x", populateTilelist);
}

This cut quite a bit of bloat out of my app and is also very reusable which saves time in the long run. The final version of this code is hosted here. You can view source on it by right-clicking in the app and selecting "View Source". Please let me know if you have any questions about it.

Tuesday, October 13, 2009

Flash / ActionScript 3 / Flex : Reading browser cookies

Part of an ActionScript 3 project I was working on required me to pull cookies from the users browser into Flash. I tried hunting around google to find a good method to achieve this, but found a lot of articles that wanted you to alter the embed code for flash. I wanted to find a way inside Flash to read the users cookies.

I wrote some code to do something similar in ActionScript 2 that used LoadVars. This class has been removed in ActionScript 3.

This is the ActionScript 3 code I came up with. It uses ExternalInterface to execute a bit of javascript that will pull the cookies directly into flash. It alters the cookie string to make it look like a URL and runs it through URLVariables.

package {
    import flash.display.Sprite;
    import flash.external.ExternalInterface;
    import flash.net.URLVariables;
    
    public class BrowserCookies extends Sprite
    {
        //this will parse the cookie data
        private var _urlVariables:URLVariables;
        
        /**
         * Return all the cookie values in one object
         * @return URLVariables 
         * 
         */
        public function get urlVariables() : URLVariables {
            return _urlVariables;
        }
        
        /**
         * Return one cookie value
         * @param value String
         * @return String
         * 
         */
        public function getCookieValue(value:String) : String {
            var returnValue:String = "";
            
            if(_urlVariables && _urlVariables[value]) {
                returnValue = _urlVariables[value];
            }
            
            return returnValue;
        }
        
        /**
         * This will connect to the browser and pull cookies into flash 
         */
        public function BrowserCookies() : void{
            //this will hold the data returned from javascript
            var browserCookieString:String;
            
            //pull the data from javascript
            browserCookieString = ExternalInterface.call("function(){return document.cookie}");
            
            //replace ; with & to make it look like a url
            browserCookieString = browserCookieString.replace(/;\s/g, "&");

            //parse the cookie string into variables. you can now access cookie variables as properties of this object
            if(browserCookieString) {
                _urlVariables = new URLVariables(browserCookieString);
            }
        }
    }
}


Now you can access any cookie property inside flash. Here is a quick example of how to use the class. Assume BrowserCookies.as exists in the same folder as the example class.
package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    
    public class Index extends Sprite{
        public function Index(){
            //this will pull all the cookies out of the browser
            var urlVars:BrowserCookies = new BrowserCookies;
            var textField:TextField = new TextField;
            
            textField.width = 200;
            textField.height = 200;
            textField.text = urlVars.getCookieValue("today");
            
            addChild(textField);
        }
    }
}

I've uploaded a Flex Projext Export version of this example available here. Feel free to contact me if you have any questions.

Flash / Actionscript 3: DataFormat doesn't exist

I was looking through the ActionScript 3.0 Cookbook today and started experimenting with the URLLoader class. The example on page 437 talks about setting the format for the incoming URL. When setting the dataFormat property of URLLoader it suggests using the constant called DataFormat. The only problem is this constant doesn't exist. It's a typo.

The real value is called URLLoaderDataFormat. You can read more about it here.

Friday, September 25, 2009

Flex / ActionScript: Debugging

I ran into an issue while working on a project in flex. I was trying to figure out why something wasn't working and had a large amount of trace calls in my code. It was a complete pain to remove them all. This lead me to develop a debug class that I can turn off at a page level or you can turn if off in the class. It's a first draft. I'd like to make it a Singlton so I can turn it off for the whole project at a page level, but that's for later.

package 
{
public class Debug
{
private var _displayDebug:Boolean = false;
private var _incomingClass:String = "";
private var _logArray:Array = [];

//to stop all debugging set this to false
private var _turnOffDebug:Boolean = false;

/**
* Create the debug object 
* @param display
* @param fileName
* 
*/
public function Debug(display:Boolean, fileName:String): void {
_displayDebug = display;
_incomingClass = fileName;
}


/**
* Display a trace message 
* @param msg
* 
*/
public function log(msg:String) : void {
//override anything a debug passes in
if(_turnOffDebug) {
return;
}

if(!_displayDebug) {
return;
}

var logMessage:String = "["+ new Date() +"]" + _incomingClass + ": " + msg; 

trace(logMessage);
_logArray.push(logMessage);
}
}
}


Using the class is simple. First create an instance of the class and tell if wither you want it on and what the name of the script you're calling it from is named.
var debugObj:Debug = new Debug(true, 'main.mxml');


To turn off debugging for the script just set the first parameter to false. To turn it off for the whole project change the class variable _turnOffDebug to true;

Use the log method to display your statement in the debug area of flash or flex.
debugObj.log('debug statement');


This is a what the trace statement should look like.
[Fri Sep 25 15:03:21 GMT-0700 2009]main.mxml: debug statement

If you have any feedback please send me a message.

Friday, September 18, 2009

Flash / ActionScript: String padding (leading zero)

I was working on a date/time format in Flash and needed a way to pad values out so they always took up the same amount of space. For example making sure a month always has two digits. Making sure it displays a "05" instead of "5". I couldn't find anything built into AS2 or AS3 to do this so I wrote something that would. It allows you to pass in a value and pad either the left or right side up to a given amount of characters.

/**
* This function will pad the left or right side of any variable passed in
* elem [AS object]
* padChar: String
* finalLength: Number
* dir: String
*
* return String
*/
function padValue(elem, padChar, finalLength, dir)
{
  //make sure the direction is in lowercase
  dir = dir.toLowerCase();

  //store the elem length
  var elemLen = elem.toString().length;

  //check the length for escape clause
  if(elemLen >= finalLength)
  {
    return elem;
  }

  //pad the value
  switch(dir)
  {
    default:
    case 'l':
      return padValue(padChar + elem, padChar, finalLength, dir);
      break;
    case 'r':
      return padValue(elem + padChar, padChar, finalLength, dir);
      break;
  }
}


This function accepts an object that can be converted to a string with the toString method, the character you want to use for padding, the final length of the string and wither you want it padded on the left or right side using the character "l" or "r".

For example if you have a number you want padded with three 0 so the final outcome will look like "0005" you would call the function like this.
var exampleNumber:Number = 5;
padValue(exampleNumber, "0", 4, 'l');


If you want to use this in FLEX you might want to type the parameters on the function and give it a return value.

Monday, August 10, 2009

Flex: setTimeout and setInterval replacement

One of the things I learned while moving from AS2 to AS3 is that setTimeout no longer exists. It's been replaced with a Timer class. It can be used like setTimeout or setInterval.

This is how you would use Timer as a setTimeout. The variable tTimer is set to launch 500 ms after start() is run. It will run once and then stop.

import flash.events.TimerEvent;
import flash.utils.Timer;

private function Timer_example()
{
var tTimer:Timer = new Timer(500, 1);
tTimer.addEventListener(TimerEvent.TIMER, onTimer);
tTimer.start();
}
private function onTimer(event:TimerEvent)
{
trace('callback event has run');
}


Timer can also function like setInterval. The second parameter tells timer how many times it should run. So if you want something to run 100 times then set timer will look like this.

var tTimer:Timer = new Timer(500, 100);

If you want it to run forever then set the interval to 0. If you do this make sure the timer is a global variable so you can run .stop() when it no longer needs to run.

Monday, August 3, 2009

Flex: Event Listeners and Array Collections

While working with some code I ran into a situation where I needed to know when an ArrayCollection was updated. Normally an event is triggered when using addItem, but I needed to know when it was set to another ArrayCollection. It's not very obvious, but it is possible.

ArrayCollection is really a wrapper for an Array. You can access the "real" array in an ArrayCollection by using ".source". When you set the source property an event called "listChanged" is triggered. You can watch for this event and then do whatever you need.

So this

var newAC1:ArrayCollection = new ArrayCollection;
var newAC2:ArrayCollection = new ArrayCollection;
newAC1 = newAC2;


Is the same as this, but with an event trigger.

var newAC1:ArrayCollection = new ArrayCollection;
var newAC2:ArrayCollection = new ArrayCollection;

newAC1.addEventListener('listChanged', function(event:Event){trace('changed');});

newAC1.source = newAC2.source;