diff options
author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
---|---|---|
committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dojox/flash | |
parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
download | semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2 |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dojox/flash')
-rw-r--r-- | includes/js/dojox/flash/DojoExternalInterface.as | 168 | ||||
-rw-r--r-- | includes/js/dojox/flash/ExpressInstall.as | 71 | ||||
-rw-r--r-- | includes/js/dojox/flash/README | 31 | ||||
-rw-r--r-- | includes/js/dojox/flash/_base.js | 762 | ||||
-rw-r--r-- | includes/js/dojox/flash/tests/TestFlash.as | 36 | ||||
-rw-r--r-- | includes/js/dojox/flash/tests/TestFlash.swf | bin | 0 -> 1863 bytes | |||
-rw-r--r-- | includes/js/dojox/flash/tests/buildFlashTest.sh | 4 | ||||
-rw-r--r-- | includes/js/dojox/flash/tests/test_flash.html | 15 | ||||
-rw-r--r-- | includes/js/dojox/flash/tests/test_flash.js | 155 |
9 files changed, 1242 insertions, 0 deletions
diff --git a/includes/js/dojox/flash/DojoExternalInterface.as b/includes/js/dojox/flash/DojoExternalInterface.as new file mode 100644 index 0000000..d857968 --- /dev/null +++ b/includes/js/dojox/flash/DojoExternalInterface.as @@ -0,0 +1,168 @@ +/**
+ A wrapper around Flash 8's ExternalInterface; this is needed
+ because ExternalInterface has a number of serialization bugs that we
+ need to correct for.
+
+ @author Brad Neuberg
+*/
+
+import flash.external.ExternalInterface;
+
+class DojoExternalInterface{
+ public static var available:Boolean;
+ public static var dojoPath = "";
+
+ public static function initialize(){
+ //trace("DojoExternalInterface.initialize");
+
+ // extract the dojo base path
+ DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
+
+ // see if we need to do an express install
+ var install:ExpressInstall = new ExpressInstall();
+ if(install.needsUpdate){
+ install.init();
+ }
+
+ // set whether communication is available
+ DojoExternalInterface.available = ExternalInterface.available;
+ }
+
+ /** Called when we are finished adding methods through addCallback. */
+ public static function done(){
+ //trace("done");
+ DojoExternalInterface.call("dojox.flash.loaded");
+ }
+
+ public static function addCallback(methodName:String, instance:Object,
+ method:Function):Boolean{
+ //trace("addCallback");
+ ExternalInterface.addCallback(methodName, instance, function(){
+ instance = (instance) ? instance : null;
+ var params = [];
+ if(arguments && arguments.length){
+ for(var i = 0; i < arguments.length; i++){
+ params[i] = DojoExternalInterface.decodeData(arguments[i]);
+ }
+ }
+
+ var results = method.apply(instance, params);
+ results = DojoExternalInterface.encodeData(results);
+
+ return results;
+ });
+
+ // tell JavaScript about DojoExternalInterface new method so we can create a proxy
+ ExternalInterface.call("dojox.flash.comm._addExternalInterfaceCallback",
+ methodName);
+
+ return true;
+ }
+
+ public static function call(methodName:String):Void{
+ // we might have any number of optional arguments, so we have to
+ // pass them in dynamically; strip out the results callback
+ var parameters = new Array();
+ for(var i = 0; i < arguments.length; i++){
+ parameters.push(arguments[i]);
+ }
+
+ // FIXME: Should we be encoding or decoding the data to get
+ // around Flash's serialization bugs?
+
+ var results = ExternalInterface.call.apply(ExternalInterface, parameters);
+
+ return results;
+ }
+
+ /**
+ 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(){
+ DojoExternalInterface.call("dojox.flash.loaded");
+ }
+
+ /**
+ Utility trace implementation that prints out to console.debug.
+ */
+ public static function trace(msg){
+ DojoExternalInterface.call("console.debug", "FLASH: " + msg);
+ }
+
+ private static function decodeData(data):String{
+ if(!data || typeof data != "string"){
+ return data;
+ }
+
+ // we have to use custom encodings for certain characters when passing
+ // them over; for example, passing a backslash over as //// from JavaScript
+ // to Flash doesn't work
+ data = replaceStr(data, "&custom_backslash;", "\\");
+
+ data = replaceStr(data, "\\\'", "\'");
+ data = replaceStr(data, "\\\"", "\"");
+
+ return data;
+ }
+
+ private static function encodeData(data):String{
+ if(!data || typeof data != "string"){
+ return data;
+ }
+
+ // certain XMLish characters break Flash's wire serialization for
+ // ExternalInterface; encode these into a custom encoding, rather than
+ // the standard entity encoding, because otherwise we won't be able to
+ // differentiate between our own encoding and any entity characters
+ // that are being used in the string itself
+ data = replaceStr(data, '<', '&custom_lt;');
+ data = replaceStr(data, '>', '&custom_gt;');
+
+ // needed for IE
+ data = replaceStr(data, '\\', '&custom_backslash;');
+
+ // encode control characters and JavaScript delimiters
+ data = replaceStr(data, "\n", "\\n");
+ data = replaceStr(data, "\r", "\\r");
+ data = replaceStr(data, "\f", "\\f");
+ data = replaceStr(data, "'", "\\'");
+ data = replaceStr(data, '"', '\"');
+
+ return data;
+ }
+
+ /**
+ Flash ActionScript has no String.replace method or support for
+ Regular Expressions! We roll our own very simple one.
+ */
+ public static function replaceStr(inputStr:String, replaceThis:String,
+ withThis:String):String{
+ var splitStr = inputStr.split(replaceThis);
+ if(!splitStr){
+ return inputStr;
+ }
+
+ inputStr = splitStr.join(withThis);
+ return inputStr;
+ }
+
+ private static function getDojoPath(){
+ var url = _root._url;
+ var start = url.indexOf("baseUrl=") + "baseUrl=".length;
+ var path = url.substring(start);
+ var end = path.indexOf("&");
+ if(end != -1){
+ path = path.substring(0, end);
+ }
+
+ // some browsers append a junk string at the end: '%20'%20quality=
+ if(path.indexOf("'%20'%20quality=") != -1){
+ path = path.substring(0, path.indexOf("'%20'%20quality="));
+ }
+ return path;
+ }
+}
diff --git a/includes/js/dojox/flash/ExpressInstall.as b/includes/js/dojox/flash/ExpressInstall.as new file mode 100644 index 0000000..1801171 --- /dev/null +++ b/includes/js/dojox/flash/ExpressInstall.as @@ -0,0 +1,71 @@ +/**
+ * Based on the expressinstall.as class created by Geoff Stearns as part
+ * of the FlashObject library.
+ *
+ * Use this file to invoke the Macromedia Flash Player Express Install functionality
+ * This file is intended for use with the FlashObject embed script. You can download FlashObject
+ * and this file at the following URL: http://blog.deconcept.com/flashobject/
+ *
+ * Usage:
+ * var ExpressInstall = new ExpressInstall();
+ *
+ * // test to see if install is needed:
+ * if (ExpressInstall.needsUpdate) { // returns true if update is needed
+ * ExpressInstall.init(); // starts the update
+ * }
+ *
+ * NOTE: Your Flash movie must be at least 214px by 137px in order to use ExpressInstall.
+ *
+ */
+
+class ExpressInstall{
+ public var needsUpdate:Boolean;
+ private var updater:MovieClip;
+ private var hold:MovieClip;
+
+ public function ExpressInstall(){
+ // does the user need to update?
+ this.needsUpdate = (_root.MMplayerType == undefined) ? false : true;
+ }
+
+ public function init():Void{
+ this.loadUpdater();
+ }
+
+ public function loadUpdater():Void{
+ System.security.allowDomain("fpdownload.macromedia.com");
+
+ // hope that nothing is at a depth of 10000000, you can change this depth if needed, but you want
+ // it to be on top of your content if you have any stuff on the first frame
+ this.updater = _root.createEmptyMovieClip("expressInstallHolder", 10000000);
+
+ // register the callback so we know if they cancel or there is an error
+ var _self = this;
+ this.updater.installStatus = _self.onInstallStatus;
+ this.hold = this.updater.createEmptyMovieClip("hold", 1);
+
+ // can't use movieClipLoader because it has to work in 6.0.65
+ this.updater.onEnterFrame = function():Void {
+ if(typeof this.hold.startUpdate == 'function'){
+ _self.initUpdater();
+ this.onEnterFrame = null;
+ }
+ }
+
+ var cacheBuster:Number = Math.random();
+
+ this.hold.loadMovie("http://fpdownload.macromedia.com/pub/flashplayer/"
+ +"update/current/swf/autoUpdater.swf?"+ cacheBuster);
+ }
+
+ private function initUpdater():Void{
+ this.hold.redirectURL = _root.MMredirectURL;
+ this.hold.MMplayerType = _root.MMplayerType;
+ this.hold.MMdoctitle = _root.MMdoctitle;
+ this.hold.startUpdate();
+ }
+
+ public function onInstallStatus(msg):Void{
+ getURL("javascript:dojox.flash.install._onInstallStatus('"+msg+"')");
+ }
+}
diff --git a/includes/js/dojox/flash/README b/includes/js/dojox/flash/README new file mode 100644 index 0000000..e01f3be --- /dev/null +++ b/includes/js/dojox/flash/README @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +dojox.flash +------------------------------------------------------------------------------- +Version 0.4 +Release date: MM/DD/YYYY +------------------------------------------------------------------------------- +Project state: experimental (currently broken) +------------------------------------------------------------------------------- +Project authors + Brad Neuberg (BradNeuberg@dojotoolkit.org) + Alex Russell (alex@dojotoolkit.org, only handled minor porting issues) +------------------------------------------------------------------------------- +Project description + +Infrastructure for high-performance Flash/JS communication +------------------------------------------------------------------------------- +Dependencies: + +MTASC for creating builds +------------------------------------------------------------------------------- +Documentation + +TODOC +------------------------------------------------------------------------------- +Installation instructions + +Not intended as a stand-alone module. +------------------------------------------------------------------------------- +Additional Notes + +TODOC diff --git a/includes/js/dojox/flash/_base.js b/includes/js/dojox/flash/_base.js new file mode 100644 index 0000000..5a372dd --- /dev/null +++ b/includes/js/dojox/flash/_base.js @@ -0,0 +1,762 @@ +if(!dojo._hasResource["dojox.flash._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.flash._base"] = true; +dojo.provide("dojox.flash._base"); + +// for dijit.getViewport(), needed by dojox.flash.Embed.center() +dojo.require("dijit._base.place"); + +dojox.flash = function(){ + // summary: + // The goal of dojox.flash is to make it easy to extend Flash's capabilities + // into an Ajax/DHTML environment. + // + // 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); 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). If you want to call methods on the Flash object + // embedded into the page it is your responsibility to use Flash's ExternalInterface + // API and get a reference to the Flash object yourself. + // + // 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: + // + // dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf")); + // + // If no SWF files are specified, then Flash is not initialized. + // + // Your Flash must use Flash's ExternalInterface to expose Flash methods and + // to call JavaScript. + // + // 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(dojo.moduleUrl("dojox", "_storage/storage.swf"), + // false); + // + // Once finished, you can query Flash version information: + // + // dojox.flash.info.version + // + // Or can communicate with Flash methods that were exposed: + // + // var f = dojox.flash.get(); + // var results = f.sayHello("Some Message"); + // + // Your Flash files should use DojoExternalInterface.as to register methods; + // this file wraps Flash's normal ExternalInterface but correct various + // serialization bugs that ExternalInterface has. + // + // Note that dojox.flash is not meant to be a generic Flash embedding + // mechanism; it is as generic as necessary to make Dojo Storage's + // Flash Storage Provider as clean and modular as possible. If you want + // a generic Flash embed mechanism see SWFObject + // (http://blog.deconcept.com/swfobject/). + // + // Notes: + // Note that dojox.flash can currently only work with one Flash object + // on the page; it does not yet support multiple Flash objects on + // the same page. + // + // 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 + // ------------------- + // * 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. + // * Things aren't super tested for sending complex objects to Flash + // methods, since Dojo Storage only needs strings + // + // Author- Brad Neuberg, http://codinginparadise.org +} + +dojox.flash = { + ready: false, + url: null, + + _visible: true, + _loadedListeners: new Array(), + _installingListeners: new Array(), + + setSwf: function(/* String */ url, /* boolean? */ visible){ + // summary: Sets the SWF files and versions we are using. + // url: String + // The URL to this Flash file. + // visible: boolean? + // Whether the Flash file is visible or not. If it is not visible we hide it off the + // screen. This defaults to true (i.e. the Flash file is visible). + this.url = url; + + if(typeof visible != "undefined"){ + this._visible = visible; + } + + // initialize ourselves + this._initialize(); + }, + + 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, add a + // loaded listener: + // + // dojox.flash.addLoadedListener(loadedListener); + + 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"); + + 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(){ + //console.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{ + // write the flash object into the page + dojox.flash.obj = new dojox.flash.Embed(this._visible); + dojox.flash.obj.write(); + + // setup the communicator + 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([ + '<script language="VBScript" type="text/vbscript"\>', + 'Function VBGetSwfVer(i)', + ' on error resume next', + ' Dim swControl, swVersion', + ' swVersion = 0', + ' set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))', + ' if (IsObject(swControl)) then', + ' swVersion = swControl.GetVariable("$version")', + ' end if', + ' VBGetSwfVer = swVersion', + 'End Function', + '</script\>'].join("\r\n")); + } + + this._detectVersion(); +} + +dojox.flash.Info.prototype = { + // version: String + // The full version string, such as "8r22". + version: -1, + + // versionMajor, versionMinor, versionRevision: String + // The major, minor, and revisions of the plugin. For example, if the + // plugin is 8r22, then the major version is 8, the minor version is 0, + // and the revision is 22. + versionMajor: -1, + versionMinor: -1, + versionRevision: -1, + + // capable: Boolean + // Whether this platform has Flash already installed. + capable: false, + + // installing: Boolean + // Set if we are in the middle of a Flash installation session. + installing: false, + + isVersionOrAbove: function( + /* int */ reqMajorVer, + /* int */ reqMinorVer, + /* int */ reqVer){ /* Boolean */ + // summary: + // Asserts that this environment has the given major, minor, and revision + // numbers for the Flash player. + // description: + // Asserts that this environment has the given major, minor, and revision + // numbers for the Flash player. + // + // Example- To test for Flash Player 7r14: + // + // dojox.flash.info.isVersionOrAbove(7, 0, 14) + // returns: + // Returns true if the player is equal + // or above the given version, false otherwise. + + // make the revision a decimal (i.e. transform revision 14 into + // 0.14 + reqVer = parseFloat("." + reqVer); + + if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer + && this.versionRevision >= reqVer){ + return true; + }else{ + return false; + } + }, + + _detectVersion: function(){ + var versionStr; + + // loop backwards through the versions until we find the newest version + for(var testVersion = 25; testVersion > 0; testVersion--){ + if(dojo.isIE){ + versionStr = VBGetSwfVer(testVersion); + }else{ + versionStr = this._JSFlashInfo(testVersion); + } + + if(versionStr == -1 ){ + this.capable = false; + return; + }else if(versionStr != 0){ + var versionArray; + if(dojo.isIE){ + var tempArray = versionStr.split(" "); + var tempString = tempArray[1]; + versionArray = tempString.split(","); + }else{ + versionArray = versionStr.split("."); + } + + this.versionMajor = versionArray[0]; + this.versionMinor = versionArray[1]; + this.versionRevision = versionArray[2]; + + // 7.0r24 == 7.24 + var versionString = this.versionMajor + "." + this.versionRevision; + this.version = parseFloat(versionString); + + this.capable = true; + + break; + } + } + }, + + // JavaScript helper required to detect Flash Player PlugIn version + // information. Internet Explorer uses a corresponding Visual Basic + // version to interact with the Flash ActiveX control. + _JSFlashInfo: function(testVersion){ + // NS/Opera version >= 3 check for Flash plugin in plugin array + if(navigator.plugins != null && navigator.plugins.length > 0){ + if(navigator.plugins["Shockwave Flash 2.0"] || + navigator.plugins["Shockwave Flash"]){ + var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; + var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; + var descArray = flashDescription.split(" "); + var tempArrayMajor = descArray[2].split("."); + var versionMajor = tempArrayMajor[0]; + var versionMinor = tempArrayMajor[1]; + if(descArray[3] != ""){ + var tempArrayMinor = descArray[3].split("r"); + }else{ + var tempArrayMinor = descArray[4].split("r"); + } + var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0; + var version = versionMajor + "." + versionMinor + "." + + versionRevision; + + return version; + } + } + + return -1; + } +}; + +dojox.flash.Embed = function(visible){ + // summary: A class that is used to write out the Flash object into the page. + // description: + // Writes out the necessary tags to embed a Flash file into the page. Note that + // these tags are written out as the page is loaded using document.write, so + // you must call this class before the page has finished loading. + + this._visible = visible; +} + +dojox.flash.Embed.prototype = { + // width: int + // The width of this Flash applet. The default is the minimal width + // necessary to show the Flash settings dialog. Current value is + // 215 pixels. + width: 215, + + // height: int + // The height of this Flash applet. The default is the minimal height + // necessary to show the Flash settings dialog. Current value is + // 138 pixels. + height: 138, + + // id: String + // The id of the Flash object. Current value is 'flashObject'. + id: "flashObject", + + // Controls whether this is a visible Flash applet or not. + _visible: true, + + protocol: function(){ + switch(window.location.protocol){ + case "https:": + return "https"; + break; + default: + return "http"; + break; + } + }, + + write: function(/* Boolean? */ doExpressInstall){ + // summary: Writes the Flash into the page. + // description: + // This must be called before the page + // is finished loading. + // doExpressInstall: Boolean + // Whether to write out Express Install + // information. Optional value; defaults to false. + + // determine our container div's styling + var containerStyle = ""; + containerStyle += ("width: " + this.width + "px; "); + containerStyle += ("height: " + this.height + "px; "); + if(!this._visible){ + containerStyle += "position: absolute; z-index: 10000; top: -1000px; left: -1000px; "; + } + + // figure out the SWF file to get and how to write out the correct HTML + // for this Flash version + var objectHTML; + var swfloc = dojox.flash.url; + var swflocObject = swfloc; + var swflocEmbed = swfloc; + var dojoUrl = dojo.baseUrl; + if(doExpressInstall){ + // the location to redirect to after installing + var redirectURL = escape(window.location); + document.title = document.title.slice(0, 47) + " - Flash Player Installation"; + var docTitle = escape(document.title); + swflocObject += "?MMredirectURL=" + redirectURL + + "&MMplayerType=ActiveX" + + "&MMdoctitle=" + docTitle + + "&baseUrl=" + escape(dojoUrl); + swflocEmbed += "?MMredirectURL=" + redirectURL + + "&MMplayerType=PlugIn" + + "&baseUrl=" + escape(dojoUrl); + }else{ + // IE/Flash has an evil bug that shows up some time: if we load the + // Flash and it isn't in the cache, ExternalInterface works fine -- + // however, the second time when its loaded from the cache a timing + // bug can keep ExternalInterface from working. The trick below + // simply invalidates the Flash object in the cache all the time to + // keep it loading fresh. -- Brad Neuberg + swflocObject += "?cachebust=" + new Date().getTime(); + } + + if(swflocEmbed.indexOf("?") == -1){ + swflocEmbed += '?baseUrl='+escape(dojoUrl); + }else{ + swflocEmbed += '&baseUrl='+escape(dojoUrl); + } + + objectHTML = + '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' + + 'codebase="' + + this.protocol() + + '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/' + + 'swflash.cab#version=8,0,0,0"\n ' + + 'width="' + this.width + '"\n ' + + 'height="' + this.height + '"\n ' + + 'id="' + this.id + '"\n ' + + 'name="' + this.id + '"\n ' + + 'align="middle">\n ' + + '<param name="allowScriptAccess" value="sameDomain"></param>\n ' + + '<param name="movie" value="' + swflocObject + '"></param>\n ' + + '<param name="quality" value="high"></param>\n ' + + '<param name="bgcolor" value="#ffffff"></param>\n ' + + '<embed src="' + swflocEmbed + '" ' + + 'quality="high" ' + + 'bgcolor="#ffffff" ' + + 'width="' + this.width + '" ' + + 'height="' + this.height + '" ' + + 'id="' + this.id + 'Embed' + '" ' + + 'name="' + this.id + '" ' + + 'swLiveConnect="true" ' + + 'align="middle" ' + + 'allowScriptAccess="sameDomain" ' + + 'type="application/x-shockwave-flash" ' + + 'pluginspage="' + + this.protocol() + +'://www.macromedia.com/go/getflashplayer" ' + + '></embed>\n' + + '</object>\n'; + + // using same mechanism on all browsers now to write out + // Flash object into page + + // document.write no longer works correctly + // due to Eolas patent workaround in IE; + // nothing happens (i.e. object doesn't + // go into page if we use it) + dojo.connect(dojo, "loaded", dojo.hitch(this, function(){ + var div = document.createElement("div"); + div.setAttribute("id", this.id + "Container"); + div.setAttribute("style", containerStyle); + div.innerHTML = objectHTML; + + var body = document.getElementsByTagName("body"); + if(!body || !body.length){ + throw new Error("No body tag for this page"); + } + body = body[0]; + body.appendChild(div); + })); + }, + + get: function(){ /* Object */ + // summary: Gets the Flash object DOM node. + if(dojo.isIE || dojo.isSafari){ + return document.getElementById(this.id); + }else{ + // different IDs on OBJECT and EMBED tags or + // else Firefox will return wrong one and + // communication won't work; + // also, document.getElementById() returns a + // plugin but ExternalInterface calls don't + // work on it so we have to use + // document[id] instead + return document[this.id + "Embed"]; + } + }, + + setVisible: function(/* Boolean */ visible){ + //console.debug("setVisible, visible="+visible); + + // summary: Sets the visibility of this Flash object. + var container = dojo.byId(this.id + "Container"); + if(visible == true){ + container.style.position = "absolute"; // IE -- Brad Neuberg + container.style.visibility = "visible"; + }else{ + container.style.position = "absolute"; + container.style.x = "-1000px"; + container.style.y = "-1000px"; + container.style.visibility = "hidden"; + } + }, + + center: function(){ + // summary: Centers the flash applet on the page. + + var elementWidth = this.width; + var elementHeight = this.height; + + var viewport = dijit.getViewport(); + + // compute the centered position + var x = viewport.l + (viewport.w - elementWidth) / 2; + var y = viewport.t + (viewport.h - elementHeight) / 2; + + // set the centered position + var container = dojo.byId(this.id + "Container"); + container.style.top = y + "px"; + container.style.left = x + "px"; + } +}; + + +dojox.flash.Communicator = function(){ + // summary: + // A class that is used to communicate between Flash and JavaScript. + // description: + // This class helps mediate Flash and JavaScript communication. Internally + // it uses Flash 8's ExternalInterface API, but adds functionality to fix + // various encoding bugs that ExternalInterface has. +} + +dojox.flash.Communicator.prototype = { + // Registers the existence of a Flash method that we can call with + // JavaScript, using Flash 8's ExternalInterface. + _addExternalInterfaceCallback: function(methodName){ + var wrapperCall = dojo.hitch(this, function(){ + // some browsers don't like us changing values in the 'arguments' array, so + // make a fresh copy of it + var methodArgs = new Array(arguments.length); + for(var i = 0; i < arguments.length; i++){ + methodArgs[i] = this._encodeData(arguments[i]); + } + + var results = this._execFlash(methodName, methodArgs); + results = this._decodeData(results); + + return results; + }); + + this[methodName] = wrapperCall; + }, + + // Encodes our data to get around ExternalInterface bugs that are still + // present even in Flash 9. + _encodeData: function(data){ + if(!data || typeof data != "string"){ + return data; + } + + // double encode all entity values, or they will be mis-decoded + // by Flash when returned + var entityRE = /\&([^;]*)\;/g; + data = data.replace(entityRE, "&$1;"); + + // entity encode XML-ish characters, or Flash's broken XML serializer + // breaks + data = data.replace(/</g, "<"); + data = data.replace(/>/g, ">"); + + // transforming \ into \\ doesn't work; just use a custom encoding + data = data.replace("\\", "&custom_backslash;"); + + data = data.replace(/\0/g, "\\0"); // null character + data = data.replace(/\"/g, """); + + return data; + }, + + // Decodes our data to get around ExternalInterface bugs that are still + // present even in Flash 9. + _decodeData: function(data){ + // wierdly enough, Flash sometimes returns the result as an + // 'object' that is actually an array, rather than as a String; + // detect this by looking for a length property; for IE + // we also make sure that we aren't dealing with a typeof string + // since string objects have length property there + if(data && data.length && typeof data != "string"){ + data = data[0]; + } + + if(!data || typeof data != "string"){ + return data; + } + + // certain XMLish characters break Flash's wire serialization for + // ExternalInterface; these are encoded on the + // DojoExternalInterface side into a custom encoding, rather than + // the standard entity encoding, because otherwise we won't be able to + // differentiate between our own encoding and any entity characters + // that are being used in the string itself + data = data.replace(/\&custom_lt\;/g, "<"); + data = data.replace(/\&custom_gt\;/g, ">"); + data = data.replace(/\&custom_backslash\;/g, '\\'); + + // needed for IE; \0 is the NULL character + data = data.replace(/\\0/g, "\0"); + + return data; + }, + + // Executes a Flash method; called from the JavaScript wrapper proxy we + // create on dojox.flash.comm. + _execFlash: function(methodName, methodArgs){ + var plugin = dojox.flash.obj.get(); + methodArgs = (methodArgs) ? methodArgs : []; + + // encode arguments that are strings + for(var i = 0; i < methodArgs; i++){ + if(typeof methodArgs[i] == "string"){ + methodArgs[i] = this._encodeData(methodArgs[i]); + } + } + + // we use this gnarly hack below instead of + // plugin[methodName] for two reasons: + // 1) plugin[methodName] has no call() method, which + // means we can't pass in multiple arguments dynamically + // to a Flash method -- we can only have one + // 2) On IE plugin[methodName] returns undefined -- + // plugin[methodName] used to work on IE when we + // used document.write but doesn't now that + // we use dynamic DOM insertion of the Flash object + // -- Brad Neuberg + var flashExec = function(){ + return eval(plugin.CallFunction( + "<invoke name=\"" + methodName + + "\" returntype=\"javascript\">" + + __flash__argumentsToXML(methodArgs, 0) + + "</invoke>")); + }; + var results = flashExec.call(methodArgs); + + if(typeof results == "string"){ + results = this._decodeData(results); + } + + return results; + } +} + +// FIXME: dojo.declare()-ify this + +// TODO: I did not test the Install code when I refactored Dojo Flash from 0.4 to +// 1.0, so am not sure if it works. If Flash is not present I now prefer +// that Gears is installed instead of Flash because GearsStorageProvider is +// much easier to work with than Flash's hacky ExternalInteface. +// -- Brad Neuberg +dojox.flash.Install = function(){ + // summary: Helps install Flash plugin if needed. + // description: + // Figures out the best way to automatically install the Flash plugin + // for this browser and platform. Also determines if installation or + // revving of the current plugin is needed on this platform. +} + +dojox.flash.Install.prototype = { + needed: function(){ /* Boolean */ + // summary: + // Determines if installation or revving of the current plugin is + // needed. + + // do we even have flash? + if(dojox.flash.info.capable == false){ + return true; + } + + // Must have ExternalInterface which came in Flash 8 + if(!dojox.flash.info.isVersionOrAbove(8, 0, 0)){ + return true; + } + + // otherwise we don't need installation + return false; + }, + + install: function(){ + // summary: Performs installation or revving of the Flash plugin. + + // indicate that we are installing + dojox.flash.info.installing = true; + dojox.flash.installing(); + + if(dojox.flash.info.capable == false){ // we have no Flash at all + // write out a simple Flash object to force the browser to prompt + // the user to install things + var installObj = new dojox.flash.Embed(false); + installObj.write(); // write out HTML for Flash + }else if(dojox.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install + var installObj = new dojox.flash.Embed(false); + installObj.write(true); // write out HTML for Flash 8 version+ + installObj.setVisible(true); + installObj.center(); + }else{ // older Flash install than version 6r65 + alert("This content requires a more recent version of the Macromedia " + +" Flash Player."); + window.location.href = + dojox.flash.Embed.protocol() + + "://www.macromedia.com/go/getflashplayer"; + } + }, + + // Called when the Express Install is either finished, failed, or was + // rejected by the user. + _onInstallStatus: function(msg){ + if (msg == "Download.Complete"){ + // Installation is complete. + dojox.flash._initialize(); + }else if(msg == "Download.Cancelled"){ + alert("This content requires a more recent version of the Macromedia " + +" Flash Player."); + window.location.href = dojox.flash.Embed.protocol() + + "://www.macromedia.com/go/getflashplayer"; + }else if (msg == "Download.Failed"){ + // The end user failed to download the installer due to a network failure + alert("There was an error downloading the Flash Player update. " + + "Please try again later, or visit macromedia.com to download " + + "the latest version of the Flash plugin."); + } + } +} + +// find out if Flash is installed +dojox.flash.info = new dojox.flash.Info(); + +// vim:ts=4:noet:tw=0: + +} diff --git a/includes/js/dojox/flash/tests/TestFlash.as b/includes/js/dojox/flash/tests/TestFlash.as new file mode 100644 index 0000000..d7be64f --- /dev/null +++ b/includes/js/dojox/flash/tests/TestFlash.as @@ -0,0 +1,36 @@ +import DojoExternalInterface; +import ExpressInstall; + +class TestFlash{ + private var message:String; + + public function TestFlash(){ + } + + public static function main(){ + //getURL("javascript:alert('main')"); + trace("main"); + DojoExternalInterface.initialize(); + + var test = new TestFlash(); + DojoExternalInterface.addCallback("setMessage", test, test.setMessage); + DojoExternalInterface.addCallback("getMessage", test, test.getMessage); + DojoExternalInterface.addCallback("multipleValues", + test, test.multipleValues); + + DojoExternalInterface.done(); + } + + public function setMessage(message:String):Void{ + this.message = message; + } + + public function getMessage():String{ + return this.message; + } + + public function multipleValues(key:String, value:String, + namespace:String):String{ + return namespace + key + value; + } +}
\ No newline at end of file diff --git a/includes/js/dojox/flash/tests/TestFlash.swf b/includes/js/dojox/flash/tests/TestFlash.swf Binary files differnew file mode 100644 index 0000000..cfd3f8d --- /dev/null +++ b/includes/js/dojox/flash/tests/TestFlash.swf diff --git a/includes/js/dojox/flash/tests/buildFlashTest.sh b/includes/js/dojox/flash/tests/buildFlashTest.sh new file mode 100644 index 0000000..a73d20c --- /dev/null +++ b/includes/js/dojox/flash/tests/buildFlashTest.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# TODO: FIXME: Get rid of this and hook it into Dojo's general build script +# You must have mtasc to run this +mtasc -trace DojoExternalInterface.trace -main -cp .. -swf TestFlash.swf -version 8 -header 215:138:10 TestFlash.as
\ No newline at end of file diff --git a/includes/js/dojox/flash/tests/test_flash.html b/includes/js/dojox/flash/tests/test_flash.html new file mode 100644 index 0000000..5e09f45 --- /dev/null +++ b/includes/js/dojox/flash/tests/test_flash.html @@ -0,0 +1,15 @@ +<html> + <head> + <script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script> + + <script src="test_flash.js"></script> + </head> + + <body> + <h1>Test Dojox Flash</h1> + + <p>For detailed test output see Firebug console (if Firefox). + This test should be run on Firefox, Internet Explorer, and Safari + to confirm that Dojox Flash is working correctly.</p> + </body> +</html>
\ No newline at end of file diff --git a/includes/js/dojox/flash/tests/test_flash.js b/includes/js/dojox/flash/tests/test_flash.js new file mode 100644 index 0000000..1b26eb2 --- /dev/null +++ b/includes/js/dojox/flash/tests/test_flash.js @@ -0,0 +1,155 @@ +// TODO: FIXME: Refactor this to use D.O.H. instead of its own assertions + +dojo.require("dojox.flash"); + +var flashLoaded = false; +var pageLoaded = false; +var testXML = testBook = null; + +function flashReady(){ + console.debug("flashReady"); + flashLoaded = true; + + if(isReady()){ + run(); + } +} + +function pageReady(){ + console.debug("pageReady"); + pageLoaded = true; + + loadResources(); + + if(isReady()){ + run(); + } +} + +function isReady(){ + return testXML && testBook && pageLoaded && flashLoaded; +} + +function loadResources(){ + console.debug("Trying to load resources"); + + var d = dojo.xhrGet({ + url: "../../storage/tests/resources/testXML.xml", + handleAs: "text" + }); + + d.addCallback(function(results){ + console.debug("testXML loaded"); + testXML = results; + if(isReady()){ + run(); + } + }); + + d.addErrback(function(error){ + console.debug("Unable to load testXML.xml: " + error); + }); + + d = dojo.xhrGet({ + url: "../../storage/tests/resources/testBook.txt", + handleAs: "text" + }); + + d.addCallback(function(results){ + console.debug("testBook loaded"); + testBook = results; + if(isReady()){ + run(); + } + }); + + d.addErrback(function(error){ + console.debug("Unable to load testXML.xml: " + error); + }); +} + +function run(){ + console.debug("run"); + try{ + var correct, actual; + + console.debug("Setting simple message..."); + correct = "hello world"; + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting simple message did not work"); + + console.debug("Setting message with evil characters..."); + // our correct and actual values get tricky when we have double back + // slashes; do a trick so that they can be compared easier + var doubleSlash = "\\"; + doubleSlash = doubleSlash.charAt(0); + correct = "hello world\n\n\nasdfasdf!@#$@#%^[]{}&<xml>" + doubleSlash + + "<div>$%^&%^&*^&()<><><>,./;\0\r\f\'][`~=\"+-]MORE!\n\rLESS"; + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting message with evil characters did not work"); + + console.debug("Setting testXML..."); + correct = testXML; + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting testXML did not work"); + + console.debug("Setting testBook(~300K)..."); + correct = testBook; + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting testBook did not work"); + + console.debug("Setting testBook 3 times (~900K)..."); + correct = testBook + testBook + testBook; + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting testBook X 3 did not work"); + + console.debug("Setting JSON..."); + var obj = {type: "car", color: "red", model: "Ford", year: "2008", + features: ["A/C", "automatic", "4-wheel drive"]}; + correct = dojo.toJson(obj, true); + dojox.flash.comm.setMessage(correct); + actual = dojox.flash.comm.getMessage(); + assert(correct, actual, "Setting/getting JSON did not work"); + + console.debug("Calling method that takes multiple values..."); + actual = dojox.flash.comm.multipleValues("key", "value", "namespace"); + assert("namespacekeyvalue", actual, "Setting/getting multiple values did not work"); + + var allPassed = document.createElement("p"); + allPassed.style.backgroundColor = "green"; + allPassed.style.color = "white"; + allPassed.style.fontSize = "24pt"; + allPassed.appendChild(document.createTextNode("All tests passed")); + var body = document.getElementsByTagName("body")[0]; + body.appendChild(allPassed); + }catch(e){ + console.debug(e.message || e); + } +} + +function assert(correct, actual, msg){ + //alert("correct="+correct+",\n\nactual="+actual); + if(correct != actual){ + var failed = document.createElement("p"); + failed.style.backgroundColor = "red"; + failed.style.color = "white"; + failed.style.fontSize = "24pt"; + failed.appendChild(document.createTextNode("Test failed: " + msg)); + var body = document.getElementsByTagName("body")[0]; + body.appendChild(failed); + + throw new Error("ASSERTION FAILED: " + msg); + }else{ + console.debug("Assertion passed"); + } +} + +console.debug("adding listeners..."); +dojox.flash.addLoadedListener(flashReady); +dojox.flash.setSwf("TestFlash.swf", true); +dojo.connect(dojo, "loaded", pageReady); |