Is the MovieClip.onLoad Event Broken?

ActionScript 2.0

Documents like Jen deHaan’s ActionScript 2.0 Best Practices (page four, in particular) recommend against attaching code directly to objects.  Generally speaking, I’m in enthusiastic agreement (see “Museum Pieces:  on() and onClipEvent()”).  Most events in AS2 are easy to handle, but MovieClip.onLoad is something of an oddball.  Before I understood that it needs to be treated differently from the others, I was stumped as to why it “didn’t work.”  (Hint:  It does work, but not the way most people expect.) 

Here’s how the ActionScript 2.0 Language Reference describes this event:

Invoked when the movie clip is instantiated and appears in the timeline. You must define a function that executes when the event handler is invoked. You can define the function on the timeline or in a class file that extends the MovieClip class or is linked to a symbol in the library.

So far, so good.  The other MovieClip events work this way, too. For example, if you want a movie clip to move to the right by one pixel whenever its timeline enters a frame, go ahead and define that function, just as the docs say.  This can be a named function or an anonymous literal:

// named
clip.onEnterFrame = someFunction;
// where someFunction() defines the rightward motion
// anonymous
clip.onEnterFrame = function():Void {
  this._x++;
}

If you take a similar approach with onLoad, you won’t see any results.  That is, the following code …

clip.onLoad = function():Void {
  trace("Clip has loaded!");
}

… has no apparent effect (normally, you’d expect to see the string “Clip has loaded!” in the Output panel).

So let’s look back at the documentation.  There’s that part about “or in a class file that extends …” blah blah blah.  It may be that the word “or” nudges people away; I’m not sure.  But the devil is often in the blah blah blahs.  ;)   Certainly, events can be handled in a timeline or a class file (or, for that matter, a class file linked to a symbol in the Library, as described), but something is lost in the muddle here.

MovieClip.onLoad requires an association with a class file

The next part of the documentation is key:

You use this handler only with movie clips for which you have a symbol in the library that is associated with a class.

To my thinking, the opening phrase, “You use this handler,” isn’t strong enough.  The truth is, you can only handle this event with movie clips that are associated with a class.  By “associated with a class,” I mean this:  create a new movie clip symbol, then right click (Windows) / Command+click (Macintosh) that symbol in the Library; select Linkage… and put a check mark in Export for ActionScript.  When you do, you’ll have the opportunity to enter something in the AS 2.0 class field — that’s your association.  Of course, you need a class file to go with it, and we’ll get to that in moment.

If you’re not familiar with associating Library symbols in this way, the process may seem a bit clunky, and maybe it is (this sort of thing is easier in AS3).  If you use the process often, it’s just par for the course.

I really don’t know why the MovieClip.onLoad event needs this association; I only know that it does.  If you regularly write your own class files (in this case, classes that extend MovieClip), it may be that you’re already handling onLoad inside the class.  If you need this event, your best bet is to do just that.

On the other hand, if you prefer to handle onLoad in a timeline script and see no practical use for a class file, you can either use a bare bones “dummy” class or a low down dirty trick.

Bare bones “dummy” class

Create a new ActionScript class (that is, a text file with the .as extension) and save it in the same folder as your FLA.  Give it the name FixOnLoad.as.  Edit this file and enter the following minimal code:

class FixOnLoad extends MovieClip {
  public function onLoad():Void {}
}

Flip to your FLA.  Enter the Linkage… setting of the desired symbol(s), as described above, and enter FixOnLoad into the AS 2.0 class field. That’s all you need.  Now the above example …

clip.onLoad = function():Void {
  trace("Clip has loaded!");
}

… works just fine.

Low down dirty trick

