Project

General

Profile

« Previous | Next » 

Revision 59824084

Added by Andreas Kohlbecker over 4 years ago

ref #7164 upgrading swfobjetct.js to fix flash detection in chrome and edge

View differences:

modules/cdm_dataportal/fsi_gallery/js/README
1
This is swfobjects derived from a fork (https://github.com/VoiSmart/swfobject).
2
The original repository is no longer being maintained.
3
The bug reported in issue #57 (https://github.com/swfobject/swfobject/issues/57) broke flash movies in chrome and edge.
4
This bug has been fixed in this fork.
modules/cdm_dataportal/fsi_gallery/js/swfobject-debug.js
1
/*!	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
2
	is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
1
/*!    SWFObject v2.3.20130521 <http://github.com/swfobject/swfobject>
2
    is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
3 3
*/
4 4

  
5
var swfobject = function() {
6
	
7
	var UNDEF = "undefined",
8
		OBJECT = "object",
9
		SHOCKWAVE_FLASH = "Shockwave Flash",
10
		SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
11
		FLASH_MIME_TYPE = "application/x-shockwave-flash",
12
		EXPRESS_INSTALL_ID = "SWFObjectExprInst",
13
		ON_READY_STATE_CHANGE = "onreadystatechange",
14
		
15
		win = window,
16
		doc = document,
17
		nav = navigator,
18
		
19
		plugin = false,
20
		domLoadFnArr = [main],
21
		regObjArr = [],
22
		objIdArr = [],
23
		listenersArr = [],
24
		storedAltContent,
25
		storedAltContentId,
26
		storedCallbackFn,
27
		storedCallbackObj,
28
		isDomLoaded = false,
29
		isExpressInstallActive = false,
30
		dynamicStylesheet,
31
		dynamicStylesheetMedia,
32
		autoHideShow = true,
33
	
34
	/* Centralized function for browser feature detection
35
		- User agent string detection is only used when no good alternative is possible
36
		- Is executed directly for optimal performance
37
	*/	
38
	ua = function() {
39
		var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
40
			u = nav.userAgent.toLowerCase(),
41
			p = nav.platform.toLowerCase(),
42
			windows = p ? /win/.test(p) : /win/.test(u),
43
			mac = p ? /mac/.test(p) : /mac/.test(u),
44
			webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
45
			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
46
			playerVersion = [0,0,0],
47
			d = null;
48
		if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
49
			d = nav.plugins[SHOCKWAVE_FLASH].description;
50
			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+
51
				plugin = true;
52
				ie = false; // cascaded feature detection for Internet Explorer
53
				d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
54
				playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
55
				playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
56
				playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
57
			}
58
		}
59
		else if (typeof win.ActiveXObject != UNDEF) {
60
			try {
61
				var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
62
				if (a) { // a will return null when ActiveX is disabled
63
					d = a.GetVariable("$version");
64
					if (d) {
65
						ie = true; // cascaded feature detection for Internet Explorer
66
						d = d.split(" ")[1].split(",");
67
						playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
68
					}
69
				}
70
			}
71
			catch(e) {}
72
		}
73
		return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
74
	}(),
75
	
76
	/* Cross-browser onDomLoad
77
		- Will fire an event as soon as the DOM of a web page is loaded
78
		- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
79
		- Regular onload serves as fallback
80
	*/ 
81
	onDomLoad = function() {
82
		if (!ua.w3) { return; }
83
		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 
84
			callDomLoadFunctions();
85
		}
86
		if (!isDomLoaded) {
87
			if (typeof doc.addEventListener != UNDEF) {
88
				doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
89
			}		
90
			if (ua.ie && ua.win) {
91
				doc.attachEvent(ON_READY_STATE_CHANGE, function() {
92
					if (doc.readyState == "complete") {
93
						doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
94
						callDomLoadFunctions();
95
					}
96
				});
97
				if (win == top) { // if not inside an iframe
98
					(function(){
99
						if (isDomLoaded) { return; }
100
						try {
101
							doc.documentElement.doScroll("left");
102
						}
103
						catch(e) {
104
							setTimeout(arguments.callee, 0);
105
							return;
106
						}
107
						callDomLoadFunctions();
108
					})();
109
				}
110
			}
111
			if (ua.wk) {
112
				(function(){
113
					if (isDomLoaded) { return; }
114
					if (!/loaded|complete/.test(doc.readyState)) {
115
						setTimeout(arguments.callee, 0);
116
						return;
117
					}
118
					callDomLoadFunctions();
119
				})();
120
			}
121
			addLoadEvent(callDomLoadFunctions);
122
		}
123
	}();
124
	
125
	function callDomLoadFunctions() {
126
		if (isDomLoaded) { return; }
127
		try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
128
			var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
129
			t.parentNode.removeChild(t);
130
		}
131
		catch (e) { return; }
132
		isDomLoaded = true;
133
		var dl = domLoadFnArr.length;
134
		for (var i = 0; i < dl; i++) {
135
			domLoadFnArr[i]();
136
		}
137
	}
138
	
139
	function addDomLoadEvent(fn) {
140
		if (isDomLoaded) {
141
			fn();
142
		}
143
		else { 
144
			domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
145
		}
146
	}
147
	
148
	/* Cross-browser onload
149
		- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
150
		- Will fire an event as soon as a web page including all of its assets are loaded 
151
	 */
152
	function addLoadEvent(fn) {
153
		if (typeof win.addEventListener != UNDEF) {
154
			win.addEventListener("load", fn, false);
155
		}
156
		else if (typeof doc.addEventListener != UNDEF) {
157
			doc.addEventListener("load", fn, false);
158
		}
159
		else if (typeof win.attachEvent != UNDEF) {
160
			addListener(win, "onload", fn);
161
		}
162
		else if (typeof win.onload == "function") {
163
			var fnOld = win.onload;
164
			win.onload = function() {
165
				fnOld();
166
				fn();
167
			};
168
		}
169
		else {
170
			win.onload = fn;
171
		}
172
	}
173
	
174
	/* Main function
175
		- Will preferably execute onDomLoad, otherwise onload (as a fallback)
176
	*/
177
	function main() { 
178
		if (plugin) {
179
			testPlayerVersion();
180
		}
181
		else {
182
			matchVersions();
183
		}
184
	}
185
	
186
	/* Detect the Flash Player version for non-Internet Explorer browsers
187
		- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
188
		  a. Both release and build numbers can be detected
189
		  b. Avoid wrong descriptions by corrupt installers provided by Adobe
190
		  c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
191
		- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
192
	*/
193
	function testPlayerVersion() {
194
		var b = doc.getElementsByTagName("body")[0];
195
		var o = createElement(OBJECT);
196
		o.setAttribute("type", FLASH_MIME_TYPE);
197
		var t = b.appendChild(o);
198
		if (t) {
199
			var counter = 0;
200
			(function(){
201
				if (typeof t.GetVariable != UNDEF) {
202
					var d = t.GetVariable("$version");
203
					if (d) {
204
						d = d.split(" ")[1].split(",");
205
						ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
206
					}
207
				}
208
				else if (counter < 10) {
209
					counter++;
210
					setTimeout(arguments.callee, 10);
211
					return;
212
				}
213
				b.removeChild(o);
214
				t = null;
215
				matchVersions();
216
			})();
217
		}
218
		else {
219
			matchVersions();
220
		}
221
	}
222
	
223
	/* Perform Flash Player and SWF version matching; static publishing only
224
	*/
225
	function matchVersions() {
226
		var rl = regObjArr.length;
227
		if (rl > 0) {
228
			for (var i = 0; i < rl; i++) { // for each registered object element
229
				var id = regObjArr[i].id;
230
				var cb = regObjArr[i].callbackFn;
231
				var cbObj = {success:false, id:id};
232
				if (ua.pv[0] > 0) {
233
					var obj = getElementById(id);
234
					if (obj) {
235
						if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
236
							setVisibility(id, true);
237
							if (cb) {
238
								cbObj.success = true;
239
								cbObj.ref = getObjectById(id);
240
								cb(cbObj);
241
							}
242
						}
243
						else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
244
							var att = {};
245
							att.data = regObjArr[i].expressInstall;
246
							att.width = obj.getAttribute("width") || "0";
247
							att.height = obj.getAttribute("height") || "0";
248
							if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
249
							if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
250
							// parse HTML object param element's name-value pairs
251
							var par = {};
252
							var p = obj.getElementsByTagName("param");
253
							var pl = p.length;
254
							for (var j = 0; j < pl; j++) {
255
								if (p[j].getAttribute("name").toLowerCase() != "movie") {
256
									par[p[j].getAttribute("name")] = p[j].getAttribute("value");
257
								}
258
							}
259
							showExpressInstall(att, par, id, cb);
260
						}
261
						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
262
							displayAltContent(obj);
263
							if (cb) { cb(cbObj); }
264
						}
265
					}
266
				}
267
				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)
268
					setVisibility(id, true);
269
					if (cb) {
270
						var o = getObjectById(id); // test whether there is an HTML object element or not
271
						if (o && typeof o.SetVariable != UNDEF) { 
272
							cbObj.success = true;
273
							cbObj.ref = o;
274
						}
275
						cb(cbObj);
276
					}
277
				}
278
			}
279
		}
280
	}
281
	
282
	function getObjectById(objectIdStr) {
283
		var r = null;
284
		var o = getElementById(objectIdStr);
285
		if (o && o.nodeName == "OBJECT") {
286
			if (typeof o.SetVariable != UNDEF) {
287
				r = o;
288
			}
289
			else {
290
				var n = o.getElementsByTagName(OBJECT)[0];
291
				if (n) {
292
					r = n;
293
				}
294
			}
295
		}
296
		return r;
297
	}
298
	
299
	/* Requirements for Adobe Express Install
300
		- only one instance can be active at a time
301
		- fp 6.0.65 or higher
302
		- Win/Mac OS only
303
		- no Webkit engines older than version 312
304
	*/
305
	function canExpressInstall() {
306
		return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
307
	}
308
	
309
	/* Show the Adobe Express Install dialog
310
		- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
311
	*/
312
	function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
313
		isExpressInstallActive = true;
314
		storedCallbackFn = callbackFn || null;
315
		storedCallbackObj = {success:false, id:replaceElemIdStr};
316
		var obj = getElementById(replaceElemIdStr);
317
		if (obj) {
318
			if (obj.nodeName == "OBJECT") { // static publishing
319
				storedAltContent = abstractAltContent(obj);
320
				storedAltContentId = null;
321
			}
322
			else { // dynamic publishing
323
				storedAltContent = obj;
324
				storedAltContentId = replaceElemIdStr;
325
			}
326
			att.id = EXPRESS_INSTALL_ID;
327
			if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
328
			if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
329
			doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
330
			var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
331
				fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
332
			if (typeof par.flashvars != UNDEF) {
333
				par.flashvars += "&" + fv;
334
			}
335
			else {
336
				par.flashvars = fv;
337
			}
338
			// 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,
339
			// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
340
			if (ua.ie && ua.win && obj.readyState != 4) {
341
				var newObj = createElement("div");
342
				replaceElemIdStr += "SWFObjectNew";
343
				newObj.setAttribute("id", replaceElemIdStr);
344
				obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
345
				obj.style.display = "none";
346
				(function(){
347
					if (obj.readyState == 4) {
348
						obj.parentNode.removeChild(obj);
349
					}
350
					else {
351
						setTimeout(arguments.callee, 10);
352
					}
353
				})();
354
			}
355
			createSWF(att, par, replaceElemIdStr);
356
		}
357
	}
358
	
359
	/* Functions to abstract and display alternative content
360
	*/
361
	function displayAltContent(obj) {
362
		if (ua.ie && ua.win && obj.readyState != 4) {
363
			// 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,
364
			// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
365
			var el = createElement("div");
366
			obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
367
			el.parentNode.replaceChild(abstractAltContent(obj), el);
368
			obj.style.display = "none";
369
			(function(){
370
				if (obj.readyState == 4) {
371
					obj.parentNode.removeChild(obj);
372
				}
373
				else {
374
					setTimeout(arguments.callee, 10);
375
				}
376
			})();
377
		}
378
		else {
379
			obj.parentNode.replaceChild(abstractAltContent(obj), obj);
380
		}
381
	} 
