Museum Pieces:  on() and onClipEvent()

ActionScript 2.0 Flash

ActionScript has evolved by leaps and bounds in the last few years.  The commercial release of Flex 2.0, and the public release of Flash Professional 9 ActionScript 3.0 Preview, in particular, nudge ActionScript 3.0 that much closer to the world in which we Flashers live.  The less-than-adventurous (nothing wrong with that!) won’t see AS3 until the commercial release of Flash 9 — still a long way off, as of this writing.  But when that does happen, our world will change.  That really isn’t an exaggeration.  There will be those who code in AS1/AS2 — there will still be plenty of room for that — and those who code in the jaw-droppingly more complex AS3.  The Flash 9 Player, already upon us, now features two virtual machines:  one that displays Flash 8 and prior content, and one that displays Flex and Flash 9 content.  That’s a first.

And yet, there’s still an awful lot of on() and onClipEvent() going on out there.  Is that so terrible?  Well, those event handling mechanisms were introduced in Flash 5.  In spite of their age, they haven’t been formally deprecated, so they’re perfectly “legal,” strictly speaking.  I can even muster a pragmatic smile for anyone who strongly feels that “if it ain’t broke, don’t fix it.”  But honestly, dot syntax event handling offers more control than that directly applied to the object.  Not only that, but the newer approach lets you organize your code into one place.  Let’s take a look. 

The old way

The on() handler is primarily aimed at button symbols, but it works with movie clips, too.  In Flash 5, it was necessary to attach the following to one of those objects (that is, you would actually click the button to select it, then open the Actions panel and enter code):

on(release) {
 // instructions here
}

This configuration specifically handles the release event, which occurs when the mouse is clicked, then released, over the button (or movie clip).  Other events include press, releaseOutside, rollOut, rollOver, dragOut, dragOver, and keyPress.

The onClipEvent() handler is geared at movie clip symbols, and only works with movie clips.  The code arrangement for this handler is the same:

onClipEvent(enterFrame) {
 // instructions here
}

This configuration handles the enterFrame event, which occurs at a rate more or less equivalent to the SWF’s framerate.  Other events include load, unload, mouseMove, mouseDown, mouseUp, keyDown, keyUp, and data.  Note that mouseUp is not the same as releaserelease is only fired when the mouse is released while hovering over the object in question; mouseUp is fired if the mouse is released anywhere.

Just remember, you can use on() with movie clips if you like. In effect, move clips handle all the events available to buttons, and then some.  But it gets even better.

The “new” way (new since Flash MX)

The dot notation approach appears as if it requires more typing — and truthfully, it does — but not by much.  In any case, it’s just as easy to code.  In this scenario, the ActionScript goes in a frame script rather than direct attachment.  Make sure your button or movie clip has an instance name (select it and look at the Property inspector; you’ll find it), then use that instance name in the following manner:

instanceName.onRelease = function() {
 // instructions here
}

In your code, “instanceName” will be replaced with the actual instance name you chose.  You’re simply calling the object by name and telling it what to do when a certain event is raised.  You may either use a function literal, as shown, or declare a named function and assign that, instead.

instanceName.onRelease = namedFunction;
function namedFunction():Void {
 // instructions here
}

Benefits of the new way

Again, why is this better?  Let me count the ways.

  1. 11 button events, versus the previous 8
  2. 18 movie clip events, versus the previous 9
  3. Code may be maintained in a single frame, if desired
  4. Events may be assigned, deleted, and changed programmatically

Okay, okay, four bullet points isn’t a boat load, but it’s certainly enough reason to make the switch, if you haven’t.

Points 1 and 2 speak for themselves.  To see all the events available to either object, look up the Button class and MovieClip class entries, respectively, in the ActionScript 2.0 Language Reference.

Point 3, to my thinking, is a significant improvement over the old Flash 5 approach.  When you have twenty buttons in front of you, it’s much more convenient to click inside a single frame to see everything you’re after than be obliged to click on each button individually.

Point 4 is perhaps the least obvious, but don’t overlook it!  Remember those twenty buttons?  What if most of them do essentially the same thing, with the one difference depending only on labeling?  What if you have forty buttons?  Is there an easier way than to write forty event handlers?

With the new approach, if you like, you can assign similar event handler functions with a for statement.  For example, if your buttons send the playhead to respective frame labels, get creative and match your instance names with those labels:

var buttons:Array = new Array("uno", "dos", "tres");
for (var i:Number = 0; i<buttons.length; i++) {
 this[buttons[i]].onRelease = function():Void {
  _root.gotoAndPlay(this._name);
 }
}

In the above, an arbitrarily named variable, buttons, points to an Array instance that contains three strings.  A for statement uses another arbitrarily named variable, i, to count from zero to the number of items in the array (thanks to the Array.length property).  Inside this loop, a pair of nested array access operators, [], resolves the array’s strings into button instance names; the Button.onRelease handler of each button, in turn, is instructed to send the main timeline to a frame label that shares the same name as the button instance itself.  (For further details on this technique, see this article on referencing objects dynamically).

In addition, you can delete event handlers, simply by using the delete statement or by setting the object’s event to null.  The following lines are functionally identical.

delete uno.onRelease;
uno.onRelease = null;

Why is this useful?  Well, if you’re using the MovieClip.onEnterFrame event to animate a clip …

clip.onEnterFrame = function():Void {
 this._x += 5;
}

… you can stop animating it by removing the function.  If you want the clip to stop moving when it hits the right site of the Stage, for example …

clip.onEnterFrame = function():Void {
 if (this._x >= Stage.width) {
  this.onEnterFrame = null;
 } else {
  this._x += 5;
 }
}

With onClipEvent(enterFrame), you’d have to change that += 5 increment to an increment of zero, instead.  Yes, the enterFrame function would keep ticking — after all, there’s nothing stopping it — but that’s just how it used to be.  It’s unnecessary processing, and enough of that sort of thing can slow a SWF down.

So when you’re digging through FlashKit.com or any other online sample code repository, keep in mind, you don’t have to use what you find 100% as is.  Break it apart, use it for inspiration, sure, but by all means, feel free to update it.  ;)

Leave a Reply