[483] | 1 | /** |
---|
| 2 | A wrapper around Flash 8's ExternalInterface; this is needed |
---|
| 3 | because ExternalInterface has a number of serialization bugs that we |
---|
| 4 | need to correct for. |
---|
| 5 | |
---|
| 6 | @author Brad Neuberg |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | import flash.external.ExternalInterface; |
---|
| 10 | |
---|
| 11 | class DojoExternalInterface{ |
---|
| 12 | public static var available:Boolean; |
---|
| 13 | public static var dojoPath = ""; |
---|
| 14 | |
---|
| 15 | public static function initialize(){ |
---|
| 16 | //trace("DojoExternalInterface.initialize"); |
---|
| 17 | |
---|
| 18 | // extract the dojo base path |
---|
| 19 | DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath(); |
---|
| 20 | |
---|
| 21 | // see if we need to do an express install |
---|
| 22 | var install:ExpressInstall = new ExpressInstall(); |
---|
| 23 | if(install.needsUpdate){ |
---|
| 24 | install.init(); |
---|
| 25 | } |
---|
| 26 | |
---|
| 27 | // set whether communication is available |
---|
| 28 | DojoExternalInterface.available = ExternalInterface.available; |
---|
| 29 | |
---|
| 30 | // make sure we can play nice in XD settings |
---|
| 31 | System.security.allowDomain(unescape(_root.xdomain)); |
---|
| 32 | } |
---|
| 33 | |
---|
| 34 | /** Called when we are finished adding methods through addCallback. */ |
---|
| 35 | public static function done(){ |
---|
| 36 | //trace("done"); |
---|
| 37 | DojoExternalInterface.call("dojox.flash.loaded"); |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | public static function addCallback(methodName:String, instance:Object, |
---|
| 41 | method:Function):Boolean{ |
---|
| 42 | //trace("addCallback"); |
---|
| 43 | ExternalInterface.addCallback(methodName, instance, function(){ |
---|
| 44 | instance = (instance) ? instance : null; |
---|
| 45 | var params = []; |
---|
| 46 | if(arguments && arguments.length){ |
---|
| 47 | for(var i = 0; i < arguments.length; i++){ |
---|
| 48 | params[i] = DojoExternalInterface.decodeData(arguments[i]); |
---|
| 49 | } |
---|
| 50 | } |
---|
| 51 | |
---|
| 52 | var results = method.apply(instance, params); |
---|
| 53 | results = DojoExternalInterface.encodeData(results); |
---|
| 54 | |
---|
| 55 | return results; |
---|
| 56 | }); |
---|
| 57 | |
---|
| 58 | // tell JavaScript about DojoExternalInterface new method so we can create a proxy |
---|
| 59 | ExternalInterface.call("dojox.flash.comm._addExternalInterfaceCallback", |
---|
| 60 | methodName); |
---|
| 61 | |
---|
| 62 | return true; |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | public static function call(methodName:String):Void{ |
---|
| 66 | // we might have any number of optional arguments, so we have to |
---|
| 67 | // pass them in dynamically; strip out the results callback |
---|
| 68 | var parameters = new Array(); |
---|
| 69 | for(var i = 0; i < arguments.length; i++){ |
---|
| 70 | parameters.push(arguments[i]); |
---|
| 71 | } |
---|
| 72 | |
---|
| 73 | // FIXME: Should we be encoding or decoding the data to get |
---|
| 74 | // around Flash's serialization bugs? |
---|
| 75 | |
---|
| 76 | var results = ExternalInterface.call.apply(ExternalInterface, parameters); |
---|
| 77 | |
---|
| 78 | return results; |
---|
| 79 | } |
---|
| 80 | |
---|
| 81 | /** |
---|
| 82 | Called by Flash to indicate to JavaScript that we are ready to have |
---|
| 83 | our Flash functions called. Calling loaded() |
---|
| 84 | will fire the dojox.flash.loaded() event, so that JavaScript can know that |
---|
| 85 | Flash has finished loading and adding its callbacks, and can begin to |
---|
| 86 | interact with the Flash file. |
---|
| 87 | */ |
---|
| 88 | public static function loaded(){ |
---|
| 89 | DojoExternalInterface.call("dojox.flash.loaded"); |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | /** |
---|
| 93 | Utility trace implementation that prints out to console.debug. |
---|
| 94 | */ |
---|
| 95 | public static function trace(msg){ |
---|
| 96 | DojoExternalInterface.call("console.debug", "FLASH: " + msg); |
---|
| 97 | } |
---|
| 98 | |
---|
| 99 | private static function decodeData(data):String{ |
---|
| 100 | if(!data || typeof data != "string"){ |
---|
| 101 | return data; |
---|
| 102 | } |
---|
| 103 | |
---|
| 104 | // JAC: Using unicode character 0001 to store instead of Unicode null |
---|
| 105 | // which causes trouble |
---|
| 106 | data = replaceStr(data, "&custom_null;", "\u0001"); |
---|
| 107 | |
---|
| 108 | // we have to use custom encodings for certain characters when passing |
---|
| 109 | // them over; for example, passing a backslash over as //// from JavaScript |
---|
| 110 | // to Flash doesn't work |
---|
| 111 | data = replaceStr(data, "&custom_backslash;", "\\"); |
---|
| 112 | |
---|
| 113 | return data; |
---|
| 114 | } |
---|
| 115 | |
---|
| 116 | private static function encodeData(data):String{ |
---|
| 117 | if(!data || typeof data != "string"){ |
---|
| 118 | return data; |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | // double encode all entity values, or they will be mis-decoded |
---|
| 122 | // by Flash when returned |
---|
| 123 | data = replaceStr(data, "&", "&"); |
---|
| 124 | |
---|
| 125 | // certain XMLish characters break Flash's wire serialization for |
---|
| 126 | // ExternalInterface; encode these into a custom encoding, rather than |
---|
| 127 | // the standard entity encoding, because otherwise we won't be able to |
---|
| 128 | // differentiate between our own encoding and any entity characters |
---|
| 129 | // that are being used in the string itself |
---|
| 130 | data = replaceStr(data, '<', '&custom_lt;'); |
---|
| 131 | data = replaceStr(data, '>', '&custom_gt;'); |
---|
| 132 | |
---|
| 133 | // needed for IE |
---|
| 134 | data = replaceStr(data, '\\', '&custom_backslash;'); |
---|
| 135 | data = replaceStr(data, "\u0001", "&custom_null;"); |
---|
| 136 | |
---|
| 137 | // encode control characters and JavaScript delimiters |
---|
| 138 | data = replaceStr(data, "\n", "\\n"); |
---|
| 139 | data = replaceStr(data, "\r", "\\r"); |
---|
| 140 | data = replaceStr(data, "\f", "\\f"); |
---|
| 141 | data = replaceStr(data, "'", "\\'"); |
---|
| 142 | data = replaceStr(data, '"', '\"'); |
---|
| 143 | |
---|
| 144 | return data; |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | /** |
---|
| 148 | Flash ActionScript has no String.replace method or support for |
---|
| 149 | Regular Expressions! We roll our own very simple one. |
---|
| 150 | */ |
---|
| 151 | public static function replaceStr(inputStr:String, replaceThis:String, |
---|
| 152 | withThis:String):String{ |
---|
| 153 | var splitStr = inputStr.split(replaceThis); |
---|
| 154 | if(!splitStr){ |
---|
| 155 | return inputStr; |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | inputStr = splitStr.join(withThis); |
---|
| 159 | return inputStr; |
---|
| 160 | } |
---|
| 161 | |
---|
| 162 | private static function getDojoPath(){ |
---|
| 163 | var url = _root._url; |
---|
| 164 | var start = url.indexOf("baseUrl=") + "baseUrl=".length; |
---|
| 165 | var path = url.substring(start); |
---|
| 166 | var end = path.indexOf("&"); |
---|
| 167 | if(end != -1){ |
---|
| 168 | path = path.substring(0, end); |
---|
| 169 | } |
---|
| 170 | |
---|
| 171 | // some browsers append a junk string at the end: '%20'%20quality= |
---|
| 172 | if(path.indexOf("'%20'%20quality=") != -1){ |
---|
| 173 | path = path.substring(0, path.indexOf("'%20'%20quality=")); |
---|
| 174 | } |
---|
| 175 | return unescape(path); |
---|
| 176 | } |
---|
| 177 | } |
---|