382

  
383
	function abstractAltContent(obj) {
384
		var ac = createElement("div");
385
		if (ua.win && ua.ie) {
386
			ac.innerHTML = obj.innerHTML;
387
		}
388
		else {
389
			var nestedObj = obj.getElementsByTagName(OBJECT)[0];
390
			if (nestedObj) {
391
				var c = nestedObj.childNodes;
392
				if (c) {
393
					var cl = c.length;
394
					for (var i = 0; i < cl; i++) {
395
						if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
396
							ac.appendChild(c[i].cloneNode(true));
397
						}
398
					}
399
				}
400
			}
401
		}
402
		return ac;
403
	}
404
	
405
	/* Cross-browser dynamic SWF creation
406
	*/
407
	function createSWF(attObj, parObj, id) {
408
		var r, el = getElementById(id);
409
		if (ua.wk && ua.wk < 312) { return r; }
410
		if (el) {
411
			if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
412
				attObj.id = id;
413
			}
414
			if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
415
				var att = "";
416
				for (var i in attObj) {
417
					if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
418
						if (i.toLowerCase() == "data") {
419
							parObj.movie = attObj[i];
420
						}
421
						else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
422
							att += ' class="' + attObj[i] + '"';
423
						}
424
						else if (i.toLowerCase() != "classid") {
425
							att += ' ' + i + '="' + attObj[i] + '"';
426
						}
427
					}
428
				}
429
				var par = "";
430
				for (var j in parObj) {
431
					if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
432
						par += '<param name="' + j + '" value="' + parObj[j] + '" />';
433
					}
434
				}
435
				el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
436
				objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
437
				r = getElementById(attObj.id);	
438
			}
439
			else { // well-behaving browsers
440
				var o = createElement(OBJECT);
441
				o.setAttribute("type", FLASH_MIME_TYPE);
442
				for (var m in attObj) {
443
					if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
444
						if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
445
							o.setAttribute("class", attObj[m]);
446
						}
447
						else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
448
							o.setAttribute(m, attObj[m]);
449
						}
450
					}
451
				}
452
				for (var n in parObj) {
453
					if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
454
						createObjParam(o, n, parObj[n]);
455
					}
456
				}
457
				el.parentNode.replaceChild(o, el);
458
				r = o;
459
			}
460
		}
461
		return r;
462
	}
463
	
464
	function createObjParam(el, pName, pValue) {
465
		var p = createElement("param");
466
		p.setAttribute("name", pName);	
467
		p.setAttribute("value", pValue);
468
		el.appendChild(p);
469
	}
470
	
471
	/* Cross-browser SWF removal
472
		- Especially needed to safely and completely remove a SWF in Internet Explorer
473
	*/
474
	function removeSWF(id) {
475
		var obj = getElementById(id);
476
		if (obj && obj.nodeName == "OBJECT") {
477
			if (ua.ie && ua.win) {
478
				obj.style.display = "none";
479
				(function(){
480
					if (obj.readyState == 4) {
481
						removeObjectInIE(id);
482
					}
483
					else {
484
						setTimeout(arguments.callee, 10);
485
					}
486
				})();
487
			}
488
			else {
489
				obj.parentNode.removeChild(obj);
490
			}
491
		}
492
	}
493
	
494
	function removeObjectInIE(id) {
495
		var obj = getElementById(id);
496
		if (obj) {
497
			for (var i in obj) {
498
				if (typeof obj[i] == "function") {
499
					obj[i] = null;
500
				}
501
			}
502
			obj.parentNode.removeChild(obj);
503
		}
504
	}
505
	
506
	/* Functions to optimize JavaScript compression
507
	*/
508
	function getElementById(id) {
509
		var el = null;
510
		try {
511
			el = doc.getElementById(id);
512
		}
513
		catch (e) {}
514
		return el;
515
	}
516
	
517
	function createElement(el) {
518
		return doc.createElement(el);
519
	}
520
	
521
	/* Updated attachEvent function for Internet Explorer
522
		- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
523
	*/	
524
	function addListener(target, eventType, fn) {
525
		target.attachEvent(eventType, fn);
526
		listenersArr[listenersArr.length] = [target, eventType, fn];
527
	}
528
	
529
	/* Flash Player and SWF content version matching
530
	*/
531
	function hasPlayerVersion(rv) {
532
		var pv = ua.pv, v = rv.split(".");
533
		v[0] = parseInt(v[0], 10);
534
		v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
535
		v[2] = parseInt(v[2], 10) || 0;
536
		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;
537
	}
538
	
539
	/* Cross-browser dynamic CSS creation
540
		- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
541
	*/	
542
	function createCSS(sel, decl, media, newStyle) {
543
		if (ua.ie && ua.mac) { return; }
544
		var h = doc.getElementsByTagName("head")[0];
545
		if (!h) { return; } // to also support badly authored HTML pages that lack a head element
546
		var m = (media && typeof media == "string") ? media : "screen";
547
		if (newStyle) {
548
			dynamicStylesheet = null;
549
			dynamicStylesheetMedia = null;
550
		}
551
		if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
552
			// create dynamic stylesheet + get a global reference to it
553
			var s = createElement("style");
554
			s.setAttribute("type", "text/css");
555
			s.setAttribute("media", m);
556
			dynamicStylesheet = h.appendChild(s);
557
			if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
558
				dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
559
			}
560
			dynamicStylesheetMedia = m;
561
		}
562
		// add style rule
563
		if (ua.ie && ua.win) {
564
			if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
565
				dynamicStylesheet.addRule(sel, decl);
566
			}
567
		}
568
		else {
569
			if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
570
				dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
571
			}
572
		}
573
	}
574
	
575
	function setVisibility(id, isVisible) {
576
		if (!autoHideShow) { return; }
577
		var v = isVisible ? "visible" : "hidden";
578
		if (isDomLoaded && getElementById(id)) {
579
			getElementById(id).style.visibility = v;
580
		}
581
		else {
582
			createCSS("#" + id, "visibility:" + v);
583
		}
584
	}
585

  
586
	/* Filter to avoid XSS attacks
587
	*/
588
	function urlEncodeIfNecessary(s) {
589
		var regex = /[\\\"<>\.;]/;
590
		var hasBadChars = regex.exec(s) != null;
591
		return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
592
	}
593
	
594
	/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
595
	*/
596
	var cleanup = function() {
597
		if (ua.ie && ua.win) {
598
			window.attachEvent("onunload", function() {
599
				// remove listeners to avoid memory leaks
600
				var ll = listenersArr.length;
601
				for (var i = 0; i < ll; i++) {
602
					listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
603
				}
604
				// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
605
				var il = objIdArr.length;
606
				for (var j = 0; j < il; j++) {
607
					removeSWF(objIdArr[j]);
608
				}
609
				// cleanup library's main closures to avoid memory leaks
610
				for (var k in ua) {
611
					ua[k] = null;
612
				}
613
				ua = null;
614
				for (var l in swfobject) {
615
					swfobject[l] = null;
616
				}
617
				swfobject = null;
618
			});
619
		}
620
	}();
621
	
622
	return {
623
		/* Public API
624
			- Reference: http://code.google.com/p/swfobject/wiki/documentation
625
		*/ 
626
		registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
627
			if (ua.w3 && objectIdStr && swfVersionStr) {
628
				var regObj = {};
629
				regObj.id = objectIdStr;
630
				regObj.swfVersion = swfVersionStr;
631
				regObj.expressInstall = xiSwfUrlStr;
632
				regObj.callbackFn = callbackFn;
633
				regObjArr[regObjArr.length] = regObj;
634
				setVisibility(objectIdStr, false);
635
			}
636
			else if (callbackFn) {
637
				callbackFn({success:false, id:objectIdStr});
638
			}
639
		},
640
		
641
		getObjectById: function(objectIdStr) {
642
			if (ua.w3) {
643
				return getObjectById(objectIdStr);
644
			}
645
		},
646
		
647
		embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
648
			var callbackObj = {success:false, id:replaceElemIdStr};
649
			if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
650
				setVisibility(replaceElemIdStr, false);
651
				addDomLoadEvent(function() {
652
					widthStr += ""; // auto-convert to string
653
					heightStr += "";
654
					var att = {};
655
					if (attObj && typeof attObj === OBJECT) {
656
						for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
657
							att[i] = attObj[i];
658
						}
659
					}
660
					att.data = swfUrlStr;
661
					att.width = widthStr;
662
					att.height = heightStr;
663
					var par = {}; 
664
					if (parObj && typeof parObj === OBJECT) {
665
						for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
666
							par[j] = parObj[j];
667
						}
668
					}
669
					if (flashvarsObj && typeof flashvarsObj === OBJECT) {
670
						for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
671
							if (typeof par.flashvars != UNDEF) {
672
								par.flashvars += "&" + k + "=" + flashvarsObj[k];
673
							}
674
							else {
675
								par.flashvars = k + "=" + flashvarsObj[k];
676
							}
677
						}
678
					}
679
					if (hasPlayerVersion(swfVersionStr)) { // create SWF
680
						var obj = createSWF(att, par, replaceElemIdStr);
681
						if (att.id == replaceElemIdStr) {
682
							setVisibility(replaceElemIdStr, true);
683
						}
684
						callbackObj.success = true;
685
						callbackObj.ref = obj;
686
					}
687
					else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
688
						att.data = xiSwfUrlStr;
689
						showExpressInstall(att, par, replaceElemIdStr, callbackFn);
690
						return;
691
					}
692
					else { // show alternative content
693
						setVisibility(replaceElemIdStr, true);
694
					}
695
					if (callbackFn) { callbackFn(callbackObj); }
696
				});
697
			}
698
			else if (callbackFn) { callbackFn(callbackObj);	}
699
		},
700
		
701
		switchOffAutoHideShow: function() {
702
			autoHideShow = false;
703
		},
704
		
705
		ua: ua,
706
		
707
		getFlashPlayerVersion: function() {
708
			return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
709
		},
710
		
711
		hasFlashPlayerVersion: hasPlayerVersion,
712
		
713
		createSWF: function(attObj, parObj, replaceElemIdStr) {
714
			if (ua.w3) {
715
				return createSWF(attObj, parObj, replaceElemIdStr);
716
			}
717
			else {
718
				return undefined;
719
			}
720
		},
721
		
722
		showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
723
			if (ua.w3 && canExpressInstall()) {
724
				showExpressInstall(att, par, replaceElemIdStr, callbackFn);
725
			}
726
		},
727
		
728
		removeSWF: function(objElemIdStr) {
729
			if (ua.w3) {
730
				removeSWF(objElemIdStr);
731
			}
732
		},
733
		
734
		createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
735
			if (ua.w3) {
736
				createCSS(selStr, declStr, mediaStr, newStyleBoolean);
737
			}
738
		},
739
		
740
		addDomLoadEvent: addDomLoadEvent,
741
		
742
		addLoadEvent: addLoadEvent,
743
		
744
		getQueryParamValue: function(param) {
745
			var q = doc.location.search || doc.location.hash;
746
			if (q) {
747
				if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
748
				if (param == null) {
749
					return urlEncodeIfNecessary(q);
750
				}
751
				var pairs = q.split("&");
752
				for (var i = 0; i < pairs.length; i++) {
753
					if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
754
						return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
755
					}
756
				}
757
			}
758
			return "";
759
		},
760
		
761
		// For internal usage only
762
		expressInstallCallback: function() {
763
			if (isExpressInstallActive) {
764
				var obj = getElementById(EXPRESS_INSTALL_ID);
765
				if (obj && storedAltContent) {
766
					obj.parentNode.replaceChild(storedAltContent, obj);
767
					if (storedAltContentId) {
768
						setVisibility(storedAltContentId, true);
769
						if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
770
					}
771
					if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
772
				}
773
				isExpressInstallActive = false;
774
			} 
775
		}
776
	};
5
/* global ActiveXObject: false */
6

  
7
var swfobject = function () {
8

  
9
    var UNDEF = "undefined",
10
        OBJECT = "object",
11
        SHOCKWAVE_FLASH = "Shockwave Flash",
12
        SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
13
        FLASH_MIME_TYPE = "application/x-shockwave-flash",
14
        EXPRESS_INSTALL_ID = "SWFObjectExprInst",
15
        ON_READY_STATE_CHANGE = "onreadystatechange",
16

  
17
        win = window,
18
        doc = document,
19
        nav = navigator,
20

  
21
        plugin = false,
22
        domLoadFnArr = [],
23
        regObjArr = [],
24
        objIdArr = [],
25
        listenersArr = [],
26
        storedFbContent,
27
        storedFbContentId,
28
        storedCallbackFn,
29
        storedCallbackObj,
30
        isDomLoaded = false,
31
        isExpressInstallActive = false,
32
        dynamicStylesheet,
33
        dynamicStylesheetMedia,
34
        autoHideShow = true,
35
        encodeURIEnabled = false,
36

  
37
    /* Centralized function for browser feature detection
38
        - User agent string detection is only used when no good alternative is possible
39
        - Is executed directly for optimal performance
40
    */
41
    ua = function () {
42
        var w3cdom = typeof doc.getElementById !== UNDEF && typeof doc.getElementsByTagName !== UNDEF && typeof doc.createElement !== UNDEF,
43
            u = nav.userAgent.toLowerCase(),
44
            p = nav.platform.toLowerCase(),
45
            windows = p ? /win/.test(p) : /win/.test(u),
46
            mac = p ? /mac/.test(p) : /mac/.test(u),
47
            webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
48
            ie = nav.appName === "Microsoft Internet Explorer",
49
            playerVersion = [0, 0, 0],
50
            d = null;
51
        if (typeof nav.plugins !== UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] === OBJECT) {
52
            d = nav.plugins[SHOCKWAVE_FLASH].description;
53
            // nav.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
54
            if (d && (typeof nav.mimeTypes !== UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
55
                plugin = true;
56
                ie = false; // cascaded feature detection for Internet Explorer
57
                d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
58
                playerVersion[0] = toInt(d.replace(/^(.*)\..*$/, "$1"));
59
                playerVersion[1] = toInt(d.replace(/^.*\.(.*)\s.*$/, "$1"));
60
                playerVersion[2] = /[a-zA-Z]/.test(d) ? toInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1")) : 0;
61
            }
62
        }
63
        else if (typeof win.ActiveXObject !== UNDEF) {
64
            try {
65
                var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
66
                if (a) { // a will return null when ActiveX is disabled
67
                    d = a.GetVariable("$version");
68
                    if (d) {
69
                        ie = true; // cascaded feature detection for Internet Explorer
70
                        d = d.split(" ")[1].split(",");
71
                        playerVersion = [toInt(d[0]), toInt(d[1]), toInt(d[2])];
72
                    }
73
                }
74
            }
75
            catch (e) {}
76
        }
77
        return {w3: w3cdom, pv: playerVersion, wk: webkit, ie: ie, win: windows, mac: mac};
78
    }(),
79

  
80
    /* Cross-browser onDomLoad
81
        - Will fire an event as soon as the DOM of a web page is loaded
82
        - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
83
        - Regular onload serves as fallback
84
    */
85
    onDomLoad = function () {
86
        if (!ua.w3) { return; }
87
        if ((typeof doc.readyState !== UNDEF && (doc.readyState === "complete" || doc.readyState === "interactive")) || (typeof doc.readyState === UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
88
            callDomLoadFunctions();
89
        }
90
        if (!isDomLoaded) {
91
            if (typeof doc.addEventListener !== UNDEF) {
92
                doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
93
            }
94
            if (ua.ie) {
95
                doc.attachEvent(ON_READY_STATE_CHANGE, function detach() {
96
                    if (doc.readyState === "complete") {
97
                        doc.detachEvent(ON_READY_STATE_CHANGE, detach);
98
                        callDomLoadFunctions();
99
                    }
100
                });
101
                if (win == top) { // if not inside an iframe
102
                    (function checkDomLoadedIE() {
103
                        if (isDomLoaded) { return; }
104
                        try {
105
                            doc.documentElement.doScroll("left");
106
                        }
107
                        catch (e) {
108
                            setTimeout(checkDomLoadedIE, 0);
109
                            return;
110
                        }
111
                        callDomLoadFunctions();
112
                    }());
113
                }
114
            }
115
            if (ua.wk) {
116
                (function checkDomLoadedWK() {
117
                    if (isDomLoaded) { return; }
118
                    if (!/loaded|complete/.test(doc.readyState)) {
119
                        setTimeout(checkDomLoadedWK, 0);
120
                        return;
121
                    }
122
                    callDomLoadFunctions();
123
                }());
124
            }
125
        }
126
    }();
127

  
128
    function callDomLoadFunctions() {
129
        if (isDomLoaded || !document.getElementsByTagName("body")[0]) { return; }
130
        try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
131
            var t, span = createElement("span");
132
            span.style.display = "none"; //hide the span in case someone has styled spans via CSS
133
            t = doc.getElementsByTagName("body")[0].appendChild(span);
134
            t.parentNode.removeChild(t);
135
            t = null; //clear the variables
136
            span = null;
137
        }
138
        catch (e) { return; }
139
        isDomLoaded = true;
140
        var dl = domLoadFnArr.length;
141
        for (var i = 0; i < dl; i++) {
142
            domLoadFnArr[i]();
143
        }
144
    }
145

  
146
    function addDomLoadEvent(fn) {
147
        if (isDomLoaded) {
148
            fn();
149
        }
150
        else {
151
            domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
152
        }
153
    }
154

  
155
    /* Cross-browser onload
156
        - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
157
        - Will fire an event as soon as a web page including all of its assets are loaded
158
     */
159
    function addLoadEvent(fn) {
160
        if (typeof win.addEventListener !== UNDEF) {
161
            win.addEventListener("load", fn, false);
162
        }
163
        else if (typeof doc.addEventListener !== UNDEF) {
164
            doc.addEventListener("load", fn, false);
165
        }
166
        else if (typeof win.attachEvent !== UNDEF) {
167
            addListener(win, "onload", fn);
168
        }
169
        else if (typeof win.onload === "function") {
170
            var fnOld = win.onload;
171
            win.onload = function () {
172
                fnOld();
173
                fn();
174
            };
175
        }
176
        else {
177
            win.onload = fn;
178
        }
179
    }
180

  
181
    /* Detect the Flash Player version for non-Internet Explorer browsers
182
        - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
183
          a. Both release and build numbers can be detected
184
          b. Avoid wrong descriptions by corrupt installers provided by Adobe
185
          c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
186
        - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
187
    */
188
    function testPlayerVersion() {
189
        var b = doc.getElementsByTagName("body")[0];
190
        var o = createElement(OBJECT);
191
        o.setAttribute("style", "visibility: hidden;");
192
        o.setAttribute("type", FLASH_MIME_TYPE);
193
        var t = b.appendChild(o);
194
        if (t) {
195
            var counter = 0;
196
            (function checkGetVariable() {
197
                if (typeof t.GetVariable !== UNDEF) {
198
                    try {
199
                        var d = t.GetVariable("$version");
200
                        if (d) {
201
                            d = d.split(" ")[1].split(",");
202
                            ua.pv = [toInt(d[0]), toInt(d[1]), toInt(d[2])];
203
                        }
204
                    } catch (e) {
205
                        //t.GetVariable("$version") is known to fail in Flash Player 8 on Firefox
206
                        //If this error is encountered, assume FP8 or lower. Time to upgrade.
207
                        ua.pv = [8, 0, 0];
208
                    }
209
                }
210
                else if (counter < 10) {
211
                    counter++;
212
                    setTimeout(checkGetVariable, 10);
213
                    return;
214
                }
215
                b.removeChild(o);
216
                t = null;
217
                matchVersions();
218
            }());
219
        }
220
        else {
221
            matchVersions();
222
        }
223
    }
224

  
225
    /* Perform Flash Player and SWF version matching; static publishing only
226
    */
227
    function matchVersions() {
228
        var rl = regObjArr.length;
229
        if (rl > 0) {
230
            for (var i = 0; i < rl; i++) { // for each registered object element
231
                var id = regObjArr[i].id;
232
                var cb = regObjArr[i].callbackFn;
233
                var cbObj = {success: false, id: id};
234
                if (ua.pv[0] > 0) {
235
                    var obj = getElementById(id);
236
                    if (obj) {
237
                        if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
238
                            setVisibility(id, true);
239
                            if (cb) {
240
                                cbObj.success = true;
241
                                cbObj.ref = getObjectById(id);
242
                                cbObj.id = id;
243
                                cb(cbObj);
244
                            }
245
                        }
246
                        else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
247
                            var att = {};
248
                            att.data = regObjArr[i].expressInstall;
249
                            att.width = obj.getAttribute("width") || "0";
250
                            att.height = obj.getAttribute("height") || "0";
251
                            if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
252
                            if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
253
                            // parse HTML object param element's name-value pairs
254
                            var par = {};
255
                            var p = obj.getElementsByTagName("param");
256
                            var pl = p.length;
257
                            for (var j = 0; j < pl; j++) {
258
                                if (p[j].getAttribute("name").toLowerCase() !== "movie") {
259
                                    par[p[j].getAttribute("name")] = p[j].getAttribute("value");
260
                                }
261
                            }
262
                            showExpressInstall(att, par, id, cb);
263
                        }
264
                        else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display fallback content instead of SWF
265
                            displayFbContent(obj);
266
                            if (cb) { cb(cbObj); }
267
                        }
268
                    }
269
                }
270
                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 fallback content)
