//	alert("Module trackerLib.js [v20050529] has loaded.");
//  <!-- to use this module, copy following (commented) line to your html file -->
//	<!-- <script src="/{server_alias}/includes/trackerLib.js"></script> -->

	/* <!--
	name:	trackerLib.js
	dir:	\htdocs\includes
	by: 	Iterate Pte Ltd
	func:	provides javascript methods for detecting and communicating client information 
			including browser type and presence/version of required plugin components;
			note that this library also includes routines to support detection of the 
			elapsed time of page viewing, and posting with other client data to remote server;

			Plugin detection can be tricky - there are at least 4 methods we can use:
			1.  check the Netscape browser list of plugins
			2.  use vbScript to create an ActiveX object using the appropriate classid or name,
				but you must handle plugins which fail to launch (using 'on error resume next')
			3.	use javaScript to create an ActiveX object using the appropriate classid or name,
				but you must handle plugins which fail to launch (using 'try/catch')
			4.	use the Internet Explorer 'clientCaps' object to detect native plugins
			A combination of the Netscape plugin list and Explorer clientCaps methods is the
			best approach, but doesn't work in all cases.  For example, to support IE4, launching 
			ActiveX in vbScript is the only option.  To detect non-native plugins, such as Acrobat,
			you may use either Javascript or vbScript to launch an ActiveX component.  To detect
			the version of the Windows Media Player in Netscape 4, you must write out the component
			to a hidden layer, and then detect the version through the player API. And finally,  
			to support Netscape 4, you must protect the try/catch code because 'try' is a reserved
			word to Netscape 4 (this is why we implement a 'safeTryCatch' function).

			For detection in legacy IE4 browsers, the supporting vbScript library is required.
			
			For more info on detecting plugins, refer to:
				http://www.sonify.org/tutorials/links/pages/other/embedded_audio_part2
				http://devedge.netscape.com/viewsource/2003/windows-media-in-netscape/
				http://1ppl.free.fr/html/article074.html
				http://developer.apple.com/internet/javascript/detectplugins_source.html
				http://www.agenturcafe.de/STATS/lib/plugins.vb

	rev: 	20031026, wmc, created this module
			20031027, wmc, added support for tracking user session via cookie
			20031110, wmc, completed migration of functions from vbScript,
				and implemented new functions using 'clientCaps' capability
			20031111, wmc, modified the function 'trackThisVisit' to remove the updating
				of form fields, and renamed the simplified function 'getClientParams'
			20040605, wmc, reduced duration of constant 'WAIT_BETWEEN_BUFFER_CHECKS' to make
				checking for image download more frequent (a long wait creates minimum
				time for the process to complete, effectively placing a cieling on the 
				maximum bitrate - a shorter wait allows at least 10 checks for each
				image download, refining the accuracy of each timing measurement);
				also, handle case where image isn't loaded (eg- no connection to Internet)
			20050326, wmc, disabled checking for Acrobat in 'getClientParams' to ensure
				broader compatability (some systems complain when Acrobat launched if
				Acrobat viewer is not installed, and the launch takes time and displays
				annoying popups from Adobe when the test is done)
			20050529, wmc, modified progress bar functions to rely on the common layer
				library functions in 'layerLib', and added new function to create a 
				progress bar - so caller doesn't need to create the progress bar first
			20050601, wmc, minor consolidation and enhancement of functions 
				'runMultiImageCheck' and 'runSingleImageCheck'
			20050710, wmc, replaced 'runSingleImageCheck' and 'runMultiImageCheck' with
				single function 'bandwidthCheck' that accepts a new parameter to indicate the
				number of times to load the image (default is 10); also modified this function
				to subtract out the time taken waiting for image downloads to finish, which
				results in a more accurate measure of bandwidth (especially at low bandwidth)
			
	--------------------------------------------------------------------------------
	Following are the common client-side functions defined in this module.
	--------------------------------------------------------------------------------

	getClientParams					retrieves client-side data on the user session
	nsCheckPlayer					checks for the existence of an installed NS plugin for selected players
	getBrowserType					gets client browser type
	getBrowserVersion				gets client browser version
	nsCheckPlayer					checks existence of player plugin using Netscape plugins array
	getWMPlayerVersion				gets WindowsMedia player version using clientCaps or Netscape plugins
	isActrobatInstalled				checks existence of Acrobat reader using ActiveX component
	getActrobatVersion				gets Acrobat reader version using ActiveX component (trial & error)
	clientCapsDetectPlugin			checks existence of native IE plugin using client capabilities object
	clientCapsDetectPluginVersion	gets major version of native IE plugin using client capabilities object
	safeTryCatch					performs try-catch in a manner that doesn't break Netscape 4.x
	bandwidthCheck					retrieves multiple images to monitor download speed with progress bar
	getDataRate						calculate data rate using startime, endtime and image size
	createProgressBar				creates a progress bar in a hidden layer
	progressBarShow					make the progress bar visible
	progressBarHide					make the progress bar hidden
	progressBarReposition			move the progress bar to the center of the viewer's screen
	progressBarUpdate				update the incremental steps in the progress bar
	progressBarTextUpdate			update the text display within a progress bar
	getRealPlayerVersion			gets Real Player version (untested)
	unpackRealVersionNumber			normalizes the Real Player version number (untested)
	
	--> */

	// declare global variables
var trackerLib = this;
var global = (top.dataframe ? top.dataframe : this);
var startTime = new Date();					// save the current timestamp (when this library loads)

function getClientParams () {
	var s = "";
		// for info on how cookies work, see 'http://www.xs4all.nl/~ppk/js/cookies.html'
	if (top.opener && top.opener.commonLib) {
		if (top.opener.commonLib.getSessionID() == "-1")
			top.opener.commonLib.setSessionID(this.startTime.getTime());
		s += "sessionID=" + top.opener.commonLib.getSessionID() + ", ";
	} else {
		s += "sessionID=n/a, ";
	}

		// estimate viewing time and time zone of viewer
	endTime = new Date();
	s += "viewingTime=" + Math.round((endTime.getTime() - this.startTime.getTime())/(1000*60)) + ", ";
	s += "timeZone=GMT+" + endTime.getTimezoneOffset()/-60 + ", ";

		// get browser language
	if (document.all) {
		s += "language=" + window.navigator.browserLanguage + ", ";
	} else if (document.getElementById) {
		s += "language=" + window.navigator.language + ", ";
	} else {
		s += "language=n/a, ";
	}		
	s += "javaEnabled=" + window.navigator.javaEnabled() + ", ";
	s += "screenSize=" + window.screen.width + "x" + window.screen.height + ", ";

		// online status, only available in IE browsers
	if (typeof(window.navigator.onLine) != "undefined") 
		s += "online=" + window.navigator.onLine + ", ";
	else 
		s += "online=n/a, ";	
	
		// connection type, only available in IE browsers
	if (document.all && document.body) {
		document.body.addBehavior("#default#clientCaps");
		s += "connectionType=" + document.body.connectionType + ", ";
	} else {
		s += "connectionType=n/a, ";
	}

		// report plugin status
	if (document.all && !document.getElementById) {		// legacy code for IE4
		// s += "hasAcrobat=" + global.trackerLibVb.ieHasPlugin("PDF") + ", ";
		s += "hasAcrobat=n/a, ";
		s += "hasWindowsMedia=" + global.trackerLibVb.ieHasPlugin("WM") + ", ";
		s += "hasRealMedia=" + global.trackerLibVb.ieHasPlugin("RM") + ", ";
	} else if (document.all || navigator.plugins) {
		// s += "hasAcrobat=" + hasPlugin("PDF") + ", ";
		s += "hasAcrobat=n/a, ";
		s += "hasWindowsMedia=" + hasPlugin("WM") + ", ";
		s += "hasRealMedia=" + hasPlugin("RM") + ", ";
	} else {
		s += "hasAcrobat=n/a, ";
		s += "hasWindowsMedia=n/a, ";
		s += "hasRealMedia=n/a, ";
	}

		// CD-ROM installed or not, only available in IE browsers
	if (document.all && !document.getElementById) {
		s += "hasCDROM=" + global.trackerLibVb.hasCDROM() + ", ";	// legacy code for IE4
	} else if (document.all) {
		var detectActiveXControl = safeTryCatch("new ActiveXObject('WMPlayer.OCX')");
		if (detectActiveXControl) {
			cdroms = (new ActiveXObject('WMPlayer.OCX')).cdromCollection;
			s += "hasCDROM=" + (cdroms.Count > 0) + ", ";
		} else {
			s += "hasCDROM=n/a, ";
		}
	} else {
		s += "hasCDROM=n/a, ";
	}	
	
	s = s.substring(0, s.lastIndexOf(','));
	return (s);
}

function getBrowserType () {
	var nAgt = navigator.userAgent.toLowerCase();
	var browser = "";
	
	if (nAgt.indexOf('konqueror') >= 0) browser = "Konqueror";
	else if (nAgt.indexOf('safari') >= 0) browser = "Safari"
	else if (nAgt.indexOf('omniweb') >= 0) browser = "OmniWeb"
	else if (nAgt.indexOf('opera') >= 0) browser = "Opera"
	else if (nAgt.indexOf('webtv') >= 0) browser = "WebTV";
	else if (nAgt.indexOf('icab') >= 0) browser = "iCab"
	else if (nAgt.indexOf('msie') >= 0) browser = "Internet Explorer"
	else if (!nAgt.indexOf('compatible') >= 0) browser = "Netscape Navigator"
	else browser = "An unknown browser";
	return (browser);
}

function getBrowserVersion () {
	var ptr = 0;
	var versionPtr = 0;
	var validNumChars = "01234567890.";
	var nVer = navigator.appVersion;
	var nAgt = navigator.userAgent;
	var fullVersion = parseFloat(nVer);
	var majorVersion;
	
	if ((versionPtr = nAgt.indexOf("MSIE")) != -1) {
		nVer = nAgt.substring(versionPtr + ("MSIE ").length);
		while (validNumChars.indexOf(nVer.charAt(ptr)) >= 0) ptr++;
		fullVersion = nVer.substring(0, ptr);
	}
	
	if ((versionPtr = nAgt.indexOf("Opera")) != -1) {
		nVer = nAgt.substring(versionPtr + ("Opera ").length);
		while (validNumChars.indexOf(nVer.charAt(ptr)) >= 0) ptr++;
		fullVersion = nVer.substring(0, ptr);
	}
	
	    // use 'vendorSub' to support Netscape6/7
    if (navigator.vendor && (navigator.vendor=="Netscape6" || navigator.vendor=="Netscape")) 
       fullVersion = navigator.vendorSub;

	majorVersion = parseInt('' + fullVersion);

	return (fullVersion);
}

function hasPlugin (typeStr) {
	var i = 0;
	var found = false;
	var supportedTypes = "WM, RM, QT, PDF, SWF";
	if (typeStr == null || (supportedTypes + ",").indexOf((typeStr + ",").toUpperCase()) == -1) {
		alert("Javascript error - function 'ieCheckPlayer' called with invalid or missing type.");
	} else {
		typeStr = typeStr.toUpperCase();
				// trial and error by launching ActiveX objects
		if (document.all && document.getElementById) {
			found |= (typeStr == "WM" && safeTryCatch("new ActiveXObject('MediaPlayer.MediaPlayer.1')")); // Windows Media
			found |= (typeStr == "RM" && safeTryCatch("new ActiveXObject('IERPCtl.IERPCtl')")); // RealOne
			found |= (typeStr == "RM" && safeTryCatch("new ActiveXObject('rmocx.RealPlayer G2 Control')")); // Real v6
			found |= (typeStr == "RM" && safeTryCatch("new ActiveXObject('RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)')")); // Real v5
			found |= (typeStr == "RM" && safeTryCatch("new ActiveXObject('RealVideo.RealVideo(tm) ActiveX Control (32-bit)')")); // Real v4
			found |= (typeStr == "QT" && safeTryCatch("new ActiveXObject('QuickTimeCheckObject.QuickTimeCheck.1')")); 
			found |= (typeStr == "PDF" && safeTryCatch("new ActiveXObject('PDF.PdfCtrl.1')"));
			found |= (typeStr == "PDF" && safeTryCatch("new ActiveXObject('PDF.PdfCtrl.4')"));
			found |= (typeStr == "PDF" && safeTryCatch("new ActiveXObject('PDF.PdfCtrl.5')"));
			found |= (typeStr == "PDF" && safeTryCatch("new ActiveXObject('PDF.PdfCtrl.6')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.1')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.2')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.3')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.4')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.5')"));
			found |= (typeStr == "SWF" && safeTryCatch("new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6')"));
		} else if (navigator.plugins) {
				// strategy here is to just check mime types for Acrobat and Flash, but check actual plugins 
				// for video players, because the video players typically support many different mime types!
			while (!found && i < navigator.plugins.length) {
				found |= (typeStr == "WM" && navigator.plugins[i].name.indexOf("Windows Media Player") == 0);
				found |= (typeStr == "RM" && (navigator.plugins[i].name.indexOf("RealPlayer") == 0 ||
					navigator.plugins[i].name.indexOf("RealOne") == 0));
				found |= (typeStr == "QT" && navigator.plugins[i].name.indexOf("QuickTime") == 0);
				i++;
			}
			found |= (typeStr == "PDF" && (navigator.mimeTypes['application/pdf'] != null)
				&& (navigator.mimeTypes['application/pdf'].enabledPlugin != null));
			found |= (typeStr == "FLA" && (navigator.mimeTypes['application/x-shockwave-flash'] != null) 
				&& (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin != null));
			found |= (typeStr == "FLA" && (navigator.mimeTypes['application/futuresplash'] != null)
				&& (navigator.mimeTypes['application/futuresplash'].enabledPlugin != null));
		} else {
			alert("Error in 'hasPlugin' - ActiveX or Netscape plugin syntax not supported for this browser.");
		}
	}
	return (found ? true : false);
}

