root / trunk / web / dojo / dojox / flash / DojoExternalInterface.as @ 12
History | View | Annotate | Download (5.31 KB)
1 | 9 | andrej.cim | /** |
---|---|---|---|
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 | } |