
	window.$import = function (scriptPath, rfx_onload)
	{
		var scriptList = document.getElementsByTagName("SCRIPT");
		for (var i = 0; i < scriptList.length; i++)
			if (scriptList[i].src == scriptPath)
				return;

		var head;
		if (head = document.getElementsByTagName("HEAD")[0])
		{
			var scriptObj = head.appendChild(document.createElement("SCRIPT"));
			scriptObj.setAttribute("type", "text/javascript");
			scriptObj.setAttribute("language", "javascript");
			
			if (rfx_onload instanceof Function)
				scriptObj.onload = rfx_onload;

			scriptObj.setAttribute("src", scriptPath);
		}
	}

	window.initializeBrowserVars = function ()
	{
		var agt = navigator.userAgent.toLowerCase();
		var ver = navigator.appVersion.toLowerCase();

		var is_minor = parseFloat(ver);
		var is_major = parseInt(is_minor);

		this.is_opera  = (agt.indexOf("opera")   != -1);
		this.is_opera2 = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
		this.is_opera3 = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
		this.is_opera4 = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
		this.is_opera5 = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
		this.is_opera6 = (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1);
		this.is_opera7 = (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1);
		this.is_opera8 = (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1);

		this.is_konq   =  agt.indexOf("konqueror") != -1;
		this.is_safari = (agt.indexOf('safari') != -1 && agt.indexOf('mac') != -1);
		this.is_khtml  = (this.is_safari || this.is_konq);
		this.is_gecko  = !this.is_khtml && navigator.product && navigator.product.toLowerCase() == "gecko";

		this.is_moz = (
			(agt.indexOf('mozilla/5')  != -1) && (agt.indexOf('spoofer') == -1) &&
			(agt.indexOf('compatible') == -1) && (agt.indexOf('opera')   == -1) &&
			(agt.indexOf('webtv')      == -1) && (agt.indexOf('hotjava') == -1));

		this.is_ie  = !this.is_opera && window.showModalDialog != null;
		this.is_ie4 = this.is_ie && window.document.getElementById == null;
		this.is_ie5 = this.is_ie && window.document.getElementById != null;
		this.is_ie6 = this.is_ie && agt.indexOf("msie 6") != -1;

		this.is_win = agt.indexOf("windows") != -1;
		this.is_mac = agt.indexOf("mac") != -1;
	}

	window.initializeBrowsers = function ()
	{
		window.initializeBrowserVars();
		if (window.is_ie)
			window.onerror = trapError;
	}

	window.xml = {};
	window.xml.createHttpRequest = function ()
	{
		try
		{
			if (window.XMLHttpRequest)
			{
				var req = new XMLHttpRequest();
				// some older versions of Moz did not support the readyState property
				// and the onreadystate event so we patch it!
				if (req.readyState == null)
				{
					req.readyState = 1;
					req.addEventListener("load", function () /**/
					{
						req.readyState = 4;
						if (typeof req.onreadystatechange == "function")
							req.onreadystatechange();

					}, false);
				}				 
				return req;
			}
			if (window.ActiveXObject)
			{
				return new ActiveXObject("MSXML2.XMLHTTP");
			}
		}
		catch (ex)
		{
			throw new Error("Your browser does not support XmlHttp objects");
		}
	};
	window.xml.createDocument = function ()
	{
		try
		{
			// DOM2
			if (document.implementation && document.implementation.createDocument)
			{
				var doc = document.implementation.createDocument("", "", null);
			
				if (doc.readyState == null)
				{
					doc.readyState = 1;
					doc.addEventListener("load", function () /**/
					{
						doc.readyState = 4;
						if (typeof doc.onreadystatechange == "function")
							doc.onreadystatechange();

					}, false);
				}				 
				return doc;
			}
			if (window.ActiveXObject)
				return new ActiveXObject("MSXML2.DomDocument");
		}
		catch (ex)
		{
			throw new Error("Your browser does not support XmlDocument objects");
		}
	};
	
	window.examine = function (elementObj)
	{
		if (elementObj)
		{
			var propList = new Array;
			for (var propName in elementObj)
			{
				var propString;
				if (elementObj[propName])
				{
					var propString = '' + elementObj[propName];
					if (typeof(elementObj[propName]) == "function" && propString.match(/\[native code\]/))
						propString = "function() [native]"; /**/
				}
				else
					propString = elementObj[propName];

				propList.push("(" + typeof(elementObj[propName]) + 
					") <b>" + propName + "</b>: " + propString + "");
			}

			domwin = window.open('', "nw", "left=0,top=0,width=300,height=" + screen.availHeight + 
				",toolbar=0,status=1,resizable=1,scrollbars=1");

			domwin.document.open();
			domwin.document.write("<style> DIV { font-family: courier new; sont-size: 11px; }</style>");
			domwin.document.write("<pre>" + propList.join("\n") + "</pre>");
			domwin.document.close();
			domwin.focus();
		}
	}

	window.displayElement = function (elementObj)
	{
		if (window.is_ie)
			elementObj.style.display = elementObj.tagName == "SPAN" ? "inline" : "block";
		else
		{
			switch(elementObj.tagName.toUpperCase())
			{
				case("TR"): 
					elementObj.style.display = "table-row";
					break;
				case("TD"): 
					elementObj.style.display = "table-cell";
					break;
				case("TABLE"): 
					elementObj.style.display = "table";
					break;
				case("SPAN"): 
					elementObj.style.display = "inline";
					break;
				default: 
					elementObj.style.display = "block";
					break;
			}
		}
	}

	/**
	 * Assigns the supplied event handler function to the supplied element.
	 * The assignment takes into account handlers already assigned for this event,
	 * and creates an array of functions to call when the event occurs, thereby 
	 * preserving any handlers previously assigned. 
	 * @param String eventName The event name for which to assign the handler.
	 * @param Object elementObj Reference to the object to which to assign the handler.
	 * @param Function eventHandler Reference to the new event handler function to assign.
	 * @param Boolean insertBefore A switch that indicates that the supplied event handler
	 * should be called before any other, previously assigned handlers.
	 */
	window.assignEventHandler = function (eventName, elementObj, eventHandler, insertBefore)
	{
		//elementObj.attachEvent(eventName, eventHandler);

		var handlerArrayName = "handlers__" + eventName;
		if (elementObj[handlerArrayName] == null)
		{
			elementObj[handlerArrayName] = new Array;
			if (elementObj[eventName] != null)
				elementObj[handlerArrayName].push(elementObj[eventName]);
		}

		var handlerExists = false;
		for (var i = 0; i < elementObj[handlerArrayName].length; i++)
			if (elementObj[handlerArrayName][i] == eventHandler)
				handlerExists = true;

		// only assign an event handler once
		if (handlerExists == false)
		{
			if (insertBefore == true)
				elementObj[handlerArrayName].unshift(eventHandler);
			else
				elementObj[handlerArrayName].push(eventHandler);
		}

		//elementObj.attachEvent(eventName, eventHandler)
		elementObj[eventName] = on_eventHandler;
		return;

	}

	function on_eventHandler(e)
	{
		var eventObj = window.getEvent(e);
		if (eventObj)
		{
			var eventHandlers = "handlers__on" + eventObj.type;

			var finalResult = true;
			var currentResult;

			for (var i = 0; i < this[eventHandlers].length; i++)
			{
				try
				{
					currentResult = this[eventHandlers][i].apply(this, arguments);
				}
				catch(x)
				{
					if (x.number == -2147418113)
						continue;
					else
						throw x;
				}
				if (currentResult != undefined && typeof(currentResult) == "boolean")
					finalResult &= currentResult;
			}

			return currentResult ? finalResult ? true : false : currentResult;
		}
	}

	/**
	 * returns an element's real left coord on screen
	 * @param Object object reference to the object
	 * @return Number the left coord of the object
	 */
	window.getLeft = function (object)
	{
		if (object == null && this && this != window)
			object = this;
		else if (object == null)
			return -1;

		var scrollLeft = 0;
		var bodyElement = object.offsetParent;
		while (bodyElement != null && bodyElement.tagName != "BODY") 
			bodyElement = bodyElement.offsetParent;

		if (bodyElement)
			scrollLeft = bodyElement.scrollLeft;

		var left = object.offsetLeft;
		object = object.offsetParent;

		while (object != null) 
		{
			if (window.is_ie)
			{
				if (object.tagName != "TABLE" && object.tagName != "BODY")
					left += object.clientLeft;
			}

			if (window.is_gecko)
			{
				if (object.tagName == "TABLE")
				{
					var borderW = parseInt(object.border);
					var frameW = object.getAttribute('frame');

					if (isNaN(borderW) && frameW != null)
						left += 1;
					else if (borderW > 0)
						left += borderW;
				}
			}

			left += object.offsetLeft - object.scrollLeft;
			object = object.offsetParent;
		}
		return left + scrollLeft;
	}

	/**
	 * returns an element's real top coord on screen
	 * @param Object object reference to the object
	 * @return Number the top coord of the object
	 */
	window.getTop = function (object)
	{
		if (object == null && this && this != window)
			object = this;
		else if (object == null)
			return -1;

		var scrollTop = 0;
		var bodyElement = object.offsetParent;
		while (bodyElement != null && bodyElement.tagName != "BODY") 
			bodyElement = bodyElement.offsetParent;

		if (bodyElement)
			scrollTop = bodyElement.scrollTop;

		var top = object.offsetTop;
		object = object.offsetParent;

		var step = 0;
		while (object != null) 
		{
			if (window.is_ie)
			{
				if (object.tagName != "TABLE" && object.tagName != "BODY")
					top += object.clientTop;
			}

			if (window.is_gecko)
			{
				if (object.tagName == "TABLE")
				{
					var borderW = parseInt(object.border);
					var frameW = object.getAttribute('frame');

					if (isNaN(borderW) && frameW != null)
						top += 1;
					else if (borderW > 0)
						top += borderW;
				}
			}

			top += object.offsetTop - object.scrollTop;
			object = object.offsetParent;
		}
		return top + scrollTop;
	}

	window.getQueryString = function (queryString)
	{
		var queryString = arguments.length == 0 ? location.search : queryString;
		queryString = queryString.substring(queryString.indexOf("?") + 1);
		var param = queryString.split("&");
		var queryObject = new Object();
		queryObject.param = new Object();

		for (var i = 0; i < param.length; i++)
		{
			if (param[i].length == 0)
				continue;

			var pair = param[i].split("=");
			var itemKey = pair[0];
			var itemValue = pair[1];

			if (queryObject.param[itemKey] != null)
			{
				if (!isArray(queryObject.param[itemKey]))
					queryObject.param[itemKey] = [queryObject.param[itemKey]];

				queryObject.param[itemKey].push(itemValue);
			}
			else
				queryObject.param[itemKey] = itemValue;
		}
		queryObject.getItem = function (itemKey) /**/
		{
			return this.param[itemKey];
		}
		queryObject.toString = function () /* inner */
		{
			var strSelf  = new String();
			var arrParam = new Array();
			for (var strName in this.param)
			{
				if (this.param[strName] && this.param[strName].constructor == Array)
				{
					for (var i = 0; i < this.param[strName].length; i++)
						arrParam.push(escape(strName) + "=" + escape(this.param[strName][i]));
				}
				else
				{
					var itemValue = String(this.param[strName]).match(/\{.*\}/) ? this.param[strName] : escape(this.param[strName]);
					arrParam.push(escape(strName) + "=" + itemValue);
				}
			}

			strSelf = arrParam.join("&");
			return strSelf;
		}
		return queryObject;
	}

	window.getEvent = function (e)
	{
		if (e != null)
			return e;
		else
			return window.event;
	}

	/**
	 * searches for an element with a given tagName in a child's hiearchy of parents
	 * @param Object refObject the child whose hiearchy of parents is to be searched
	 * @param String tagName the tag name of the parent that we are looking for
	 * @return Object Reference to the object, if found, or null if it was not found
	 */
	window.getParentByTagName = function (refObject, tagName)
	{
		if (refObject == null || tagName == null)
			return null;

		var objParent = refObject;
		var tagName = String(tagName).toUpperCase();
		while(objParent = objParent.parentNode)
		{
			if (objParent.tagName == tagName)
				return objParent;
		}
		return null;
	}

	window.hideOverlappingSelects = function (elementObj, documentObj)
	{
		var doc = documentObj || document;

		var top = window.getTop(elementObj);
		var left = window.getLeft(elementObj);
		var bottom = top + elementObj.offsetHeight;
		var right = left + elementObj.offsetWidth;

		var selectList = doc.getElementsByTagName("SELECT");
		for (var i = 0; i < selectList.length; i++)
		{
			var t = window.getTop(selectList[i]);
			var l = window.getLeft(selectList[i]);
			var r = l + selectList[i].offsetWidth;
			var b = t + selectList[i].offsetHeight;

			// tl
			if ((t < bottom && t > top) && (l > left && l < right))
				selectList[i].overlapping = true;
			// tr
			else if ((t < bottom && t > top) && (r > left && r < right))
				selectList[i].overlapping = true;
			// bl
			else if ((b < bottom && b > top) && (l > left && l < right))
				selectList[i].overlapping = true;
			// br
			else if ((b < bottom && t > top) && (r > left && r < right))
				selectList[i].overlapping = true;

			// topleft
			else if ((top < b && top > t) && (left > l && left < r))
				selectList[i].overlapping = true;
			// topright
			else if ((top < b && top > t) && (right > l && right < r))
				selectList[i].overlapping = true;
			// bottomleft
			else if ((bottom < b && bottom > t) && (left > l && left < r))
				selectList[i].overlapping = true;
			// bottomright
			else if ((bottom < b && bottom > t) && (right > l && right < r))
				selectList[i].overlapping = true;
		}
		for (var i = 0; i < selectList.length; i++)
		{
			if (selectList[i].overlapping)
			{
				selectList[i].parentNode.style.width = selectList[i].parentNode.offsetWidth;
				selectList[i].parentNode.style.height = selectList[i].parentNode.offsetHeight;
				selectList[i].style.display = "none";
			}
		}
	}

	window.setStatus = function (message, timeout)
	{
		var statusObj = document.getElementById("status");

		if (statusObj)
			statusObj.innerText = message;
		else
			window.status = message;

		if (timeout)
			window.setTimeout(clearStatus, timeout);
	}

	window.clearStatus = function ()
	{
		var statusObj = document.getElementById("status");

		if (statusObj)
			statusObj.innerText = "";
		else
			window.status = "";
	}
	

	window.showOverlappingSelects = function (documentObj)
	{
		var doc = documentObj || document;
		var selectList = doc.getElementsByTagName("SELECT");
		for (var i = 0; i < selectList.length; i++)
		{
			if (selectList[i].overlapping)
			{
				selectList[i].style.display = "block";
				selectList[i].overlapping = null;
			}
		}
	}

	window.err = function (message)
	{
		window.setStatus(message, 10000);
	}

	window.trapError = function (errorText, errorFile, errorLine)
	{
		var fileLocation = String(errorFile).replace(/.*\//, "");
		window.err(errorText + " (" + "line " + errorLine + " in " + fileLocation + ")");
		window.returnValue = true;
		return true;
	}

	window.warn = function (message)
	{
		window.setStatus("WARNING: " + message, 10000);
	}

	/**
	 * Sets/adds a cookie to the document.cookies collection
	 * @param String name The name of the cookie. Required.
	 * @param String value The value of the cookie. Required.
	 * @param String expires An expression, signifying the expires property of the cookie. See <code>dateCalc</code>. Optional.
	 * @param String domain The domain property of the cookie. Optional.
	 * @param Boolean secure The secure property of the cookie. Optional.
	 * @return String The value of the cookie that has just been set.
	 */
	window.setCookie = function (name, value, expires, domain, path, secure)
	{
		var cookie = name + "=" + escape(value);

		if (expires) cookie += "; expires=" + dateCalc(expires);
		if (domain)  cookie += "; domain="  + domain;
		if (path)    cookie += "; path="    + path;
		if (secure)  cookie += "; secure=true";

		document.cookie = cookie;

		return getCookie(name);
	}

	/**
	 * Returns a cookie with the specified name from the document.cookies collection, if present,
	 * and a <code>null</code> if not.
	 * @param String name The name of the cookie. Required.
	 * @return String|null The value of the cookie, if found, and a <code>null</code> otherwise.
	 */
	window.getCookie = function (name)
	{
		var cookies = document.cookie.split("; ");
		for (var i = 0; i < cookies.length; i++)
		{
			var cookieName  = cookies[i].substring(0, cookies[i].indexOf("="));
			var cookieValue = cookies[i].substring(cookies[i].indexOf("=") + 1, cookies[i].length);
			if (cookieName == name)
			{
				if (cookieValue.indexOf("&") != -1)
				{
					var pairs  = strValue.split("&");
					var cookie = new Object();
					for (var i in pairs)
					{
						var arrTemp = pairs[i].split("=");
						cookie[arrTemp[0]] = arrTemp[1];
					}
					return cookie;
				}
				else
					return unescape(cookieValue);
			}
		}
		return null;
	}

	/**
	 * Deletes a cookie with the specified name from the document.cookies collection, by setting its expires property
	 * to the current date [expire now].
	 * @param String name The name of the cookie. Required.
	 */
	window.deleteCookie = function (name)
	{
		var dateObj = new Date();
		document.cookie = name + "=null; expires=" + dateObj.toGMTString();
	}

	window.dateCalc = function (offsetString)
	{
		var dateObj = new Date();
		var multip = new Object();
		var offsetTime;
		multip['s'] = 1000*1;
		multip['m'] = 1000*60;
		multip['h'] = 1000*60*60;
		multip['d'] = 1000*60*60*24;
		multip['M'] = 1000*60*60*24*30;
		multip['y'] = 1000*60*60*24*365;

		if (!offsetString || (offsetString == '') || (offsetString.toLowerCase() == 'now')) 
		{ // this will set the time calc to now
			offsetTime = 0;
		}
		else if ( matches = offsetString.match( /^([+-]?(\d+|\d*\.\d*))([mhdMy]?)/ ) ) 
		{ // perform calculation if offsetString matches specification
			offsetTime = multip[matches[3]] * matches[2];
		} 
		else 
		{ // otherwise assume that we're providing the date ourselves so just return original
			return offsetString;
		}
		dateObj.setTime(dateObj.getTime() + offsetTime);
		return (dateObj.toGMTString());
	}

	window.assignEventHandler("onload", window, initializeBrowsers);

