//  DEVELOPER NOTES TO SELF:

//  doublecheck alt content stuff.
//  add in flash installation options for ie and such...
//  try to strip methods from attributes for IE.
//  try to figure out what exactly is IE's problem for movies with externalinterface methods exposed to javascript ... 

	//// BEGIN HEADER ////////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	////                                                                                          ////
	////    SWFHANDLER CLASS. V2.0                                                                ////
	////                                                                                          ////
	////    Copyright 2007, Jose Cao-Garcia                                                       ////
	////                                                                                          ////
	////    This software is licensed under the Creative Commons                                  ////
	////    Attribution-ShareAlike 2.5 License:                                                   ////
	////    <http://creativecommons.org/licenses/by-sa/2.5/legalcode>                             ////
	////                                                                                          ////
	////    HELP/INFO/DEVELOPER CONTACT: jose@jcao.com, http://jcao.com                           ////
	////                                                                                          ////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	////                                                                                          ////
	////    SWFHANDLER is a simple, powerful and lightweight JavaScript class that provides       ////
	////    support for flash deployment across all major/modern browsers (as well as Internet    ////
	////    Explorer) via W3C DOM and JavaScript. SWFHANDLER detects for the availability and     ////
	////    version of the shockwave flash plugin, It generates a pure-dom swf object that can    ////
	////    be inserted and manipulated via standard W3C DOM methods. In addition to detecting    ////
	////    the flash plugin and generating SWF objects, this script also provides object-level   ////
	////    support for javascript/flash interaction, via the Flash 'liveconnect' methods         ////
	////    provided by the shockwave flash browser plugin. Finally, this script provides a       ////
	////    flexible mechanism for serving alternate content to browsers with missing or          ////
	////    inadequate flash support. Although this class does not rely on string-based code      ////
	////    insertion by design, a method for markup extraction is provided--however, using       ////
	////    markup for string-based code insertion is recommended against, as it is vastly        ////
	////    inferior to dom based insertion.                                                      ////
	////                                                                                          ////
	////    FOR MORE INFO VISIT: http://jcao.com/scripts/swfHandler/                              ////
	////                                                                                          ////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	//// END HEADER //////////////////////////////////////////////////////////////////////////////////

	//// OBJECT CREATOR FOR WORKING WITH SHOCKWAVE FLASH FILES
		function swfHandler(defaultUrl, defaultOpts, defaultAlt) {
		// error handling for defaults
			if (defaultUrl  && typeof(defaultUrl)  != 'string')  { throw('new swfHandler(url, options): default url for swf movies must be a string');     }
			if (defaultOpts && typeof(defaultOpts) != 'object')  { throw('new swfHandler(url, options): default options for swf movies must be a string'); }
		// root for scope
			var root  = this;
				root.defaultUrl  = defaultUrl  || false;
				root.defaultOpts = defaultOpts || {};
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// TEST FOR FLASH PLUGIN CONSERVATIVELY (RETURNS FALSE IF VERSION INDETERMINATE)           ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			var swfStr     = false;
			var swfValue   = false;
		// msie handholding requred ...
			if (typeof(ActiveXObject) != 'undefined') {
				for (var loop = 0; loop < 50; loop++){
					try {
						var swfAxObj = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.' + loop);
						swfValue = loop;
					} catch(e) {  }
				}
		// for standards-based browsers:
			} else {
			    if (navigator.plugins && navigator.plugins.length > 0) {
					if (navigator.plugins['Shockwave Flash 2.0'])  { swfValue = 2; }
					if (navigator.plugins['Shockwave Flash'])      {
						swfStr = navigator.plugins['Shockwave Flash'].description;
						swfValue = swfStr.split('.')[0].substring(swfStr.split('.')[0].lastIndexOf(' '));
					}
				}
			}
		// set the revision value
			root.rev = swfValue;
		// include an override test
			if (document.location.href.indexOf('flash=false') != -1) { root.rev = false; }
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// CREATES A BASIC SWF OBJECT, AND RETURNS IT                                              ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.movie = function(swfUrl, swfOpts) {
			// set options or introduce defaults
				swfUrl  = swfUrl  || root.defaultUrl;
				swfOpts = swfOpts || {};
			// set altCont and revReq for movie
				var revReq = swfOpts.revReq || root.defaultOpts.revReq || false;
				if (revReq) {
					var altCont = swfOpts.altCont || root.defaultOpts.altCont || false;
				}
			// splice in default values for undeclared
				for (var loop in root.defaultOpts) {
					var propName  = loop;
					var propValue = root.defaultOpts[loop];
					if (typeof(swfOpts[propName]) == 'undefined') { swfOpts[propName] = propValue; }
				}
			// create object and set attributes
				var swfObject   = document.createElement('object');
			// for standards-challenged browsers ...
				if (typeof(ActiveXObject) == 'function') {
					try {
						var embObject = document.createElement('embed');
							embObject = swfObject.appendChild(embObject);
					} catch (e) {
						swfObject = document.createElement('embed');
					}
				}
			// handle fallback content if specified
				if (revReq) {
					if (!root.rev || parseFloat(revReq) > parseFloat(root.rev)) {
						if (altCont) {
							if (typeof(altCont) == 'string')   {
								if ((/\.png$/.test(altCont)) || (/\.jpg$/.test(altCont)) || (/\.jpeg$/.test(altCont)) || (/\.gif$/.test(altCont))) {
								// alternate image content
									swfObject        = document.createElement('img');
									swfObject.src    = altCont;
									swfObject.width  = swfWidth;
									swfObject.height = swfHeight;
								} else if ((/\.html$/.test(altCont)) || (/\.htm$/.test(altCont)) || (/\.shtml$/.test(altCont)) || (/\.asp$/.test(altCont)) || (/\.aspx$/.test(altCont)) || (/\.php$/.test(altCont)) || (/^http/.test(altCont)) || (/^https/.test(altCont)) ) {
								// go to alternative location ...
									parent.location.replace(altCont);
								} else {
								// assume alternate content specified is innerHTML text
									swfObject = altCont;
								}
							} else {
								if (typeof(altCont) == 'function') {
								// assume alternate is function fired
									altCont();
									swfObject = false;
								} else {
								// assume alternate dom content (hope for the best)
									swfObject = altCont;
								}
							}
						} else {
							return false;
						}
					}
				}
			// set params if object supported
				if (swfObject) {
				// add a method for adding new parameters
					swfObject.setParam  = root.setParam;
				// add a method for removing parameters
					swfObject.killParam = root.killParam;
				// register liveconnect methods
					swfObject.getVar    = root.getVar;
					swfObject.setVar    = root.setVar;
					swfObject.goFrame   = root.goFrame;
					swfObject.pause     = root.pause;
					swfObject.play      = root.play;
					swfObject.rewind    = root.rewind;
					swfObject.loadMov   = root.loadMov;
				// add the basic object attributes/parameters
					swfObject.setParam('data',  swfUrl);
					swfObject.setParam('movie', swfUrl);
					swfObject.setParam('src',   swfUrl);
					swfObject.setParam('type', 'application/x-shockwave-flash');
				// set options
					for (var loop in swfOpts) {
						var propName  = loop;
						var propValue = swfOpts[loop];
					// set params, as long as they are not the altCont or reqRev properties
						if (propName != 'altCont' && propName != 'reqRev') { swfObject.setParam(propName, propValue); }
					}
				// add a method for extracting object markup. This should be a 
				// property, but can't, thanks to standards-challenged browsers.
					swfObject.markup   = root.getMarkup;
				}
			// return object
				return swfObject;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD ADDS PARAMS/ATTRIBUTES TO AN SWF OBJECT.                                         ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setParam = function(name, value, killRecursion) {
			// only perform this operation if this is is a flash movie
			// eg: ignore alt content returned for deficient flash support
				if (this.nodeName == 'OBJECT' || this.nodeName == 'EMBED') {
				//  remove preexisting params/attributes first ?
					this.killParam(name, true);
				// set attribute in initial object
					this.setAttribute(name, value);
				// handle child-embed support if there, exclude id to prevent screwing up dom
					if (this.getElementsByTagName('embed').length && name != 'id') {
						this.getElementsByTagName('embed')[0].setAttribute(name, value);
					}
				// support object param elements
					if (this.nodeName != 'EMBED') {
					// add param within object tag
						var param = document.createElement('param');
							param.name  = name;
							param.value = value;
						var param = this.appendChild(param);
					}
				// handle id/name synchronization
					if ((name == 'id' || name == 'name') && !killRecursion) {
						this.setParam((name == 'id') ? 'name' : 'id', value, true);
					}
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD REMOVES PARAMS/ATTRIBUTES FROM AN SWF OBJECT.                                    ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.killParam = function(name, killRecursion) {
			// only perform this operation if this is is a flash movie
			// eg: ignore alt content returned for deficient flash support
				if (this.nodeName == 'OBJECT' || this.nodeName == 'EMBED') {
				// remove attribute from initial object
					this.removeAttribute(name);
				// handle child-embed support if there, exclude id to prevent screwing up dom
					if (this.hasChildNodes() && this.firstChild.nodeName.toLowerCase() == 'embed' && name != 'id') {
						if (this.firstChild.hasAttribute(name)) { this.firstChild.removeAttribute(name) }
					}
				// remove param
					if (this.hasChildNodes()) {
						for (var loop = 0; loop < this.childNodes.length; loop++) {
							if (this.childNodes[loop].nodeName.toLowerCase() == 'param' && this.childNodes[loop].name == name) { this.removeChild(this.childNodes[loop]); }
						}
					}
				// handle id/name synchronization
					if ((name == 'id' || name == 'name') && !killRecursion) {
						this.killParam((name == 'id') ? 'name' : 'id', true);
					}
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// SUPPORTS ACCESS TO THE OBJECT MARKUP. NOTE: STRING BASED INSERTION HAS MAJOR DRAWBACKS. ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.getMarkup =  function() {
				if (this.parentNode) {
					var markup = this.parentNode.innerHTML
				} else {
					var tempDiv = document.createElement('div');
						tempSwf = tempDiv.appendChild(this);
					var markup  = tempDiv.innerHTML;
				}
				return markup;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHODS PROVIDE WAYS TO INTERACT WITH YOUR SWF MOVIE VIA JAVASCRIPT. NO ICAB SUPPORT.   ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			// get value of a variable in a flash movie
			root.getVar = function(varName, swfMovie) {
				swfMovie = root.getObjRef(swfMovie) || this;
				try {
					return swfMovie.GetVariable(varName);
				} catch (e) { return 'undefined'; }
			}
			// set value of a variable in a flash movie
			root.setVar = function(varName, varValue, swfMovie) {
				swfMovie = root.getObjRef(swfMovie) || this;
				try {
					swfMovie.SetVariable(varName, varValue);
				} catch (e) {  }
			}
			// go to a frame number (or label) in a flash movie
			root.goFrame = function(swfFrame, swfLayer, swfMovie) {
				try {
				swfMovie = root.getObjRef(swfMovie) || this;
					var movieLayer = (swfLayer) ? swfLayer : '_level0/';
					if (parseInt(swfFrame) == NaN) {
						swfMovie.TGotoLabel(movieLayer, swfFrame);
					} else {
						swfMovie.TGotoFrame(movieLayer, swfFrame);
					}
				} catch (e) {  }
			}
			// pause playback of a flash movie
			root.pause = function(swfLayer, swfMovie) {
				swfMovie = root.getObjRef(swfMovie) || this;
				try {
					var movieLayer = (swfLayer) ? swfLayer : '_level0/';
					swfMovie.TStopPlay(movieLayer);
				} catch (e) {  }
			}
			// resume playback of a flash movie
			root.play = function(swfLayer, swfMovie) {
				swfMovie = root.getObjRef(swfMovie) || this;
				try {
					var movieLayer = (swfLayer) ? swfLayer : '_level0/';
					swfMovie.TPlay(movieLayer);
				} catch (e) {  }
			}
			// rewind movie, reset variables
			root.rewind = function() {
				swfMovie = root.getObjRef(swfMovie) || this;
				try {
					swfMovie.Rewind();
				} catch (e) {  }
			}
			// load a separate flash movie into a layer of an existing movie
			// set 'newSwf' to false to unload a movie from a particular layer
			root.loadMov = function(layer, newSwf, swfMovie) {
				swfMovie = root.getObjRef(swfMovie) || this;
				newSwf = newSwf || '';
				try {
					swfMovie.LoadMovie(layer, newSwf);
				} catch (e) {  }
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// SUPPORTS THE LIVECONNECT METHODS ABOVE WHEN USED WITH A SWF OBJECT THAT HAS BEEN ADDED  ////
		//// TO THE PAGE VIA STRING BASED MARKUP (obj.innerHTML or document.write()). THIS WILL NOT  ////
		//// WORK IN OMNIWEB, ICAB OR VERSIONS OF OPERA OLDER THAN 9. FOR THIS REASON, STRING BASED  ////
		//// INSERTION IS VASTLY INFERIOR TO DOM BASED INSERTION, AND IS NOT RECCOMMENDED.           ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.getObjRef = function(swfId) {
				var objRef = false;
				if (window.document[swfId])  { objRef = window.document[swfId]; }
				if (typeof(ActiveXObject) != 'undefined') {
					if (document.embeds && document.embeds[swfId]) { objRef =  document.embeds[swfId]; }
				} else {
					objRef = document.getElementById(swfId);
				}
				return objRef;
			}
		// if the browser doesn't support the movie method, don't indicate flash support,
		// as it does the user no benefit to try and insert a movie if they cant see it.
		// It is better to rely on the fallback content if root.movie is unsupported.
			try {
				var testMovie = root.movie('', 1, 1);
			} catch (e) {
				root.rev = false;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// HANDLES AUTOMATED OBJECT-ATTRIBUTE BASED FLASH INSERTION/ALTERNATE CONTENT DISPLAY      ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setAll = function(revReq, postProcess){
			// check for errors
				if (revReq && typeof(revReq) != 'number')                { throw('swf.setAll(revReq, postProcess): revReq must be a number, null, or boolean false'); }
				if (postProcess  && typeof(postProcess)  != 'function')  { throw('swf.setAll(revReq, postProcess): postProcess must be null, or a function!');        }
			// root level object will store references to all replaced movies
				root.allSwfs = [];
			// get all page elements
				var allElements = document.getElementsByTagName('body')[0].getElementsByTagName('*');
			// boolean determines flash or alternate content
				var showFlash = !!(!revReq || root.rev >= revReq);
			// supports building swfOpts objects from element attribute lists
				var objBuilder  = function(thisObj, postProcess) {
				// construct anonymous objed
					var options = {};
				// get attributes and convert to object properties, post process if neccessary
					var attbrs  = thisObj.attributes;
					for (var ii = 0; ii < attbrs.length; ii++) { options[attbrs[ii].name] = attbrs[ii].value; } // choking here ... why?
					if (postProcess) { options = postProcess(options); }
				// do some stuff
					return options;
				}
			// loop through the dom and handle conversions
				for (var i = 0; i<allElements.length; i++) {
					var thisObj = allElements[i];
					var thisOpt = thisObj.getAttribute('swfhandler') || thisObj.getAttribute('swfHandler') || thisObj.getAttribute('SWFHANDLER');
					if (thisOpt) {
						thisOpt = thisOpt.toLowerCase();
					// element is alternate content 
						if (thisOpt == 'altcont')  {
						// keep or kill, show or hide.
							thisObj.style.display   = (showFlash) ? 'none'   : 'block';
							thisObj.style.visiblity = (showFlash) ? 'hidden' : 'visible';
						}
					// element holds a flash movie
						if (thisOpt == 'swfmovie' && showFlash) {
						// div must be visible before we create or insert (webkit bug).
							thisObj.style.display   = 'block';
							thisObj.style.visiblity = 'visible';
						// create swfOpts obj from attributes
							swfOpts = objBuilder(thisObj, postProcess);
						// insert the movie into the DOM
							var thisMovie = root.movie(swfOpts);
							var thisMovie = root.movie(swfOpts.swfUrl, swfOpts);
								thisMovie = thisObj.appendChild(thisMovie);
						}
					}
				}
			}
		}
	// instantiate swfHandler object
		var swf = new swfHandler(false, {allowScriptAccess:'always', swfLiveConnect:'true', quality:'best'});