function getWMPlayerVersion () {
	var version = "";

	if (document.all && document.getElementById) {
		version = clientCapsDetectPluginVersion('6BF52A52-394A-11d3-B153-00C04F79FAA6');
		if (!version)
			version = clientCapsDetectPluginVersion('22D6F312-B0F6-11D0-94AB-0080C74C7E95');
	} else {
			// strategy is to write our embed tag to a hidden layer, and then check the attributes
		var layername = "playerEmbedDiv";
		var strWMP7 = "<object classid='clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6' id='WMPlayer7' height='0' width='0'>"
		var strWMP6 = "<embed type='application/x-mplayer2' name='WMPlayer6' src='' width='0' height='0'>";
		var playerObj;

		if (layerLib && document.getElementById) {
			layerLib.layerWriteInFrame(layername, strWMP7);
			playerObj = document.WMPlayer7;
		} else if (layerLib && document.layers) {
			layerLib.writeInlineText(layername + "_Layer", layername + "_Span", strWMP6); 
			playerObj = document.layers.playerEmbedDiv_Layer.document.WMPlayer6;
		} else {
			alert("Error in 'getWMPlayerVersion' - clientCaps or layer writing syntax not supported for this browser.");
		}

		if (playerObj.GetFileName != null)
			version = 6.4;
		else if (playerObj.URL != null) 
			version = playerObj.versionInfo;
		else
			version = 0;
	}

	return (version == 0 ? null : "" + version);
}

function isActrobatInstalled () {
	return (getActrobatVersion() != null);
}

	// instantiates the plugin using ActiveX (only works in IE5 or later);
function getActrobatVersion () {
	var i = 0;
	var version = "";
	if (document.all && document.getElementById) {
		var detectActiveXControl;
		for (i = 8; i > 0; i--) {
			detectActiveXControl = safeTryCatch("new ActiveXObject('PDF.PdfCtrl." + i + "');");
			if (detectActiveXControl) break;
		}
		version = ((i > 0 && i < 4) ? 4 : i);
	} else if (navigator.plugins) {
		while (navigator.plugins[i].name.indexOf("Adobe Acrobat") != 0) i++;
		if (i < navigator.plugins.length)
			version = parseFloat(navigator.plugins[i].description.split('Version ')[1]);
	} else {
		alert("Error in 'getActrobatVersion' - ActiveXObject or Navigator plugin syntax not supported for this browser.");
	}
	return (version == 0 ? null : "" + version);
}

	/*
	'clientCaps' provides information about features supported in Internet Explorer
	without actually instantiating the component; it requires IE5 or later;
	only 'internal' plugins are supported, such as the following:
		var flash = clientCapsDetectPlugin('D27CDB6E-AE6D-11CF-96B8-444553540000');
		var sw = clientCapsDetectPlugin('2A202491-F00D-11CF-87CC-0020AFEECF20');
		var wmp6 = clientCapsDetectPlugin('22D6F312-B0F6-11D0-94AB-0080C74C7E95');
		var wmp7 = clientCapsDetectPlugin('6BF52A52-394A-11d3-B153-00C04F79FAA6');
	*/
var clientCapsId = 0;
function clientCapsDetectPlugin (componentClassID, minVersionStr) {
	var isInstalled = false;
	if (document.all && document.getElementById && document.body) {
		if (clientCapsId == 0)
			clientCapsId = document.body.addBehavior("#default#clientCaps");
		isInstalled = document.body.isComponentInstalled('{' + componentClassID + '}','ComponentID', minVersionStr);
	}
	return (isInstalled);
}

	// returns major version detected by clientCaps
function clientCapsDetectPluginVersion (componentClassID) {
	var version;
	if (document.all && document.getElementById && document.body) {
		if (clientCapsId == 0)
			clientCapsId = document.body.addBehavior("#default#clientCaps");
		version = document.body.getComponentVersion('{' + componentClassID + '}','ComponentID');
	}
	return (version ? parseFloat(version) : null);
}

function safeTryCatch (functionDeclaration, errMsg) {
		// this is necessary to prevent 'try' syntax errors in NS4 browsers
		// if we simply lock out browsers that don't support JS1.4, we omit IE5
	var errEncountered = false;
	if (document.all || document.getElementById) 
		eval ("try {" + functionDeclaration + ";} catch(err) " +
		  "{ if (errMsg) alert(\"" + errMsg + "\"); errEncountered = true;}");
	else 
		alert("Error in 'safeTryCatch' - try/catch syntax not supported for this browser.");
	return (!errEncountered);
}

	// declare variables global to bandwidth detection
var POSITION_HORZ = 0;  					// initial position of Progress bar set to center of window
var POSITION_VERT = 250;  					// initial position of Progress bar set down from top of window
var BORDERSIZE = 3;							// pixel width of *inner* border in Progress bar
var BAR_HEIGHT = 22;						// vertical height of the Progress bar
var BAR_WIDTH = 256;						// chosen so that width - (2 * bordersize) is evenly divisible by 10
var SLIDER_LAYER_COLOR = "6699cc";			// bar colors (text is black)
var BACKGROUND_LAYER_COLOR = "#eeeeee";
var WAIT_BETWEEN_BUFFER_CHECKS = 2;			// shorter durations mean more frequent checks for image download
var WAIT_BEFORE_QUITTING = 2000;			// time to leave up display after test completed
var buffer = new Array();					// create a buffer to hold images during loading
var bufptr = 0;								// create and initialize a pointer in the buffer
var countWaitsPerImage;						// count each wait between checking if image is loaded
var countTotalWaits;						// count total waits (deduct waits for more accurate detection)
var startTimeMS;							// create a global variable to save the starting time
var timerID;								// create a pointer to the current countdown timer 
var progressBar;							// create a global variable to handle the progress bar object
											// which will include two hidden layers: referred to as  
											// 'sliderLayerId'and 'textLayerId'

