1 if(!dojo._hasResource["dojox.flash._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.flash._base"] = true;
3 dojo.provide("dojox.flash._base");
5 // for dijit.getViewport(), needed by dojox.flash.Embed.center()
6 dojo.require("dijit._base.place");
8 dojox.flash = function(){
10 // The goal of dojox.flash is to make it easy to extend Flash's capabilities
11 // into an Ajax/DHTML environment.
13 // dojox.flash provides an easy object for interacting with the Flash plugin.
14 // This object provides methods to determine the current version of the Flash
15 // plugin (dojox.flash.info); write out the necessary markup to
16 // dynamically insert a Flash object into the page (dojox.flash.Embed; and
17 // do dynamic installation and upgrading of the current Flash plugin in
18 // use (dojox.flash.Install). If you want to call methods on the Flash object
19 // embedded into the page it is your responsibility to use Flash's ExternalInterface
20 // API and get a reference to the Flash object yourself.
22 // To use dojox.flash, you must first wait until Flash is finished loading
23 // and initializing before you attempt communication or interaction.
24 // To know when Flash is finished use dojo.connect:
26 // dojo.connect(dojox.flash, "loaded", myInstance, "myCallback");
28 // Then, while the page is still loading provide the file name:
30 // dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf"));
32 // If no SWF files are specified, then Flash is not initialized.
34 // Your Flash must use Flash's ExternalInterface to expose Flash methods and
35 // to call JavaScript.
37 // setSwf can take an optional 'visible' attribute to control whether
38 // the Flash object is visible or not on the page; the default is visible:
40 // dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf"),
43 // Once finished, you can query Flash version information:
45 // dojox.flash.info.version
47 // Or can communicate with Flash methods that were exposed:
49 // var f = dojox.flash.get();
50 // var results = f.sayHello("Some Message");
52 // Your Flash files should use DojoExternalInterface.as to register methods;
53 // this file wraps Flash's normal ExternalInterface but correct various
54 // serialization bugs that ExternalInterface has.
56 // Note that dojox.flash is not meant to be a generic Flash embedding
57 // mechanism; it is as generic as necessary to make Dojo Storage's
58 // Flash Storage Provider as clean and modular as possible. If you want
59 // a generic Flash embed mechanism see SWFObject
60 // (http://blog.deconcept.com/swfobject/).
63 // Note that dojox.flash can currently only work with one Flash object
64 // on the page; it does not yet support multiple Flash objects on
67 // Your code can detect whether the Flash player is installing or having
68 // its version revved in two ways. First, if dojox.flash detects that
69 // Flash installation needs to occur, it sets dojox.flash.info.installing
70 // to true. Second, you can detect if installation is necessary with the
71 // following callback:
73 // dojo.connect(dojox.flash, "installing", myInstance, "myCallback");
75 // You can use this callback to delay further actions that might need Flash;
76 // when installation is finished the full page will be refreshed and the
77 // user will be placed back on your page with Flash installed.
79 // -------------------
81 // -------------------
82 // * On Internet Explorer, after doing a basic install, the page is
83 // not refreshed or does not detect that Flash is now available. The way
84 // to fix this is to create a custom small Flash file that is pointed to
85 // during installation; when it is finished loading, it does a callback
86 // that says that Flash installation is complete on IE, and we can proceed
87 // to initialize the dojox.flash subsystem.
88 // * Things aren't super tested for sending complex objects to Flash
89 // methods, since Dojo Storage only needs strings
91 // Author- Brad Neuberg, http://codinginparadise.org
99 _loadedListeners: new Array(),
100 _installingListeners: new Array(),
102 setSwf: function(/* String */ url, /* boolean? */ visible){
103 // summary: Sets the SWF files and versions we are using.
105 // The URL to this Flash file.
107 // Whether the Flash file is visible or not. If it is not visible we hide it off the
108 // screen. This defaults to true (i.e. the Flash file is visible).
111 if(typeof visible != "undefined"){
112 this._visible = visible;
115 // initialize ourselves
119 addLoadedListener: function(/* Function */ listener){
121 // Adds a listener to know when Flash is finished loading.
122 // Useful if you don't want a dependency on dojo.event.
123 // listener: Function
124 // A function that will be called when Flash is done loading.
126 this._loadedListeners.push(listener);
129 addInstallingListener: function(/* Function */ listener){
131 // Adds a listener to know if Flash is being installed.
132 // Useful if you don't want a dependency on dojo.event.
133 // listener: Function
134 // A function that will be called if Flash is being
137 this._installingListeners.push(listener);
141 // summary: Called back when the Flash subsystem is finished loading.
143 // A callback when the Flash subsystem is finished loading and can be
144 // worked with. To be notified when Flash is finished loading, add a
147 // dojox.flash.addLoadedListener(loadedListener);
149 dojox.flash.ready = true;
150 if(dojox.flash._loadedListeners.length > 0){
151 for(var i = 0;i < dojox.flash._loadedListeners.length; i++){
152 dojox.flash._loadedListeners[i].call(null);
157 installing: function(){
158 // summary: Called if Flash is being installed.
160 // A callback to know if Flash is currently being installed or
161 // having its version revved. To be notified if Flash is installing, connect
162 // your callback to this method using the following:
164 // dojo.event.connect(dojox.flash, "installing", myInstance, "myCallback");
166 if(dojox.flash._installingListeners.length > 0){
167 for(var i = 0; i < dojox.flash._installingListeners.length; i++){
168 dojox.flash._installingListeners[i].call(null);
173 // Initializes dojox.flash.
174 _initialize: function(){
175 //console.debug("dojox.flash._initialize");
176 // see if we need to rev or install Flash on this platform
177 var installer = new dojox.flash.Install();
178 dojox.flash.installer = installer;
180 if(installer.needed() == true){
183 // write the flash object into the page
184 dojox.flash.obj = new dojox.flash.Embed(this._visible);
185 dojox.flash.obj.write();
187 // setup the communicator
188 dojox.flash.comm = new dojox.flash.Communicator();
194 dojox.flash.Info = function(){
195 // summary: A class that helps us determine whether Flash is available.
197 // A class that helps us determine whether Flash is available,
198 // it's major and minor versions, and what Flash version features should
199 // be used for Flash/JavaScript communication. Parts of this code
200 // are adapted from the automatic Flash plugin detection code autogenerated
201 // by the Macromedia Flash 8 authoring environment.
203 // An instance of this class can be accessed on dojox.flash.info after
204 // the page is finished loading.
206 // This constructor must be called before the page is finished loading.
208 // Visual basic helper required to detect Flash Player ActiveX control
209 // version information on Internet Explorer
212 '<script language="VBScript" type="text/vbscript"\>',
213 'Function VBGetSwfVer(i)',
214 ' on error resume next',
215 ' Dim swControl, swVersion',
217 ' set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))',
218 ' if (IsObject(swControl)) then',
219 ' swVersion = swControl.GetVariable("$version")',
221 ' VBGetSwfVer = swVersion',
223 '</script\>'].join("\r\n"));
226 this._detectVersion();
229 dojox.flash.Info.prototype = {
231 // The full version string, such as "8r22".
234 // versionMajor, versionMinor, versionRevision: String
235 // The major, minor, and revisions of the plugin. For example, if the
236 // plugin is 8r22, then the major version is 8, the minor version is 0,
237 // and the revision is 22.
243 // Whether this platform has Flash already installed.
246 // installing: Boolean
247 // Set if we are in the middle of a Flash installation session.
250 isVersionOrAbove: function(
251 /* int */ reqMajorVer,
252 /* int */ reqMinorVer,
253 /* int */ reqVer){ /* Boolean */
255 // Asserts that this environment has the given major, minor, and revision
256 // numbers for the Flash player.
258 // Asserts that this environment has the given major, minor, and revision
259 // numbers for the Flash player.
261 // Example- To test for Flash Player 7r14:
263 // dojox.flash.info.isVersionOrAbove(7, 0, 14)
265 // Returns true if the player is equal
266 // or above the given version, false otherwise.
268 // make the revision a decimal (i.e. transform revision 14 into
270 reqVer = parseFloat("." + reqVer);
272 if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
273 && this.versionRevision >= reqVer){
280 _detectVersion: function(){
283 // loop backwards through the versions until we find the newest version
284 for(var testVersion = 25; testVersion > 0; testVersion--){
286 versionStr = VBGetSwfVer(testVersion);
288 versionStr = this._JSFlashInfo(testVersion);
291 if(versionStr == -1 ){
292 this.capable = false;
294 }else if(versionStr != 0){
297 var tempArray = versionStr.split(" ");
298 var tempString = tempArray[1];
299 versionArray = tempString.split(",");
301 versionArray = versionStr.split(".");
304 this.versionMajor = versionArray[0];
305 this.versionMinor = versionArray[1];
306 this.versionRevision = versionArray[2];
309 var versionString = this.versionMajor + "." + this.versionRevision;
310 this.version = parseFloat(versionString);
319 // JavaScript helper required to detect Flash Player PlugIn version
320 // information. Internet Explorer uses a corresponding Visual Basic
321 // version to interact with the Flash ActiveX control.
322 _JSFlashInfo: function(testVersion){
323 // NS/Opera version >= 3 check for Flash plugin in plugin array
324 if(navigator.plugins != null && navigator.plugins.length > 0){
325 if(navigator.plugins["Shockwave Flash 2.0"] ||
326 navigator.plugins["Shockwave Flash"]){
327 var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
328 var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
329 var descArray = flashDescription.split(" ");
330 var tempArrayMajor = descArray[2].split(".");
331 var versionMajor = tempArrayMajor[0];
332 var versionMinor = tempArrayMajor[1];
333 if(descArray[3] != ""){
334 var tempArrayMinor = descArray[3].split("r");
336 var tempArrayMinor = descArray[4].split("r");
338 var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
339 var version = versionMajor + "." + versionMinor + "."
350 dojox.flash.Embed = function(visible){
351 // summary: A class that is used to write out the Flash object into the page.
353 // Writes out the necessary tags to embed a Flash file into the page. Note that
354 // these tags are written out as the page is loaded using document.write, so
355 // you must call this class before the page has finished loading.
357 this._visible = visible;
360 dojox.flash.Embed.prototype = {
362 // The width of this Flash applet. The default is the minimal width
363 // necessary to show the Flash settings dialog. Current value is
368 // The height of this Flash applet. The default is the minimal height
369 // necessary to show the Flash settings dialog. Current value is
374 // The id of the Flash object. Current value is 'flashObject'.
377 // Controls whether this is a visible Flash applet or not.
380 protocol: function(){
381 switch(window.location.protocol){
391 write: function(/* Boolean? */ doExpressInstall){
392 // summary: Writes the Flash into the page.
394 // This must be called before the page
395 // is finished loading.
396 // doExpressInstall: Boolean
397 // Whether to write out Express Install
398 // information. Optional value; defaults to false.
400 // determine our container div's styling
401 var containerStyle = "";
402 containerStyle += ("width: " + this.width + "px; ");
403 containerStyle += ("height: " + this.height + "px; ");
405 containerStyle += "position: absolute; z-index: 10000; top: -1000px; left: -1000px; ";
408 // figure out the SWF file to get and how to write out the correct HTML
409 // for this Flash version
411 var swfloc = dojox.flash.url;
412 var swflocObject = swfloc;
413 var swflocEmbed = swfloc;
414 var dojoUrl = dojo.baseUrl;
415 if(doExpressInstall){
416 // the location to redirect to after installing
417 var redirectURL = escape(window.location);
418 document.title = document.title.slice(0, 47) + " - Flash Player Installation";
419 var docTitle = escape(document.title);
420 swflocObject += "?MMredirectURL=" + redirectURL
421 + "&MMplayerType=ActiveX"
422 + "&MMdoctitle=" + docTitle
423 + "&baseUrl=" + escape(dojoUrl);
424 swflocEmbed += "?MMredirectURL=" + redirectURL
425 + "&MMplayerType=PlugIn"
426 + "&baseUrl=" + escape(dojoUrl);
428 // IE/Flash has an evil bug that shows up some time: if we load the
429 // Flash and it isn't in the cache, ExternalInterface works fine --
430 // however, the second time when its loaded from the cache a timing
431 // bug can keep ExternalInterface from working. The trick below
432 // simply invalidates the Flash object in the cache all the time to
433 // keep it loading fresh. -- Brad Neuberg
434 swflocObject += "?cachebust=" + new Date().getTime();
437 if(swflocEmbed.indexOf("?") == -1){
438 swflocEmbed += '?baseUrl='+escape(dojoUrl);
440 swflocEmbed += '&baseUrl='+escape(dojoUrl);
444 '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
447 + '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/'
448 + 'swflash.cab#version=8,0,0,0"\n '
449 + 'width="' + this.width + '"\n '
450 + 'height="' + this.height + '"\n '
451 + 'id="' + this.id + '"\n '
452 + 'name="' + this.id + '"\n '
453 + 'align="middle">\n '
454 + '<param name="allowScriptAccess" value="sameDomain"></param>\n '
455 + '<param name="movie" value="' + swflocObject + '"></param>\n '
456 + '<param name="quality" value="high"></param>\n '
457 + '<param name="bgcolor" value="#ffffff"></param>\n '
458 + '<embed src="' + swflocEmbed + '" '
460 + 'bgcolor="#ffffff" '
461 + 'width="' + this.width + '" '
462 + 'height="' + this.height + '" '
463 + 'id="' + this.id + 'Embed' + '" '
464 + 'name="' + this.id + '" '
465 + 'swLiveConnect="true" '
467 + 'allowScriptAccess="sameDomain" '
468 + 'type="application/x-shockwave-flash" '
471 +'://www.macromedia.com/go/getflashplayer" '
475 // using same mechanism on all browsers now to write out
476 // Flash object into page
478 // document.write no longer works correctly
479 // due to Eolas patent workaround in IE;
480 // nothing happens (i.e. object doesn't
481 // go into page if we use it)
482 dojo.connect(dojo, "loaded", dojo.hitch(this, function(){
483 var div = document.createElement("div");
484 div.setAttribute("id", this.id + "Container");
485 div.setAttribute("style", containerStyle);
486 div.innerHTML = objectHTML;
488 var body = document.getElementsByTagName("body");
489 if(!body || !body.length){
490 throw new Error("No body tag for this page");
493 body.appendChild(div);
497 get: function(){ /* Object */
498 // summary: Gets the Flash object DOM node.
499 if(dojo.isIE || dojo.isSafari){
500 return document.getElementById(this.id);
502 // different IDs on OBJECT and EMBED tags or
503 // else Firefox will return wrong one and
504 // communication won't work;
505 // also, document.getElementById() returns a
506 // plugin but ExternalInterface calls don't
507 // work on it so we have to use
508 // document[id] instead
509 return document[this.id + "Embed"];
513 setVisible: function(/* Boolean */ visible){
514 //console.debug("setVisible, visible="+visible);
516 // summary: Sets the visibility of this Flash object.
517 var container = dojo.byId(this.id + "Container");
519 container.style.position = "absolute"; // IE -- Brad Neuberg
520 container.style.visibility = "visible";
522 container.style.position = "absolute";
523 container.style.x = "-1000px";
524 container.style.y = "-1000px";
525 container.style.visibility = "hidden";
530 // summary: Centers the flash applet on the page.
532 var elementWidth = this.width;
533 var elementHeight = this.height;
535 var viewport = dijit.getViewport();
537 // compute the centered position
538 var x = viewport.l + (viewport.w - elementWidth) / 2;
539 var y = viewport.t + (viewport.h - elementHeight) / 2;
541 // set the centered position
542 var container = dojo.byId(this.id + "Container");
543 container.style.top = y + "px";
544 container.style.left = x + "px";
549 dojox.flash.Communicator = function(){
551 // A class that is used to communicate between Flash and JavaScript.
553 // This class helps mediate Flash and JavaScript communication. Internally
554 // it uses Flash 8's ExternalInterface API, but adds functionality to fix
555 // various encoding bugs that ExternalInterface has.
558 dojox.flash.Communicator.prototype = {
559 // Registers the existence of a Flash method that we can call with
560 // JavaScript, using Flash 8's ExternalInterface.
561 _addExternalInterfaceCallback: function(methodName){
562 var wrapperCall = dojo.hitch(this, function(){
563 // some browsers don't like us changing values in the 'arguments' array, so
564 // make a fresh copy of it
565 var methodArgs = new Array(arguments.length);
566 for(var i = 0; i < arguments.length; i++){
567 methodArgs[i] = this._encodeData(arguments[i]);
570 var results = this._execFlash(methodName, methodArgs);
571 results = this._decodeData(results);
576 this[methodName] = wrapperCall;
579 // Encodes our data to get around ExternalInterface bugs that are still
580 // present even in Flash 9.
581 _encodeData: function(data){
582 if(!data || typeof data != "string"){
586 // double encode all entity values, or they will be mis-decoded
587 // by Flash when returned
588 var entityRE = /\&([^;]*)\;/g;
589 data = data.replace(entityRE, "&$1;");
591 // entity encode XML-ish characters, or Flash's broken XML serializer
593 data = data.replace(/</g, "<");
594 data = data.replace(/>/g, ">");
596 // transforming \ into \\ doesn't work; just use a custom encoding
597 data = data.replace("\\", "&custom_backslash;");
599 data = data.replace(/\0/g, "\\0"); // null character
600 data = data.replace(/\"/g, """);
605 // Decodes our data to get around ExternalInterface bugs that are still
606 // present even in Flash 9.
607 _decodeData: function(data){
608 // wierdly enough, Flash sometimes returns the result as an
609 // 'object' that is actually an array, rather than as a String;
610 // detect this by looking for a length property; for IE
611 // we also make sure that we aren't dealing with a typeof string
612 // since string objects have length property there
613 if(data && data.length && typeof data != "string"){
617 if(!data || typeof data != "string"){
621 // certain XMLish characters break Flash's wire serialization for
622 // ExternalInterface; these are encoded on the
623 // DojoExternalInterface side into a custom encoding, rather than
624 // the standard entity encoding, because otherwise we won't be able to
625 // differentiate between our own encoding and any entity characters
626 // that are being used in the string itself
627 data = data.replace(/\&custom_lt\;/g, "<");
628 data = data.replace(/\&custom_gt\;/g, ">");
629 data = data.replace(/\&custom_backslash\;/g, '\\');
631 // needed for IE; \0 is the NULL character
632 data = data.replace(/\\0/g, "\0");
637 // Executes a Flash method; called from the JavaScript wrapper proxy we
638 // create on dojox.flash.comm.
639 _execFlash: function(methodName, methodArgs){
640 var plugin = dojox.flash.obj.get();
641 methodArgs = (methodArgs) ? methodArgs : [];
643 // encode arguments that are strings
644 for(var i = 0; i < methodArgs; i++){
645 if(typeof methodArgs[i] == "string"){
646 methodArgs[i] = this._encodeData(methodArgs[i]);
650 // we use this gnarly hack below instead of
651 // plugin[methodName] for two reasons:
652 // 1) plugin[methodName] has no call() method, which
653 // means we can't pass in multiple arguments dynamically
654 // to a Flash method -- we can only have one
655 // 2) On IE plugin[methodName] returns undefined --
656 // plugin[methodName] used to work on IE when we
657 // used document.write but doesn't now that
658 // we use dynamic DOM insertion of the Flash object
660 var flashExec = function(){
661 return eval(plugin.CallFunction(
662 "<invoke name=\"" + methodName
663 + "\" returntype=\"javascript\">"
664 + __flash__argumentsToXML(methodArgs, 0)
667 var results = flashExec.call(methodArgs);
669 if(typeof results == "string"){
670 results = this._decodeData(results);
677 // FIXME: dojo.declare()-ify this
679 // TODO: I did not test the Install code when I refactored Dojo Flash from 0.4 to
680 // 1.0, so am not sure if it works. If Flash is not present I now prefer
681 // that Gears is installed instead of Flash because GearsStorageProvider is
682 // much easier to work with than Flash's hacky ExternalInteface.
684 dojox.flash.Install = function(){
685 // summary: Helps install Flash plugin if needed.
687 // Figures out the best way to automatically install the Flash plugin
688 // for this browser and platform. Also determines if installation or
689 // revving of the current plugin is needed on this platform.
692 dojox.flash.Install.prototype = {
693 needed: function(){ /* Boolean */
695 // Determines if installation or revving of the current plugin is
698 // do we even have flash?
699 if(dojox.flash.info.capable == false){
703 // Must have ExternalInterface which came in Flash 8
704 if(!dojox.flash.info.isVersionOrAbove(8, 0, 0)){
708 // otherwise we don't need installation
713 // summary: Performs installation or revving of the Flash plugin.
715 // indicate that we are installing
716 dojox.flash.info.installing = true;
717 dojox.flash.installing();
719 if(dojox.flash.info.capable == false){ // we have no Flash at all
720 // write out a simple Flash object to force the browser to prompt
721 // the user to install things
722 var installObj = new dojox.flash.Embed(false);
723 installObj.write(); // write out HTML for Flash
724 }else if(dojox.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install
725 var installObj = new dojox.flash.Embed(false);
726 installObj.write(true); // write out HTML for Flash 8 version+
727 installObj.setVisible(true);
729 }else{ // older Flash install than version 6r65
730 alert("This content requires a more recent version of the Macromedia "
732 window.location.href = + dojox.flash.Embed.protocol() +
733 "://www.macromedia.com/go/getflashplayer";
737 // Called when the Express Install is either finished, failed, or was
738 // rejected by the user.
739 _onInstallStatus: function(msg){
740 if (msg == "Download.Complete"){
741 // Installation is complete.
742 dojox.flash._initialize();
743 }else if(msg == "Download.Cancelled"){
744 alert("This content requires a more recent version of the Macromedia "
746 window.location.href = dojox.flash.Embed.protocol() +
747 "://www.macromedia.com/go/getflashplayer";
748 }else if (msg == "Download.Failed"){
749 // The end user failed to download the installer due to a network failure
750 alert("There was an error downloading the Flash Player update. "
751 + "Please try again later, or visit macromedia.com to download "
752 + "the latest version of the Flash plugin.");
757 // find out if Flash is installed
758 dojox.flash.info = new dojox.flash.Info();
760 // vim:ts=4:noet:tw=0: