Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / swfobject.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">/*!
9  * Ext JS Library 3.0.3
10  * Copyright(c) 2006-2009 Ext JS, LLC
11  * licensing@extjs.com
12  * http://www.extjs.com/license
13  */
14 /*! SWFObject v2.2 <http://code.google.com/p/swfobject/> \r
15     is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \r
16 */\r
17 \r
18 var swfobject = function() {\r
19     \r
20     var UNDEF = "undefined",\r
21         OBJECT = "object",\r
22         SHOCKWAVE_FLASH = "Shockwave Flash",\r
23         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",\r
24         FLASH_MIME_TYPE = "application/x-shockwave-flash",\r
25         EXPRESS_INSTALL_ID = "SWFObjectExprInst",\r
26         ON_READY_STATE_CHANGE = "onreadystatechange",\r
27         \r
28         win = window,\r
29         doc = document,\r
30         nav = navigator,\r
31         \r
32         plugin = false,\r
33         domLoadFnArr = [main],\r
34         regObjArr = [],\r
35         objIdArr = [],\r
36         listenersArr = [],\r
37         storedAltContent,\r
38         storedAltContentId,\r
39         storedCallbackFn,\r
40         storedCallbackObj,\r
41         isDomLoaded = false,\r
42         isExpressInstallActive = false,\r
43         dynamicStylesheet,\r
44         dynamicStylesheetMedia,\r
45         autoHideShow = true,\r
46     \r
47     /* Centralized function for browser feature detection\r
48         - User agent string detection is only used when no good alternative is possible\r
49         - Is executed directly for optimal performance\r
50     */  \r
51     ua = function() {\r
52         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,\r
53             u = nav.userAgent.toLowerCase(),\r
54             p = nav.platform.toLowerCase(),\r
55             windows = p ? /win/.test(p) : /win/.test(u),\r
56             mac = p ? /mac/.test(p) : /mac/.test(u),\r
57             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit\r
58             ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html\r
59             playerVersion = [0,0,0],\r
60             d = null;\r
61         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {\r
62             d = nav.plugins[SHOCKWAVE_FLASH].description;\r
63             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+\r
64                 plugin = true;\r
65                 ie = false; // cascaded feature detection for Internet Explorer\r
66                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");\r
67                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);\r
68                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);\r
69                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;\r
70             }\r
71         }\r
72         else if (typeof win.ActiveXObject != UNDEF) {\r
73             try {\r
74                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);\r
75                 if (a) { // a will return null when ActiveX is disabled\r
76                     d = a.GetVariable("$version");\r
77                     if (d) {\r
78                         ie = true; // cascaded feature detection for Internet Explorer\r
79                         d = d.split(" ")[1].split(",");\r
80                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];\r
81                     }\r
82                 }\r
83             }\r
84             catch(e) {}\r
85         }\r
86         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };\r
87     }(),\r
88     \r
89     /* Cross-browser onDomLoad\r
90         - Will fire an event as soon as the DOM of a web page is loaded\r
91         - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/\r
92         - Regular onload serves as fallback\r
93     */ \r
94     onDomLoad = function() {\r
95         if (!ua.w3) { return; }\r
96         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically \r
97             callDomLoadFunctions();\r
98         }\r
99         if (!isDomLoaded) {\r
100             if (typeof doc.addEventListener != UNDEF) {\r
101                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);\r
102             }       \r
103             if (ua.ie && ua.win) {\r
104                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {\r
105                     if (doc.readyState == "complete") {\r
106                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);\r
107                         callDomLoadFunctions();\r
108                     }\r
109                 });\r
110                 if (win == top) { // if not inside an iframe\r
111                     (function(){\r
112                         if (isDomLoaded) { return; }\r
113                         try {\r
114                             doc.documentElement.doScroll("left");\r
115                         }\r
116                         catch(e) {\r
117                             setTimeout(arguments.callee, 0);\r
118                             return;\r
119                         }\r
120                         callDomLoadFunctions();\r
121                     })();\r
122                 }\r
123             }\r
124             if (ua.wk) {\r
125                 (function(){\r
126                     if (isDomLoaded) { return; }\r
127                     if (!/loaded|complete/.test(doc.readyState)) {\r
128                         setTimeout(arguments.callee, 0);\r
129                         return;\r
130                     }\r
131                     callDomLoadFunctions();\r
132                 })();\r
133             }\r
134             addLoadEvent(callDomLoadFunctions);\r
135         }\r
136     }();\r
137     \r
138     function callDomLoadFunctions() {\r
139         if (isDomLoaded) { return; }\r
140         try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early\r
141             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));\r
142             t.parentNode.removeChild(t);\r
143         }\r
144         catch (e) { return; }\r
145         isDomLoaded = true;\r
146         var dl = domLoadFnArr.length;\r
147         for (var i = 0; i < dl; i++) {\r
148             domLoadFnArr[i]();\r
149         }\r
150     }\r
151     \r
152     function addDomLoadEvent(fn) {\r
153         if (isDomLoaded) {\r
154             fn();\r
155         }\r
156         else { \r
157             domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+\r
158         }\r
159     }\r
160     \r
161     /* Cross-browser onload\r
162         - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/\r
163         - Will fire an event as soon as a web page including all of its assets are loaded \r
164      */\r
165     function addLoadEvent(fn) {\r
166         if (typeof win.addEventListener != UNDEF) {\r
167             win.addEventListener("load", fn, false);\r
168         }\r
169         else if (typeof doc.addEventListener != UNDEF) {\r
170             doc.addEventListener("load", fn, false);\r
171         }\r
172         else if (typeof win.attachEvent != UNDEF) {\r
173             addListener(win, "onload", fn);\r
174         }\r
175         else if (typeof win.onload == "function") {\r
176             var fnOld = win.onload;\r
177             win.onload = function() {\r
178                 fnOld();\r
179                 fn();\r
180             };\r
181         }\r
182         else {\r
183             win.onload = fn;\r
184         }\r
185     }\r
186     \r
187     /* Main function\r
188         - Will preferably execute onDomLoad, otherwise onload (as a fallback)\r
189     */\r
190     function main() { \r
191         if (plugin) {\r
192             testPlayerVersion();\r
193         }\r
194         else {\r
195             matchVersions();\r
196         }\r
197     }\r
198     \r
199     /* Detect the Flash Player version for non-Internet Explorer browsers\r
200         - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:\r
201           a. Both release and build numbers can be detected\r
202           b. Avoid wrong descriptions by corrupt installers provided by Adobe\r
203           c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports\r
204         - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available\r
205     */\r
206     function testPlayerVersion() {\r
207         var b = doc.getElementsByTagName("body")[0];\r
208         var o = createElement(OBJECT);\r
209         o.setAttribute("type", FLASH_MIME_TYPE);\r
210         var t = b.appendChild(o);\r
211         if (t) {\r
212             var counter = 0;\r
213             (function(){\r
214                 if (typeof t.GetVariable != UNDEF) {\r
215                     var d = t.GetVariable("$version");\r
216                     if (d) {\r
217                         d = d.split(" ")[1].split(",");\r
218                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];\r
219                     }\r
220                 }\r
221                 else if (counter < 10) {\r
222                     counter++;\r
223                     setTimeout(arguments.callee, 10);\r
224                     return;\r
225                 }\r
226                 b.removeChild(o);\r
227                 t = null;\r
228                 matchVersions();\r
229             })();\r
230         }\r
231         else {\r
232             matchVersions();\r
233         }\r
234     }\r
235     \r
236     /* Perform Flash Player and SWF version matching; static publishing only\r
237     */\r
238     function matchVersions() {\r
239         var rl = regObjArr.length;\r
240         if (rl > 0) {\r
241             for (var i = 0; i < rl; i++) { // for each registered object element\r
242                 var id = regObjArr[i].id;\r
243                 var cb = regObjArr[i].callbackFn;\r
244                 var cbObj = {success:false, id:id};\r
245                 if (ua.pv[0] > 0) {\r
246                     var obj = getElementById(id);\r
247                     if (obj) {\r
248                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!\r
249                             setVisibility(id, true);\r
250                             if (cb) {\r
251                                 cbObj.success = true;\r
252                                 cbObj.ref = getObjectById(id);\r
253                                 cb(cbObj);\r
254                             }\r
255                         }\r
256                         else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported\r
257                             var att = {};\r
258                             att.data = regObjArr[i].expressInstall;\r
259                             att.width = obj.getAttribute("width") || "0";\r
260                             att.height = obj.getAttribute("height") || "0";\r
261                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }\r
262                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }\r
263                             // parse HTML object param element's name-value pairs\r
264                             var par = {};\r
265                             var p = obj.getElementsByTagName("param");\r
266                             var pl = p.length;\r
267                             for (var j = 0; j < pl; j++) {\r
268                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {\r
269                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");\r
270                                 }\r
271                             }\r
272                             showExpressInstall(att, par, id, cb);\r
273                         }\r
274                         else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF\r
275                             displayAltContent(obj);\r
276                             if (cb) { cb(cbObj); }\r
277                         }\r
278                     }\r
279                 }\r
280                 else {  // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)\r
281                     setVisibility(id, true);\r
282                     if (cb) {\r
283                         var o = getObjectById(id); // test whether there is an HTML object element or not\r
284                         if (o && typeof o.SetVariable != UNDEF) { \r
285                             cbObj.success = true;\r
286                             cbObj.ref = o;\r
287                         }\r
288                         cb(cbObj);\r
289                     }\r
290                 }\r
291             }\r
292         }\r
293     }\r
294     \r
295     function getObjectById(objectIdStr) {\r
296         var r = null;\r
297         var o = getElementById(objectIdStr);\r
298         if (o && o.nodeName == "OBJECT") {\r
299             if (typeof o.SetVariable != UNDEF) {\r
300                 r = o;\r
301             }\r
302             else {\r
303                 var n = o.getElementsByTagName(OBJECT)[0];\r
304                 if (n) {\r
305                     r = n;\r
306                 }\r
307             }\r
308         }\r
309         return r;\r
310     }\r
311     \r
312     /* Requirements for Adobe Express Install\r
313         - only one instance can be active at a time\r
314         - fp 6.0.65 or higher\r
315         - Win/Mac OS only\r
316         - no Webkit engines older than version 312\r
317     */\r
318     function canExpressInstall() {\r
319         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);\r
320     }\r
321     \r
322     /* Show the Adobe Express Install dialog\r
323         - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75\r
324     */\r
325     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {\r
326         isExpressInstallActive = true;\r
327         storedCallbackFn = callbackFn || null;\r
328         storedCallbackObj = {success:false, id:replaceElemIdStr};\r
329         var obj = getElementById(replaceElemIdStr);\r
330         if (obj) {\r
331             if (obj.nodeName == "OBJECT") { // static publishing\r
332                 storedAltContent = abstractAltContent(obj);\r
333                 storedAltContentId = null;\r
334             }\r
335             else { // dynamic publishing\r
336                 storedAltContent = obj;\r
337                 storedAltContentId = replaceElemIdStr;\r
338             }\r
339             att.id = EXPRESS_INSTALL_ID;\r
340             if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }\r
341             if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }\r
342             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";\r
343             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",\r
344                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;\r
345             if (typeof par.flashvars != UNDEF) {\r
346                 par.flashvars += "&" + fv;\r
347             }\r
348             else {\r
349                 par.flashvars = fv;\r
350             }\r
351             // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,\r
352             // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work\r
353             if (ua.ie && ua.win && obj.readyState != 4) {\r
354                 var newObj = createElement("div");\r
355                 replaceElemIdStr += "SWFObjectNew";\r
356                 newObj.setAttribute("id", replaceElemIdStr);\r
357                 obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf\r
358                 obj.style.display = "none";\r
359                 (function(){\r
360                     if (obj.readyState == 4) {\r
361                         obj.parentNode.removeChild(obj);\r
362                     }\r
363                     else {\r
364                         setTimeout(arguments.callee, 10);\r
365                     }\r
366                 })();\r
367             }\r
368             createSWF(att, par, replaceElemIdStr);\r
369         }\r
370     }\r
371     \r
372     /* Functions to abstract and display alternative content\r
373     */\r
374     function displayAltContent(obj) {\r
375         if (ua.ie && ua.win && obj.readyState != 4) {\r
376             // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,\r
377             // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work\r
378             var el = createElement("div");\r
379             obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content\r
380             el.parentNode.replaceChild(abstractAltContent(obj), el);\r
381             obj.style.display = "none";\r
382             (function(){\r
383                 if (obj.readyState == 4) {\r
384                     obj.parentNode.removeChild(obj);\r
385                 }\r
386                 else {\r
387                     setTimeout(arguments.callee, 10);\r
388                 }\r
389             })();\r
390         }\r
391         else {\r
392             obj.parentNode.replaceChild(abstractAltContent(obj), obj);\r
393         }\r
394     } \r
395 \r
396     function abstractAltContent(obj) {\r
397         var ac = createElement("div");\r
398         if (ua.win && ua.ie) {\r
399             ac.innerHTML = obj.innerHTML;\r
400         }\r
401         else {\r
402             var nestedObj = obj.getElementsByTagName(OBJECT)[0];\r
403             if (nestedObj) {\r
404                 var c = nestedObj.childNodes;\r
405                 if (c) {\r
406                     var cl = c.length;\r
407                     for (var i = 0; i < cl; i++) {\r
408                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {\r
409                             ac.appendChild(c[i].cloneNode(true));\r
410                         }\r
411                     }\r
412                 }\r
413             }\r
414         }\r
415         return ac;\r
416     }\r
417     \r
418     /* Cross-browser dynamic SWF creation\r
419     */\r
420     function createSWF(attObj, parObj, id) {\r
421         var r, el = getElementById(id);\r
422         if (ua.wk && ua.wk < 312) { return r; }\r
423         if (el) {\r
424             if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content\r
425                 attObj.id = id;\r
426             }\r
427             if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML\r
428                 var att = "";\r
429                 for (var i in attObj) {\r
430                     if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries\r
431                         if (i.toLowerCase() == "data") {\r
432                             parObj.movie = attObj[i];\r
433                         }\r
434                         else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword\r
435                             att += ' class="' + attObj[i] + '"';\r
436                         }\r
437                         else if (i.toLowerCase() != "classid") {\r
438                             att += ' ' + i + '="' + attObj[i] + '"';\r
439                         }\r
440                     }\r
441                 }\r
442                 var par = "";\r
443                 for (var j in parObj) {\r
444                     if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries\r
445                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';\r
446                     }\r
447                 }\r
448                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';\r
449                 objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)\r
450                 r = getElementById(attObj.id);  \r
451             }\r
452             else { // well-behaving browsers\r
453                 var o = createElement(OBJECT);\r
454                 o.setAttribute("type", FLASH_MIME_TYPE);\r
455                 for (var m in attObj) {\r
456                     if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries\r
457                         if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword\r
458                             o.setAttribute("class", attObj[m]);\r
459                         }\r
460                         else if (m.toLowerCase() != "classid") { // filter out IE specific attribute\r
461                             o.setAttribute(m, attObj[m]);\r
462                         }\r
463                     }\r
464                 }\r
465                 for (var n in parObj) {\r
466                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element\r
467                         createObjParam(o, n, parObj[n]);\r
468                     }\r
469                 }\r
470                 el.parentNode.replaceChild(o, el);\r
471                 r = o;\r
472             }\r
473         }\r
474         return r;\r
475     }\r
476     \r
477     function createObjParam(el, pName, pValue) {\r
478         var p = createElement("param");\r
479         p.setAttribute("name", pName);  \r
480         p.setAttribute("value", pValue);\r
481         el.appendChild(p);\r
482     }\r
483     \r
484     /* Cross-browser SWF removal\r
485         - Especially needed to safely and completely remove a SWF in Internet Explorer\r
486     */\r
487     function removeSWF(id) {\r
488         var obj = getElementById(id);\r
489         if (obj && obj.nodeName == "OBJECT") {\r
490             if (ua.ie && ua.win) {\r
491                 obj.style.display = "none";\r
492                 (function(){\r
493                     if (obj.readyState == 4) {\r
494                         removeObjectInIE(id);\r
495                     }\r
496                     else {\r
497                         setTimeout(arguments.callee, 10);\r
498                     }\r
499                 })();\r
500             }\r
501             else {\r
502                 obj.parentNode.removeChild(obj);\r
503             }\r
504         }\r
505     }\r
506     \r
507     function removeObjectInIE(id) {\r
508         var obj = getElementById(id);\r
509         if (obj) {\r
510             for (var i in obj) {\r
511                 if (typeof obj[i] == "function") {\r
512                     obj[i] = null;\r
513                 }\r
514             }\r
515             obj.parentNode.removeChild(obj);\r
516         }\r
517     }\r
518     \r
519     /* Functions to optimize JavaScript compression\r
520     */\r
521     function getElementById(id) {\r
522         var el = null;\r
523         try {\r
524             el = doc.getElementById(id);\r
525         }\r
526         catch (e) {}\r
527         return el;\r
528     }\r
529     \r
530     function createElement(el) {\r
531         return doc.createElement(el);\r
532     }\r
533     \r
534     /* Updated attachEvent function for Internet Explorer\r
535         - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks\r
536     */  \r
537     function addListener(target, eventType, fn) {\r
538         target.attachEvent(eventType, fn);\r
539         listenersArr[listenersArr.length] = [target, eventType, fn];\r
540     }\r
541     \r
542     /* Flash Player and SWF content version matching\r
543     */\r
544     function hasPlayerVersion(rv) {\r
545         var pv = ua.pv, v = rv.split(".");\r
546         v[0] = parseInt(v[0], 10);\r
547         v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"\r
548         v[2] = parseInt(v[2], 10) || 0;\r
549         return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;\r
550     }\r
551     \r
552     /* Cross-browser dynamic CSS creation\r
553         - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php\r
554     */  \r
555     function createCSS(sel, decl, media, newStyle) {\r
556         if (ua.ie && ua.mac) { return; }\r
557         var h = doc.getElementsByTagName("head")[0];\r
558         if (!h) { return; } // to also support badly authored HTML pages that lack a head element\r
559         var m = (media && typeof media == "string") ? media : "screen";\r
560         if (newStyle) {\r
561             dynamicStylesheet = null;\r
562             dynamicStylesheetMedia = null;\r
563         }\r
564         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { \r
565             // create dynamic stylesheet + get a global reference to it\r
566             var s = createElement("style");\r
567             s.setAttribute("type", "text/css");\r
568             s.setAttribute("media", m);\r
569             dynamicStylesheet = h.appendChild(s);\r
570             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {\r
571                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];\r
572             }\r
573             dynamicStylesheetMedia = m;\r
574         }\r
575         // add style rule\r
576         if (ua.ie && ua.win) {\r
577             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {\r
578                 dynamicStylesheet.addRule(sel, decl);\r
579             }\r
580         }\r
581         else {\r
582             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {\r
583                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));\r
584             }\r
585         }\r
586     }\r
587     \r
588     function setVisibility(id, isVisible) {\r
589         if (!autoHideShow) { return; }\r
590         var v = isVisible ? "visible" : "hidden";\r
591         if (isDomLoaded && getElementById(id)) {\r
592             getElementById(id).style.visibility = v;\r
593         }\r
594         else {\r
595             createCSS("#" + id, "visibility:" + v);\r
596         }\r
597     }\r
598 \r
599     /* Filter to avoid XSS attacks\r
600     */\r
601     function urlEncodeIfNecessary(s) {\r
602         var regex = /[\\\"<>\.;]/;\r
603         var hasBadChars = regex.exec(s) != null;\r
604         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;\r
605     }\r
606     \r
607     /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)\r
608     */\r
609     var cleanup = function() {\r
610         if (ua.ie && ua.win) {\r
611             window.attachEvent("onunload", function() {\r
612                 // remove listeners to avoid memory leaks\r
613                 var ll = listenersArr.length;\r
614                 for (var i = 0; i < ll; i++) {\r
615                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);\r
616                 }\r
617                 // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect\r
618                 var il = objIdArr.length;\r
619                 for (var j = 0; j < il; j++) {\r
620                     removeSWF(objIdArr[j]);\r
621                 }\r
622                 // cleanup library's main closures to avoid memory leaks\r
623                 for (var k in ua) {\r
624                     ua[k] = null;\r
625                 }\r
626                 ua = null;\r
627                 for (var l in swfobject) {\r
628                     swfobject[l] = null;\r
629                 }\r
630                 swfobject = null;\r
631             });\r
632         }\r
633     }();\r
634     \r
635     return {\r
636         /* Public API\r
637             - Reference: http://code.google.com/p/swfobject/wiki/documentation\r
638         */ \r
639         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {\r
640             if (ua.w3 && objectIdStr && swfVersionStr) {\r
641                 var regObj = {};\r
642                 regObj.id = objectIdStr;\r
643                 regObj.swfVersion = swfVersionStr;\r
644                 regObj.expressInstall = xiSwfUrlStr;\r
645                 regObj.callbackFn = callbackFn;\r
646                 regObjArr[regObjArr.length] = regObj;\r
647                 setVisibility(objectIdStr, false);\r
648             }\r
649             else if (callbackFn) {\r
650                 callbackFn({success:false, id:objectIdStr});\r
651             }\r
652         },\r
653         \r
654         getObjectById: function(objectIdStr) {\r
655             if (ua.w3) {\r
656                 return getObjectById(objectIdStr);\r
657             }\r
658         },\r
659         \r
660         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {\r
661             var callbackObj = {success:false, id:replaceElemIdStr};\r
662             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {\r
663                 setVisibility(replaceElemIdStr, false);\r
664                 addDomLoadEvent(function() {\r
665                     widthStr += ""; // auto-convert to string\r
666                     heightStr += "";\r
667                     var att = {};\r
668                     if (attObj && typeof attObj === OBJECT) {\r
669                         for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs\r
670                             att[i] = attObj[i];\r
671                         }\r
672                     }\r
673                     att.data = swfUrlStr;\r
674                     att.width = widthStr;\r
675                     att.height = heightStr;\r
676                     var par = {}; \r
677                     if (parObj && typeof parObj === OBJECT) {\r
678                         for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs\r
679                             par[j] = parObj[j];\r
680                         }\r
681                     }\r
682                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {\r
683                         for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs\r
684                             if (typeof par.flashvars != UNDEF) {\r
685                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];\r
686                             }\r
687                             else {\r
688                                 par.flashvars = k + "=" + flashvarsObj[k];\r
689                             }\r
690                         }\r
691                     }\r
692                     if (hasPlayerVersion(swfVersionStr)) { // create SWF\r
693                         var obj = createSWF(att, par, replaceElemIdStr);\r
694                         if (att.id == replaceElemIdStr) {\r
695                             setVisibility(replaceElemIdStr, true);\r
696                         }\r
697                         callbackObj.success = true;\r
698                         callbackObj.ref = obj;\r
699                     }\r
700                     else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install\r
701                         att.data = xiSwfUrlStr;\r
702                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);\r
703                         return;\r
704                     }\r
705                     else { // show alternative content\r
706                         setVisibility(replaceElemIdStr, true);\r
707                     }\r
708                     if (callbackFn) { callbackFn(callbackObj); }\r
709                 });\r
710             }\r
711             else if (callbackFn) { callbackFn(callbackObj); }\r
712         },\r
713         \r
714         switchOffAutoHideShow: function() {\r
715             autoHideShow = false;\r
716         },\r
717         \r
718         ua: ua,\r
719         \r
720         getFlashPlayerVersion: function() {\r
721             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };\r
722         },\r
723         \r
724         hasFlashPlayerVersion: hasPlayerVersion,\r
725         \r
726         createSWF: function(attObj, parObj, replaceElemIdStr) {\r
727             if (ua.w3) {\r
728                 return createSWF(attObj, parObj, replaceElemIdStr);\r
729             }\r
730             else {\r
731                 return undefined;\r
732             }\r
733         },\r
734         \r
735         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {\r
736             if (ua.w3 && canExpressInstall()) {\r
737                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);\r
738             }\r
739         },\r
740         \r
741         removeSWF: function(objElemIdStr) {\r
742             if (ua.w3) {\r
743                 removeSWF(objElemIdStr);\r
744             }\r
745         },\r
746         \r
747         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {\r
748             if (ua.w3) {\r
749                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);\r
750             }\r
751         },\r
752         \r
753         addDomLoadEvent: addDomLoadEvent,\r
754         \r
755         addLoadEvent: addLoadEvent,\r
756         \r
757         getQueryParamValue: function(param) {\r
758             var q = doc.location.search || doc.location.hash;\r
759             if (q) {\r
760                 if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark\r
761                 if (param == null) {\r
762                     return urlEncodeIfNecessary(q);\r
763                 }\r
764                 var pairs = q.split("&");\r
765                 for (var i = 0; i < pairs.length; i++) {\r
766                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {\r
767                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));\r
768                     }\r
769                 }\r
770             }\r
771             return "";\r
772         },\r
773         \r
774         // For internal usage only\r
775         expressInstallCallback: function() {\r
776             if (isExpressInstallActive) {\r
777                 var obj = getElementById(EXPRESS_INSTALL_ID);\r
778                 if (obj && storedAltContent) {\r
779                     obj.parentNode.replaceChild(storedAltContent, obj);\r
780                     if (storedAltContentId) {\r
781                         setVisibility(storedAltContentId, true);\r
782                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }\r
783                     }\r
784                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }\r
785                 }\r
786                 isExpressInstallActive = false;\r
787             } \r
788         }\r
789     };\r
790 }();\r
791 </pre>
792 </body>
793 </html>