123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /**
- An implementation of Flash 8's ExternalInterface that works with Flash 6
- and which is source-compatible with Flash 8.
-
- @author Brad Neuberg, bkn3@columbia.edu
- */
- class DojoExternalInterface{
- public static var available:Boolean;
- public static var dojoPath = "";
-
- public static var _fscommandReady = false;
- public static var _callbacks = new Array();
- public static function initialize(){
- //getURL("javascript:console.debug('FLASH:DojoExternalInterface initialize')");
- // FIXME: Set available variable by testing for capabilities
- DojoExternalInterface.available = true;
-
- // extract the dojo base path
- DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
- //getURL("javascript:console.debug('FLASH:dojoPath="+DojoExternalInterface.dojoPath+"')");
-
- // Sometimes, on IE, the fscommand infrastructure can take a few hundred
- // milliseconds the first time a page loads. Set a timer to keep checking
- // to make sure we can issue fscommands; otherwise, our calls to fscommand
- // for setCallback() and loaded() will just "disappear"
- _root.fscommandReady = false;
- var fsChecker = function(){
- // issue a test fscommand
- fscommand("fscommandReady");
-
- // JavaScript should set _root.fscommandReady if it got the call
- if(_root.fscommandReady == "true"){
- DojoExternalInterface._fscommandReady = true;
- clearInterval(_root.fsTimer);
- }
- };
- _root.fsTimer = setInterval(fsChecker, 100);
- }
-
- public static function addCallback(methodName:String, instance:Object,
- method:Function) : Boolean{
- // A variable that indicates whether the call below succeeded
- _root._succeeded = null;
-
- // Callbacks are registered with the JavaScript side as follows.
- // On the Flash side, we maintain a lookup table that associates
- // the methodName with the actual instance and method that are
- // associated with this method.
- // Using fscommand, we send over the action "addCallback", with the
- // argument being the methodName to add, such as "foobar".
- // The JavaScript takes these values and registers the existence of
- // this callback point.
-
- // precede the method name with a _ character in case it starts
- // with a number
- _callbacks["_" + methodName] = {_instance: instance, _method: method};
- _callbacks[_callbacks.length] = methodName;
-
- // The API for ExternalInterface says we have to make sure the call
- // succeeded; check to see if there is a value
- // for _succeeded, which is set by the JavaScript side
- if(_root._succeeded == null){
- return false;
- }else{
- return true;
- }
- }
-
- public static function call(methodName:String,
- resultsCallback:Function) : Void{
- // FIXME: support full JSON serialization
-
- // First, we pack up all of the arguments to this call and set them
- // as Flash variables, which the JavaScript side will unpack using
- // plugin.GetVariable(). We set the number of arguments as "_numArgs",
- // and add each argument as a variable, such as "_1", "_2", etc., starting
- // from 0.
- // We then execute an fscommand with the action "call" and the
- // argument being the method name. JavaScript takes the method name,
- // retrieves the arguments using GetVariable, executes the method,
- // and then places the return result in a Flash variable
- // named "_returnResult".
- _root._numArgs = arguments.length - 2;
- for(var i = 2; i < arguments.length; i++){
- var argIndex = i - 2;
- _root["_" + argIndex] = arguments[i];
- }
-
- _root._returnResult = undefined;
- fscommand("call", methodName);
-
- // immediately return if the caller is not waiting for return results
- if(resultsCallback == undefined || resultsCallback == null){
- return;
- }
-
- // check at regular intervals for return results
- var resultsChecker = function(){
- if((typeof _root._returnResult != "undefined")&&
- (_root._returnResult != "undefined")){
- clearInterval(_root._callbackID);
- resultsCallback.call(null, _root._returnResult);
- }
- };
- _root._callbackID = setInterval(resultsChecker, 100);
- }
-
- /**
- Called by Flash to indicate to JavaScript that we are ready to have
- our Flash functions called. Calling loaded()
- will fire the dojox.flash.loaded() event, so that JavaScript can know that
- Flash has finished loading and adding its callbacks, and can begin to
- interact with the Flash file.
- */
- public static function loaded(){
- //getURL("javascript:console.debug('FLASH:loaded')");
-
- // one more step: see if fscommands are ready to be executed; if not,
- // set an interval that will keep running until fscommands are ready;
- // make sure the gateway is loaded as well
- var execLoaded = function(){
- if(DojoExternalInterface._fscommandReady == true){
- clearInterval(_root.loadedInterval);
-
- // initialize the small Flash file that helps gateway JS to Flash
- // calls
- DojoExternalInterface._initializeFlashRunner();
- }
- };
-
- if(_fscommandReady == true){
- execLoaded();
- }else{
- _root.loadedInterval = setInterval(execLoaded, 50);
- }
- }
-
- /**
- Handles and executes a JavaScript to Flash method call. Used by
- initializeFlashRunner.
- */
- public static function _handleJSCall(){
- // get our parameters
- var numArgs = parseInt(_root._numArgs);
- var jsArgs = new Array();
- for(var i = 0; i < numArgs; i++){
- var currentValue = _root["_" + i];
- jsArgs.push(currentValue);
- }
-
- // get our function name
- var functionName = _root._functionName;
-
- // now get the actual instance and method object to execute on,
- // using our lookup table that was constructed by calls to
- // addCallback on initialization
- var instance = _callbacks["_" + functionName]._instance;
- var method = _callbacks["_" + functionName]._method;
-
- // execute it
- var results = method.apply(instance, jsArgs);
-
- // return the results
- _root._returnResult = results;
- }
-
- /** Called by the flash6_gateway.swf to indicate that it is loaded. */
- public static function _gatewayReady(){
- for(var i = 0; i < _callbacks.length; i++){
- fscommand("addCallback", _callbacks[i]);
- }
- call("dojox.flash.loaded");
- }
-
- /**
- When JavaScript wants to communicate with Flash it simply sets
- the Flash variable "_execute" to true; this method creates the
- internal Movie Clip, called the Flash Runner, that makes this
- magic happen.
- */
- public static function _initializeFlashRunner(){
- // figure out where our Flash movie is
- var swfLoc = DojoExternalInterface.dojoPath + "flash6_gateway.swf";
-
- // load our gateway helper file
- _root.createEmptyMovieClip("_flashRunner", 5000);
- _root._flashRunner._lockroot = true;
- _root._flashRunner.loadMovie(swfLoc);
- }
-
- private static function getDojoPath(){
- var url = _root._url;
- var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
- var path = url.substring(start);
- var end = path.indexOf("&");
- if(end != -1){
- path = path.substring(0, end);
- }
- return path;
- }
- }
- // vim:ts=4:noet:tw=0:
|