//  DEVELOPER NOTES TO SELF:

//  add better support for externalInterface methods

//  find a way to save/replace innerHTML for flash movies.

// sifr support

// set up object references for flash movies.

// test externalinterface methods

// add in liveconnect methods

// swfaddress support?

// set up intelligent transfer of querystrings to flashvars, and also add an option to carry over querystrings.

//  set up object referenceces returned by browser etc ...
//  test movies with externalInterface methods exposed
//  set up and test the liveconnect methods.

	//// BEGIN HEADER ////////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////////////////////////
	////                                                                                          ////
	////    SWFHANDLER CLASS. V3.0                                                                ////
	////                                                                                          ////
	////    Copyright 2008, 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('         embed.swfhandler-sifr-replaced { margin: 0px; padding: 0px; position: none; } ');
			document.writeln('     }                                                                                 ');
			document.writeln('     @media print  {                                                                   ');
			document.writeln('         span.swfhandler-sifr-replaced  { visibility: visible; display: inline; }      ');
			document.writeln('         object.swfhandler-sifr-replaced,                                              ');
			document.writeln('         embed.swfhandler-sifr-replaced { visibility: hidden;  display: none;   }      ');
			document.writeln('     }                                                                                 ');
			document.writeln(' </style>                                                                              ');
		}

	//// OBJECT CREATOR FOR WORKING WITH SHOCKWAVE FLASH FILES
		function swfHandler(defaults, scope) {
		// error handling for defaults
			if (defaults && typeof(defaults) != 'object')  { throw('new swfHandler(defaults): default options for swf movies must be an object'); }
		// root for scope, and default swf attributes
			var root             = this;
				root.scope       = scope    || document.body;
				root.defaults    = defaults || {
					align             : 'middle',
					allowScriptAccess : 'sameDomain',
					quality           : 'high',
					type              : 'application/x-shockwave-flash',
					pluginspage       : 'http://www.adobe.com/go/getflashplayer'
				};
				root.fontStyles       = [];
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// DICTIONARY OF RULES FOR APPLYING/VALIDATING SWF OBJECT PROPERTIES                       ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.propDict = {
			// these properties describe application rules for html object/embed/param attributes,
			// altering them will alter the flash object markup this script produces. Be careful...
				markupProps : {
					align             : { applyTo:{ OBJECT: true,  PARAM: true,  EMBED: false }, valueType:'string', values:['left', 'top', 'right', 'bottom', 'middle'] },   // <-- (attribute for Object) - Possible values: l, t, r, b.
					allowScriptAccess : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string', values:['always', 'never', 'sameDomain'] },              // <-- Sets permissions for scripting acess across domains.
					base              : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string:url' },                                                    // <-- Specifies the base directory or URL used to resolve all relative path statements in the Flash Player movie.
					bgcolor           : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string:hexadecimal' },                                            // <-- Specifies the background color of the movie/player.
					classid           : { applyTo:{ OBJECT: false, PARAM: false, EMBED: true  }, valueType:'string' },                                                        // <-- identifies the ActiveX control for the browser.
					codebase          : { applyTo:{ OBJECT: false, PARAM: false, EMBED: true  }, valueType:'string:url' },                                                    // <-- url of the Flash Player ActiveX control for automatic installation on windows.
					flashvars         : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string' },                                                        // <-- name-value pairs to pass into the flash movie.
					height            : { applyTo:{ OBJECT: true,  PARAM: false, EMBED: true  }, valueType:'number' },                                                        // <-- specifies hidth in pixels.
					id                : { applyTo:{ OBJECT: true,  PARAM: true,  EMBED: false }, valueType:'string' },                                                        // <-- (attribute for object, object only) - Movie Identifier. Identifies the Flash movie to the host environment (a web browser, for example) so that it can be referenced using a scripting language.
					loop              : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'boolean' },                                                       // <-- Should the movie repeat indefinitely? Default value is true if omitted.
					menu              : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'boolean' },                                                       // <-- ??
					movie             : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: false }, valueType:'string:url' },                                                    // <-- Specifies the location (URL) of the movie to be loaded.
					name              : { applyTo:{ OBJECT: false, PARAM: false, EMBED: true  }, valueType:'string' },                                                        // <-- Identifies the Flash movie to the host environment so that it can be referenced using JavaScript.
					play              : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'boolean' },                                                       // <-- Should the movie begins playing immediately on loading in the browser? Default is true if omitted.
					pluginspage       : { applyTo:{ OBJECT: true,  PARAM: true,  EMBED: false }, valueType:'string' },                                                        // <-- url of the Flash Player ActiveX control for automatic installation on windows Identifies the location of the Flash Player plug-in so that the user can download it if it is not already installed. EMBED only. (See example code in TechNote tn_4150 for the correct value.)
					quality           : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string', values:['low', 'high', 'autolow', 'autohigh', 'best'] }, // <-- Sets playback quality..
					salign            : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string', values:['l', 't', 'r', 'b', 'tl', 'tr', 'bl', 'br'] },   // <-- sets movie alignment within flash player.
					scale             : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string', values:['showall', 'noborder', 'exactfit'] },            // <-- determine how movie should scale.
					swliveconnect     : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'boolean' },                                                       // <-- Should the browser start Java when loading the Flash Player? Default is false if omitted. If you use JavaScript and Flash on the same page. Java must be running for the FSCommand to work.
					src               : { applyTo:{ OBJECT: false, PARAM: false, EMBED: true  }, valueType:'string:url' },                                                    // <-- Specifies the location (URL) of the movie to be loaded.
					type              : { applyTo:{ OBJECT: false, PARAM: false, EMBED: true  }, valueType:'string', values:['application/x-shockwave-flash'] },              // <-- sets type for embed object.
					width             : { applyTo:{ OBJECT: true,  PARAM: false, EMBED: true  }, valueType:'number' },                                                        // <-- specifies width in pixels.
					wmode             : { applyTo:{ OBJECT: false, PARAM: true,  EMBED: true  }, valueType:'string', values:['window', 'opaque', 'transparent'] }             // <-- sets the Window Mode property of the Flash movie for transparency, layering, and positioning in the browser.
				},
			// these properties are used by root.movie, for movie creation, but are not passed on
			// into the markup, they indicate how the swf should be treated by the movie creation script.
				objectProps : {
					revreq            : { valueType:'number'     },                                                                                                           // <-- specifies the minimum required flash player version to display movie
					altcont           : { valueType:'string:url' },                                                                                                           // <-- specifies alternate content, in the event that flash support is inadequate
					swfhandler        : { valueType:'string', values:['swfcont', 'altcont', 'sifrtxt:']},                                                                     // <-- used in markup-based insertion, indicates how to handle the flash movie.
					objref            : { valueType:'string'     },                                                                                                           // <-- used to create a window level variable, object reference for a movie.
					url               : { valueType:'string:url' }                                                                                                            // <-- the url of your movie, so you don't have to include it twice.
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// DICTIONARY OF ERRORS THAT CAN BE CALLED BY VARIOUS METHODS WITHIN THE SWFHANDLER.       ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.error = {
				beyondScope  : function(){ throw('swfHandler: you are trying to call swfHandler methods within an element that is beyond the swfHandler\'s scope of influence.'); },
				badType      : function(){ throw(''); },
				badSubType   : function(){ throw(''); },
				badValue     : function(){ throw(''); },
				badProp      : function(){ throw(''); },
				noRevreq     : function(){ throw('swfHandler: no required version indicated in swfOpts object or swfHandler element attributes - you must indicate a minimum required plugin version using the revreq property.'); },
				noUrl        : function(){ throw('swfHandler: no url indicated in swfOpts object or swfHandler element attributes - you must indicate a swf url using the url property.'); },
				altTarget    : function(){ throw('swfHandler: No target element specified to host alternate content. If alternate content is specified as an image, then a target element must be specified for it to be inserted within.'); }
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// ADDS FONT-STYLES FOR USE WITH sIFR TEXT REPLACEMENT                                     ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.newFont = function(styleName, styleValues) {
				if (!styleName || !styleValues || typeof(styleName) != 'string' || typeof(styleValues) != 'object') {
					throw('swf.fontStyles: you must specify a styleName, and styleValues');
				} else {
				// set or accept defaults
					root.fontStyles[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
					};
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD CREATES A BASIC SWF OBJECT, AND RETURNS IT                                       ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.movie = function(swfOpts, target) {
			// validate/process swfOpts?
				swfOpts = root.validateSwfOpts(swfOpts);
			// return swf content or alternate content
				var returnType  = (swf.rev >= swfOpts.revreq) ? 'swfCont' : 'altcont';
			// insert flash or alternate content, set return value to movie reference, or boolean false
				switch(returnType) {
				// return swfContent
					case 'swfCont':
					// default markup for movies
						var swfMarkup = {
							OBJECT : '<object<!--ins-->><!-- children --></object>\n',
							PARAM  : '<!--ins-->',
							EMBED  : '\t<embed<!--ins--> />\n'
						}
						// set all unignored properties
						for (var propName in swfOpts) { if (root.propDict.markupProps[propName]) { swfMarkup = root.setSwfOpt(swfMarkup, propName, swfOpts[propName]); } }
					// process markup ...
						swfMarkup = (typeof(ActiveXObject) == 'function') ? swfMarkup.EMBED : swfMarkup.OBJECT.split('<!-- children -->').join(swfMarkup.PARAM + swfMarkup.EMBED);
						swfMarkup = swfMarkup.split('<!--ins-->').join('');
					// insert in page, and return reference, or return a pure dom element
						if (target) {
							target.innerHTML  = swfMarkup; target.normalize();
							var returnValue   = target.firstChild;
						} else {
							target            = document.createElement('div');
							target.innerHTML  = swfMarkup; target.normalize();
							var returnValue   = target.removeChild(target.firstChild);
						}
					break;
				// return alternate content
					case 'altcont':
						if (swfOpts.altcont) {
						// determine type of alternate content
							var isImg  = (/\.png$|\.jpg$|\.jpeg$|\.gif$/.test(swfOpts.altcont));
							var isUrl  = ((/\.html$|\.htm$|\.shtml$|\.asp$|\.aspx$|\.php$|^http|^https/.test(swfOpts.altcont)));
							var isHTML = (!isImg && !isUrl);
						// insert/forward to alternate content
							if (isImg)  { if (target) { target.innerHTML = '<img src="' + swfOpts.altcont + '" width="' + swfOpts.width + '" height="' + swfOpts.height + '" />'; } else {  root.error.altTarget(); } }
							if (isHTML) { if (target) { taget.innerHTML  = swfOpts.altcont; } else {  root.error.altTarget(); } }
							if (isUrl)  { location.replace(swfOpts.altcont); }
						}
					break;
				}
			return returnValue;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD ADDS PARAMS/ATTRIBUTES TO A SWF OBJECT.                                          //// -- should make this private.
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setSwfOpt = function(swfMarkup, propName, propValue) {
			// get rules
				var applicationRules = root.propDict.markupProps[propName].applyTo;
				var splitStr         = '<!--ins-->';
			// apply attributes
				if (applicationRules.OBJECT)  {
					swfMarkup.OBJECT = swfMarkup.OBJECT.split(splitStr).join(' '+ propName + '="' + propValue + '"' + splitStr);
				}
				if (applicationRules.EMBED)   {
					swfMarkup.EMBED = swfMarkup.EMBED.split(splitStr).join(' '+ propName + '="' + propValue + '"' + splitStr);
				}
				if (applicationRules.PARAM)   {
					swfMarkup.PARAM = swfMarkup.PARAM.split(splitStr).join('\t<param name="' + propName + '" value="' + propValue + '" />\n' + splitStr);
				}
			// send it back
				return swfMarkup;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD VALIDATES/PROCESSES SWF PARAMS/ATTRIBUTES AGAINST DICTIONARY OBJECT RULES.       //// -- should make this private.
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.validateSwfOpts = function(swfOpts) {
			// splice in default values for undecleared
				for (var loop in root.defaults) { if (typeof(swfOpts[loop]) == 'undefined') { swfOpts[loop] = root.defaults[loop]; } }
			// convert url to movie/src property
				if (swfOpts.url) {
					swfOpts.movie = swfOpts.src = swfOpts.url;
				} else {
					root.error.noUrl();
				}
				if (!swfOpts.revreq) { root.error.noRevreq(); }
			// check the final properties
				for (var i in swfOpts) {
				// get name/value
					var propName    = i;
					var propValue   = swfOpts[i];
				// some basic error reporting vars
					var errorString = 'swfHandler: there were some problems with your movie.\n';
					var errorCount  = 0;
				// make sure it is represented
					var isValid     = (root.propDict.markupProps[propName] || root.propDict.objectProps[propName]);
				// return error if property is unknown
					if (!isValid) {
					// unknown property error
						errorCount++;
						errorString += '\t\'' + propName + '\' is an unknown property, I don\'t know how to work with it, so it has been dropped.\n';
						delete swfOpts[propName];
					} else {
						if (isValid)  {
							var rules       = root.propDict.markupProps[propName] || root.propDict.objectProps[propName];
							var majType     = rules.valueType.split(':')[0];
							var minType     = (rules.valueType.indexOf(':') != -1) ? rules.valueType.split(':')[1] : null;
							var legalValues = rules.values || null
						// make sure numbers expressed as strings, are stored as numbers
							if (majType == 'number') { propValue = swfOpts[i] = parseInt(propValue); }
						// begin typing tests
							if (typeof(propValue) != majType) {
							// invalid type error
								errorCount++;
								errorString += '\tThe property, \'' + propName + '\' has been set to the wrong type. It is a ' + typeof(propValue) + ' when it should be a ' + majType + ', so it has been dropped.\n';
								delete swfOpts[propName];
							} else {
								if (legalValues && legalValues.join().indexOf(propValue) == -1) {
								// invalid value error (no match)
									errorCount++;
									errorString += '\tThe value \'' + propValue + '\' for property \'' + propName + '\' is invalid, so it has been dropped. Valid values are "' + legalValues.join('", "') + '" \n';
									delete swfOpts[propName];
								} else if (minType) {
								// invalid value error (fail subtype test)
									switch(minType) {
										case 'url':
											// somehow validate that this is a url/path?
											if (false) {
											// invalid value error (not a url)
												errorCount++;
												errorString += '\tThe value \'' + propValue + '\' for property \'' + propName + '\' is invalid, so it has been dropped. This value must be a url or path such as "http://jcao.com/" or "/media/myMovie.swf".\n';
												delete swfOpts[propName];
											}
										break;
										case 'hexidecimal':
											if (!(/^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$/.test(str))) {
											// invalid value error (not a hex value)
												errorCount++;
												errorString += '\tThe value \'' + propValue + '\' for property \'' + propName + '\' is invalid, so it has been dropped. This value must be a hexidedimal color value such as #FFFFFF.\n';
												delete swfOpts[propName];
											}
										break;
									}
								}
							}
						}
					}
				}
			// warn if there are errors and the console is available.
				if(errorCount) {
					try { console.warn(errorString); } catch(e) {  }
				}
				return swfOpts;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// CONVERTS AN HTML DIV WITH SWFHANDLER ATTRIBUTES INTO FLASH/ALTERNATE CONTENT            ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setOne = function(thisObj, forceAlt) {
			// builds swfOpts objects from element attribute lists
				var objBuilder  = function(thisObj) {
				// construct anonymous obj
					var options = {};
				// get attributes and convert to object properties
					var attbrs  = thisObj.attributes;
					for (var ii = 0; ii < attbrs.length; ii++) { 
						var name  = attbrs[ii].name;
						var value = attbrs[ii].value;
					// skip standard html attribute names
						if (!root.propDict.objectProps[name] && !root.propDict.markupProps[name]) { continue; }
					// set object property for attribute names
						options[name] = value;
					}
					return options;
				}
			// create swfOpts obj from attributes
				var swfOpts = objBuilder(thisObj);
			// create movie and add to dom.
				root.movie(swfOpts, thisObj);
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// CONVERTS AN HTML DIV WITH SWFHANDLER ATTRIBUTES INTO FLASH/ALTERNATE CONTENT            ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setOneSifr = function(thisObj, forceAlt) {
				var textStr     = thisObj.getAttribute('textStr') || escape(thisObj.innerHTML);
				var fontStyle   = thisObj.getAttribute('swfhandler').split(':')[1].split(' ').join('');
				var prntStr     = '<span class="swfhandler-sifr-replaced">' + unescape(textStr) + '</span>';
				if (typeof(root.fontStyles[fontStyle]) != 'undefined' && root.rev >= 6) {
				// prepare for measurement by relasing dimensional styling and restoring / hiding content.
					thisObj.innerHTML        = unescape(textStr);
					thisObj.style.width      = '';
					thisObj.style.height     = '';
					thisObj.style.visibility = 'hidden';
					thisObj.style.display    = 'block';
					thisObj.normalize();
				// store original block dimensions.
					var origWidth            = thisObj.offsetWidth  + 'px';
					var origHeight           = thisObj.offsetHeight + 'px';
				// perform any type-metrics tuning necessary for matching overall type density.
					if (typeof(root.fontStyles[fontStyle].adjFontSize)      != 'undefined') { thisObj.style.fontSize      = root.fontStyles[fontStyle].adjFontSize;      }
					if (typeof(root.fontStyles[fontStyle].adjLineHeight)    != 'undefined') { thisObj.style.lineHeight    = root.fontStyles[fontStyle].adjLineHeight;    }
					if (typeof(root.fontStyles[fontStyle].adjLetterSpacing) != 'undefined') { thisObj.style.letterSpacing = root.fontStyles[fontStyle].adjLetterSpacing; }
					if (typeof(root.fontStyles[fontStyle].adjWordSpacing)   != 'undefined') { thisObj.style.wordSpacing   = root.fontStyles[fontStyle].adjWordSpacing;   }
				// construct flashVars string.
					var flashvars  = 'txt='         + textStr;
						flashvars += '&textalign='  + escape(root.fontStyles[fontStyle].textalign);
						flashvars += '&offsetTop='  + escape(root.fontStyles[fontStyle].offsetTop);
						flashvars += '&textcolor='  + escape(root.fontStyles[fontStyle].textcolor);
						flashvars += '&hovercolor=' + escape(root.fontStyles[fontStyle].hovercolor);
						flashvars += '&linkcolor='  + escape(root.fontStyles[fontStyle].linkcolor);
						flashvars += '&w='          + escape(thisObj.offsetWidth);
						flashvars += '&h='          + escape(thisObj.offsetHeight);
						flashvars += '&sifr_url_0=' + escape(root.fontStyles[fontStyle].sifr_url_0);
				// construct swfOpts object
					var swfOpts = {
						url       : root.fontStyles[fontStyle].face,
						flashvars : flashvars,
						width     : thisObj.offsetWidth,
						height    : thisObj.offsetHeight,
						quality   : 'best',
						wmode     : 'transparent'
					}
				// only convert the element to sifr text if it is visible.
					if (swfOpts.height > 0 && swfOpts.width > 0) {
					// prepare target element
						if (!thisObj.getAttribute('textStr')) { thisObj.setAttribute('textStr', textStr); }
					// write in sifr and show element contents
						thisObj.innerHTML           = ['<embed class="swfhandler-sifr-replaced" type="application/x-shockwave-flash" src="', swfOpts.url, '" quality="', swfOpts.url, '" wmode="', swfOpts.wmode, '" bgcolor="" flashvars="', swfOpts.flashvars, '" width="', swfOpts.width, '" height="', swfOpts.height, '" sifr="true"></embed>', prntStr].join("");
					}
				// clear type metrics manipulation styles
					if (typeof(root.fontStyles[fontStyle].adjFontSize)      != 'undefined') { thisObj.style.fontSize      = ''; }
					if (typeof(root.fontStyles[fontStyle].adjLineHeight)    != 'undefined') { thisObj.style.lineHeight    = ''; }
					if (typeof(root.fontStyles[fontStyle].adjLetterSpacing) != 'undefined') { thisObj.style.letterSpacing = ''; }
					if (typeof(root.fontStyles[fontStyle].adjWordSpacing)   != 'undefined') { thisObj.style.wordSpacing   = ''; }
				// enforce original measured container dimensions, and show.
					thisObj.style.width      = origWidth;
					thisObj.style.height     = ''; thisObj.style.height     = thisObj.offsetHeight;
					thisObj.style.visibility = 'visible';
				}
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// HANDLES AUTOMATED HTML-BASED FLASH/ALTERNATE CONTENT INSERTION AND  DISPLAY             ////
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.setAll = function(subScope, forceAlt, movieType) {
			// get all divs
				var allSwfDivs = root.getAll();
			// send each div to processor method, or sifr processing method
				for (var i in allSwfDivs) {
					var thisSwfDiv = allSwfDivs[i];
					if (typeof(thisSwfDiv) == 'function') { continue; }
					var isSifr     = (/^font\:/).test(thisSwfDiv.getAttribute('swfhandler'));
					if (isSifr) {
						if (!movieType || movieType == 'fonts') {
							if (thisSwfDiv.offsetHeight > 0) { root.setOneSifr(thisSwfDiv, forceAlt); }  // <!-- ignore divs that are hidden
						}
					} else {
						if (!movieType || movieType == 'movies') {
							root.setOne(thisSwfDiv, forceAlt);
						}
					}
				}
			}
		// these aliases ti setAll restrict to affecting particular movie types.
			root.setFonts  = function(subScope, forceAlt) { root.setAll(subScope || root.scope, forceAlt, 'fonts');  }
			root.setMovies = function(subScope, forceAlt) { root.setAll(subScope || root.scope, forceAlt, 'movies'); }
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// RETURNS AN ARRAY CONTAINING ALL OF THE SWFHANDLER DIVS IN THE DOM                       //// -- should make this private?
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.getAll = function(subScope) {
			// empty array will hold swfHandler elements
				var allSwfDivs = [];
			// set subscope to default if unspecified
				subScope   = subScope || root.scope;
			// test to make sure subscope is within scope, throw error if not
				var parent = subScope;
				while (parent != document.body) {
					if (parent == root.scope)    { break; }
					parent = parent.parentNode;
					if (parent == document.body) { root.error.beyondScope(); }
				}
			// get all page elements within scope
				var allElements = subScope.getElementsByTagName('*');
			// save elements that contain the swfHandler into the array
				for (var i = 0; i < allElements.length; i++) {
					var thisObj = allElements[i];
					var thisOpt = thisObj.getAttribute('swfhandler');
					if (thisOpt) { allSwfDivs.push(thisObj); }
				}
				return allSwfDivs;
			}
		/////////////////////////////////////////////////////////////////////////////////////////////////
		//// METHOD TESTS FOR FLASH PLUGIN CONSERVATIVELY (RETURNS FALSE IF VERSION INDETERMINATE)   //// -- should make this private.
		/////////////////////////////////////////////////////////////////////////////////////////////////
			root.testPlugin = function() {
				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; }
			}
		// test flash support
			root.testPlugin();
		// process html on a slight delay.
			setTimeout(root.setMovies, 150);  // do main movies first since there will be fewer of them
			setTimeout(root.setFonts,  300);  // do sifr next, since there will be many requests
		}


