DojoExternalInterface.as 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. An implementation of Flash 8's ExternalInterface that works with Flash 6
  3. and which is source-compatible with Flash 8.
  4. @author Brad Neuberg, bkn3@columbia.edu
  5. */
  6. class DojoExternalInterface{
  7. public static var available:Boolean;
  8. public static var dojoPath = "";
  9. public static var _fscommandReady = false;
  10. public static var _callbacks = new Array();
  11. public static function initialize(){
  12. //getURL("javascript:console.debug('FLASH:DojoExternalInterface initialize')");
  13. // FIXME: Set available variable by testing for capabilities
  14. DojoExternalInterface.available = true;
  15. // extract the dojo base path
  16. DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
  17. //getURL("javascript:console.debug('FLASH:dojoPath="+DojoExternalInterface.dojoPath+"')");
  18. // Sometimes, on IE, the fscommand infrastructure can take a few hundred
  19. // milliseconds the first time a page loads. Set a timer to keep checking
  20. // to make sure we can issue fscommands; otherwise, our calls to fscommand
  21. // for setCallback() and loaded() will just "disappear"
  22. _root.fscommandReady = false;
  23. var fsChecker = function(){
  24. // issue a test fscommand
  25. fscommand("fscommandReady");
  26. // JavaScript should set _root.fscommandReady if it got the call
  27. if(_root.fscommandReady == "true"){
  28. DojoExternalInterface._fscommandReady = true;
  29. clearInterval(_root.fsTimer);
  30. }
  31. };
  32. _root.fsTimer = setInterval(fsChecker, 100);
  33. }
  34. public static function addCallback(methodName:String, instance:Object,
  35. method:Function) : Boolean{
  36. // A variable that indicates whether the call below succeeded
  37. _root._succeeded = null;
  38. // Callbacks are registered with the JavaScript side as follows.
  39. // On the Flash side, we maintain a lookup table that associates
  40. // the methodName with the actual instance and method that are
  41. // associated with this method.
  42. // Using fscommand, we send over the action "addCallback", with the
  43. // argument being the methodName to add, such as "foobar".
  44. // The JavaScript takes these values and registers the existence of
  45. // this callback point.
  46. // precede the method name with a _ character in case it starts
  47. // with a number
  48. _callbacks["_" + methodName] = {_instance: instance, _method: method};
  49. _callbacks[_callbacks.length] = methodName;
  50. // The API for ExternalInterface says we have to make sure the call
  51. // succeeded; check to see if there is a value
  52. // for _succeeded, which is set by the JavaScript side
  53. if(_root._succeeded == null){
  54. return false;
  55. }else{
  56. return true;
  57. }
  58. }
  59. public static function call(methodName:String,
  60. resultsCallback:Function) : Void{
  61. // FIXME: support full JSON serialization
  62. // First, we pack up all of the arguments to this call and set them
  63. // as Flash variables, which the JavaScript side will unpack using
  64. // plugin.GetVariable(). We set the number of arguments as "_numArgs",
  65. // and add each argument as a variable, such as "_1", "_2", etc., starting
  66. // from 0.
  67. // We then execute an fscommand with the action "call" and the
  68. // argument being the method name. JavaScript takes the method name,
  69. // retrieves the arguments using GetVariable, executes the method,
  70. // and then places the return result in a Flash variable
  71. // named "_returnResult".
  72. _root._numArgs = arguments.length - 2;
  73. for(var i = 2; i < arguments.length; i++){
  74. var argIndex = i - 2;
  75. _root["_" + argIndex] = arguments[i];
  76. }
  77. _root._returnResult = undefined;
  78. fscommand("call", methodName);
  79. // immediately return if the caller is not waiting for return results
  80. if(resultsCallback == undefined || resultsCallback == null){
  81. return;
  82. }
  83. // check at regular intervals for return results
  84. var resultsChecker = function(){
  85. if((typeof _root._returnResult != "undefined")&&
  86. (_root._returnResult != "undefined")){
  87. clearInterval(_root._callbackID);
  88. resultsCallback.call(null, _root._returnResult);
  89. }
  90. };
  91. _root._callbackID = setInterval(resultsChecker, 100);
  92. }
  93. /**
  94. Called by Flash to indicate to JavaScript that we are ready to have
  95. our Flash functions called. Calling loaded()
  96. will fire the dojox.flash.loaded() event, so that JavaScript can know that
  97. Flash has finished loading and adding its callbacks, and can begin to
  98. interact with the Flash file.
  99. */
  100. public static function loaded(){
  101. //getURL("javascript:console.debug('FLASH:loaded')");
  102. // one more step: see if fscommands are ready to be executed; if not,
  103. // set an interval that will keep running until fscommands are ready;
  104. // make sure the gateway is loaded as well
  105. var execLoaded = function(){
  106. if(DojoExternalInterface._fscommandReady == true){
  107. clearInterval(_root.loadedInterval);
  108. // initialize the small Flash file that helps gateway JS to Flash
  109. // calls
  110. DojoExternalInterface._initializeFlashRunner();
  111. }
  112. };
  113. if(_fscommandReady == true){
  114. execLoaded();
  115. }else{
  116. _root.loadedInterval = setInterval(execLoaded, 50);
  117. }
  118. }
  119. /**
  120. Handles and executes a JavaScript to Flash method call. Used by
  121. initializeFlashRunner.
  122. */
  123. public static function _handleJSCall(){
  124. // get our parameters
  125. var numArgs = parseInt(_root._numArgs);
  126. var jsArgs = new Array();
  127. for(var i = 0; i < numArgs; i++){
  128. var currentValue = _root["_" + i];
  129. jsArgs.push(currentValue);
  130. }
  131. // get our function name
  132. var functionName = _root._functionName;
  133. // now get the actual instance and method object to execute on,
  134. // using our lookup table that was constructed by calls to
  135. // addCallback on initialization
  136. var instance = _callbacks["_" + functionName]._instance;
  137. var method = _callbacks["_" + functionName]._method;
  138. // execute it
  139. var results = method.apply(instance, jsArgs);
  140. // return the results
  141. _root._returnResult = results;
  142. }
  143. /** Called by the flash6_gateway.swf to indicate that it is loaded. */
  144. public static function _gatewayReady(){
  145. for(var i = 0; i < _callbacks.length; i++){
  146. fscommand("addCallback", _callbacks[i]);
  147. }
  148. call("dojox.flash.loaded");
  149. }
  150. /**
  151. When JavaScript wants to communicate with Flash it simply sets
  152. the Flash variable "_execute" to true; this method creates the
  153. internal Movie Clip, called the Flash Runner, that makes this
  154. magic happen.
  155. */
  156. public static function _initializeFlashRunner(){
  157. // figure out where our Flash movie is
  158. var swfLoc = DojoExternalInterface.dojoPath + "flash6_gateway.swf";
  159. // load our gateway helper file
  160. _root.createEmptyMovieClip("_flashRunner", 5000);
  161. _root._flashRunner._lockroot = true;
  162. _root._flashRunner.loadMovie(swfLoc);
  163. }
  164. private static function getDojoPath(){
  165. var url = _root._url;
  166. var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
  167. var path = url.substring(start);
  168. var end = path.indexOf("&");
  169. if(end != -1){
  170. path = path.substring(0, end);
  171. }
  172. return path;
  173. }
  174. }
  175. // vim:ts=4:noet:tw=0: