| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| /**
|
| 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:dojo.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:dojo.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 dojo.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:dojo.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("dojo.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:
|