gskinner.com: gBlog: FlashMX 2004 source code, news, reviews and opinions
Back to gBlog Main gskinner.com website: source code, portfolio, etc. contact Grant Skinner

Syndication
RSS 1.0
RSS 2.0


Subscribe
Enter your email address to be notified when posts are added.

Search

Resources
Conference Session Notes

Flash Blogs
Waxpraxis
Philterblog
W3Blog
Jonas Galvez
Josh Dura
Quasimondo
Flashguru
Sean Voisen
Colin Moock
Flazoom
Greg Burch
Pope De Flash
Peter Hall
Glyn Thomas
actionscript.com
Princess Pegg


Aggregators
Flog
FullAsAGoog
MXNA
Hall of Justhese


« Aww... I'm blushing. | Back to Main | The ultimate AS2 XML solution! »

February 26, 2004


IMPORTANT NOTE: This is an old archive. It is only here to support outdated external links. To view the updated version of this archive, please go to the blog index, and search for the title of this document using the search form.

XML vs. AS2 - scoping callbacks
Posted by Grant
I've run into quite a few people wondering how to get an XML object to trigger a particular method in a class instance on load using ActionScript 2.0. In trying to accomplish this, you will encounter two issues, both of which can be circumvented.

Firstly, the scope of the onLoad function is within the method that created it, and it does not have direct access to any of the methods of the class instance. Using this. , you can explicitly access the scope of the XML object from within the handler. Many people are taking advantage of this by assigning an "owner" or "_parent" property to their XML object, then using that reference to access the class instance methods. It looks something like this:
class MyClass {
   var myXML;

   function loadData():Void {
      myXML = new XML();
      myXML.ignoreWhite = true
      myXML.owner = this; //used as reference in myXML
      myXML.onLoad = function(p_success:Boolean):Void {
         this.owner.myXMLOnLoad(p_success);
       }
      myXML.load("url.xml");
    }

   function myXMLOnLoad(p_success:Boolean):Void {
      trace("XML Loaded: "+myXML.toString());
    }
}

This works, but the moment you try to type myXML as XML, the compiler will spit back an error. This is because XML is not a dynamic class, so you are not allowed to add new properties to its instances arbitrarily.

So, how can we strict type our myXML object, and still call class instance methods in the right scope from within our onLoad handler? The trick is to take advantage of a relatively obscure feature of function creation called the "activation object". This allows you to access any locally scoped variables that were in existence when your function was created. In this case, we can simply define an owner variable in the loadData method, and point it back to the class instance with "this". You can then use that reference inside your anonymous "onLoad" function to trigger the appropriate method inside the class instance. For example:
class MyClass {
   var myXML:XML;

   function loadData():Void {
      myXML = new XML();
      myXML.ignoreWhite = true
      var owner:MyClass = this; //used as reference in myXML
      myXML.onLoad = function(p_success:Boolean):Void {
         owner.myXMLOnLoad(p_success);
       }
      myXML.load("url.xml");
    }

   function myXMLOnLoad(p_success:Boolean):Void {
      trace("XML Loaded: "+myXML.toString());
    }
}

The changes are subtle, so let's take a quick look at them:
  1. I typed myXML as XML.
  2. Instead of creating a new property of myXML called owner, I defined a local variable called owner that references the class instance with "this".
  3. In the onLoad handler, I accessed the owner variable that was made available through the function's activation object. Notice that I did not use "this.".
I hope this helps some people out. For a great explanation of scope, and how the activation object works, check out Scope Chain and Memory waste in Flash MX by Timothée Groleau.

Posted @ 11:28 AM by Grant | TrackBack


Comments

I was unaware of this feature, but it brings up a couple of additional concerns for me:

First, if this works then it means all of the temporary variables declared in loadData(). In this case no big deal, but there could be cases where a large amount of useless data is retained because a function is holding it in scope.

Second, you could call an instance method of the class from inside your onLoad with a completely different scope than should be allowed and not get a compiler error. This is a MM problem, but could be painful if you forget the above solution.

Thanks for the explaination, it saved me a lot of time :)

Posted by: Kendrick at April 30, 2004 12:45 PM

Great piece of code. I was creating global refs to the parent object before. Thanks.

Posted by: Tim at May 27, 2004 04:29 PM


Hosting by NetKeepers.ca | Powered by Movable Type 2.661
The text content of this blog is licensed under a Creative Commons License. Graphics are ©2003 Grant Skinner.