2150 |
mathias |
1 |
if(!dojo._hasResource["dojox.flash._common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojox.flash._common"] = true;
|
|
|
3 |
dojo.provide("dojox.flash._common");
|
|
|
4 |
|
|
|
5 |
dojox.flash = function(){
|
|
|
6 |
// summary:
|
|
|
7 |
// The goal of dojox.flash is to make it easy to extend Flash's capabilities
|
|
|
8 |
// into an AJAX/DHTML environment.
|
|
|
9 |
// description:
|
|
|
10 |
// The goal of dojox.flash is to make it easy to extend Flash's capabilities
|
|
|
11 |
// into an AJAX/DHTML environment. Robust, performant, reliable
|
|
|
12 |
// JavaScript/Flash communication is harder than most realize when they
|
|
|
13 |
// delve into the topic, especially if you want it
|
|
|
14 |
// to work on Internet Explorer, Firefox, and Safari, and to be able to
|
|
|
15 |
// push around hundreds of K of information quickly. dojox.flash makes it
|
|
|
16 |
// possible to support these platforms; you have to jump through a few
|
|
|
17 |
// hoops to get its capabilites, but if you are a library writer
|
|
|
18 |
// who wants to bring Flash's storage or streaming sockets ability into
|
|
|
19 |
// DHTML, for example, then dojox.flash is perfect for you.
|
|
|
20 |
//
|
|
|
21 |
// dojox.flash provides an easy object for interacting with the Flash plugin.
|
|
|
22 |
// This object provides methods to determine the current version of the Flash
|
|
|
23 |
// plugin (dojox.flash.info); execute Flash instance methods
|
|
|
24 |
// independent of the Flash version
|
|
|
25 |
// being used (dojox.flash.comm); write out the necessary markup to
|
|
|
26 |
// dynamically insert a Flash object into the page (dojox.flash.Embed; and
|
|
|
27 |
// do dynamic installation and upgrading of the current Flash plugin in
|
|
|
28 |
// use (dojox.flash.Install).
|
|
|
29 |
//
|
|
|
30 |
// To use dojox.flash, you must first wait until Flash is finished loading
|
|
|
31 |
// and initializing before you attempt communication or interaction.
|
|
|
32 |
// To know when Flash is finished use dojo.connect:
|
|
|
33 |
//
|
|
|
34 |
// dojo.connect(dojox.flash, "loaded", myInstance, "myCallback");
|
|
|
35 |
//
|
|
|
36 |
// Then, while the page is still loading provide the file name
|
|
|
37 |
// and the major version of Flash that will be used for Flash/JavaScript
|
|
|
38 |
// communication (see "Flash Communication" below for information on the
|
|
|
39 |
// different kinds of Flash/JavaScript communication supported and how they
|
|
|
40 |
// depend on the version of Flash installed):
|
|
|
41 |
//
|
|
|
42 |
// dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", "_storage/storage_flash6.swf"),
|
|
|
43 |
// flash8: dojo.moduleUrl("dojox", "_storage/storage_flash8.swf")});
|
|
|
44 |
//
|
|
|
45 |
// This will cause dojox.flash to pick the best way of communicating
|
|
|
46 |
// between Flash and JavaScript based on the platform.
|
|
|
47 |
//
|
|
|
48 |
// If no SWF files are specified, then Flash is not initialized.
|
|
|
49 |
//
|
|
|
50 |
// Your Flash must use DojoExternalInterface to expose Flash methods and
|
|
|
51 |
// to call JavaScript; see "Flash Communication" below for details.
|
|
|
52 |
//
|
|
|
53 |
// setSwf can take an optional 'visible' attribute to control whether
|
|
|
54 |
// the Flash object is visible or not on the page; the default is visible:
|
|
|
55 |
//
|
|
|
56 |
// dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", "_storage/storage_flash6.swf"),
|
|
|
57 |
// flash8: dojo.moduleUrl("dojox", "_storage/storage_flash8.swf"),
|
|
|
58 |
// visible: false });
|
|
|
59 |
//
|
|
|
60 |
// Once finished, you can query Flash version information:
|
|
|
61 |
//
|
|
|
62 |
// dojox.flash.info.version
|
|
|
63 |
//
|
|
|
64 |
// Or can communicate with Flash methods that were exposed:
|
|
|
65 |
//
|
|
|
66 |
// var results = dojox.flash.comm.sayHello("Some Message");
|
|
|
67 |
//
|
|
|
68 |
// Only string values are currently supported for both arguments and
|
|
|
69 |
// for return results. Everything will be cast to a string on both
|
|
|
70 |
// the JavaScript and Flash sides.
|
|
|
71 |
//
|
|
|
72 |
// -------------------
|
|
|
73 |
// Flash Communication
|
|
|
74 |
// -------------------
|
|
|
75 |
//
|
|
|
76 |
// dojox.flash allows Flash/JavaScript communication in
|
|
|
77 |
// a way that can pass large amounts of data back and forth reliably and
|
|
|
78 |
// very fast. The dojox.flash
|
|
|
79 |
// framework encapsulates the specific way in which this communication occurs,
|
|
|
80 |
// presenting a common interface to JavaScript irrespective of the underlying
|
|
|
81 |
// Flash version.
|
|
|
82 |
//
|
|
|
83 |
// There are currently three major ways to do Flash/JavaScript communication
|
|
|
84 |
// in the Flash community:
|
|
|
85 |
//
|
|
|
86 |
// 1) Flash 6+ - Uses Flash methods, such as SetVariable and TCallLabel,
|
|
|
87 |
// and the fscommand handler to do communication. Strengths: Very fast,
|
|
|
88 |
// mature, and can send extremely large amounts of data; can do
|
|
|
89 |
// synchronous method calls. Problems: Does not work on Safari; works on
|
|
|
90 |
// Firefox/Mac OS X only if Flash 8 plugin is installed; cryptic to work with.
|
|
|
91 |
//
|
|
|
92 |
// 2) Flash 8+ - Uses ExternalInterface, which provides a way for Flash
|
|
|
93 |
// methods to register themselves for callbacks from JavaScript, and a way
|
|
|
94 |
// for Flash to call JavaScript. Strengths: Works on Safari; elegant to
|
|
|
95 |
// work with; can do synchronous method calls. Problems: Extremely buggy
|
|
|
96 |
// (fails if there are new lines in the data, for example); performance
|
|
|
97 |
// degrades drastically in O(n^2) time as data grows; locks up the browser while
|
|
|
98 |
// it is communicating; does not work in Internet Explorer if Flash
|
|
|
99 |
// object is dynamically added to page with document.writeln, DOM methods,
|
|
|
100 |
// or innerHTML.
|
|
|
101 |
//
|
|
|
102 |
// 3) Flash 6+ - Uses two seperate Flash applets, one that we
|
|
|
103 |
// create over and over, passing input data into it using the PARAM tag,
|
|
|
104 |
// which then uses a Flash LocalConnection to pass the data to the main Flash
|
|
|
105 |
// applet; communication back to Flash is accomplished using a getURL
|
|
|
106 |
// call with a javascript protocol handler, such as "javascript:myMethod()".
|
|
|
107 |
// Strengths: the most cross browser, cross platform pre-Flash 8 method
|
|
|
108 |
// of Flash communication known; works on Safari. Problems: Timing issues;
|
|
|
109 |
// clunky and complicated; slow; can only send very small amounts of
|
|
|
110 |
// data (several K); all method calls are asynchronous.
|
|
|
111 |
//
|
|
|
112 |
// dojox.flash.comm uses only the first two methods. This framework
|
|
|
113 |
// was created primarily for dojox.storage, which needs to pass very large
|
|
|
114 |
// amounts of data synchronously and reliably across the Flash/JavaScript
|
|
|
115 |
// boundary. We use the first method, the Flash 6 method, on all platforms
|
|
|
116 |
// that support it, while using the Flash 8 ExternalInterface method
|
|
|
117 |
// only on Safari with some special code to help correct ExternalInterface's
|
|
|
118 |
// bugs.
|
|
|
119 |
//
|
|
|
120 |
// Since dojox.flash needs to have two versions of the Flash
|
|
|
121 |
// file it wants to generate, a Flash 6 and a Flash 8 version to gain
|
|
|
122 |
// true cross-browser compatibility, several tools are provided to ease
|
|
|
123 |
// development on the Flash side.
|
|
|
124 |
//
|
|
|
125 |
// In your Flash file, if you want to expose Flash methods that can be
|
|
|
126 |
// called, use the DojoExternalInterface class to register methods. This
|
|
|
127 |
// class is an exact API clone of the standard ExternalInterface class, but
|
|
|
128 |
// can work in Flash 6+ browsers. Under the covers it uses the best
|
|
|
129 |
// mechanism to do communication:
|
|
|
130 |
//
|
|
|
131 |
// class HelloWorld{
|
|
|
132 |
// function HelloWorld(){
|
|
|
133 |
// // Initialize the DojoExternalInterface class
|
|
|
134 |
// DojoExternalInterface.initialize();
|
|
|
135 |
//
|
|
|
136 |
// // Expose your methods
|
|
|
137 |
// DojoExternalInterface.addCallback("sayHello", this, this.sayHello);
|
|
|
138 |
//
|
|
|
139 |
// // Tell JavaScript that you are ready to have method calls
|
|
|
140 |
// DojoExternalInterface.loaded();
|
|
|
141 |
//
|
|
|
142 |
// // Call some JavaScript
|
|
|
143 |
// var resultsReady = function(results){
|
|
|
144 |
// trace("Received the following results from JavaScript: " + results);
|
|
|
145 |
// }
|
|
|
146 |
// DojoExternalInterface.call("someJavaScriptMethod", resultsReady,
|
|
|
147 |
// someParameter);
|
|
|
148 |
// }
|
|
|
149 |
//
|
|
|
150 |
// function sayHello(){ ... }
|
|
|
151 |
//
|
|
|
152 |
// static main(){ ... }
|
|
|
153 |
// }
|
|
|
154 |
//
|
|
|
155 |
// DojoExternalInterface adds two new functions to the ExternalInterface
|
|
|
156 |
// API: initialize() and loaded(). initialize() must be called before
|
|
|
157 |
// any addCallback() or call() methods are run, and loaded() must be
|
|
|
158 |
// called after you are finished adding your callbacks. Calling loaded()
|
|
|
159 |
// will fire the dojox.flash.loaded() event, so that JavaScript can know that
|
|
|
160 |
// Flash has finished loading and adding its callbacks, and can begin to
|
|
|
161 |
// interact with the Flash file.
|
|
|
162 |
//
|
|
|
163 |
// To generate your SWF files, use the ant task
|
|
|
164 |
// "buildFlash". You must have the open source Motion Twin ActionScript
|
|
|
165 |
// compiler (mtasc) installed and in your path to use the "buildFlash"
|
|
|
166 |
// ant task; download and install mtasc from http://www.mtasc.org/.
|
|
|
167 |
//
|
|
|
168 |
//
|
|
|
169 |
//
|
|
|
170 |
// buildFlash usage:
|
|
|
171 |
//
|
|
|
172 |
// // FIXME: this is not correct in the 0.9 world!
|
|
|
173 |
// ant buildFlash -Ddojox.flash.file=../tests/flash/HelloWorld.as
|
|
|
174 |
//
|
|
|
175 |
// where "dojox.flash.file" is the relative path to your Flash
|
|
|
176 |
// ActionScript file.
|
|
|
177 |
//
|
|
|
178 |
// This will generate two SWF files, one ending in _flash6.swf and the other
|
|
|
179 |
// ending in _flash8.swf in the same directory as your ActionScript method:
|
|
|
180 |
//
|
|
|
181 |
// HelloWorld_flash6.swf
|
|
|
182 |
// HelloWorld_flash8.swf
|
|
|
183 |
//
|
|
|
184 |
// Initialize dojox.flash with the filename and Flash communication version to
|
|
|
185 |
// use during page load; see the documentation for dojox.flash for details:
|
|
|
186 |
//
|
|
|
187 |
// dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", "flash/tests/flash/HelloWorld_flash6.swf"),
|
|
|
188 |
// flash8: dojo.moduleUrl("dojox", "flash/tests/flash/HelloWorld_flash8.swf")});
|
|
|
189 |
//
|
|
|
190 |
// Now, your Flash methods can be called from JavaScript as if they are native
|
|
|
191 |
// Flash methods, mirrored exactly on the JavaScript side:
|
|
|
192 |
//
|
|
|
193 |
// dojox.flash.comm.sayHello();
|
|
|
194 |
//
|
|
|
195 |
// Only Strings are supported being passed back and forth currently.
|
|
|
196 |
//
|
|
|
197 |
// JavaScript to Flash communication is synchronous; i.e., results are returned
|
|
|
198 |
// directly from the method call:
|
|
|
199 |
//
|
|
|
200 |
// var results = dojox.flash.comm.sayHello();
|
|
|
201 |
//
|
|
|
202 |
// Flash to JavaScript communication is asynchronous due to limitations in
|
|
|
203 |
// the underlying technologies; you must use a results callback to handle
|
|
|
204 |
// results returned by JavaScript in your Flash AS files:
|
|
|
205 |
//
|
|
|
206 |
// var resultsReady = function(results){
|
|
|
207 |
// trace("Received the following results from JavaScript: " + results);
|
|
|
208 |
// }
|
|
|
209 |
// DojoExternalInterface.call("someJavaScriptMethod", resultsReady);
|
|
|
210 |
//
|
|
|
211 |
//
|
|
|
212 |
//
|
|
|
213 |
// -------------------
|
|
|
214 |
// Notes
|
|
|
215 |
// -------------------
|
|
|
216 |
//
|
|
|
217 |
// If you have both Flash 6 and Flash 8 versions of your file:
|
|
|
218 |
//
|
|
|
219 |
// dojox.flash.setSwf({flash6: dojo.moduleUrl("dojox", "flash/tests/flash/HelloWorld_flash6.swf"),
|
|
|
220 |
// flash8: dojo.moduleUrl("dojox", "flash/tests/flash/HelloWorld_flash8.swf")});
|
|
|
221 |
//
|
|
|
222 |
// but want to force the browser to use a certain version of Flash for
|
|
|
223 |
// all platforms (for testing, for example), use the djConfig
|
|
|
224 |
// variable 'forceFlashComm' with the version number to force:
|
|
|
225 |
//
|
|
|
226 |
// var djConfig = { forceFlashComm: 6 };
|
|
|
227 |
//
|
|
|
228 |
// Two values are currently supported, 6 and 8, for the two styles of
|
|
|
229 |
// communication described above. Just because you force dojox.flash
|
|
|
230 |
// to use a particular communication style is no guarantee that it will
|
|
|
231 |
// work; for example, Flash 8 communication doesn't work in Internet
|
|
|
232 |
// Explorer due to bugs in Flash, and Flash 6 communication does not work
|
|
|
233 |
// in Safari. It is best to let dojox.flash determine the best communication
|
|
|
234 |
// mechanism, and to use the value above only for debugging the dojox.flash
|
|
|
235 |
// framework itself.
|
|
|
236 |
//
|
|
|
237 |
// Also note that dojox.flash can currently only work with one Flash object
|
|
|
238 |
// on the page; it and the API do not yet support multiple Flash objects on
|
|
|
239 |
// the same page.
|
|
|
240 |
//
|
|
|
241 |
// We use some special tricks to get decent, linear performance
|
|
|
242 |
// out of Flash 8's ExternalInterface on Safari; see the blog
|
|
|
243 |
// post
|
|
|
244 |
// http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
|
|
|
245 |
// for details.
|
|
|
246 |
//
|
|
|
247 |
// Your code can detect whether the Flash player is installing or having
|
|
|
248 |
// its version revved in two ways. First, if dojox.flash detects that
|
|
|
249 |
// Flash installation needs to occur, it sets dojox.flash.info.installing
|
|
|
250 |
// to true. Second, you can detect if installation is necessary with the
|
|
|
251 |
// following callback:
|
|
|
252 |
//
|
|
|
253 |
// dojo.connect(dojox.flash, "installing", myInstance, "myCallback");
|
|
|
254 |
//
|
|
|
255 |
// You can use this callback to delay further actions that might need Flash;
|
|
|
256 |
// when installation is finished the full page will be refreshed and the
|
|
|
257 |
// user will be placed back on your page with Flash installed.
|
|
|
258 |
//
|
|
|
259 |
// -------------------
|
|
|
260 |
// Todo/Known Issues
|
|
|
261 |
// -------------------
|
|
|
262 |
//
|
|
|
263 |
// There are several tasks I was not able to do, or did not need to fix
|
|
|
264 |
// to get dojo.storage out:
|
|
|
265 |
//
|
|
|
266 |
// * When using Flash 8 communication, Flash method calls to JavaScript
|
|
|
267 |
// are not working properly; serialization might also be broken for certain
|
|
|
268 |
// invalid characters when it is Flash invoking JavaScript methods.
|
|
|
269 |
// The Flash side needs to have more sophisticated serialization/
|
|
|
270 |
// deserialization mechanisms like JavaScript currently has. The
|
|
|
271 |
// test_flash2.html unit tests should also be updated to have much more
|
|
|
272 |
// sophisticated Flash to JavaScript unit tests, including large
|
|
|
273 |
// amounts of data.
|
|
|
274 |
//
|
|
|
275 |
// * On Internet Explorer, after doing a basic install, the page is
|
|
|
276 |
// not refreshed or does not detect that Flash is now available. The way
|
|
|
277 |
// to fix this is to create a custom small Flash file that is pointed to
|
|
|
278 |
// during installation; when it is finished loading, it does a callback
|
|
|
279 |
// that says that Flash installation is complete on IE, and we can proceed
|
|
|
280 |
// to initialize the dojox.flash subsystem.
|
|
|
281 |
//
|
|
|
282 |
// Author- Brad Neuberg, bkn3@columbia.edu
|
|
|
283 |
}
|
|
|
284 |
|
|
|
285 |
dojox.flash = {
|
|
|
286 |
flash6_version: null,
|
|
|
287 |
flash8_version: null,
|
|
|
288 |
ready: false,
|
|
|
289 |
_visible: true,
|
|
|
290 |
_loadedListeners: new Array(),
|
|
|
291 |
_installingListeners: new Array(),
|
|
|
292 |
|
|
|
293 |
setSwf: function(/* Object */ fileInfo){
|
|
|
294 |
// summary: Sets the SWF files and versions we are using.
|
|
|
295 |
// fileInfo: Object
|
|
|
296 |
// An object that contains two attributes, 'flash6' and 'flash8',
|
|
|
297 |
// each of which contains the path to our Flash 6 and Flash 8
|
|
|
298 |
// versions of the file we want to script.
|
|
|
299 |
// example:
|
|
|
300 |
// var swfloc6 = dojo.moduleUrl("dojox.storage", "Storage_version6.swf").toString();
|
|
|
301 |
// var swfloc8 = dojo.moduleUrl("dojox.storage", "Storage_version8.swf").toString();
|
|
|
302 |
// dojox.flash.setSwf({flash6: swfloc6, flash8: swfloc8, visible: false});
|
|
|
303 |
|
|
|
304 |
if(!fileInfo){
|
|
|
305 |
return;
|
|
|
306 |
}
|
|
|
307 |
|
|
|
308 |
if(fileInfo["flash6"]){
|
|
|
309 |
this.flash6_version = fileInfo.flash6;
|
|
|
310 |
}
|
|
|
311 |
|
|
|
312 |
if(fileInfo["flash8"]){
|
|
|
313 |
this.flash8_version = fileInfo.flash8;
|
|
|
314 |
}
|
|
|
315 |
|
|
|
316 |
if(fileInfo["visible"]){
|
|
|
317 |
this._visible = fileInfo.visible;
|
|
|
318 |
}
|
|
|
319 |
|
|
|
320 |
// initialize ourselves
|
|
|
321 |
this._initialize();
|
|
|
322 |
},
|
|
|
323 |
|
|
|
324 |
useFlash6: function(){ /* Boolean */
|
|
|
325 |
// summary: Returns whether we are using Flash 6 for communication on this platform.
|
|
|
326 |
|
|
|
327 |
if(this.flash6_version == null){
|
|
|
328 |
return false;
|
|
|
329 |
}else if (this.flash6_version != null && dojox.flash.info.commVersion == 6){
|
|
|
330 |
// if we have a flash 6 version of this SWF, and this browser supports
|
|
|
331 |
// communicating using Flash 6 features...
|
|
|
332 |
return true;
|
|
|
333 |
}else{
|
|
|
334 |
return false;
|
|
|
335 |
}
|
|
|
336 |
},
|
|
|
337 |
|
|
|
338 |
useFlash8: function(){ /* Boolean */
|
|
|
339 |
// summary: Returns whether we are using Flash 8 for communication on this platform.
|
|
|
340 |
|
|
|
341 |
if(this.flash8_version == null){
|
|
|
342 |
return false;
|
|
|
343 |
}else if (this.flash8_version != null && dojox.flash.info.commVersion == 8){
|
|
|
344 |
// if we have a flash 8 version of this SWF, and this browser supports
|
|
|
345 |
// communicating using Flash 8 features...
|
|
|
346 |
return true;
|
|
|
347 |
}else{
|
|
|
348 |
return false;
|
|
|
349 |
}
|
|
|
350 |
},
|
|
|
351 |
|
|
|
352 |
addLoadedListener: function(/* Function */ listener){
|
|
|
353 |
// summary:
|
|
|
354 |
// Adds a listener to know when Flash is finished loading.
|
|
|
355 |
// Useful if you don't want a dependency on dojo.event.
|
|
|
356 |
// listener: Function
|
|
|
357 |
// A function that will be called when Flash is done loading.
|
|
|
358 |
|
|
|
359 |
this._loadedListeners.push(listener);
|
|
|
360 |
},
|
|
|
361 |
|
|
|
362 |
addInstallingListener: function(/* Function */ listener){
|
|
|
363 |
// summary:
|
|
|
364 |
// Adds a listener to know if Flash is being installed.
|
|
|
365 |
// Useful if you don't want a dependency on dojo.event.
|
|
|
366 |
// listener: Function
|
|
|
367 |
// A function that will be called if Flash is being
|
|
|
368 |
// installed
|
|
|
369 |
|
|
|
370 |
this._installingListeners.push(listener);
|
|
|
371 |
},
|
|
|
372 |
|
|
|
373 |
loaded: function(){
|
|
|
374 |
// summary: Called back when the Flash subsystem is finished loading.
|
|
|
375 |
// description:
|
|
|
376 |
// A callback when the Flash subsystem is finished loading and can be
|
|
|
377 |
// worked with. To be notified when Flash is finished loading, connect
|
|
|
378 |
// your callback to this method using the following:
|
|
|
379 |
//
|
|
|
380 |
// dojo.event.connect(dojox.flash, "loaded", myInstance, "myCallback");
|
|
|
381 |
|
|
|
382 |
//dojo.debug("dojox.flash.loaded");
|
|
|
383 |
dojox.flash.ready = true;
|
|
|
384 |
if(dojox.flash._loadedListeners.length > 0){
|
|
|
385 |
for(var i = 0;i < dojox.flash._loadedListeners.length; i++){
|
|
|
386 |
dojox.flash._loadedListeners[i].call(null);
|
|
|
387 |
}
|
|
|
388 |
}
|
|
|
389 |
},
|
|
|
390 |
|
|
|
391 |
installing: function(){
|
|
|
392 |
// summary: Called if Flash is being installed.
|
|
|
393 |
// description:
|
|
|
394 |
// A callback to know if Flash is currently being installed or
|
|
|
395 |
// having its version revved. To be notified if Flash is installing, connect
|
|
|
396 |
// your callback to this method using the following:
|
|
|
397 |
//
|
|
|
398 |
// dojo.event.connect(dojox.flash, "installing", myInstance, "myCallback");
|
|
|
399 |
|
|
|
400 |
//dojo.debug("installing");
|
|
|
401 |
if(dojox.flash._installingListeners.length > 0){
|
|
|
402 |
for(var i = 0; i < dojox.flash._installingListeners.length; i++){
|
|
|
403 |
dojox.flash._installingListeners[i].call(null);
|
|
|
404 |
}
|
|
|
405 |
}
|
|
|
406 |
},
|
|
|
407 |
|
|
|
408 |
// Initializes dojox.flash.
|
|
|
409 |
_initialize: function(){
|
|
|
410 |
//dojo.debug("dojox.flash._initialize");
|
|
|
411 |
// see if we need to rev or install Flash on this platform
|
|
|
412 |
var installer = new dojox.flash.Install();
|
|
|
413 |
dojox.flash.installer = installer;
|
|
|
414 |
|
|
|
415 |
if(installer.needed() == true){
|
|
|
416 |
installer.install();
|
|
|
417 |
}else{
|
|
|
418 |
//dojo.debug("Writing object out");
|
|
|
419 |
// write the flash object into the page
|
|
|
420 |
dojox.flash.obj = new dojox.flash.Embed(this._visible);
|
|
|
421 |
dojox.flash.obj.write(dojox.flash.info.commVersion);
|
|
|
422 |
|
|
|
423 |
// initialize the way we do Flash/JavaScript communication
|
|
|
424 |
dojox.flash.comm = new dojox.flash.Communicator();
|
|
|
425 |
}
|
|
|
426 |
}
|
|
|
427 |
};
|
|
|
428 |
|
|
|
429 |
|
|
|
430 |
dojox.flash.Info = function(){
|
|
|
431 |
// summary: A class that helps us determine whether Flash is available.
|
|
|
432 |
// description:
|
|
|
433 |
// A class that helps us determine whether Flash is available,
|
|
|
434 |
// it's major and minor versions, and what Flash version features should
|
|
|
435 |
// be used for Flash/JavaScript communication. Parts of this code
|
|
|
436 |
// are adapted from the automatic Flash plugin detection code autogenerated
|
|
|
437 |
// by the Macromedia Flash 8 authoring environment.
|
|
|
438 |
//
|
|
|
439 |
// An instance of this class can be accessed on dojox.flash.info after
|
|
|
440 |
// the page is finished loading.
|
|
|
441 |
//
|
|
|
442 |
// This constructor must be called before the page is finished loading.
|
|
|
443 |
|
|
|
444 |
// Visual basic helper required to detect Flash Player ActiveX control
|
|
|
445 |
// version information on Internet Explorer
|
|
|
446 |
if(dojo.isIE){
|
|
|
447 |
document.write([
|
|
|
448 |
'<script language="VBScript" type="text/vbscript"\>',
|
|
|
449 |
'Function VBGetSwfVer(i)',
|
|
|
450 |
' on error resume next',
|
|
|
451 |
' Dim swControl, swVersion',
|
|
|
452 |
' swVersion = 0',
|
|
|
453 |
' set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))',
|
|
|
454 |
' if (IsObject(swControl)) then',
|
|
|
455 |
' swVersion = swControl.GetVariable("$version")',
|
|
|
456 |
' end if',
|
|
|
457 |
' VBGetSwfVer = swVersion',
|
|
|
458 |
'End Function',
|
|
|
459 |
'</script\>'].join("\r\n"));
|
|
|
460 |
}
|
|
|
461 |
|
|
|
462 |
this._detectVersion();
|
|
|
463 |
this._detectCommunicationVersion();
|
|
|
464 |
}
|
|
|
465 |
|
|
|
466 |
dojox.flash.Info.prototype = {
|
|
|
467 |
// version: String
|
|
|
468 |
// The full version string, such as "8r22".
|
|
|
469 |
version: -1,
|
|
|
470 |
|
|
|
471 |
// versionMajor, versionMinor, versionRevision: String
|
|
|
472 |
// The major, minor, and revisions of the plugin. For example, if the
|
|
|
473 |
// plugin is 8r22, then the major version is 8, the minor version is 0,
|
|
|
474 |
// and the revision is 22.
|
|
|
475 |
versionMajor: -1,
|
|
|
476 |
versionMinor: -1,
|
|
|
477 |
versionRevision: -1,
|
|
|
478 |
|
|
|
479 |
// capable: Boolean
|
|
|
480 |
// Whether this platform has Flash already installed.
|
|
|
481 |
capable: false,
|
|
|
482 |
|
|
|
483 |
// commVersion: int
|
|
|
484 |
// The major version number for how our Flash and JavaScript communicate.
|
|
|
485 |
// This can currently be the following values:
|
|
|
486 |
// 6 - We use a combination of the Flash plugin methods, such as SetVariable
|
|
|
487 |
// and TCallLabel, along with fscommands, to do communication.
|
|
|
488 |
// 8 - We use the ExternalInterface API.
|
|
|
489 |
// -1 - For some reason neither method is supported, and no communication
|
|
|
490 |
// is possible.
|
|
|
491 |
commVersion: 6,
|
|
|
492 |
|
|
|
493 |
// installing: Boolean
|
|
|
494 |
// Set if we are in the middle of a Flash installation session.
|
|
|
495 |
installing: false,
|
|
|
496 |
|
|
|
497 |
isVersionOrAbove: function(
|
|
|
498 |
/* int */ reqMajorVer,
|
|
|
499 |
/* int */ reqMinorVer,
|
|
|
500 |
/* int */ reqVer){ /* Boolean */
|
|
|
501 |
// summary:
|
|
|
502 |
// Asserts that this environment has the given major, minor, and revision
|
|
|
503 |
// numbers for the Flash player.
|
|
|
504 |
// description:
|
|
|
505 |
// Asserts that this environment has the given major, minor, and revision
|
|
|
506 |
// numbers for the Flash player.
|
|
|
507 |
//
|
|
|
508 |
// Example- To test for Flash Player 7r14:
|
|
|
509 |
//
|
|
|
510 |
// dojox.flash.info.isVersionOrAbove(7, 0, 14)
|
|
|
511 |
// returns:
|
|
|
512 |
// Returns true if the player is equal
|
|
|
513 |
// or above the given version, false otherwise.
|
|
|
514 |
|
|
|
515 |
// make the revision a decimal (i.e. transform revision 14 into
|
|
|
516 |
// 0.14
|
|
|
517 |
reqVer = parseFloat("." + reqVer);
|
|
|
518 |
|
|
|
519 |
if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
|
|
|
520 |
&& this.versionRevision >= reqVer){
|
|
|
521 |
return true;
|
|
|
522 |
}else{
|
|
|
523 |
return false;
|
|
|
524 |
}
|
|
|
525 |
},
|
|
|
526 |
|
|
|
527 |
getResourceList: function(/*string*/ swfloc6, /*String*/ swfloc8){ /*String[]*/
|
|
|
528 |
// summary:
|
|
|
529 |
// Returns all resources required for embedding.
|
|
|
530 |
// description:
|
|
|
531 |
// This is a convenience method for Dojo Offline, meant to
|
|
|
532 |
// encapsulate us from the specific resources necessary for
|
|
|
533 |
// embedding. Dojo Offline requires that we sync our offline
|
|
|
534 |
// resources for offline availability; this method will return all
|
|
|
535 |
// offline resources, including any possible query parameters that
|
|
|
536 |
// might be used since caches treat resources with query
|
|
|
537 |
// parameters as different than ones that have query parameters.
|
|
|
538 |
// If offline and we request a resource with a query parameter
|
|
|
539 |
// that was not cached with a query parameter, then we will have a
|
|
|
540 |
// cache miss and not be able to work offline
|
|
|
541 |
var results = [];
|
|
|
542 |
|
|
|
543 |
// flash 6
|
|
|
544 |
var swfloc = swfloc6;
|
|
|
545 |
results.push(swfloc);
|
|
|
546 |
swfloc = swfloc + "?baseRelativePath=" + escape(dojo.baseUrl); // FIXME: should this be encodeURIComponent?
|
|
|
547 |
results.push(swfloc);
|
|
|
548 |
// Safari has a strange bug where it appends '%20'%20quality=
|
|
|
549 |
// to the end of Flash movies taken through XHR while offline;
|
|
|
550 |
// append this so we don't get a cache miss
|
|
|
551 |
swfloc += "'%20'%20quality=";
|
|
|
552 |
results.push(swfloc);
|
|
|
553 |
|
|
|
554 |
// flash 8
|
|
|
555 |
swfloc = swfloc8;
|
|
|
556 |
results.push(swfloc);
|
|
|
557 |
swfloc += "?baseRelativePath="+escape(dojo.baseUrl); // FIXME: should this be encodeURIComponent?
|
|
|
558 |
results.push(swfloc);
|
|
|
559 |
// Safari has a strange bug where it appends '%20'%20quality=
|
|
|
560 |
// to the end of Flash movies taken through XHR while offline;
|
|
|
561 |
// append this so we don't get a cache miss
|
|
|
562 |
swfloc += "'%20'%20quality=";
|
|
|
563 |
results.push(swfloc);
|
|
|
564 |
|
|
|
565 |
// flash 6 gateway
|
|
|
566 |
results.push(dojo.moduleUrl("dojox", "flash/flash6/flash6_gateway.swf")+"");
|
|
|
567 |
|
|
|
568 |
return results;
|
|
|
569 |
},
|
|
|
570 |
|
|
|
571 |
_detectVersion: function(){
|
|
|
572 |
var versionStr;
|
|
|
573 |
|
|
|
574 |
// loop backwards through the versions until we find the newest version
|
|
|
575 |
for(var testVersion = 25; testVersion > 0; testVersion--){
|
|
|
576 |
if(dojo.isIE){
|
|
|
577 |
versionStr = VBGetSwfVer(testVersion);
|
|
|
578 |
}else{
|
|
|
579 |
versionStr = this._JSFlashInfo(testVersion);
|
|
|
580 |
}
|
|
|
581 |
|
|
|
582 |
if(versionStr == -1 ){
|
|
|
583 |
this.capable = false;
|
|
|
584 |
return;
|
|
|
585 |
}else if(versionStr != 0){
|
|
|
586 |
var versionArray;
|
|
|
587 |
if(dojo.isIE){
|
|
|
588 |
var tempArray = versionStr.split(" ");
|
|
|
589 |
var tempString = tempArray[1];
|
|
|
590 |
versionArray = tempString.split(",");
|
|
|
591 |
}else{
|
|
|
592 |
versionArray = versionStr.split(".");
|
|
|
593 |
}
|
|
|
594 |
|
|
|
595 |
this.versionMajor = versionArray[0];
|
|
|
596 |
this.versionMinor = versionArray[1];
|
|
|
597 |
this.versionRevision = versionArray[2];
|
|
|
598 |
|
|
|
599 |
// 7.0r24 == 7.24
|
|
|
600 |
var versionString = this.versionMajor + "." + this.versionRevision;
|
|
|
601 |
this.version = parseFloat(versionString);
|
|
|
602 |
|
|
|
603 |
this.capable = true;
|
|
|
604 |
|
|
|
605 |
break;
|
|
|
606 |
}
|
|
|
607 |
}
|
|
|
608 |
},
|
|
|
609 |
|
|
|
610 |
// JavaScript helper required to detect Flash Player PlugIn version
|
|
|
611 |
// information. Internet Explorer uses a corresponding Visual Basic
|
|
|
612 |
// version to interact with the Flash ActiveX control.
|
|
|
613 |
_JSFlashInfo: function(testVersion){
|
|
|
614 |
// NS/Opera version >= 3 check for Flash plugin in plugin array
|
|
|
615 |
if(navigator.plugins != null && navigator.plugins.length > 0){
|
|
|
616 |
if(navigator.plugins["Shockwave Flash 2.0"] ||
|
|
|
617 |
navigator.plugins["Shockwave Flash"]){
|
|
|
618 |
var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
|
|
|
619 |
var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
|
|
|
620 |
var descArray = flashDescription.split(" ");
|
|
|
621 |
var tempArrayMajor = descArray[2].split(".");
|
|
|
622 |
var versionMajor = tempArrayMajor[0];
|
|
|
623 |
var versionMinor = tempArrayMajor[1];
|
|
|
624 |
if(descArray[3] != ""){
|
|
|
625 |
var tempArrayMinor = descArray[3].split("r");
|
|
|
626 |
}else{
|
|
|
627 |
var tempArrayMinor = descArray[4].split("r");
|
|
|
628 |
}
|
|
|
629 |
var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
|
|
|
630 |
var version = versionMajor + "." + versionMinor + "."
|
|
|
631 |
+ versionRevision;
|
|
|
632 |
|
|
|
633 |
return version;
|
|
|
634 |
}
|
|
|
635 |
}
|
|
|
636 |
|
|
|
637 |
return -1;
|
|
|
638 |
},
|
|
|
639 |
|
|
|
640 |
// Detects the mechanisms that should be used for Flash/JavaScript
|
|
|
641 |
// communication, setting 'commVersion' to either 6 or 8. If the value is
|
|
|
642 |
// 6, we use Flash Plugin 6+ features, such as GetVariable, TCallLabel,
|
|
|
643 |
// and fscommand, to do Flash/JavaScript communication; if the value is
|
|
|
644 |
// 8, we use the ExternalInterface API for communication.
|
|
|
645 |
_detectCommunicationVersion: function(){
|
|
|
646 |
if(this.capable == false){
|
|
|
647 |
this.commVersion = null;
|
|
|
648 |
return;
|
|
|
649 |
}
|
|
|
650 |
|
|
|
651 |
// detect if the user has over-ridden the default flash version
|
|
|
652 |
if (typeof djConfig["forceFlashComm"] != "undefined" &&
|
|
|
653 |
typeof djConfig["forceFlashComm"] != null){
|
|
|
654 |
this.commVersion = djConfig["forceFlashComm"];
|
|
|
655 |
return;
|
|
|
656 |
}
|
|
|
657 |
|
|
|
658 |
// we prefer Flash 6 features over Flash 8, because they are much faster
|
|
|
659 |
// and much less buggy
|
|
|
660 |
|
|
|
661 |
// at this point, we don't have a flash file to detect features on,
|
|
|
662 |
// so we need to instead look at the browser environment we are in
|
|
|
663 |
if(dojo.isSafari||dojo.isOpera){
|
|
|
664 |
this.commVersion = 8;
|
|
|
665 |
}else{
|
|
|
666 |
this.commVersion = 6;
|
|
|
667 |
}
|
|
|
668 |
}
|
|
|
669 |
};
|
|
|
670 |
|
|
|
671 |
dojox.flash.Embed = function(visible){
|
|
|
672 |
// summary: A class that is used to write out the Flash object into the page.
|
|
|
673 |
|
|
|
674 |
this._visible = visible;
|
|
|
675 |
}
|
|
|
676 |
|
|
|
677 |
dojox.flash.Embed.prototype = {
|
|
|
678 |
// width: int
|
|
|
679 |
// The width of this Flash applet. The default is the minimal width
|
|
|
680 |
// necessary to show the Flash settings dialog. Current value is
|
|
|
681 |
// 215 pixels.
|
|
|
682 |
width: 215,
|
|
|
683 |
|
|
|
684 |
// height: int
|
|
|
685 |
// The height of this Flash applet. The default is the minimal height
|
|
|
686 |
// necessary to show the Flash settings dialog. Current value is
|
|
|
687 |
// 138 pixels.
|
|
|
688 |
height: 138,
|
|
|
689 |
|
|
|
690 |
// id: String
|
|
|
691 |
// The id of the Flash object. Current value is 'flashObject'.
|
|
|
692 |
id: "flashObject",
|
|
|
693 |
|
|
|
694 |
// Controls whether this is a visible Flash applet or not.
|
|
|
695 |
_visible: true,
|
|
|
696 |
|
|
|
697 |
protocol: function(){
|
|
|
698 |
switch(window.location.protocol){
|
|
|
699 |
case "https:":
|
|
|
700 |
return "https";
|
|
|
701 |
break;
|
|
|
702 |
default:
|
|
|
703 |
return "http";
|
|
|
704 |
break;
|
|
|
705 |
}
|
|
|
706 |
},
|
|
|
707 |
|
|
|
708 |
write: function(/* String */ flashVer, /* Boolean? */ doExpressInstall){
|
|
|
709 |
// summary: Writes the Flash into the page.
|
|
|
710 |
// description:
|
|
|
711 |
// This must be called before the page
|
|
|
712 |
// is finished loading.
|
|
|
713 |
// flashVer: String
|
|
|
714 |
// The Flash version to write.
|
|
|
715 |
// doExpressInstall: Boolean
|
|
|
716 |
// Whether to write out Express Install
|
|
|
717 |
// information. Optional value; defaults to false.
|
|
|
718 |
|
|
|
719 |
//dojo.debug("write");
|
|
|
720 |
doExpressInstall = !!doExpressInstall;
|
|
|
721 |
|
|
|
722 |
// determine our container div's styling
|
|
|
723 |
var containerStyle = "";
|
|
|
724 |
containerStyle += ("width: " + this.width + "px; ");
|
|
|
725 |
containerStyle += ("height: " + this.height + "px; ");
|
|
|
726 |
if(this._visible == false){
|
|
|
727 |
containerStyle += "position: absolute; z-index: 10000; top: -1000px; left: -1000px; ";
|
|
|
728 |
}
|
|
|
729 |
|
|
|
730 |
// figure out the SWF file to get and how to write out the correct HTML
|
|
|
731 |
// for this Flash version
|
|
|
732 |
var objectHTML;
|
|
|
733 |
var swfloc;
|
|
|
734 |
// Flash 6
|
|
|
735 |
if(flashVer == 6){
|
|
|
736 |
swfloc = dojox.flash.flash6_version;
|
|
|
737 |
var dojoPath = djConfig.baseRelativePath;
|
|
|
738 |
swfloc = swfloc + "?baseRelativePath=" + escape(dojoPath);
|
|
|
739 |
objectHTML =
|
|
|
740 |
'<embed id="' + this.id + '" src="' + swfloc + '" '
|
|
|
741 |
+ ' quality="high" bgcolor="#ffffff" '
|
|
|
742 |
+ ' width="' + this.width + '" height="' + this.height + '" '
|
|
|
743 |
+ ' name="' + this.id + '" '
|
|
|
744 |
+ ' align="middle" allowScriptAccess="sameDomain" '
|
|
|
745 |
+ ' type="application/x-shockwave-flash" swLiveConnect="true" '
|
|
|
746 |
+ ' pluginspage="'
|
|
|
747 |
+ this.protocol()
|
|
|
748 |
+ '://www.macromedia.com/go/getflashplayer">';
|
|
|
749 |
}else{ // Flash 8
|
|
|
750 |
swfloc = dojox.flash.flash8_version;
|
|
|
751 |
var swflocObject = swfloc;
|
|
|
752 |
var swflocEmbed = swfloc;
|
|
|
753 |
var dojoPath = djConfig.baseRelativePath;
|
|
|
754 |
if(doExpressInstall){
|
|
|
755 |
// the location to redirect to after installing
|
|
|
756 |
var redirectURL = escape(window.location);
|
|
|
757 |
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
|
|
|
758 |
var docTitle = escape(document.title);
|
|
|
759 |
swflocObject += "?MMredirectURL=" + redirectURL
|
|
|
760 |
+ "&MMplayerType=ActiveX"
|
|
|
761 |
+ "&MMdoctitle=" + docTitle
|
|
|
762 |
+ "&baseRelativePath=" + escape(dojoPath);
|
|
|
763 |
swflocEmbed += "?MMredirectURL=" + redirectURL
|
|
|
764 |
+ "&MMplayerType=PlugIn"
|
|
|
765 |
+ "&baseRelativePath=" + escape(dojoPath);
|
|
|
766 |
}
|
|
|
767 |
|
|
|
768 |
if(swflocEmbed.indexOf("?") == -1){
|
|
|
769 |
swflocEmbed += "?baseRelativePath="+escape(dojoPath)+"' ";
|
|
|
770 |
}
|
|
|
771 |
|
|
|
772 |
objectHTML =
|
|
|
773 |
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
|
|
|
774 |
+ 'codebase="'
|
|
|
775 |
+ this.protocol()
|
|
|
776 |
+ '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/'
|
|
|
777 |
+ 'swflash.cab#version=8,0,0,0" '
|
|
|
778 |
+ 'width="' + this.width + '" '
|
|
|
779 |
+ 'height="' + this.height + '" '
|
|
|
780 |
+ 'id="' + this.id + '" '
|
|
|
781 |
+ 'align="middle"> '
|
|
|
782 |
+ '<param name="allowScriptAccess" value="sameDomain" /> '
|
|
|
783 |
+ '<param name="movie" value="' + swflocObject + '" /> '
|
|
|
784 |
+ '<param name="quality" value="high" /> '
|
|
|
785 |
+ '<param name="bgcolor" value="#ffffff" /> '
|
|
|
786 |
+ '<embed src="' + swflocEmbed + "' "
|
|
|
787 |
+ 'quality="high" '
|
|
|
788 |
+ 'bgcolor="#ffffff" '
|
|
|
789 |
+ 'width="' + this.width + '" '
|
|
|
790 |
+ 'height="' + this.height + '" '
|
|
|
791 |
+ 'id="' + this.id + '" '
|
|
|
792 |
+ 'name="' + this.id + '" '
|
|
|
793 |
+ 'swLiveConnect="true" '
|
|
|
794 |
+ 'align="middle" '
|
|
|
795 |
+ 'allowScriptAccess="sameDomain" '
|
|
|
796 |
+ 'type="application/x-shockwave-flash" '
|
|
|
797 |
+ 'pluginspage="'
|
|
|
798 |
+ this.protocol()
|
|
|
799 |
+'://www.macromedia.com/go/getflashplayer" />'
|
|
|
800 |
+ '</object>';
|
|
|
801 |
}
|
|
|
802 |
|
|
|
803 |
// now write everything out
|
|
|
804 |
objectHTML = '<div id="' + this.id + 'Container" style="' + containerStyle + '"> '
|
|
|
805 |
+ objectHTML
|
|
|
806 |
+ '</div>';
|
|
|
807 |
document.writeln(objectHTML);
|
|
|
808 |
},
|
|
|
809 |
|
|
|
810 |
get: function(){ /* Object */
|
|
|
811 |
// summary: Gets the Flash object DOM node.
|
|
|
812 |
|
|
|
813 |
//return (dojo.render.html.ie) ? window[this.id] : document[this.id];
|
|
|
814 |
|
|
|
815 |
// more robust way to get Flash object; version above can break
|
|
|
816 |
// communication on IE sometimes
|
|
|
817 |
return document.getElementById(this.id);
|
|
|
818 |
},
|
|
|
819 |
|
|
|
820 |
setVisible: function(/* Boolean */ visible){
|
|
|
821 |
// summary: Sets the visibility of this Flash object.
|
|
|
822 |
|
|
|
823 |
var container = dojo.byId(this.id + "Container");
|
|
|
824 |
if(visible == true){
|
|
|
825 |
container.style.visibility = "visible";
|
|
|
826 |
}else{
|
|
|
827 |
container.style.position = "absolute";
|
|
|
828 |
container.style.x = "-1000px";
|
|
|
829 |
container.style.y = "-1000px";
|
|
|
830 |
container.style.visibility = "hidden";
|
|
|
831 |
}
|
|
|
832 |
},
|
|
|
833 |
|
|
|
834 |
center: function(){
|
|
|
835 |
// summary: Centers the flash applet on the page.
|
|
|
836 |
|
|
|
837 |
/*
|
|
|
838 |
var elementWidth = this.width;
|
|
|
839 |
var elementHeight = this.height;
|
|
|
840 |
|
|
|
841 |
var scroll_offset = dojo._docScroll();
|
|
|
842 |
var viewport_size = dojo.html.getViewport();
|
|
|
843 |
|
|
|
844 |
// compute the centered position
|
|
|
845 |
var x = scroll_offset.x + (viewport_size.width - elementWidth) / 2;
|
|
|
846 |
var y = scroll_offset.y + (viewport_size.height - elementHeight) / 2;
|
|
|
847 |
*/
|
|
|
848 |
var x = 100;
|
|
|
849 |
var y = 100;
|
|
|
850 |
|
|
|
851 |
// set the centered position
|
|
|
852 |
var container = dojo.byId(this.id + "Container");
|
|
|
853 |
container.style.top = y + "px";
|
|
|
854 |
container.style.left = x + "px";
|
|
|
855 |
}
|
|
|
856 |
};
|
|
|
857 |
|
|
|
858 |
|
|
|
859 |
dojox.flash.Communicator = function(){
|
|
|
860 |
// summary:
|
|
|
861 |
// A class that is used to communicate between Flash and JavaScript in
|
|
|
862 |
// a way that can pass large amounts of data back and forth reliably,
|
|
|
863 |
// very fast, and with synchronous method calls.
|
|
|
864 |
// description:
|
|
|
865 |
// A class that is used to communicate between Flash and JavaScript in
|
|
|
866 |
// a way that can pass large amounts of data back and forth reliably,
|
|
|
867 |
// very fast, and with synchronous method calls. This class encapsulates the
|
|
|
868 |
// specific way in which this communication occurs,
|
|
|
869 |
// presenting a common interface to JavaScript irrespective of the underlying
|
|
|
870 |
// Flash version.
|
|
|
871 |
|
|
|
872 |
if(dojox.flash.useFlash6()){
|
|
|
873 |
this._writeFlash6();
|
|
|
874 |
}else if(dojox.flash.useFlash8()){
|
|
|
875 |
this._writeFlash8();
|
|
|
876 |
}
|
|
|
877 |
}
|
|
|
878 |
|
|
|
879 |
dojox.flash.Communicator.prototype = {
|
|
|
880 |
_writeFlash6: function(){
|
|
|
881 |
var id = dojox.flash.obj.id;
|
|
|
882 |
|
|
|
883 |
// global function needed for Flash 6 callback;
|
|
|
884 |
// we write it out as a script tag because the VBScript hook for IE
|
|
|
885 |
// callbacks does not work properly if this function is evalled() from
|
|
|
886 |
// within the Dojo system
|
|
|
887 |
document.writeln('<script language="JavaScript">');
|
|
|
888 |
document.writeln(' function ' + id + '_DoFSCommand(command, args){ ');
|
|
|
889 |
document.writeln(' dojox.flash.comm._handleFSCommand(command, args); ');
|
|
|
890 |
document.writeln('}');
|
|
|
891 |
document.writeln('</script>');
|
|
|
892 |
|
|
|
893 |
// hook for Internet Explorer to receive FSCommands from Flash
|
|
|
894 |
if(dojo.isIE){
|
|
|
895 |
document.writeln('<SCRIPT LANGUAGE=VBScript\> ');
|
|
|
896 |
document.writeln('on error resume next ');
|
|
|
897 |
document.writeln('Sub ' + id + '_FSCommand(ByVal command, ByVal args)');
|
|
|
898 |
document.writeln(' call ' + id + '_DoFSCommand(command, args)');
|
|
|
899 |
document.writeln('end sub');
|
|
|
900 |
document.writeln('</SCRIPT\> ');
|
|
|
901 |
}
|
|
|
902 |
},
|
|
|
903 |
|
|
|
904 |
_writeFlash8: function(){
|
|
|
905 |
// nothing needs to be written out for Flash 8 communication;
|
|
|
906 |
// happens automatically
|
|
|
907 |
},
|
|
|
908 |
|
|
|
909 |
//Flash 6 communication.
|
|
|
910 |
|
|
|
911 |
// Handles fscommand's from Flash to JavaScript. Flash 6 communication.
|
|
|
912 |
_handleFSCommand: function(command, args){
|
|
|
913 |
//console.debug("fscommand, command="+command+", args="+args);
|
|
|
914 |
// Flash 8 on Mac/Firefox precedes all commands with the string "FSCommand:";
|
|
|
915 |
// strip it off if it is present
|
|
|
916 |
if((command) && dojo.isString(command) && (/^FSCommand:(.*)/.test(command) == true)){
|
|
|
917 |
command = command.match(/^FSCommand:(.*)/)[1];
|
|
|
918 |
}
|
|
|
919 |
|
|
|
920 |
if(command == "addCallback"){ // add Flash method for JavaScript callback
|
|
|
921 |
this._fscommandAddCallback(command, args);
|
|
|
922 |
}else if(command == "call"){ // Flash to JavaScript method call
|
|
|
923 |
this._fscommandCall(command, args);
|
|
|
924 |
}else if(command == "fscommandReady"){ // see if fscommands are ready
|
|
|
925 |
this._fscommandReady();
|
|
|
926 |
}
|
|
|
927 |
},
|
|
|
928 |
|
|
|
929 |
// Handles registering a callable Flash function. Flash 6 communication.
|
|
|
930 |
_fscommandAddCallback: function(command, args){
|
|
|
931 |
var functionName = args;
|
|
|
932 |
|
|
|
933 |
// do a trick, where we link this function name to our wrapper
|
|
|
934 |
// function, _call, that does the actual JavaScript to Flash call
|
|
|
935 |
var callFunc = function(){
|
|
|
936 |
return dojox.flash.comm._call(functionName, arguments);
|
|
|
937 |
};
|
|
|
938 |
dojox.flash.comm[functionName] = callFunc;
|
|
|
939 |
|
|
|
940 |
// indicate that the call was successful
|
|
|
941 |
dojox.flash.obj.get().SetVariable("_succeeded", true);
|
|
|
942 |
},
|
|
|
943 |
|
|
|
944 |
// Handles Flash calling a JavaScript function. Flash 6 communication.
|
|
|
945 |
_fscommandCall: function(command, args){
|
|
|
946 |
var plugin = dojox.flash.obj.get();
|
|
|
947 |
var functionName = args;
|
|
|
948 |
|
|
|
949 |
// get the number of arguments to this method call and build them up
|
|
|
950 |
var numArgs = parseInt(plugin.GetVariable("_numArgs"));
|
|
|
951 |
var flashArgs = new Array();
|
|
|
952 |
for(var i = 0; i < numArgs; i++){
|
|
|
953 |
var currentArg = plugin.GetVariable("_" + i);
|
|
|
954 |
flashArgs.push(currentArg);
|
|
|
955 |
}
|
|
|
956 |
|
|
|
957 |
// get the function instance; we technically support more capabilities
|
|
|
958 |
// than ExternalInterface, which can only call global functions; if
|
|
|
959 |
// the method name has a dot in it, such as "dojox.flash.loaded", we
|
|
|
960 |
// eval it so that the method gets run against an instance
|
|
|
961 |
var runMe;
|
|
|
962 |
if(functionName.indexOf(".") == -1){ // global function
|
|
|
963 |
runMe = window[functionName];
|
|
|
964 |
}else{
|
|
|
965 |
// instance function
|
|
|
966 |
runMe = eval(functionName);
|
|
|
967 |
}
|
|
|
968 |
|
|
|
969 |
// make the call and get the results
|
|
|
970 |
var results = null;
|
|
|
971 |
if(dojo.isFunction(runMe)){
|
|
|
972 |
results = runMe.apply(null, flashArgs);
|
|
|
973 |
}
|
|
|
974 |
|
|
|
975 |
// return the results to flash
|
|
|
976 |
plugin.SetVariable("_returnResult", results);
|
|
|
977 |
},
|
|
|
978 |
|
|
|
979 |
// Reports that fscommands are ready to run if executed from Flash.
|
|
|
980 |
_fscommandReady: function(){
|
|
|
981 |
var plugin = dojox.flash.obj.get();
|
|
|
982 |
plugin.SetVariable("fscommandReady", "true");
|
|
|
983 |
},
|
|
|
984 |
|
|
|
985 |
// The actual function that will execute a JavaScript to Flash call; used
|
|
|
986 |
// by the Flash 6 communication method.
|
|
|
987 |
_call: function(functionName, args){
|
|
|
988 |
// we do JavaScript to Flash method calls by setting a Flash variable
|
|
|
989 |
// "_functionName" with the function name; "_numArgs" with the number
|
|
|
990 |
// of arguments; and "_0", "_1", etc for each numbered argument. Flash
|
|
|
991 |
// reads these, executes the function call, and returns the result
|
|
|
992 |
// in "_returnResult"
|
|
|
993 |
var plugin = dojox.flash.obj.get();
|
|
|
994 |
plugin.SetVariable("_functionName", functionName);
|
|
|
995 |
plugin.SetVariable("_numArgs", args.length);
|
|
|
996 |
for(var i = 0; i < args.length; i++){
|
|
|
997 |
// unlike Flash 8's ExternalInterface, Flash 6 has no problem with
|
|
|
998 |
// any special characters _except_ for the null character \0; double
|
|
|
999 |
// encode this so the Flash side never sees it, but we can get it
|
|
|
1000 |
// back if the value comes back to JavaScript
|
|
|
1001 |
var value = args[i];
|
|
|
1002 |
value = value.replace(/\0/g, "\\0");
|
|
|
1003 |
|
|
|
1004 |
plugin.SetVariable("_" + i, value);
|
|
|
1005 |
}
|
|
|
1006 |
|
|
|
1007 |
// now tell Flash to execute this method using the Flash Runner
|
|
|
1008 |
plugin.TCallLabel("/_flashRunner", "execute");
|
|
|
1009 |
|
|
|
1010 |
// get the results
|
|
|
1011 |
var results = plugin.GetVariable("_returnResult");
|
|
|
1012 |
|
|
|
1013 |
// we double encoded all null characters as //0 because Flash breaks
|
|
|
1014 |
// if they are present; turn the //0 back into /0
|
|
|
1015 |
results = results.replace(/\\0/g, "\0");
|
|
|
1016 |
|
|
|
1017 |
return results;
|
|
|
1018 |
},
|
|
|
1019 |
|
|
|
1020 |
// Flash 8 communication.
|
|
|
1021 |
|
|
|
1022 |
// Registers the existence of a Flash method that we can call with
|
|
|
1023 |
// JavaScript, using Flash 8's ExternalInterface.
|
|
|
1024 |
_addExternalInterfaceCallback: function(methodName){
|
|
|
1025 |
var wrapperCall = function(){
|
|
|
1026 |
// some browsers don't like us changing values in the 'arguments' array, so
|
|
|
1027 |
// make a fresh copy of it
|
|
|
1028 |
var methodArgs = new Array(arguments.length);
|
|
|
1029 |
for(var i = 0; i < arguments.length; i++){
|
|
|
1030 |
methodArgs[i] = arguments[i];
|
|
|
1031 |
}
|
|
|
1032 |
return dojox.flash.comm._execFlash(methodName, methodArgs);
|
|
|
1033 |
};
|
|
|
1034 |
|
|
|
1035 |
dojox.flash.comm[methodName] = wrapperCall;
|
|
|
1036 |
},
|
|
|
1037 |
|
|
|
1038 |
// Encodes our data to get around ExternalInterface bugs.
|
|
|
1039 |
// Flash 8 communication.
|
|
|
1040 |
_encodeData: function(data){
|
|
|
1041 |
// double encode all entity values, or they will be mis-decoded
|
|
|
1042 |
// by Flash when returned
|
|
|
1043 |
var entityRE = /\&([^;]*)\;/g;
|
|
|
1044 |
data = data.replace(entityRE, "&$1;");
|
|
|
1045 |
|
|
|
1046 |
// entity encode XML-ish characters, or Flash's broken XML serializer
|
|
|
1047 |
// breaks
|
|
|
1048 |
data = data.replace(/</g, "<");
|
|
|
1049 |
data = data.replace(/>/g, ">");
|
|
|
1050 |
|
|
|
1051 |
// transforming \ into \\ doesn't work; just use a custom encoding
|
|
|
1052 |
data = data.replace("\\", "&custom_backslash;&custom_backslash;");
|
|
|
1053 |
|
|
|
1054 |
data = data.replace(/\n/g, "\\n");
|
|
|
1055 |
data = data.replace(/\r/g, "\\r");
|
|
|
1056 |
data = data.replace(/\f/g, "\\f");
|
|
|
1057 |
data = data.replace(/\0/g, "\\0"); // null character
|
|
|
1058 |
data = data.replace(/\'/g, "\\\'");
|
|
|
1059 |
data = data.replace(/\"/g, '\\\"');
|
|
|
1060 |
|
|
|
1061 |
return data;
|
|
|
1062 |
},
|
|
|
1063 |
|
|
|
1064 |
// Decodes our data to get around ExternalInterface bugs.
|
|
|
1065 |
// Flash 8 communication.
|
|
|
1066 |
_decodeData: function(data){
|
|
|
1067 |
if(data == null || typeof data == "undefined"){
|
|
|
1068 |
return data;
|
|
|
1069 |
}
|
|
|
1070 |
|
|
|
1071 |
// certain XMLish characters break Flash's wire serialization for
|
|
|
1072 |
// ExternalInterface; these are encoded on the
|
|
|
1073 |
// DojoExternalInterface side into a custom encoding, rather than
|
|
|
1074 |
// the standard entity encoding, because otherwise we won't be able to
|
|
|
1075 |
// differentiate between our own encoding and any entity characters
|
|
|
1076 |
// that are being used in the string itself
|
|
|
1077 |
data = data.replace(/\&custom_lt\;/g, "<");
|
|
|
1078 |
data = data.replace(/\&custom_gt\;/g, ">");
|
|
|
1079 |
|
|
|
1080 |
// Unfortunately, Flash returns us our String with special characters
|
|
|
1081 |
// like newlines broken into seperate characters. So if \n represents
|
|
|
1082 |
// a new line, Flash returns it as "\" and "n". This means the character
|
|
|
1083 |
// is _not_ a newline. This forces us to eval() the string to cause
|
|
|
1084 |
// escaped characters to turn into their real special character values.
|
|
|
1085 |
data = eval('"' + data + '"');
|
|
|
1086 |
|
|
|
1087 |
return data;
|
|
|
1088 |
},
|
|
|
1089 |
|
|
|
1090 |
// Sends our method arguments over to Flash in chunks in order to
|
|
|
1091 |
// have ExternalInterface's performance not be O(n^2).
|
|
|
1092 |
// Flash 8 communication.
|
|
|
1093 |
_chunkArgumentData: function(value, argIndex){
|
|
|
1094 |
var plugin = dojox.flash.obj.get();
|
|
|
1095 |
|
|
|
1096 |
// cut up the string into pieces, and push over each piece one
|
|
|
1097 |
// at a time
|
|
|
1098 |
var numSegments = Math.ceil(value.length / 1024);
|
|
|
1099 |
for(var i = 0; i < numSegments; i++){
|
|
|
1100 |
var startCut = i * 1024;
|
|
|
1101 |
var endCut = i * 1024 + 1024;
|
|
|
1102 |
if(i == (numSegments - 1)){
|
|
|
1103 |
endCut = i * 1024 + value.length;
|
|
|
1104 |
}
|
|
|
1105 |
|
|
|
1106 |
var piece = value.substring(startCut, endCut);
|
|
|
1107 |
|
|
|
1108 |
// encode each piece seperately, rather than the entire
|
|
|
1109 |
// argument data, because ocassionally a special
|
|
|
1110 |
// character, such as an entity like &foobar;, will fall between
|
|
|
1111 |
// piece boundaries, and we _don't_ want to encode that value if
|
|
|
1112 |
// it falls between boundaries, or else we will end up with incorrect
|
|
|
1113 |
// data when we patch the pieces back together on the other side
|
|
|
1114 |
piece = this._encodeData(piece);
|
|
|
1115 |
|
|
|
1116 |
// directly use the underlying CallFunction method used by
|
|
|
1117 |
// ExternalInterface, which is vastly faster for large strings
|
|
|
1118 |
// and lets us bypass some Flash serialization bugs
|
|
|
1119 |
plugin.CallFunction('<invoke name="chunkArgumentData" '
|
|
|
1120 |
+ 'returntype="javascript">'
|
|
|
1121 |
+ '<arguments>'
|
|
|
1122 |
+ '<string>' + piece + '</string>'
|
|
|
1123 |
+ '<number>' + argIndex + '</number>'
|
|
|
1124 |
+ '</arguments>'
|
|
|
1125 |
+ '</invoke>');
|
|
|
1126 |
}
|
|
|
1127 |
},
|
|
|
1128 |
|
|
|
1129 |
// Gets our method return data in chunks for better performance.
|
|
|
1130 |
// Flash 8 communication.
|
|
|
1131 |
_chunkReturnData: function(){
|
|
|
1132 |
var plugin = dojox.flash.obj.get();
|
|
|
1133 |
|
|
|
1134 |
var numSegments = plugin.getReturnLength();
|
|
|
1135 |
var resultsArray = new Array();
|
|
|
1136 |
for(var i = 0; i < numSegments; i++){
|
|
|
1137 |
// directly use the underlying CallFunction method used by
|
|
|
1138 |
// ExternalInterface, which is vastly faster for large strings
|
|
|
1139 |
var piece =
|
|
|
1140 |
plugin.CallFunction('<invoke name="chunkReturnData" '
|
|
|
1141 |
+ 'returntype="javascript">'
|
|
|
1142 |
+ '<arguments>'
|
|
|
1143 |
+ '<number>' + i + '</number>'
|
|
|
1144 |
+ '</arguments>'
|
|
|
1145 |
+ '</invoke>');
|
|
|
1146 |
|
|
|
1147 |
// remove any leading or trailing JavaScript delimiters, which surround
|
|
|
1148 |
// our String when it comes back from Flash since we bypass Flash's
|
|
|
1149 |
// deserialization routines by directly calling CallFunction on the
|
|
|
1150 |
// plugin
|
|
|
1151 |
if(piece == '""' || piece == "''"){
|
|
|
1152 |
piece = "";
|
|
|
1153 |
}else{
|
|
|
1154 |
piece = piece.substring(1, piece.length-1);
|
|
|
1155 |
}
|
|
|
1156 |
|
|
|
1157 |
resultsArray.push(piece);
|
|
|
1158 |
}
|
|
|
1159 |
var results = resultsArray.join("");
|
|
|
1160 |
|
|
|
1161 |
return results;
|
|
|
1162 |
},
|
|
|
1163 |
|
|
|
1164 |
// Executes a Flash method; called from the JavaScript wrapper proxy we
|
|
|
1165 |
// create on dojox.flash.comm.
|
|
|
1166 |
// Flash 8 communication.
|
|
|
1167 |
_execFlash: function(methodName, methodArgs){
|
|
|
1168 |
var plugin = dojox.flash.obj.get();
|
|
|
1169 |
|
|
|
1170 |
// begin Flash method execution
|
|
|
1171 |
plugin.startExec();
|
|
|
1172 |
|
|
|
1173 |
// set the number of arguments
|
|
|
1174 |
plugin.setNumberArguments(methodArgs.length);
|
|
|
1175 |
|
|
|
1176 |
// chunk and send over each argument
|
|
|
1177 |
for(var i = 0; i < methodArgs.length; i++){
|
|
|
1178 |
this._chunkArgumentData(methodArgs[i], i);
|
|
|
1179 |
}
|
|
|
1180 |
|
|
|
1181 |
// execute the method
|
|
|
1182 |
plugin.exec(methodName);
|
|
|
1183 |
|
|
|
1184 |
// get the return result
|
|
|
1185 |
var results = this._chunkReturnData();
|
|
|
1186 |
|
|
|
1187 |
// decode the results
|
|
|
1188 |
results = this._decodeData(results);
|
|
|
1189 |
|
|
|
1190 |
// reset everything
|
|
|
1191 |
plugin.endExec();
|
|
|
1192 |
|
|
|
1193 |
return results;
|
|
|
1194 |
}
|
|
|
1195 |
}
|
|
|
1196 |
|
|
|
1197 |
// FIXME: dojo.declare()-ify this
|
|
|
1198 |
|
|
|
1199 |
dojox.flash.Install = function(){
|
|
|
1200 |
// summary: Helps install Flash plugin if needed.
|
|
|
1201 |
// description:
|
|
|
1202 |
// Figures out the best way to automatically install the Flash plugin
|
|
|
1203 |
// for this browser and platform. Also determines if installation or
|
|
|
1204 |
// revving of the current plugin is needed on this platform.
|
|
|
1205 |
}
|
|
|
1206 |
|
|
|
1207 |
dojox.flash.Install.prototype = {
|
|
|
1208 |
needed: function(){ /* Boolean */
|
|
|
1209 |
// summary:
|
|
|
1210 |
// Determines if installation or revving of the current plugin is
|
|
|
1211 |
// needed.
|
|
|
1212 |
|
|
|
1213 |
// do we even have flash?
|
|
|
1214 |
if(dojox.flash.info.capable == false){
|
|
|
1215 |
return true;
|
|
|
1216 |
}
|
|
|
1217 |
|
|
|
1218 |
var isMac = (navigator.appVersion.indexOf("Macintosh") >= 0);
|
|
|
1219 |
|
|
|
1220 |
// are we on the Mac? Safari needs Flash version 8 to do Flash 8
|
|
|
1221 |
// communication, while Firefox/Mac needs Flash 8 to fix bugs it has
|
|
|
1222 |
// with Flash 6 communication
|
|
|
1223 |
if(isMac && (!dojox.flash.info.isVersionOrAbove(8, 0, 0))){
|
|
|
1224 |
return true;
|
|
|
1225 |
}
|
|
|
1226 |
|
|
|
1227 |
// other platforms need at least Flash 6 or above
|
|
|
1228 |
if(!dojox.flash.info.isVersionOrAbove(6, 0, 0)){
|
|
|
1229 |
return true;
|
|
|
1230 |
}
|
|
|
1231 |
|
|
|
1232 |
// otherwise we don't need installation
|
|
|
1233 |
return false;
|
|
|
1234 |
},
|
|
|
1235 |
|
|
|
1236 |
install: function(){
|
|
|
1237 |
// summary: Performs installation or revving of the Flash plugin.
|
|
|
1238 |
|
|
|
1239 |
//dojo.debug("install");
|
|
|
1240 |
// indicate that we are installing
|
|
|
1241 |
dojox.flash.info.installing = true;
|
|
|
1242 |
dojox.flash.installing();
|
|
|
1243 |
|
|
|
1244 |
if(dojox.flash.info.capable == false){ // we have no Flash at all
|
|
|
1245 |
//dojo.debug("Completely new install");
|
|
|
1246 |
// write out a simple Flash object to force the browser to prompt
|
|
|
1247 |
// the user to install things
|
|
|
1248 |
var installObj = new dojox.flash.Embed(false);
|
|
|
1249 |
installObj.write(8); // write out HTML for Flash 8 version+
|
|
|
1250 |
}else if(dojox.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install
|
|
|
1251 |
//dojo.debug("Express install");
|
|
|
1252 |
var installObj = new dojox.flash.Embed(false);
|
|
|
1253 |
installObj.write(8, true); // write out HTML for Flash 8 version+
|
|
|
1254 |
installObj.setVisible(true);
|
|
|
1255 |
installObj.center();
|
|
|
1256 |
}else{ // older Flash install than version 6r65
|
|
|
1257 |
alert("This content requires a more recent version of the Macromedia "
|
|
|
1258 |
+" Flash Player.");
|
|
|
1259 |
window.location.href = + dojox.flash.Embed.protocol() +
|
|
|
1260 |
"://www.macromedia.com/go/getflashplayer";
|
|
|
1261 |
}
|
|
|
1262 |
},
|
|
|
1263 |
|
|
|
1264 |
// Called when the Express Install is either finished, failed, or was
|
|
|
1265 |
// rejected by the user.
|
|
|
1266 |
_onInstallStatus: function(msg){
|
|
|
1267 |
if (msg == "Download.Complete"){
|
|
|
1268 |
// Installation is complete.
|
|
|
1269 |
dojox.flash._initialize();
|
|
|
1270 |
}else if(msg == "Download.Cancelled"){
|
|
|
1271 |
alert("This content requires a more recent version of the Macromedia "
|
|
|
1272 |
+" Flash Player.");
|
|
|
1273 |
window.location.href = dojox.flash.Embed.protocol() +
|
|
|
1274 |
"://www.macromedia.com/go/getflashplayer";
|
|
|
1275 |
}else if (msg == "Download.Failed"){
|
|
|
1276 |
// The end user failed to download the installer due to a network failure
|
|
|
1277 |
alert("There was an error downloading the Flash Player update. "
|
|
|
1278 |
+ "Please try again later, or visit macromedia.com to download "
|
|
|
1279 |
+ "the latest version of the Flash plugin.");
|
|
|
1280 |
}
|
|
|
1281 |
}
|
|
|
1282 |
}
|
|
|
1283 |
|
|
|
1284 |
// find out if Flash is installed
|
|
|
1285 |
dojox.flash.info = new dojox.flash.Info();
|
|
|
1286 |
|
|
|
1287 |
// vim:ts=4:noet:tw=0:
|
|
|
1288 |
|
|
|
1289 |
}
|