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 | } |
---|