if (!dojo._hasResource["dojox.flash._common"]) { // _hasResource checks added // by build. Do not use // _hasResource directly in // your code. dojo._hasResource["dojox.flash._common"] = true; dojo.provide("dojox.flash._common"); dojox.flash = function() { // summary: // The goal of dojox.flash is to make it easy to extend Flash's // capabilities // into an AJAX/DHTML environment. // description: // The goal of dojox.flash is to make it easy to extend Flash's // capabilities // into an AJAX/DHTML environment. Robust, performant, reliable // JavaScript/Flash communication is harder than most realize when they // delve into the topic, especially if you want it // to work on Internet Explorer, Firefox, and Safari, and to be able to // push around hundreds of K of information quickly. dojox.flash makes // it // possible to support these platforms; you have to jump through a few // hoops to get its capabilites, but if you are a library writer // who wants to bring Flash's storage or streaming sockets ability into // DHTML, for example, then dojox.flash is perfect for you. // // dojox.flash provides an easy object for interacting with the Flash // plugin. // This object provides methods to determine the current version of the // Flash // plugin (dojox.flash.info); execute Flash instance methods // independent of the Flash version // being used (dojox.flash.comm); write out the necessary markup to // dynamically insert a Flash object into the page (dojox.flash.Embed; // and // do dynamic installation and upgrading of the current Flash plugin in // use (dojox.flash.Install). // // To use dojox.flash, you must first wait until Flash is finished // loading // and initializing before you attempt communication or interaction. // To know when Flash is finished use dojo.connect: // // dojo.connect(dojox.flash, "loaded", myInstance, "myCallback"); // // Then, while the page is still loading provide the file name // and the major version of Flash that will be used for Flash/JavaScript // communication (see "Flash Communication" below for information on the // different kinds of Flash/JavaScript communication supported and how // they // depend on the version of Flash installed): // // dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", // "_storage/storage_flash6.swf"), // flash8: dojo.moduleUrl("dojox", "_storage/storage_flash8.swf")}); // // This will cause dojox.flash to pick the best way of communicating // between Flash and JavaScript based on the platform. // // If no SWF files are specified, then Flash is not initialized. // // Your Flash must use DojoExternalInterface to expose Flash methods and // to call JavaScript; see "Flash Communication" below for details. // // setSwf can take an optional 'visible' attribute to control whether // the Flash object is visible or not on the page; the default is // visible: // // dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", // "_storage/storage_flash6.swf"), // flash8: dojo.moduleUrl("dojox", "_storage/storage_flash8.swf"), // visible: false }); // // Once finished, you can query Flash version information: // // dojox.flash.info.version // // Or can communicate with Flash methods that were exposed: // // var results = dojox.flash.comm.sayHello("Some Message"); // // Only string values are currently supported for both arguments and // for return results. Everything will be cast to a string on both // the JavaScript and Flash sides. // // ------------------- // Flash Communication // ------------------- // // dojox.flash allows Flash/JavaScript communication in // a way that can pass large amounts of data back and forth reliably and // very fast. The dojox.flash // framework encapsulates the specific way in which this communication // occurs, // presenting a common interface to JavaScript irrespective of the // underlying // Flash version. // // There are currently three major ways to do Flash/JavaScript // communication // in the Flash community: // // 1) Flash 6+ - Uses Flash methods, such as SetVariable and TCallLabel, // and the fscommand handler to do communication. Strengths: Very fast, // mature, and can send extremely large amounts of data; can do // synchronous method calls. Problems: Does not work on Safari; works on // Firefox/Mac OS X only if Flash 8 plugin is installed; cryptic to work // with. // // 2) Flash 8+ - Uses ExternalInterface, which provides a way for Flash // methods to register themselves for callbacks from JavaScript, and a // way // for Flash to call JavaScript. Strengths: Works on Safari; elegant to // work with; can do synchronous method calls. Problems: Extremely buggy // (fails if there are new lines in the data, for example); performance // degrades drastically in O(n^2) time as data grows; locks up the // browser while // it is communicating; does not work in Internet Explorer if Flash // object is dynamically added to page with document.writeln, DOM // methods, // or innerHTML. // // 3) Flash 6+ - Uses two seperate Flash applets, one that we // create over and over, passing input data into it using the PARAM tag, // which then uses a Flash LocalConnection to pass the data to the main // Flash // applet; communication back to Flash is accomplished using a getURL // call with a javascript protocol handler, such as // "javascript:myMethod()". // Strengths: the most cross browser, cross platform pre-Flash 8 method // of Flash communication known; works on Safari. Problems: Timing // issues; // clunky and complicated; slow; can only send very small amounts of // data (several K); all method calls are asynchronous. // // dojox.flash.comm uses only the first two methods. This framework // was created primarily for dojox.storage, which needs to pass very // large // amounts of data synchronously and reliably across the // Flash/JavaScript // boundary. We use the first method, the Flash 6 method, on all // platforms // that support it, while using the Flash 8 ExternalInterface method // only on Safari with some special code to help correct // ExternalInterface's // bugs. // // Since dojox.flash needs to have two versions of the Flash // file it wants to generate, a Flash 6 and a Flash 8 version to gain // true cross-browser compatibility, several tools are provided to ease // development on the Flash side. // // In your Flash file, if you want to expose Flash methods that can be // called, use the DojoExternalInterface class to register methods. This // class is an exact API clone of the standard ExternalInterface class, // but // can work in Flash 6+ browsers. Under the covers it uses the best // mechanism to do communication: // // class HelloWorld{ // function HelloWorld(){ // // Initialize the DojoExternalInterface class // DojoExternalInterface.initialize(); // // // Expose your methods // DojoExternalInterface.addCallback("sayHello", this, this.sayHello); // // // Tell JavaScript that you are ready to have method calls // DojoExternalInterface.loaded(); // // // Call some JavaScript // var resultsReady = function(results){ // trace("Received the following results from JavaScript: " + results); // } // DojoExternalInterface.call("someJavaScriptMethod", resultsReady, // someParameter); // } // // function sayHello(){ ... } // // static main(){ ... } // } // // DojoExternalInterface adds two new functions to the ExternalInterface // API: initialize() and loaded(). initialize() must be called before // any addCallback() or call() methods are run, and loaded() must be // called after you are finished adding your callbacks. 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. // // To generate your SWF files, use the ant task // "buildFlash". You must have the open source Motion Twin ActionScript // compiler (mtasc) installed and in your path to use the "buildFlash" // ant task; download and install mtasc from http://www.mtasc.org/. // // // // buildFlash usage: // // // FIXME: this is not correct in the 0.9 world! // ant buildFlash -Ddojox.flash.file=../tests/flash/HelloWorld.as // // where "dojox.flash.file" is the relative path to your Flash // ActionScript file. // // This will generate two SWF files, one ending in _flash6.swf and the // other // ending in _flash8.swf in the same directory as your ActionScript // method: // // HelloWorld_flash6.swf // HelloWorld_flash8.swf // // Initialize dojox.flash with the filename and Flash communication // version to // use during page load; see the documentation for dojox.flash for // details: // // dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", // "flash/tests/flash/HelloWorld_flash6.swf"), // flash8: dojo.moduleUrl("dojox", // "flash/tests/flash/HelloWorld_flash8.swf")}); // // Now, your Flash methods can be called from JavaScript as if they are // native // Flash methods, mirrored exactly on the JavaScript side: // // dojox.flash.comm.sayHello(); // // Only Strings are supported being passed back and forth currently. // // JavaScript to Flash communication is synchronous; i.e., results are // returned // directly from the method call: // // var results = dojox.flash.comm.sayHello(); // // Flash to JavaScript communication is asynchronous due to limitations // in // the underlying technologies; you must use a results callback to // handle // results returned by JavaScript in your Flash AS files: // // var resultsReady = function(results){ // trace("Received the following results from JavaScript: " + results); // } // DojoExternalInterface.call("someJavaScriptMethod", resultsReady); // // // // ------------------- // Notes // ------------------- // // If you have both Flash 6 and Flash 8 versions of your file: // // dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", // "flash/tests/flash/HelloWorld_flash6.swf"), // flash8: dojo.moduleUrl("dojox", // "flash/tests/flash/HelloWorld_flash8.swf")}); // // but want to force the browser to use a certain version of Flash for // all platforms (for testing, for example), use the djConfig // variable 'forceFlashComm' with the version number to force: // // var djConfig = { forceFlashComm: 6 }; // // Two values are currently supported, 6 and 8, for the two styles of // communication described above. Just because you force dojox.flash // to use a particular communication style is no guarantee that it will // work; for example, Flash 8 communication doesn't work in Internet // Explorer due to bugs in Flash, and Flash 6 communication does not // work // in Safari. It is best to let dojox.flash determine the best // communication // mechanism, and to use the value above only for debugging the // dojox.flash // framework itself. // // Also note that dojox.flash can currently only work with one Flash // object // on the page; it and the API do not yet support multiple Flash objects // on // the same page. // // We use some special tricks to get decent, linear performance // out of Flash 8's ExternalInterface on Safari; see the blog // post // http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html // for details. // // Your code can detect whether the Flash player is installing or having // its version revved in two ways. First, if dojox.flash detects that // Flash installation needs to occur, it sets // dojox.flash.info.installing // to true. Second, you can detect if installation is necessary with the // following callback: // // dojo.connect(dojox.flash, "installing", myInstance, "myCallback"); // // You can use this callback to delay further actions that might need // Flash; // when installation is finished the full page will be refreshed and the // user will be placed back on your page with Flash installed. // // ------------------- // Todo/Known Issues // ------------------- // // There are several tasks I was not able to do, or did not need to fix // to get dojo.storage out: // // * When using Flash 8 communication, Flash method calls to JavaScript // are not working properly; serialization might also be broken for // certain // invalid characters when it is Flash invoking JavaScript methods. // The Flash side needs to have more sophisticated serialization/ // deserialization mechanisms like JavaScript currently has. The // test_flash2.html unit tests should also be updated to have much more // sophisticated Flash to JavaScript unit tests, including large // amounts of data. // // * On Internet Explorer, after doing a basic install, the page is // not refreshed or does not detect that Flash is now available. The way // to fix this is to create a custom small Flash file that is pointed to // during installation; when it is finished loading, it does a callback // that says that Flash installation is complete on IE, and we can // proceed // to initialize the dojox.flash subsystem. // // Author- Brad Neuberg, bkn3@columbia.edu } dojox.flash = { flash6_version : null, flash8_version : null, ready : false, _visible : true, _loadedListeners : new Array(), _installingListeners : new Array(), setSwf : function(/* Object */fileInfo) { // summary: Sets the SWF files and versions we are using. // fileInfo: Object // An object that contains two attributes, 'flash6' and 'flash8', // each of which contains the path to our Flash 6 and Flash 8 // versions of the file we want to script. // example: // var swfloc6 = dojo.moduleUrl("dojox.storage", // "Storage_version6.swf").toString(); // var swfloc8 = dojo.moduleUrl("dojox.storage", // "Storage_version8.swf").toString(); // dojox.flash.setSwf({flash6: swfloc6, flash8: swfloc8, visible: // false}); if (!fileInfo) { return; } if (fileInfo["flash6"]) { this.flash6_version = fileInfo.flash6; } if (fileInfo["flash8"]) { this.flash8_version = fileInfo.flash8; } if (fileInfo["visible"]) { this._visible = fileInfo.visible; } // initialize ourselves this._initialize(); }, useFlash6 : function() { /* Boolean */ // summary: Returns whether we are using Flash 6 for communication // on this platform. if (this.flash6_version == null) { return false; } else if (this.flash6_version != null && dojox.flash.info.commVersion == 6) { // if we have a flash 6 version of this SWF, and this browser // supports // communicating using Flash 6 features... return true; } else { return false; } }, useFlash8 : function() { /* Boolean */ // summary: Returns whether we are using Flash 8 for communication // on this platform. if (this.flash8_version == null) { return false; } else if (this.flash8_version != null && dojox.flash.info.commVersion == 8) { // if we have a flash 8 version of this SWF, and this browser // supports // communicating using Flash 8 features... return true; } else { return false; } }, addLoadedListener : function(/* Function */listener) { // summary: // Adds a listener to know when Flash is finished loading. // Useful if you don't want a dependency on dojo.event. // listener: Function // A function that will be called when Flash is done loading. this._loadedListeners.push(listener); }, addInstallingListener : function(/* Function */listener) { // summary: // Adds a listener to know if Flash is being installed. // Useful if you don't want a dependency on dojo.event. // listener: Function // A function that will be called if Flash is being // installed this._installingListeners.push(listener); }, loaded : function() { // summary: Called back when the Flash subsystem is finished // loading. // description: // A callback when the Flash subsystem is finished loading and can // be // worked with. To be notified when Flash is finished loading, // connect // your callback to this method using the following: // // dojo.event.connect(dojox.flash, "loaded", myInstance, // "myCallback"); // dojo.debug("dojox.flash.loaded"); dojox.flash.ready = true; if (dojox.flash._loadedListeners.length > 0) { for (var i = 0; i < dojox.flash._loadedListeners.length; i++) { dojox.flash._loadedListeners[i].call(null); } } }, installing : function() { // summary: Called if Flash is being installed. // description: // A callback to know if Flash is currently being installed or // having its version revved. To be notified if Flash is installing, // connect // your callback to this method using the following: // // dojo.event.connect(dojox.flash, "installing", myInstance, // "myCallback"); // dojo.debug("installing"); if (dojox.flash._installingListeners.length > 0) { for (var i = 0; i < dojox.flash._installingListeners.length; i++) { dojox.flash._installingListeners[i].call(null); } } }, // Initializes dojox.flash. _initialize : function() { // dojo.debug("dojox.flash._initialize"); // see if we need to rev or install Flash on this platform var installer = new dojox.flash.Install(); dojox.flash.installer = installer; if (installer.needed() == true) { installer.install(); } else { // dojo.debug("Writing object out"); // write the flash object into the page dojox.flash.obj = new dojox.flash.Embed(this._visible); dojox.flash.obj.write(dojox.flash.info.commVersion); // initialize the way we do Flash/JavaScript communication dojox.flash.comm = new dojox.flash.Communicator(); } } }; dojox.flash.Info = function() { // summary: A class that helps us determine whether Flash is available. // description: // A class that helps us determine whether Flash is available, // it's major and minor versions, and what Flash version features should // be used for Flash/JavaScript communication. Parts of this code // are adapted from the automatic Flash plugin detection code // autogenerated // by the Macromedia Flash 8 authoring environment. // // An instance of this class can be accessed on dojox.flash.info after // the page is finished loading. // // This constructor must be called before the page is finished loading. // Visual basic helper required to detect Flash Player ActiveX control // version information on Internet Explorer if (dojo.isIE) { document .write([ ''); // hook for Internet Explorer to receive FSCommands from Flash if (dojo.isIE) { document.writeln('