This is a hack.  I’m not saying it’s pretty, but to trick the IDE into giving you want you want, dispense with the whole class business. Clear out the AS 2.0 class field of the Linkage… setting.  Select the symbol on the Stage, open your Actions panel, and enter a space character.  Seriously.  Just a space, or put in comments, if you like (just a pair of slashes //).  That’ll do it.

To be clear, I’m not advocating this hack.  I’m definitely a fan of using class files.  In real-world projects, however, you sometimes just need to whip something together and neaten up at a later time.

12 Responses to “Is the MovieClip.onLoad Event Broken?”

  1. NSurveyor Says:

    Interesting… something that I never knew about! I don’t do much class work, but maybe I’ll experiment with it to see what this is all about.

    By the way, you’ve got some typos in here and a lotta missing spaces! :)

  2. David Stiller Says:

    Thanks, NSurveyor. I fixed the spaces. That was odd. :-p

  3. eRez Says:

    doesn’t work for me :-(
    first - as this class might be handy in many cases, i thought why have it available only for my current project instead of having it available for all my future projects as well? so i saved the as file (after i copy-pasted your code into it as is) in “C:\Documents and Settings\user\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\Classes\mx\utils” and named it ‘FixOnLoad.as’, then linked my movie clip in the library to ‘mx.utils.FixOnLoad’. when i tested my movie i got the following errors:

    **Error** C:\Documents and Settings\user\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\Classes\mx\utils\FixOnLoad.as: Line 1: The class being compiled, ‘FixOnLoad’, does not match the class that was imported, ‘mx.utils.FixOnLoad’.
    class FixOnLoad extends MovieClip {

    **Error** C:\Documents and Settings\user\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\Classes\mx\utils\FixOnLoad.as: Line 2: A member attribute was used incorrectly.
    public functiononLoad():Void {}

    **Error** C:\Documents and Settings\user\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\Classes\mx\utils\FixOnLoad.as: Line 3: A member attribute was used incorrectly.
    }

    so just to make sure, i saved my as file in the same folder as my fla file (changed the linkage only to ‘FixOnLoad’), and now got only the 2nd and 3rd errors i had before.
    where did i go wrong?

    ps - just for the record, your ‘Low down dirty trick’ did the work :-)

  4. David Stiller Says:

    eErez,

    doesn’t work for me :-(

    Two issues, here. First, a mistake on my part. For some reason, a number of words got mashed together in this article (spaces arbitrarily missing), which NSurveyor discovered. I thought I’d caught them all, but there was still one in the code that goes inside the class. The word “functiononLoad” should have been “function onLoad” (I’ve since corrected the article).

    Second, you changed the location of the file. ;) You correctly linked to mx.utils.FixOnLoad in your Linkage… setting, but that package would also need to go into the class, then. This existing code …

    class FixOnLoad extends MovieClip {

    … would become …

    class mx.utils.FixOnLoad extends MovieClip {
  5. eRez Says:

    now it works 4 me!! :-)
    thanks,
    eRez

  6. David Stiller Says:

    Woo hoo! This is funny, considering my “devil in the blah blah blahs” remark. It’s those darned details, I tell ya! I don’t know how I messed up those spaces.

  7. myIP Says:

    I understand that you need to associate the symbol with a class, but is it possible to associate the parent’s symbol instead of the child’s symbol? For an example, if I had a symbol named “Engine” that had 4 instances of “Piston” symbols inside of it and wanted to make sure that all 4 pistons are loaded before assigning them with code, would it be safe to just associate the Engine symbol with a class? I think this question is starting to head out of scope with the article of yours and is heading into the scope of how Flash loads symbols, which would be a nice subject for an article :D

  8. David Stiller Says:

    myIP,

    Interesting question. Honestly, I’m not sure how to answer it. The MovieClip.onLoad event is dispatched when the movie clip in question first appears on the timeline (even virtually, if the clip is attached at runtime). So it’s not really a matter of ensuring that child clips have loaded — they “ship with the SWF,” so to speak; you can count on it they’ll load — it’s really more about initializing a movie clip when it first appears. If you wanted to ensure that child clips were initialized … that might be something. But even there, depending on the complexity of your app, you might just dispatch your own event onInit, say, if it came to that.

  9. NSurveyor Says:

    This turned out to be rather useful. On the KEYFRAMER forum, it was inquired if you can put code (like an event handler assignment) before actually instantiating a clip. Using the space hack, I managed to get it to work.

    http://www.keyframer.com/forum/viewtopic.php?t=392

  10. Laurie Says:

    I just can’t say how grateful I am for seeing this. I have been struggling to see how MovieClip.onLoad might work from the timeline (and thus find a way to avoid onClipEven(Load)) for 18 months or more. A big thank you.

  11. davies Says:

    this site is very resource full!

  12. David Stiller Says:

    To Laurie …

    Wow, I think this might be the longest I’ve taken to reply to a comment. Sorry about that! And thanks for the happy comment. :-D Glad to help.

    To davies …

    Thanks to you too! :)

Leave a Reply