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