source: Dev/trunk/src/client/dojox/embed/Flash.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 14.8 KB
Line 
1define(["dojo"], function(dojo) {
2
3        // module:
4        //              dojox/embed/Flash
5        // summary:
6        //              Base functionality to insert a flash movie into
7        //              a document on the fly.
8        // example:
9        //      |       var movie=new Flash({ args }, containerNode);
10
11
12        var fMarkup, fVersion;
13        var minimumVersion = 9; // anything below this will throw an error (may overwrite)
14        var keyBase = "dojox-embed-flash-", keyCount=0;
15        var _baseKwArgs = {
16                expressInstall: false,
17                width: 320,
18                height: 240,
19                swLiveConnect: "true",
20                allowScriptAccess: "sameDomain",
21                allowNetworking:"all",
22                style: null,
23                redirect: null
24        };
25
26        function prep(kwArgs){
27                kwArgs = dojo.delegate(_baseKwArgs, kwArgs);
28
29                if(!("path" in kwArgs)){
30                        console.error("dojox.embed.Flash(ctor):: no path reference to a Flash movie was provided.");
31                        return null;
32                }
33
34                if(!("id" in kwArgs)){
35                        kwArgs.id = (keyBase + keyCount++);
36                }
37                return kwArgs;
38        }
39
40        if(dojo.isIE){
41                fMarkup = function(kwArgs){
42                        kwArgs = prep(kwArgs);
43                        if(!kwArgs){ return null; }
44
45                        var p;
46                        var path = kwArgs.path;
47                        if(kwArgs.vars){
48                                var a = [];
49                                for(p in kwArgs.vars){
50                                        a.push(p + '=' + kwArgs.vars[p]);
51                                }
52                                kwArgs.params.FlashVars = a.join("&");
53                                delete kwArgs.vars;
54                        }
55                        var s = '<object id="' + kwArgs.id + '" '
56                                + 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
57                                + 'width="' + kwArgs.width + '" '
58                                + 'height="' + kwArgs.height + '"'
59                                + ((kwArgs.style)?' style="' + kwArgs.style + '"':'')
60                                + '>'
61                                + '<param name="movie" value="' + path + '" />';
62                        if(kwArgs.params){
63                                for(p in kwArgs.params){
64                                        s += '<param name="' + p + '" value="' + kwArgs.params[p] + '" />';
65                                }
66                        }
67                        s += '</object>';
68                        return { id: kwArgs.id, markup: s };
69                };
70
71                fVersion = (function(){
72                        var testVersion = 10, testObj = null;
73                        while(!testObj && testVersion > 7){
74                                try {
75                                        testObj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + testVersion--);
76                                }catch(e){ }
77                        }
78                        if(testObj){
79                                var v = testObj.GetVariable("$version").split(" ")[1].split(",");
80                                return {
81                                        major: (v[0]!=null) ? parseInt(v[0]) : 0,
82                                        minor: (v[1]!=null) ? parseInt(v[1]) : 0,
83                                        rev: (v[2]!=null) ? parseInt(v[2]) : 0
84                                };
85                        }
86                        return { major: 0, minor: 0, rev: 0 };
87                })();
88
89                //      attach some cleanup for IE, thanks to deconcept :)
90                dojo.addOnWindowUnload(function(){
91                        console.warn('***************UNLOAD');
92                        var dummy = function(){};
93                        var objs = dojo.query("object").
94                                reverse().
95                                style("display", "none").
96                                forEach(function(i){
97                                        for(var p in i){
98                                                if((p != "FlashVars") && dojo.isFunction(i[p])){
99                                                        try{
100                                                                i[p] = dummy;
101                                                        }catch(e){}
102                                                }
103                                        }
104                                });
105                });
106
107        } else {
108                //      *** Sane browsers branch ******************************************************************
109                fMarkup = function(kwArgs){
110                        kwArgs = prep(kwArgs);
111                        if(!kwArgs){ return null; }
112
113                        var p;
114                        var path = kwArgs.path;
115                        if(kwArgs.vars){
116                                var a = [];
117                                for(p in kwArgs.vars){
118                                        a.push(p + '=' + kwArgs.vars[p]);
119                                }
120                                kwArgs.params.flashVars = a.join("&");
121                                delete kwArgs.vars;
122                        }
123                        var s = '<embed type="application/x-shockwave-flash" '
124                                + 'src="' + path + '" '
125                                + 'id="' + kwArgs.id + '" '
126                                + 'width="' + kwArgs.width + '" '
127                                + 'height="' + kwArgs.height + '"'
128                                + ((kwArgs.style)?' style="' + kwArgs.style + '" ':'')
129
130                                + 'pluginspage="' + window.location.protocol + '//www.adobe.com/go/getflashplayer" ';
131                        if(kwArgs.params){
132                                for(p in kwArgs.params){
133                                        s += ' ' + p + '="' + kwArgs.params[p] + '"';
134                                }
135                        }
136                        s += ' />';
137                        return { id: kwArgs.id, markup: s };
138                };
139
140                fVersion=(function(){
141                        var plugin = navigator.plugins["Shockwave Flash"];
142                        if(plugin && plugin.description){
143                                var v = plugin.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".");
144                                return {
145                                        major: (v[0]!=null) ? parseInt(v[0]) : 0,
146                                        minor: (v[1]!=null) ? parseInt(v[1]) : 0,
147                                        rev: (v[2]!=null) ? parseInt(v[2]) : 0
148                                };
149                        }
150                        return { major: 0, minor: 0, rev: 0 };
151                })();
152        }
153
154
155/*=====
156var __flashArgs = {
157        // path: String
158        //              The URL of the movie to embed.
159        // id: String?
160        //              A unique key that will be used as the id of the created markup.  If you don't
161        //              provide this, a unique key will be generated.
162        // width: Number?
163        //              The width of the embedded movie; the default value is 320px.
164        // height: Number?
165        //              The height of the embedded movie; the default value is 240px
166        // minimumVersion: Number?
167        //              The minimum targeted version of the Flash Player (defaults to 9)
168        // style: String?
169        //              Any CSS style information (i.e. style="background-color:transparent") you want
170        //              to define on the markup.
171        // params: Object?
172        //              A set of key/value pairs that you want to define in the resultant markup.
173        // vars: Object?
174        //              A set of key/value pairs that the Flash movie will interpret as FlashVars.
175        // expressInstall: Boolean?
176        //              Whether or not to include any kind of expressInstall info. Default is false.
177        // redirect: String?
178        //              A url to redirect the browser to if the current Flash version is not supported.
179};
180=====*/
181
182        //      the main entry point
183        var Flash = function(/*__flashArgs*/ kwArgs, /*DOMNode*/ node){
184                // summary:
185                //              Create a wrapper object around a Flash movie; this is the DojoX equivilent
186                //              to SWFObject.
187                //
188                // description:
189                //              Creates a wrapper object around a Flash movie.  Wrapper object will
190                //              insert the movie reference in node; when the browser first starts
191                //              grabbing the movie, onReady will be fired; when the movie has finished
192                //              loading, it will fire onLoad.
193                //
194                //              If your movie uses ExternalInterface, you should use the onLoad event
195                //              to do any kind of proxy setup (see dojox.embed.Flash.proxy); this seems
196                //              to be the only consistent time calling EI methods are stable (since the
197                //              Flash movie will shoot several methods into the window object before
198                //              EI callbacks can be used properly).
199                //
200                // kwArgs: __flashArgs
201                //              The various arguments that will be used to help define the Flash movie.
202                // node: DomNode
203                //              The node where the embed object will be placed
204                //
205                // example:
206                //              Embed a flash movie in a document using the new operator, and get a reference to it.
207                //      |       var movie = new dojox.embed.Flash({
208                //      |               path: "path/to/my/movie.swf",
209                //      |               width: 400,
210                //      |               height: 300
211                //      |       }, myWrapperNode, "testLoaded");
212                //
213                // example:
214                //              Embed a flash movie in a document without using the new operator.
215                //      |       var movie = dojox.embed.Flash({
216                //      |               path: "path/to/my/movie.swf",
217                //      |               width: 400,
218                //      |               height: 300,
219                //      |               style: "position:absolute;top:0;left:0"
220                //      |       }, myWrapperNode, "testLoaded");
221
222                // File can only be run from a server, due to SWF dependency.
223                if(location.href.toLowerCase().indexOf("file://")>-1){
224                        throw new Error("dojox.embed.Flash can't be run directly from a file. To instatiate the required SWF correctly it must be run from a server, like localHost.");
225                }
226
227                // available: Number
228                //              If there is a flash player available, and if so what version.
229                this.available = dojox.embed.Flash.available;
230
231                // minimumVersion: Number
232                //              The minimum version of Flash required to run this movie.
233                this.minimumVersion = kwArgs.minimumVersion || minimumVersion;
234
235                // id: String
236                //              The id of the DOMNode to be used for this movie.  Can be used with dojo.byId to get a reference.
237                this.id = null;
238
239                // movie: FlashObject
240                //              A reference to the movie itself.
241                this.movie = null;
242
243                // domNode: DOMNode
244                //              A reference to the DOMNode that contains this movie.
245                this.domNode = null;
246                if(node){
247                        node = dojo.byId(node);
248                }
249                // setTimeout Fixes #8743 - creating double SWFs
250                // also allows time for code to attach to onError
251                setTimeout(dojo.hitch(this, function(){
252                        if(kwArgs.expressInstall || this.available && this.available >= this.minimumVersion){
253                                if(kwArgs && node){
254                                        this.init(kwArgs, node);
255                                }else{
256                                        this.onError("embed.Flash was not provided with the proper arguments.");
257                                }
258                        }else{
259                                if(!this.available){
260                                        this.onError("Flash is not installed.");
261                                }else{
262                                        this.onError("Flash version detected: "+this.available+" is out of date. Minimum required: "+this.minimumVersion);
263                                }
264                        }
265                }), 100);
266        };
267
268        dojo.extend(Flash, {
269                onReady: function(/*HTMLObject*/ movie){
270                        // summary:
271                        //              Stub function for you to attach to when the movie reference is first
272                        //              pushed into the document.
273                },
274                onLoad: function(/*HTMLObject*/ movie){
275                        // summary:
276                        //              Stub function for you to attach to when the movie has finished downloading
277                        //              and is ready to be manipulated.
278                },
279                onError: function(msg){
280
281                },
282                _onload: function(){
283                        // summary:
284                        //      Internal. Cleans up before calling onLoad.
285                        clearInterval(this._poller);
286                        delete this._poller;
287                        delete this._pollCount;
288                        delete this._pollMax;
289                        this.onLoad(this.movie);
290                },
291                init: function(/*__flashArgs*/ kwArgs, /*DOMNode?*/ node){
292                        // summary:
293                        //              Initialize (i.e. place and load) the movie based on kwArgs.
294                        this.destroy();         //      ensure we are clean first.
295                        node = dojo.byId(node || this.domNode);
296                        if(!node){ throw new Error("dojox.embed.Flash: no domNode reference has been passed."); }
297
298                        // vars to help determine load status
299                        var p = 0, testLoaded=false;
300                        this._poller = null; this._pollCount = 0; this._pollMax = 15; this.pollTime = 100;
301
302                        if(dojox.embed.Flash.initialized){
303
304                                this.id = dojox.embed.Flash.place(kwArgs, node);
305                                this.domNode = node;
306
307                                setTimeout(dojo.hitch(this, function(){
308                                        this.movie = this.byId(this.id, kwArgs.doc);
309                                        this.onReady(this.movie);
310
311                                        this._poller = setInterval(dojo.hitch(this, function(){
312
313                                                // catch errors if not quite ready.
314                                                try{
315                                                        p = this.movie.PercentLoaded();
316                                                }catch(e){
317                                                        console.warn("this.movie.PercentLoaded() failed", e, this.movie);
318                                                }
319
320                                                if(p == 100){
321                                                        // if percent = 100, movie is fully loaded and we're communicating
322                                                        this._onload();
323
324                                                }else if(p==0 && this._pollCount++ > this._pollMax){
325                                                        // after several attempts, we're not past zero.
326                                                        clearInterval(this._poller);
327                                                        throw new Error("Building SWF failed.");
328                                                }
329                                        }), this.pollTime);
330                                }), 1);
331                        }
332                },
333                _destroy: function(){
334                        // summary:
335                        //              Kill the movie and reset all the properties of this object.
336                        try{
337                                this.domNode.removeChild(this.movie);
338                        }catch(e){}
339                        this.id = this.movie = this.domNode = null;
340                },
341                destroy: function(){
342                        // summary:
343                        //              Public interface for destroying all the properties in this object.
344                        //              Will also clean all proxied methods.
345                        if(!this.movie){ return; }
346
347                        //      remove any proxy functions
348                        var test = dojo.delegate({
349                                id: true,
350                                movie: true,
351                                domNode: true,
352                                onReady: true,
353                                onLoad: true
354                        });
355                        for(var p in this){
356                                if(!test[p]){
357                                        delete this[p];
358                                }
359                        }
360
361                        //      poll the movie
362                        if(this._poller){
363                                //      wait until onLoad to destroy
364                                dojo.connect(this, "onLoad", this, "_destroy");
365                        } else {
366                                this._destroy();
367                        }
368                },
369                byId: function (movieName, doc){
370                        // summary:
371                        //              Gets Flash movie by id.
372                        // description:
373                        //              Probably includes methods for outdated
374                        //              browsers, but this should catch all cases.
375                        // movieName: String
376                        //              The name of the SWF
377                        // doc: Object
378                        //              The document, if not current window
379                        //              (not fully supported)
380                        // example:
381                        //      |       var movie = dojox.embed.Flash.byId("myId");
382
383                        doc = doc || document;
384                        if(doc.embeds[movieName]){
385                                return doc.embeds[movieName];
386                        }
387                        if(doc[movieName]){
388                                return doc[movieName];
389                        }
390                        if(window[movieName]){
391                                return window[movieName];
392                        }
393                        if(document[movieName]){
394                                return document[movieName];
395                        }
396                        return null;
397                }
398        });
399
400        //      expose information through the constructor function itself.
401        dojo.mixin(Flash, {
402                // summary:
403                //              A singleton object used internally to get information
404                //              about the Flash player available in a browser, and
405                //              as the factory for generating and placing markup in a
406                //              document.
407                //
408                // minSupported: Number
409                //              The minimum supported version of the Flash Player, defaults to 8.
410                // available: Number
411                //              Used as both a detection (i.e. if(dojox.embed.Flash.available){ })
412                //              and as a variable holding the major version of the player installed.
413                // supported: Boolean
414                //              Whether or not the Flash Player installed is supported by dojox.embed.
415                // version: Object
416                //              The version of the installed Flash Player; takes the form of
417                //              { major, minor, rev }.  To get the major version, you'd do this:
418                //              var v=dojox.embed.Flash.version.major;
419                // initialized: Boolean
420                //              Whether or not the Flash engine is available for use.
421                // onInitialize: Function
422                //              A stub you can connect to if you are looking to fire code when the
423                //              engine becomes available.  A note: DO NOT use this event to
424                //              place a movie in a document; it will usually fire before DOMContentLoaded
425                //              is fired, and you will get an error.  Use dojo.addOnLoad instead.
426                minSupported : 8,
427                available: fVersion.major,
428                supported: (fVersion.major >= fVersion.required),
429                minimumRequired: fVersion.required,
430                version: fVersion,
431                initialized: false,
432                onInitialize: function(){
433                        Flash.initialized = true;
434                },
435                __ie_markup__: function(kwArgs){
436                        return fMarkup(kwArgs);
437                },
438                proxy: function(/*Flash*/ obj, /*Array|String*/ methods){
439                        // summary:
440                        //              Create the set of passed methods on the Flash object
441                        //              so that you can call that object directly, as opposed to having to
442                        //              delve into the internal movie to do this.  Intended to make working
443                        //              with Flash movies that use ExternalInterface much easier to use.
444                        //
445                        // example:
446                        //              Create "setMessage" and "getMessage" methods on foo.
447                        //      |       var foo = new Flash(args, someNode);
448                        //      |       dojo.connect(foo, "onLoad", dojo.hitch(foo, function(){
449                        //      |               Flash.proxy(this, [ "setMessage", "getMessage" ]);
450                        //      |               this.setMessage("Flash.proxy is pretty cool...");
451                        //      |               console.log(this.getMessage());
452                        //      |       }));
453                        dojo.forEach((dojo.isArray(methods) ? methods : [ methods ]), function(item){
454                                this[item] = dojo.hitch(this, function(){
455                                        return (function(){
456                                                return eval(this.movie.CallFunction(
457                                                        '<invoke name="' + item + '" returntype="javascript">'
458                                                        + '<arguments>'
459                                                        + dojo.map(arguments, function(item){
460                                                                // FIXME:
461                                                                //              investigate if __flash__toXML will
462                                                                //              accept direct application via map()
463                                                                //              (e.g., does it ignore args past the
464                                                                //              first? or does it blow up?)
465                                                                return __flash__toXML(item);
466                                                        }).join("")
467                                                        + '</arguments>'
468                                                        + '</invoke>'
469                                                ));
470                                        }).apply(this, arguments||[]);
471                                });
472                        }, obj);
473                }
474        });
475
476        Flash.place = function(kwArgs, node){
477                var o = fMarkup(kwArgs);
478                node = dojo.byId(node);
479                if(!node){
480                        node = dojo.doc.createElement("div");
481                        node.id = o.id+"-container";
482                        dojo.body().appendChild(node);
483                }
484                if(o){
485                        node.innerHTML = o.markup;
486                        return o.id;
487                }
488                return null;
489        }
490        Flash.onInitialize();
491
492        dojo.setObject("dojox.embed.Flash", Flash);
493
494        return Flash;
495});
Note: See TracBrowser for help on using the repository browser.