271
                    setVisibility(id, true);
272
                    if (cb) {
273
                        var o = getObjectById(id); // test whether there is an HTML object element or not
274
                        if (o && typeof o.SetVariable !== UNDEF) {
275
                            cbObj.success = true;
276
                            cbObj.ref = o;
277
                            cbObj.id = o.id;
278
                        }
279
                        cb(cbObj);
280
                    }
281
                }
282
            }
283
        }
284
    }
285

  
286
    /* Main function
287
        - Will preferably execute onDomLoad, otherwise onload (as a fallback)
288
    */
289
    domLoadFnArr[0] = function () {
290
        if (plugin) {
291
            testPlayerVersion();
292
        }
293
        else {
294
            matchVersions();
295
        }
296
    };
297

  
298
    function getObjectById(objectIdStr) {
299
        var r = null,
300
            o = getElementById(objectIdStr);
301

  
302
        if (o && o.nodeName.toUpperCase() === "OBJECT") {
303
            //If targeted object is valid Flash file
304
            if (typeof o.SetVariable !== UNDEF) {
305
                r = o;
306
            } else {
307
                //If SetVariable is not working on targeted object but a nested object is
308
                //available, assume classic nested object markup. Return nested object.
309

  
310
                //If SetVariable is not working on targeted object and there is no nested object,
311
                //return the original object anyway. This is probably new simplified markup.
312

  
313
                r = o.getElementsByTagName(OBJECT)[0] || o;
314
            }
315
        }
316

  
317
        return r;
318
    }
319

  
320
    /* Requirements for Adobe Express Install
321
        - only one instance can be active at a time
322
        - fp 6.0.65 or higher
323
        - Win/Mac OS only
324
        - no Webkit engines older than version 312
325
    */
326
    function canExpressInstall() {
327
        return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
328
    }
329

  
330
    /* Show the Adobe Express Install dialog
331
        - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
332
    */
333
    function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
334

  
335
        var obj = getElementById(replaceElemIdStr);
336

  
337
        //Ensure that replaceElemIdStr is really a string and not an element
338
        replaceElemIdStr = getId(replaceElemIdStr);
339

  
340
        isExpressInstallActive = true;
341
        storedCallbackFn = callbackFn || null;
342
        storedCallbackObj = {success: false, id: replaceElemIdStr};
