//  DEVELOPER NOTES TO SELF:

//  add better support for externalInterface methods

//  doublecheck alt content stuff
//  add in flash installation options for ie and such ...
//  try to strip methods from attributes for IE ... would be nice if we could set markup as a property instead of a method.
//  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 object creator 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.                                                             ////
	////                                                                                          ////
	////    FOR MORE INFO VISIT: http://jcao.com/scripts/swfHandler/                              ////
	////                                                                                          ////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	//// END HEADER //////////////////////////////////////////////////////////////////////////////////




	//// these CSS rules complement the built-in sifr support.
	
	if (document.location.href.indexOf('sifrAdjustMode=true') != -1) {
		document.writeln(' <style type="text/css">                                                          ');
		document.writeln('         span.swfhandler-sifr-replaced  { visibility: visible; display: block;  } ');
		document.writeln('         object.swfhandler-sifr-replaced,                                         ');
		document.writeln('         embed.swfhandler-sifr-replaced { visibility: visible; display: block;  } ');
		document.writeln(' </style>                                                                         ');
	} else {
	
		document.writeln(' <style type="text/css">                                                          ');
		document.writeln('     @media screen {                                                              ');
		document.writeln('         span.swfhandler-sifr-replaced  { visibility: hidden;  display: none;   } ');
		document.writeln('     }                                                                            ');
		document.writeln('     @media print  {                                                              ');
		document.writeln('         span.swfhandler-sifr-replaced  { visibility: visible; display: block; }  ');
		//CODE MODIFIED BY GRAY LOON TO FIX DOUBLE HEADER PRINT ISSUE 8.8.08
		if(navigator.userAgent.search(/msie/i)!= -1) {
		document.writeln('         h1 object, h1 embed { visibility: hidden;  display: block; height: 1px; overflow: hidden; width: 1px; float: right; background: #fff; padding: 5px; color: #fff; margin-top: -1000px; } ');
		} else {
		document.writeln('         h1 object.swfhandler-sifr-replaced, h1 embed.swfhandler-sifr-replaced { visibility: visible; display: block; }   ');
		} 
		//CODE MODIFIED BY GRAY LOON TO FIX DOUBLE HEADER PRINT ISSUE 8.8.08
		document.writeln('     }                                                                            ');
		document.writeln(' </style>                                                                         ');
	
	}



	//// 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 an object'); }
		// some basic setup
			var root             = this;
				root.defaultUrl  = defaultUrl    || false;
				root.defaultOpts = defaultOpts   || {};
				root.scope       = document.body || root.defaultOpts.scope;
				root.allSwfs     = [];
				root.sifrStyles  = {};
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// TEST FOR FLASH PLUGIN CONSERVATIVELY (RETURNS FALSE IF VERSION INDETERMINATE)           ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			var swfStr     = false;
			var swfValue   = false;
		// for standards-challenged browsers:
			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-capable 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 mechanism to force display of alternate content
			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 undecleared
				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 basic 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 custom params
					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 A 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 .. exclude preexisting ids and warn via console if present
					if ((name == 'id' || name == 'name') && !(name == 'id' && document.getElementById(value)) && !killRecursion) {
						this.setParam((name == 'id') ? 'name' : 'id', value, true);
					} else if ((name == 'id' || name == 'name') && (name == 'id' && document.getElementById(value))) {
						try { console.log('swf.setParam: ID \'' + value + '\' allready exists, cannot set as id for movie'); } catch(e) {} //<-- politely warn when preexisting ID prevents ID setting.
					}
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD REMOVES PARAMS/ATTRIBUTES FROM A 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 = this.childNodes.length - 1; loop > -1; 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;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// ADDS FONT-STYLES FOR USE WITH sIFR text                                                 ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.newFont = function(styleName, styleValues) {
				if (!styleName || !styleValues || typeof(styleName) != 'string' || typeof(styleValues) != 'object') {
					throw('swf.sifrStyles: you must specify a styleName, and styleValues');
				} else {
				// set or accept defaults
					root.sifrStyles[styleName] = {
						face             : styleValues.face,
						textalign        : styleValues.textalign        || 'left',
						offsetTop        : styleValues.offsetTop        || 0,
						textcolor        : styleValues.textcolor        || '#000000',
						hovercolor       : styleValues.hovercolor       || styleValues.textcolor || '#000000',
						linkcolor        : styleValues.linkcolor        || styleValues.textcolor || '#000000',
						sifr_url_0       : styleValues.sifr_url_0       || null,
					// these are special properties for adjusting the pre-converted type's dimensions.
						adjFontSize      : styleValues.adjFontSize      || null,
						adjLineHeight    : styleValues.adjLineHeight    || null,
						adjLetterSpacing : styleValues.adjLetterSpacing || null,
						adjWordSpacing   : styleValues.adjWordSpacing   || null
					};
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// CONVERTS AN HTML DIV WITH SWFHANDLER ATTRIBUTES INTO FLASH/ALTERNATE/SIFR CONTENT       ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setOne = function(thisObj, revReq, postProcess) {
			// check for errors
				if (revReq && typeof(revReq) != 'number')                { throw('root.setOne(revReq, postProcess): revReq must be a number, null, or boolean false'); }
				if (postProcess  && typeof(postProcess)  != 'function')  { throw('root.setOne(revReq, postProcess): postProcess must be null, or a function!');        }
			// determine treatment type
				var thisOpt = thisObj.getAttribute('swfhandler');
				if (thisOpt) {
					var treatment = thisOpt.toLowerCase().split(':')[0];
					if (treatment == 'sifrtxt') { revReq = 6; var fontStyle = thisOpt.split(':')[1]; }
				}
			// showFlash boolean determines flash or alternate content
				if (!root.rev) {
					var showFlash = false;
				} else {
					if (!revReq) {
						var showFlash = true;
					} else {
						if (root.rev >= revReq) {
							var showFlash = true;
						} else {
							var showFlash = false;
						}
					}
				}
			// process the dom object into a swf or alternate content
				switch(treatment) {
					case 'sifrtxt':
						root.prepSifr(thisObj, fontStyle, showFlash);
					break;
					case 'swfcont':
						root.prepSwf(thisObj, showFlash, postProcess);
					break;
					case 'altcont':
						root.prepAlt(thisObj, showFlash);
					break;
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// PREPARES SIFR-DESIGNIATED SWFHANDLER ELEMENTS FOR PROCESSING BY root.prepSwf()          ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.prepSifr = function(thisObj, fontStyle, showFlash) {
			// Function that alters visibility of element, once processed by sifr.
			// This is called on delay to prevent FOUC-type display problems
				var showElement = function() { thisObj.style.visibility = 'visible'; }
			// if flash support is there run the conversion.
			// If not just show the default html based copy.
				if (showFlash) {
					if (typeof(root.sifrStyles[fontStyle]) != 'undefined') {
					// first, perform any type-metrics tuning necessary for matching overall type density.
					// this *must* happen first, as it will affect the containment element.
						if (typeof(root.sifrStyles[fontStyle].adjFontSize) == 'undefined'     ) { thisObj.style.fontSize      = root.sifrStyles[fontStyle].adjFontSize;      }
						if (typeof(root.sifrStyles[fontStyle].adjLineHeight) == 'undefined'   ) { thisObj.style.lineHeight    = root.sifrStyles[fontStyle].adjLineHeight;    }
						if (typeof(root.sifrStyles[fontStyle].adjLetterSpacing) == 'undefined') { thisObj.style.letterSpacing = root.sifrStyles[fontStyle].adjLetterSpacing; }
						if (typeof(root.sifrStyles[fontStyle].adjWordSpacing) == 'undefined'  ) { thisObj.style.wordSpacing   = root.sifrStyles[fontStyle].adjWordSpacing;   }
					// construct flashVars string.
						var flashvars  = 'txt='         + escape(thisObj.innerHTML);
							flashvars += '&textalign='  + escape(root.sifrStyles[fontStyle].textalign);
							flashvars += '&offsetTop='  + escape(root.sifrStyles[fontStyle].offsetTop);
							flashvars += '&textcolor='  + escape(root.sifrStyles[fontStyle].textcolor);
							flashvars += '&hovercolor=' + escape(root.sifrStyles[fontStyle].hovercolor);
							flashvars += '&linkcolor='  + escape(root.sifrStyles[fontStyle].linkcolor);
							flashvars += '&w='          + escape(thisObj.offsetWidth);
							flashvars += '&h='          + escape(thisObj.offsetHeight);
							flashvars += '&sifr_url_0=' + escape(root.sifrStyles[fontStyle].sifr_url_0);
					// set attributes
						thisObj.setAttribute('flashvars',  flashvars);
						thisObj.setAttribute('width',      thisObj.offsetWidth);
						thisObj.setAttribute('height',     thisObj.offsetHeight);
						thisObj.setAttribute('url',        root.sifrStyles[fontStyle].face);
						thisObj.setAttribute('wmode',      'transparent');
					// prep fallback content
						thisObj.innerHTML = '<span class="swfhandler-sifr-replaced">' + thisObj.innerHTML + '</span>';
							setTimeout(showElement, 150);
					// prep swf
						root.prepSwf(thisObj, showFlash);
					// return font metrics to normal (so that print metrics remains unaffected by sifr adjustments).
						if (document.location.href.indexOf('sifrAdjustMode=true') == -1) {
							thisObj.style.fontSize      = '';
							thisObj.style.lineHeight    = '';
							thisObj.style.letterSpacing = '';
							thisObj.style.wordSpacing   = '';
						}
					} else {
						throw('swf.prepSifr(): the font style "' + fontStyle + '" is undefined');
					}
				} else {
					showElement();
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// CREATES AND INSERTS SWF MOVIES BASED UPON SWFHANDLER CUSTOM ATTRIBUTES.                 ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.prepSwf = function(thisObj, showFlash, postProcess) {


// START HACK. not sure why this try/catch is necessary.

// IE freaks out when there are multiple sequential calls to root.setAll().
// For some reason, calls the creation function (this) too many times, with bad
// arguments or something. Try catch fixes for now but better to find a more
// complete solution later on when time is not in short supply. 
try{


			// supports building swfOpts objects from element attribute lists
				var objBuilder  = function(thisObj, revReq, postProcess) {
				// construct anonymous objed
					var options = {};
				// get attributes and convert to object properties, post process if neccessary
					var attbrs  = thisObj.attributes;
					for (var ii = attbrs.length-1; ii > -1; ii--) {
						var name  = attbrs[ii].name;
						var value = attbrs[ii].value;
					// exclude illegal attribute names
						if (
							name == 'id'     ||
							name == 'style'  ||
							name == 'objref' ||
							name == 'class'
						) { continue; }
					// set object property for attribute names
						options[name.toLowerCase()] = value;
						options.width = (options.width > 0) ? options.width : thisObj.offsetWidth;
					}
					if (postProcess) { options = postProcess(options); }
					return options;
				}
				if (!showFlash) { 
					thisObj.style.display    = 'none';
					thisObj.style.visibility = 'hidden';
					return;
				} else {
					thisObj.normalize();
					if (!thisObj.getElementsByTagName('object').length &&!thisObj.getElementsByTagName('object').length) {
					// div must be visible before we create or insert (due to webkit bug).
						thisObj.style.display   = 'block';
						thisObj.style.visibility = 'visible';
					// create swfOpts obj from attributes
						var swfOpts = objBuilder(thisObj, postProcess);
					// get url for swf, and append querystring if applicable
					// create swf movie and append to parent, storing reference in object/property indicated
						if (thisObj.getAttribute('objref')) {
							var objRef = thisObj.getAttribute('objref');
							if (typeof(window[objRef]) != 'undefined') {
								try { console.log('changing value of: ' + objRef + ' to swf.movie object reference'); } catch(e) {}
							}
							window[objRef] = root.movie(swfOpts.url, swfOpts);
							window[objRef] = thisObj.appendChild(window[objRef]);
						} else {
					// create swf movie and append to parent
							var thisMovie = root.movie(swfOpts.url, swfOpts);
								thisMovie = thisObj.appendChild(thisMovie);
						}
					}
					thisObj.removeAttribute('swfhandler');
					thisObj.removeAttribute('swfHandler');
				}



// END HACK. 
} catch(e) {}



			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// SHOWS OR HIDES AN ALTERNATE CONTENT ELEMENT BASED UPON PLUGIN VERSION/AVAILABILITY.     ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.prepAlt = function(thisObj, showFlash) {
				thisObj.style.visibility = (showFlash) ? 'hidden' : 'visible';
				thisObj.style.display    = (showFlash) ? 'none'   : 'block';
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// DESTROYS A SWFHANDLER-CREATED MOVIE, KEEPING THE SURROUNDING DIV AND ITS ATTRIBUTES     ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.killOne = function(thisObj) {
				var thisOpt = thisObj.getAttribute('swfhandler');
				if (thisOpt == 'swfcont') {
					thisObj.innerHTML = '';
					thisObj.normalize();
				}
				if (thisOpt == 'altcont') {
					thisObj.style.visibility = 'hidden';
					thisObj.style.display    = 'none';
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// DESTROYS A SWFHANDLER-CREATED MOVIE, KEEPING THE SURROUNDING DIV AND ITS ATTRIBUTES     ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.altOne = function(thisObj) {
				var thisOpt = thisObj.getAttribute('swfhandler').toLowerCase();
				if (thisOpt == 'swfcont') {
					thisObj.innerHTML = '';
					thisObj.normalize();
				}
				if (thisOpt == 'altcont') {
					thisObj.style.visibility = 'visible';
					thisObj.style.display    = 'block';
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// HANDLES AUTOMATED HTML-BASED FLASH/ALTERNATE CONTENT INSERTION AND  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!');        }
			// get all divs
				var allSwfDivs = root.getAll();
			// send each div to processor method
				for (var i in allSwfDivs) {
					var thisSwfDiv = allSwfDivs[i];
					root.setOne(thisSwfDiv, revReq, postProcess);
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// HANDLES AUTOMATED HTML-BASED FLASH/ALTERNATE CONTENT INSERTION AND  DISPLAY             ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.killAll = function(){
			// get all divs
				var allSwfDivs = root.getAll();
			// send each div to processor method
				for (var i in allSwfDivs) {
					var thisSwfDiv = allSwfDivs[i];
					root.killOne(thisSwfDiv);
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// HANDLES AUTOMATED HTML-BASED FLASH/ALTERNATE CONTENT INSERTION AND  DISPLAY             ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.altAll = function(){
			// get all divs
				var allSwfDivs = root.getAll();
			// send each div to processor method
				for (var i in allSwfDivs) {
					var thisSwfDiv = allSwfDivs[i];
					root.altOne(thisSwfDiv);
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// RETURNS AN ARRAY CONTAINING ALL OF THE SWFHANDLER DIVS IN THE DOM                       ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.getAll = function(){
				var allSwfDivs = [];
			// get all page elements
				var allElements = root.scope.getElementsByTagName('*');
			// loop through the dom and handle conversions
				for (var i = 0, thisObj; thisObj = allElements[i]; i++) {
					var thisOpt = thisObj.getAttribute('swfhandler');
					if (thisOpt) {
						allSwfDivs.push(thisObj);
					}
				}
				return allSwfDivs;
			}
		}