function bandwidthCheck (imgName, sizeInBytes, numTimesToLoad, callbackStr) {
	var maxTries = 5000;			// sanity check for images that don't load (5 seconds)
	if (!sizeInBytes || !imgName) return;
	if (!numTimesToLoad || numTimesToLoad == 0) numTimesToLoad = 10;

	if (buffer == null) return(false);
	if (!buffer[bufptr]) {
		countWaitsPerImage = 0;							// initialize counter for wait states
		countTotalWaits = 0;
		progressBarCreate();							// create progress bar in floating layer
		startTimeMS = (new Date()).getTime();			// set the stopwatch to start
		buffer[bufptr] = new Image;						// load first image into buffer
		buffer[bufptr].src = imgName + "?timestamp=" + startTimeMS + "&id=" + bufptr;
	} else {
			// if it is already initialized, check if the previous image is done loading
		countWaitsPerImage++;
		countTotalWaits++;
		window.status = "Millisecond wait: " + countWaitsPerImage * WAIT_BETWEEN_BUFFER_CHECKS + 
		  " this image, out of " + countTotalWaits * WAIT_BETWEEN_BUFFER_CHECKS + " for this test.";
		if (buffer[bufptr].complete) {
				// if last image is already loaded, begin loading the next image 
				// window.status = "completed loading of: " + buffer[bufptr].src;
			if (++bufptr < numTimesToLoad) {
				buffer[bufptr] = new Image;				// load next image into buffer 
				buffer[bufptr].src = imgName + "?timestamp=" + startTimeMS + "&id=" + bufptr;
			}
			progressBarUpdate(bufptr, numTimesToLoad);
			countWaitsPerImage = 0;
		} else if (countWaitsPerImage > maxTries) {
				// handle image that cannot load
			progressBarHide();
			alert("Error: Image file '" + imgName + "' could not load.");
			return (false);
		}
	}
	if (bufptr < numTimesToLoad) {				
			// if this is not the last image, sleep a while so previous image can load					
		timerID = setTimeout("bandwidthCheck('" + imgName + "', " + sizeInBytes + ", " + 
		  numTimesToLoad + ", '" + callbackStr + "')", WAIT_BETWEEN_BUFFER_CHECKS);	
	} else {
			// if this is the last image, get timestamp, deduct wait times and prepare to exit
		var endTimeMS = (new Date()).getTime() - (countTotalWaits * WAIT_BETWEEN_BUFFER_CHECKS);
		var kbs = getDataRate (startTimeMS, endTimeMS, sizeInBytes * numTimesToLoad);
		progressBarTextUpdate("Your bandwidth is: " + kbs + " (kb/sec).");
		timerID = setTimeout("progressBarHide(); window.status='';", WAIT_BEFORE_QUITTING);
		if (callbackStr) eval(callbackStr + "(" + kbs + ")");
	}
}

function getDataRate (startTimeMS, endTimeMS, sizeInBytes) {
	if (endTimeMS == startTimeMS) return (0);
	var elapsedTimeMS = endTimeMS - startTimeMS; 		// calculate time elapsed during transfer
	var elapsedTime = elapsedTimeMS/1000; 				// convert milliseconds to seconds
	var sizeInKBits = (sizeInBytes * 8) / 1024;			// convert bytes to kilobits
	var kbps = (sizeInKBits/elapsedTime) * 0.93; 		// allow for 7% IP packet header overhead
	return (Math.floor(kbps)); 							// return user friendly number
}

function progressBarCreate () {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarCreate', 'layerLib' is not found.");
	} else {
		if (containerObj = layerLib.createLayer('progressBarDiv')) {
			this.progressBar = containerObj;
			this.progressBar.textLayerId = "progressBarTextDiv";
			this.progressBar.sliderLayerId = "progressBarSliderDiv";

			layerLib.moveLayerTo(containerObj, (layerLib.getWindowWidth()/2 - BAR_WIDTH/2), 
			  layerLib.getPageScrollY() + POSITION_VERT);
			layerLib.setWidth(containerObj, BAR_WIDTH);
			layerLib.setHeight(containerObj, BAR_HEIGHT);
			layerLib.setBgColor(containerObj, BACKGROUND_LAYER_COLOR);

			var sliderLayerObj = layerLib.createLayerInLayer(this.progressBar.sliderLayerId, containerObj);
			layerLib.setLayerVisibility(sliderLayerObj, 'inherit');
			layerLib.moveLayerTo(sliderLayerObj, BORDERSIZE, BORDERSIZE);
			layerLib.setWidth(sliderLayerObj, 0);
			layerLib.setHeight(sliderLayerObj, (BAR_HEIGHT - (2 * BORDERSIZE)));
			layerLib.setBgColor(sliderLayerObj, SLIDER_LAYER_COLOR);

			var textLayerObj = layerLib.createLayerInLayer(this.progressBar.textLayerId, containerObj);
			layerLib.setLayerVisibility(textLayerObj, 'inherit');
			layerLib.moveLayerTo(textLayerObj, BORDERSIZE, BORDERSIZE);
			layerLib.setWidth(textLayerObj, BAR_WIDTH);
			layerLib.setHeight(textLayerObj, (BAR_HEIGHT - (2 * BORDERSIZE)));
			layerLib.setBgColor(textLayerObj, "");

			progressBarShow();
			progressBarTextUpdate("Checking bandwidth...");
		}
	}
}

function progressBarShow () {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarShow', 'layerLib' is not found.");
	} else {
		if (this.progressBar)
			layerLib.setLayerVisibility(this.progressBar, 'visible');
	}
}

function progressBarHide () {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarHide', 'layerLib' is not found.");
	} else {
		if (this.progressBar) 
			layerLib.setLayerVisibility(this.progressBar, 'hidden');
	}
}

function progressBarUpdate (currentLoadCount, numTimesToLoad) {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarUpdate', 'layerLib' is not found.");
	} else {
		var pixelWidth = Math.floor((BAR_WIDTH  - (2 * BORDERSIZE)) * (currentLoadCount / numTimesToLoad));
		if (this.progressBar && (layerObj = layerLib.getLayerObj(this.progressBar.sliderLayerId)))
			layerLib.setWidth(layerObj, pixelWidth);
	}
}

function progressBarTextUpdate (str) {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarTextUpdate', 'layerLib' is not found.");
	} else {
		if (this.progressBar && (layerObj = layerLib.getLayerObj(this.progressBar.textLayerId))) {
			if (document.all || document.getElementById) {
				layerLib.writeLayerStr(layerObj, '<center>' + str + '</center>');
			} else if (document.layers) {
					// layer write in NS4 trashes the CSS style, so we rewrite it
				layerLib.writeLayerStr(layerObj, '<p class="progress_bar"><center>' + str + '</center></p>');
			}
		}
	}
}

// *** the code below is untested *** //

function getRealPlayerVersion (pVersion) {
	var isPlayerInstalled = false;
	var thisPlayerVersion = "";
	var undefined;
        
	if (navigator.appName == "Netscape") { 
		for( var i=0; i<navigator.plugins.length; i++ ) {
			if ((navigator.plugins[i].name) == 'RealOne Player Version Plugin')        {
				isPlayerInstalled = true;
				thisPlayerVersion = navigator.plugins[i].description;
				break;
			}
		}
	}
	
	if (navigator.appName == "Microsoft Internet Explorer") {
    	var nRPVersion = IERPCtl.RealPlayerVersion;
		if ( undefined == nRPVersion ) {
			isPlayerInstalled = false;
		} else {
			isPlayerInstalled = true;
			thisPlayerVersion = unpackRealVersionNumber(nRPVersion);
		}
	}
        
	if (isPlayerInstalled) {
		thisPlayerVersion = parseInt(thisPlayerVersion.replace(/6.0.10./,""));
		if (thisPlayerVersion >= pVersion ) {
			return true;
		}
	}
	return false;
}

function unpackRealVersionNumber (n) {
	return '' + (n >> 28) + '.' + ((n & 0xFF00000) >> 20) + '.' + 
	((n & 0xFF000) >> 12) + '.' + ( n & 0xFFF);
}
        
	// deprecated to reorder the parameters									
function runMultiImageCheck (imgName, sizeInBytes, callbackStr) {
	bandwidthCheck (imgName, sizeInBytes, 10, callbackStr);
}
											
	// deprecated to consolidate into single function (with numTimesToLoad = 1)									
function runSingleImageCheck (imgName, sizeInBytes, callbackStr) {
	bandwidthCheck (imgName, sizeInBytes, 1, callbackStr);
}

	// deprecated function to manually write progress bar (use 'progressBarCreate' instead)
function getProgressBarStr () {
	return ("");
}

	// deprecated function not in use
function progressBarReposition () {
	if (!layerLib) {
		alert("Error - in 'trackerLib.progressBarReposition', 'layerLib' is not found.");
	} else {
		if (this.progressBar && (layerObj = layerLib.getLayerObj(this.progressBar.sliderLayerId)))
			layerLib.moveLayerTo(layerObj, layerLib.getWindowWidth()/2 - BAR_WIDTH/2, POSITION_VERT);
	}
}