343

  
344
        if (obj) {
345
            if (obj.nodeName.toUpperCase() === "OBJECT") { // static publishing
346
                storedFbContent = abstractFbContent(obj);
347
                storedFbContentId = null;
348
            }
349
            else { // dynamic publishing
350
                storedFbContent = obj;
351
                storedFbContentId = replaceElemIdStr;
352
            }
353
            att.id = EXPRESS_INSTALL_ID;
354
            if (typeof att.width === UNDEF || (!/%$/.test(att.width) && toInt(att.width) < 310)) { att.width = "310"; }
355
            if (typeof att.height === UNDEF || (!/%$/.test(att.height) && toInt(att.height) < 137)) { att.height = "137"; }
356
            var pt = ua.ie ? "ActiveX" : "PlugIn",
357
                fv = "MMredirectURL=" + encodeURIComponent(win.location.toString().replace(/&/g, "%26")) + "&MMplayerType=" + pt + "&MMdoctitle=" + encodeURIComponent(doc.title.slice(0, 47) + " - Flash Player Installation");
358
            if (typeof par.flashvars !== UNDEF) {
359
                par.flashvars += "&" + fv;
360
            }
361
            else {
362
                par.flashvars = fv;
363
            }
364
            // 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,
365
            // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
366
            if (ua.ie && obj.readyState != 4) {
367
                var newObj = createElement("div");
368
                replaceElemIdStr += "SWFObjectNew";
369
                newObj.setAttribute("id", replaceElemIdStr);
370
                obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
371
                obj.style.display = "none";
372
                removeSWF(obj); //removeSWF accepts elements now
373
            }
374
            createSWF(att, par, replaceElemIdStr);
375
        }
376
    }
377

  
378
    /* Functions to abstract and display fallback content
379
    */
380
    function displayFbContent(obj) {
381
        if (ua.ie && obj.readyState != 4) {
382
            // 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,
383
            // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
384
            obj.style.display = "none";
385
            var el = createElement("div");
386
            obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the fallback content
387
            el.parentNode.replaceChild(abstractFbContent(obj), el);
388
            removeSWF(obj); //removeSWF accepts elements now
389
        }
390
        else {
391
            obj.parentNode.replaceChild(abstractFbContent(obj), obj);
392
        }
393
    }
394

  
395
    function abstractFbContent(obj) {
396
        var ac = createElement("div");
397
        if (ua.win && ua.ie) {
398
            ac.innerHTML = obj.innerHTML;
399
        }
400
        else {
401
            var nestedObj = obj.getElementsByTagName(OBJECT)[0];
402
            if (nestedObj) {
403
                var c = nestedObj.childNodes;
404
                if (c) {
405
                    var cl = c.length;
406
                    for (var i = 0; i < cl; i++) {
407
                        if (!(c[i].nodeType == 1 && c[i].nodeName === "PARAM") && !(c[i].nodeType == 8)) {
408
                            ac.appendChild(c[i].cloneNode(true));
409
                        }
410
                    }
411
                }
412
            }
413
        }
414
        return ac;
415
    }
416

  
417
    function createIeObject(url, paramStr) {
418
        var div = createElement("div");
419
        div.innerHTML = "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'><param name='movie' value='" + url + "'>" + paramStr + "</object>";
420
        return div.firstChild;
421
    }
422

  
423
    /* Cross-browser dynamic SWF creation
424
    */
425
    function createSWF(attObj, parObj, id) {
426
        var r, el = getElementById(id);
427
        id = getId(id); // ensure id is truly an ID and not an element
428

  
429
        if (ua.wk && ua.wk < 312) { return r; }
430

  
431
        if (el) {
432
            var o = (ua.ie) ? createElement("div") : createElement(OBJECT),
433
                attr,
434
                attrLower,
435
                param;
436

  
437
            if (typeof attObj.id === UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the fallback content
438
                attObj.id = id;
439
            }
440

  
441
            //Add params
442
            for (param in parObj) {
443
                //filter out prototype additions from other potential libraries and IE specific param element
444
                if (parObj.hasOwnProperty(param) && param.toLowerCase() !== "movie") {
445
                    createObjParam(o, param, parObj[param]);
446
                }
447
            }
448

  
449
            //Create IE object, complete with param nodes
450
            if (ua.ie) { o = createIeObject(attObj.data, o.innerHTML); }
451

  
452
            //Add attributes to object
453
            for (attr in attObj) {
454
                if (attObj.hasOwnProperty(attr)) { // filter out prototype additions from other potential libraries
455
                    attrLower = attr.toLowerCase();
456

  
457
                    // 'class' is an ECMA4 reserved keyword
458
                    if (attrLower === "styleclass") {
459
                        o.setAttribute("class", attObj[attr]);
460
                    } else if (attrLower !== "classid" && attrLower !== "data") {
461
                        o.setAttribute(attr, attObj[attr]);
462
                    }
463
                }
464
            }
465

  
466
            if (ua.ie) {
467
                objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
468
            } else {
469
                o.setAttribute("type", FLASH_MIME_TYPE);
470
                o.setAttribute("data", attObj.data);
471
            }
472

  
473
            el.parentNode.replaceChild(o, el);
474
            r = o;
475
        }
476

  
477
        return r;
478
    }
479

  
480
    function createObjParam(el, pName, pValue) {
481
        var p = createElement("param");
482
        p.setAttribute("name", pName);
483
        p.setAttribute("value", pValue);
484
        el.appendChild(p);
485
    }
486

  
487
    /* Cross-browser SWF removal
488
        - Especially needed to safely and completely remove a SWF in Internet Explorer
489
    */
490
    function removeSWF(id) {
491
        var obj = getElementById(id);
492
        if (obj && obj.nodeName.toUpperCase() === "OBJECT") {
493
            if (ua.ie) {
494
                obj.style.display = "none";
495
                (function removeSWFInIE() {
496
                    if (obj.readyState == 4) {
497
                        //This step prevents memory leaks in Internet Explorer
498
                        for (var i in obj) {
499
                            if (typeof obj[i] === "function") {
500
                                obj[i] = null;
501
                            }
502
                        }
503
                        obj.parentNode.removeChild(obj);
504
                    } else {
505
                        setTimeout(removeSWFInIE, 10);
506
                    }
507
                }());
508
            }
509
            else {
510
                obj.parentNode.removeChild(obj);
511
            }
512
        }
513
    }
514

  
515
    function isElement(id) {
516
        return (id && id.nodeType && id.nodeType === 1);
517
    }
518

  
519
    function getId(thing) {
520
        return (isElement(thing)) ? thing.id : thing;
521
    }
522

  
523
    /* Functions to optimize JavaScript compression
524
    */
