How to respond to events in a custom WindowSWF panel (Actionscript 3)

One power you have in making custom panels for Flash (or whatever recent Adobe programs that support flash-based panels) that is almost never realized is the ability to respond to events. Does anything like this sound familiar to you: you want to update the panel every time the user changes a document or creates a new one? You want to do something when the document closes? The user moves their mouse (and not directly above the panel)? Fools all over the internet dogmatically claim that it’s impossible. It’s not. Here’s how you do it:

Writing purely in Javascript for Flash (JSFL), you might notice that you can attach events much like you can in actionscript thusly:

someCallback = function () {
    alert('all your bases are belong to us');
    }

fl.addEventListener("documentChanged", someCallback);

To do that in your flash panel, simply enclose that stuff in an MMExecute(); Thusly:

MMExecute("someCallback = function () { alert('all your bases are belong to us'); }");
MMExecute("fl.addEventListener("documentChanged", someCallback);");

And.. it works. Sure enough. But that’s not very interactive. I want FLASH to do something (since javascript just doesn’t do much in the authoring environment), like, say, update the display with new info. Wouldn’t it be cool if I could do this?

MMExecute("fl.addEventListener("documentChanged", SomeAS3Function);");

Alas, not possible. Holy Hell. ExternalInterface can’t even help us out here (right? I’d love to be wrong here…) But here’s what you can do. It’s not terribly pretty, but it does the job and when Adobe comes to their senses and builds AS3 JSFL communication into newer products, it would be very easy to modify the code for a more elegant solution. You can have global variables in the javascript and access them anywhere in the flash document. So, try this:

MMExecute("var updt = false");
MMExecute("updateDoc = function() { updt = true; }");
MMExecute("fl.addEventListener('documentChanged', updateDoc);");

Then, somewhere that is always looping (i.e., where stop() wasn’t called), you’ll want to add an event listener for entering the frame:

this.addEventListener(Event.ENTER_FRAME, updatey);
function updatey(event:Event) {
if(MMExecute("updt") == "true") {
   // whatever you wanna do! Resurrect dinosaurs, make robots feel...
   MMExecute("updt = false;");
   }
}

Note, that MMExecute returns a string so, though it be boolean in javascript, it’s converted to “true” and “false” in actionscript. When dealing with arrays and such, this becomes particularly frustrating, though you must question the design of your program any time you are passing complicated objects around… think about it.

Oh, one final note. It seems the capabilities I wish existed in Flash do exist in Fireworks (?) as detailed here. I looked and looked but could not find any equivalent to IsFwCallbackInstalled for Flash. Given how many things I’ve had to discover that were not anywhere to be found on Adobe’s site and how many undocumented features there are, I can’t help but wondering if a more elegant solution is lurking below.. Do tell me if you find it, mmkay?