525
    function getElementById(id) {
526

  
527
        //Allow users to pass an element OR an element's ID
528
        if (isElement(id)) { return id; }
529

  
530
        var el = null;
531
        try {
532
            el = doc.getElementById(id);
533
        }
534
        catch (e) {}
535
        return el;
536
    }
537

  
538
    function createElement(el) {
539
        return doc.createElement(el);
540
    }
541

  
542
    //To aid compression; replaces 14 instances of pareseInt with radix
543
    function toInt(str) {
544
        return parseInt(str, 10);
545
    }
546

  
547
    /* Updated attachEvent function for Internet Explorer
548
        - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
549
    */
550
    function addListener(target, eventType, fn) {
551
        target.attachEvent(eventType, fn);
552
        listenersArr[listenersArr.length] = [target, eventType, fn];
553
    }
554

  
555
    /* Flash Player and SWF content version matching
556
    */
557
    function hasPlayerVersion(rv) {
558
        rv += ""; //Coerce number to string, if needed.
559
        var pv = ua.pv, v = rv.split(".");
560
        v[0] = toInt(v[0]);
561
        v[1] = toInt(v[1]) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
562
        v[2] = toInt(v[2]) || 0;
563
        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;
564
    }
565

  
566
    /* Cross-browser dynamic CSS creation
567
        - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
568
    */
569
    function createCSS(sel, decl, media, newStyle) {
570
        var h = doc.getElementsByTagName("head")[0];
571
        if (!h) { return; } // to also support badly authored HTML pages that lack a head element
572
        var m = (typeof media === "string") ? media : "screen";
573
        if (newStyle) {
574
            dynamicStylesheet = null;
575
            dynamicStylesheetMedia = null;
576
        }
577
        if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
578
            // create dynamic stylesheet + get a global reference to it
579
            var s = createElement("style");
580
            s.setAttribute("type", "text/css");
581
            s.setAttribute("media", m);
582
            dynamicStylesheet = h.appendChild(s);
583
            if (ua.ie && typeof doc.styleSheets !== UNDEF && doc.styleSheets.length > 0) {
584
                dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
585
            }
586
            dynamicStylesheetMedia = m;
587
        }
588
        // add style rule
589
        if (dynamicStylesheet) {
590
            if (typeof dynamicStylesheet.addRule !== UNDEF) {
591
                dynamicStylesheet.addRule(sel, decl);
592
            } else if (typeof doc.createTextNode !== UNDEF) {
593
                dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
594
            }
595
        }
596
    }
597

  
598
    function setVisibility(id, isVisible) {
599
        if (!autoHideShow) { return; }
600
        var v = isVisible ? "visible" : "hidden",
601
            el = getElementById(id);
602
        if (isDomLoaded && el) {
603
            el.style.visibility = v;
604
        } else if (typeof id === "string") {
605
            createCSS("#" + id, "visibility:" + v);
606
        }
607
    }
608

  
609
    /* Filter to avoid XSS attacks
610
    */
611
    function urlEncodeIfNecessary(s) {
612
        var regex = /[\\\"<>\.;]/;
613
        var hasBadChars = regex.exec(s) !== null;
614
        return hasBadChars && typeof encodeURIComponent !== UNDEF ? encodeURIComponent(s) : s;
615
    }
616

  
617
    /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
618
    */
619
    var cleanup = function () {
620
        if (ua.ie) {
621
            window.attachEvent("onunload", function () {
622
                // remove listeners to avoid memory leaks
623
                var ll = listenersArr.length;
624
                for (var i = 0; i < ll; i++) {
625
                    listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
626
                }
627
                // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
628
                var il = objIdArr.length;
629
                for (var j = 0; j < il; j++) {
630
                    removeSWF(objIdArr[j]);
631
                }
632
                // cleanup library's main closures to avoid memory leaks
633
                for (var k in ua) {
634
                    ua[k] = null;
635
                }
636
                ua = null;
637
                for (var l in swfobject) {
638
                    swfobject[l] = null;
639
                }
640
                swfobject = null;
641
            });
642
        }
643
    }();
644

  
645
    return {
646
        /* Public API
647
            - Reference: http://code.google.com/p/swfobject/wiki/documentation
648
        */
649
        registerObject: function (objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
650
            if (ua.w3 && objectIdStr && swfVersionStr) {
651
                var regObj = {};
652
                regObj.id = objectIdStr;
653
                regObj.swfVersion = swfVersionStr;
654
                regObj.expressInstall = xiSwfUrlStr;
655
                regObj.callbackFn = callbackFn;
656
                regObjArr[regObjArr.length] = regObj;
657
                setVisibility(objectIdStr, false);
658
            }
659
            else if (callbackFn) {
660
                callbackFn({success: false, id: objectIdStr});
661
            }
662
        },
663

  
664
        getObjectById: function (objectIdStr) {
665
            if (ua.w3) {
666
                return getObjectById(objectIdStr);
667
            }
668
        },
669

  
670
        embedSWF: function (swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
671

  
672
            var id = getId(replaceElemIdStr),
673
                callbackObj = {success: false, id: id};
674

  
675
            if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
676
                setVisibility(id, false);
677
                addDomLoadEvent(function () {
678
                    widthStr += ""; // auto-convert to string
679
                    heightStr += "";
680
                    var att = {};
681
                    if (attObj && typeof attObj === OBJECT) {
682
                        for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
683
                            att[i] = attObj[i];
684
                        }
685
                    }
686
                    att.data = swfUrlStr;
687
                    att.width = widthStr;
688
                    att.height = heightStr;
689
                    var par = {};
690
                    if (parObj && typeof parObj === OBJECT) {
691
                        for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
692
                            par[j] = parObj[j];
693
                        }
694
                    }
695
                    if (flashvarsObj && typeof flashvarsObj === OBJECT) {
696
                        for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
697
                            if (flashvarsObj.hasOwnProperty(k)) {
698

  
699
                                var key = (encodeURIEnabled) ? encodeURIComponent(k) : k,
700
                                    value = (encodeURIEnabled) ? encodeURIComponent(flashvarsObj[k]) : flashvarsObj[k];
701

  
702
                                if (typeof par.flashvars !== UNDEF) {
703
                                    par.flashvars += "&" + key + "=" + value;
704
                                }
705
                                else {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff