    ////////////////////////////////////////////////////////////////////////////////
    //
    // Toolbox.js -
    //    Various extremely useful JavaScript function. Do not put project-specific
    //    functionality in this file.
    //
    ////////////////////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////////////////////
    //
    // setSelected(selectField, strValue) -
    //    Macro for setting the selected string in the input <select> object. Also
    //    works for setting selected value of a <radio> button set.
    //    Also works for setting a checkbox. strValue should be an integer 0 or -1
    //    in this case.
    //    Note that if strValue is not an option (or radio button value), no action 
    //    is taken. If boolMulti (optional) is supplied and true, the item will
    //    be selected *in addition* to any already selected items, such as in
    //    a <select multiple> input field.
    
    function deleteCookie( name ) 
    {
        d = new Date()
        document.cookie = name + "=blah; expires=" + d.toGMTString() + "; ; path=/";
    }
        

    function setSelected(selectField, strValue, boolMulti)
    {
    	if(selectField.options)
    	{
    		////This is a <select> object
    		options = selectField.options;
    		for(i=0; i < options.length; i++)
    		{
    			if(options[i].value == strValue)
    			{
    				if(boolMulti)
    					options[i].selected = true;
    				else
    					selectField.selectedIndex = i;
    
    				return;
    			}
    			else
    				options[i].selected = false
    		}
    	}
    	else if(selectField.type == "checkbox")
    	{
    		if(new Boolean(strValue) == true)
    			selectField.checked = true
    		else
    			selectField.checked = false
    	}
    	else
    	{
    		////This is a <radio> object
    		for(var i=0; i < selectField.length; i++)
    		{
    			if(selectField[i].value == strValue)
    			{
    				selectField[i].checked = true;
    				return;
    			}
    			else
    				selectField[i].checked = false
    		}
    	
    	}
    }
    
    
    ////////////////////////////////////////////////////////////////////////////////
    //
    // getSelected(selectField) -
    //    Macro for returning the selected string in the input <select> object.
    
    function getSelected(selectField)
    {
		if(selectField.options)
		{
	    	return selectField.options[selectField.selectedIndex].value
	    }
	    else
    	{
    		////This is a <radio> object
    		if(typeof(selectField.length) == "undefined")
    			if(selectField.checked)
	    			return selectField.value
	    		else
	    			return ""
    		else
    			for(var i=0; i < selectField.length; i++)
    			{
    				if(selectField[i].checked)
    					return selectField[i].value
    			}

    		return ""
    	}
    }
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // 
    // closeWindowAndReturn() -
    //    Macro for closing the current window and focusing the previous window.
    
    function closeWindowAndReturn()
    {
    	if(typeof(window.opener) != "undefined")
    		if(!window.opener.closed)
    			window.opener.focus()
    
    	window.close()
    }
    function closeWindowRefreshAndReturn()
    {
    	// if the window.open reference appends # to the URL, strip it off
    	try
    	{
    		strLocation = new String(window.opener.location.href)
    		if (strLocation.search('#') > -1)
    			strLocation = strLocation.substring(0,strLocation.search('#'))
    		window.opener.location.href = strLocation
    	}
    	catch(something)
    	{
    		///Possible to get "permission denied" exception if user browsed somewhere
    		// else or parent window was closed.
    	}
    	
    	closeWindowAndReturn()
    }
    
    
    ////////////////////////////////////////////////////////////////////////////////
    //
    // containsUnicode(strInput) -
    //    Returns true if there are any non-ASCII characters in the string.
    
    function containsUnicode(strInput)
    {
    	//alert("hello: " + strInput.length)
    	for(i=0; i < strInput.length; i++)
    	{
    		if(strInput.charCodeAt(i) > 128)
    		{
    			return true
    		}
    	}
    
    	return false
    }
    
    
    ////////////////////////////////////////////////////////////////////////////////
    //
    // iBytesize(strInput) -
    //    Returns the number of [SQL Server] bytes required to store the string, 
    //    accounting for double-byte characters.
    
    function iBytesize(strInput)
    {	
    	iSize = strInput.length
    	
    	for(i=0; i<strInput.length; i++)
    	{
    		//// Test for Uniode:
    		//   - Doesn't account for half-width Kana
    		//   - CR/LF is two bytes in SQL Server and JavaScript, 
    		//     so this is not an issue
    		//   - C++-style null-terminator not included
    		//   - Arbitrary choice of 128 might not be quite right
    		
    		if(strInput.charCodeAt(i) > 128)
    		{
    			iSize++
    		}
    	}
    	
    	return iSize
    }
    
    function checkAlertUnicode(element, strMessage)
    {
    	if(containsUnicode(element.value))
    	{
    		alert(strAlphaOnlyMessage.replace("#FIELD_NAME#", strFieldName))
    		element.focus()
    		return false
    	}
    	else
    		return true
    }
    
    function checkAlertNull2(element, strFieldName)
    {
    	if(element.value == "")
    	{
    		alert(strNullFieldMessage.replace("#FIELD_NAME#", strFieldName))
    		if(element.type != "hidden") //could happen in the case of node picker, color picker, etc.
    			element.focus()
    		return false
    	}
    	else
    		return true
    }
    function checkAlertNonNumeric(element, strFieldName)
    {
    	if(isNaN(element.value))
    	{
    		alert(strNumberFieldMessage.replace("#FIELD_NAME#", strFieldName))
    		element.focus()
    		return false
    	}
    	else
    		return true
    }
    function checkAlertNull(element, strMessage)
    {
    	if(element.value == "")
    	{
    		alert(strMessage)
    		element.focus()
    		return false
    	}
    	else
    		return true
    }
    
    // allow push to work the same for all browser versions
    // we do this by prototyping push method as our own
    // if it does not do what we want
    if (Array.prototype.push && ([0].push(true)==true))
            Array.prototype.push = null;
    
    if(!Array.prototype.push) {
    
        function array_push() {
            for(i=0;i<arguments.length;i++){
                this[this.length] = arguments[i];
            }
            return this.length;
        }
    
        Array.prototype.push = array_push;
    }
    
    // allow splice method to work the same for all browser versions
    // not supported in most IE versions
    // prototype same as above method (push)
    if(Array.prototype.splice && typeof([0].splice(0))=="number")
        Array.prototype.splice = null;
    
    if(!Array.prototype.splice) {
    
        function array_splice(ind,cnt){
    
            removeArray = this.slice(ind,ind+cnt);
            endArray = this.slice(ind+cnt);
    
            this.length = ind;
    
            for(var i=2;i<arguments.length;i++){
                this[this.length] = arguments[i];
            }
    
            for(var i=0;i<endArray.length;i++){
                this[this.length] = endArray[i];
            }
    
            return removeArray;
        }
    
        Array.prototype.splice = array_splice;
    
    }
    
    function strGetCookie(sName)
    {
      // cookies are separated by semicolons
      var aCookie = document.cookie.split("; ");
      for (var i=0; i < aCookie.length; i++)
      {
        // a name/value pair (a crumb) is separated by an equal sign
        var aCrumb = aCookie[i].split("=");
        if (sName == aCrumb[0]) 
        {
    		//alert("returning cookie '" + sName + "' = '" + unescape(aCrumb[1]) + "'")
          return unescape(aCrumb[1]);
        }
      }
    
      // a cookie with the requested name does not exist
      return "";
    }
    
    function setCookie(sName, sValue)
    {
      document.cookie = sName + "=" + escape(sValue) + ";"
    }
    
    function boolFifthGenBrowser()
    {
    	//Mozilla (5.0) not supported
    	
    	if(
    	     navigator.userAgent.search("MSIE 5") > 0
    	  || navigator.userAgent.search("MSIE 6") > 0
    	  || navigator.userAgent.search("MSIE 6") > 0
    	  || navigator.userAgent.search("Netscape6") > 0
    	  || navigator.userAgent.search("MSIE 7") > 0
    	  || navigator.userAgent.search("Netscape7") > 0
    	)
    		return true;
    	else
    		return false;
    }
    
    function HashTable()
    {
    	this.add = HashTable_add;
    	this.item = HashTable_item;
    	this.set = HashTable_set;
    	this.remove = HashTable_remove;
    	this.contains = HashTable_contains;
    		
    	this.indexes = new Array();
    	this.objects = new Array();
    }
    
    function HashTable_contains(strKey)
    {
    	for(i=0; i<this.indexes.length;i++)
    		if(this.indexes[i] == strKey)
    			return true
    	
    	return false
    }
    
    function HashTable_add(strKey, obj)
    {
    	this.indexes[this.indexes.length] = strKey;
    	this.objects[this.objects.length] = obj;
    }
    
    function HashTable_set(strKey, obj)
    {
    	for(i=0; i<this.indexes.length;i++)
    		if(this.indexes[i] == strKey)
    			this.objects[i] = obj
    }
    
    function HashTable_item(strKey)
    {
    	for(i=0; i<this.indexes.length;i++)
    		if(this.indexes[i] == strKey)
    			return this.objects[i];
    
    	return null;
    }
    
    function HashTable_remove(strKey)
    {
    	for(i=0; i<this.indexes.length;i++)
    	{
    		if(this.indexes[i] == strKey)
    		{
    			this.indexes.splice(i, 1)
    			this.objects.splice(i, 1)
    		}
    	}
    }
    
    
    function strTrimWithDots(strInput, iMaxLength)
    {
    	if(strInput.length > iMaxLength)
    		return strInput.slice(0, iMaxLength-3) + "...";
    	else
    		return strInput;
    }
    
    function strLeftZeroPad(iInput, iNumDigits)
    {
    
    	//TODO: I had a function for this somewhere, don't feel like writing it again...
    	//Warning, only works for certain cases just now!
    	if(iNumDigits != 2)
    	{
    		alert("Not implemented")
    		return false;
    	}
    	
    	if(iInput == 0)
    		return "00";
    	else if(iInput < 10)
    		return "0" + iInput;
    	else
    		return iInput;
    }
    function prefCheckbox(strId, iValue, iDefaultValue, boolDisabled)
    {
    	if(!document.defaults)
    	{
    		document.defaults = new Object()
    		document.straDefaultKeys = new Array()
    	}
    		
    	////Save default value so reset works:
    	document.defaults[strId] = iDefaultValue
    	document.straDefaultKeys.push(strId)
    	
    	if(iValue == iDefaultValue)
    		document.write("<input type='hidden' name='" + strId + "' value='default'/>")
    	else
    		document.write("<input type='hidden' name='" + strId + "' value='" + iValue + "'/>")
    	
    	////Visual checkbox with ID = strId. Value is always iValue (default if user hasn't overridden)
    	if(parseInt(iValue) == 0)
    		strChecked = ""
    	else
    		strChecked = " checked='true'"
  
		var strDisabled = ""
		if(typeof(boolDisabled) != "undefined" && boolDisabled)
			strDisabled = "disabled='yup'"
    
    	document.write("<input type='checkbox' " + strDisabled + " name='" + strId + "_GUI' onchange='prefCheckboxOnChecked(this)'" + strChecked + "/>")
    }
    
    function prefCheckboxOnChecked(srcCheckbox)
    {
    	////User overrode the default, so set the hidden input accordingly:
    	document.forms[0][strIdFromGuiElem(srcCheckbox.name)].value = new Number(srcCheckbox.checked)
    	
    	if(typeof(onformchange) != "undefined")
    		onformchange()
    }
    
    function strIdFromGuiElem(strGuiElemId)
    {
    	return strGuiElemId.slice(0, strGuiElemId.length - "_GUI".length)
    }
    
    function prefDropdown(strId, strValue, strDefaultValue)
    {
    	if(!document.defaults)
    	{
    		document.defaults = new Object()
    		document.straDefaultKeys = new Array()
    	}
    
    	document.defaults[strId] = strDefaultValue
    	document.straDefaultKeys.push(strId)
    	
    	if(strValue == strDefaultValue)
    		document.write("<input type='hidden' name='" + strId + "' value='default'/>")
    	else
    		document.write("<input type='hidden' name='" + strId + "' value='" + strValue + "'/>")
    		
    	setSelected(document.all[strId+"_GUI"], strValue)
    	document.forms[0][strId+"_GUI"].onchange = function()
    	{
    		//document.title = ++temp
    		document.forms[0][strIdFromGuiElem(event.srcElement.name)].value = getSelected(event.srcElement)
    	}
    }
    
    function prefRestoreDefaults()
    {
    	for(var i=0; i<document.straDefaultKeys.length; i++)
    	{
    		strKey = document.straDefaultKeys[i]
    		strValue = document.defaults[strKey]
    		setSelected(document.forms[0][strKey+"_GUI"], strValue)
    		document.forms[0][strKey].value = "default"
    	}
    }
    
    function strNowPrefValue(strKey)
    {
    	if("default" == document.forms[0][strKey].value)
    		return document.defaults[strKey]
    	else
    		return document.forms[0][strKey].value
    }


if(typeof(strTbl) == "undefined")
{
	strTbl = new StringTable()
	document.strTbl = strTbl
}
function StringTable()
{
	this.iTblCount = 0
	this.tbl = new Object()
	
	this.strGet = function(strIdPath)
	{
		var strValue = this.tbl[strIdPath]
		if(!strValue)
		{
			return "{" + strIdPath + "}"
		}

		if(arguments.length > 1)
		{
			for(iArg = 1; iArg+1 < arguments.length; iArg+=2)
			{
				var strParam = arguments[iArg]
				var strParamValue = arguments[iArg+1]
				strValue = strValue.replace(strParam, strParamValue)
			}
		}

		return strValue
	}
	
	this.add = function(strIdPath, strValue)
	{
		this.tbl[strIdPath] = strValue
		this.iTblCount++
	}
}

function debugError(strMessage)
{
	if(confirm("Error Occured: '" + strMessage + "'\nClick OK to debug or Cancel to ignore."))
		x = y + z
}

function strTextFromHTML(strHTML)
{
	////Line feeds have no meaning for HTML:
	strText = strHTML.replace(/\n/g, "")

	////<BR>Always a single line feed:
	strText = strText.replace(/<BR>/g, "\n")

	////<P>xxx</P> replace with xxx\n\n:
	var onMatch = function(strMatch)
	{
		var strReturn = strMatch
		strReturn = strReturn.replace(/<P>/g, "")
		strReturn = strReturn.replace(/<\/P>/g, "\n\n")
		return strReturn
	}
	strText = strText.replace(/<P>[^<]*<\/P>/g, onMatch)

	strText = strText.replace(/&nbsp;/g, " ")
	strText = strText.replace(/&lt;/g, "<")
	strText = strText.replace(/&gt;/g, "<")
	strText = strText.replace(/&amp;/g, "&")
	
	if(strText.substring(strText.length-2) == "\n\n")
		strText = strText.substring(0, strText.length-2)

	return strText
}

function strHTMLFromText(strText)
{
	strHTML = strText.replace(/</g, "&lt;")
	strHTML = strHTML.replace(/>/g, "&gt;")

	var onMatch = function(strMatch)
	{
		var strReturn = strMatch.replace(/\n\n/g, "")
		return "<P>" + strReturn + "</P>"
	}
	
	strHTML = strHTML.replace(/ \n/g, "&nbsp;<BR>")
	strHTML = strHTML.replace(/\n/g, "<BR>")

	//strHTML = strHTML.replace(/[^\n\n]*\n\n/g, onMatch)

	return strHTML
}

function removeHtmlTags(elem)
{
	var strValue = elem.innerHTML

	var onMatch = function(strMatch)
	{
		if(strMatch == "<P>" || strMatch == "</P>" || strMatch == "<BR>")
			return strMatch
		else
			return ""
	}
	
	////Get rid of all the HTML codes except <BR> and <P>xxx</P>:
	strValue = strValue.replace(/<[^>]*>/g, onMatch)
	
	elem.innerHTML = strValue
}

function elemParentNamed(strParentName, elemChild)
{
	if(!elemChild)
		elemChild = event.srcElement
	
	for(var elemParent = elemChild; elemParent != null; elemParent = elemParent.parentElement)
		if(elemParent.nodeName == strParentName)
			return elemParent
	
	return null
}

function elemParentWithAttr(strAttrName, elemChild)
{
	if(!elemChild)
		elemChild = event.srcElement
	
	while(null == elemChild.getAttribute(strAttrName))
		elemChild = elemChild.parentElement
	
	return elemChild
}

function ObjectWithCallback(strType)
{
	this.strObjectType = strType
	if(typeof(document[strType + "_nextId"]) == "undefined")
		document[strType + "_nextId"] = 0
	this.iUniqueId = document[strType + "_nextId"]
	document[strType + "_nextId"]++
	
	document[strType + "_" + this.iUniqueId] = this
}

var FileUploadTools = new Object()

FileUploadTools.strExtractFromInput = function(uploadInput)
{
	var strFilename = uploadInput.value
	
	var iSep = strFilename.lastIndexOf("/")
	if(iSep == -1)
		iSep = strFilename.lastIndexOf("\\")

	if(iSep == -1)
		return strFilename
	else
		return strFilename.substring( iSep+1 )
}

FileUploadTools.strGetExtension = function(strFilename)
{
	var iDot = strFilename.lastIndexOf(".")
	if(iDot < 0)
		return ""
	else
		return strFilename.substring(iDot+1)
}

//resolveUrl_test()

function resolveUrl_test()
{
	boolExportMode = true
	assertEquals(resolveUrl("../default.aspx?Id=25")
		, "../default_63id_6125.htm", "")

	assertEquals(resolveUrl("../default.asp")
		, "../default.htm", "")

	assertEquals(resolveUrl("../default.aspx?Id=25&outputFormat=.csv") 
		, "../default_63id_6125_38outputformat_61_46csv.csv", "")

	assertEquals(resolveUrl("../superstuff/findIt.asp?name=bob_smith") 
		, "../superstuff/findit_63name_61bob__smith.htm", "") 

	assertEquals(resolveUrl("../default.aspx?Id=25&random=25333232&blah=blee") 
		, "../default_63id_6125_38blah_61blee.htm", "")
	
	assertEquals(resolveUrl("../default.aspx?blah=blee&random=25333232") 
		, "../default_63blah_61blee.htm", "")

	assertEquals(resolveUrl("../default.aspx?Id=25&selFileId=25333232&blah=blee") 
		, "../default_63id_6125_38blah_61blee.htm", "")
	
	assertEquals(resolveUrl("../default.aspx?blah=blee&selFileId=25333232") 
		, "../default_63blah_61blee.htm", "")

	assertEquals(resolveUrl("../default.aspx?random=2232122&blah=blee&selFileId=25333232") 
		, "../default_63blah_61blee.htm", "")

	alert("resolveUrl_test() finished")
}

function assertEquals(item1, item2, message)
{
	if(item1 != item2)
		alert(message + "(" + item1 + " != " + item2 + ")")
}

function assert(expression, message)
{
	if(!expression)
		alert(message)
}

function resolveUrl(url)
{
	if(boolExportMode)
	{
		///special key 'random', used to avoid caching the url, should be removed:
		url = url.replace(/random=([^&])+/g, "")
		///selFileId likewise is not applicable for export mode:
		url = url.replace(/selFileId=([^&])+/gi, "")
		url = url.replace(/&&/g, "&")
		url = url.replace(/&$/g, "")
		url = url.replace(/\?&/g, "\?")

		///Decide what extension to use:
		outputFormat = /outputFormat=\.(\S+)$/.exec(url)
		if(outputFormat != null)
			///Script produces a non-html result with extension as indicated in the param:
			extension = "." + RegExp.$1;
		else
			///Assume we'd never call this function except to call asp or aspx scripts:
			extension = ".htm"

		///Get rid of the script file extension:
		url = url.replace(/(\.aspx?)(\?|$)/, "$2")
		
		///Encode the querystring part:
		parser = url.match(/^(\S+)\?(\S+)$/g)
		if(parser != null)
		{
			url = RegExp.$1 + "_" + "?".charCodeAt(0)
			
			qs = RegExp.$2
			unescaped = /([0-9a-zA-Z])/
			for(var i=0; i < qs.length; i++)
				if(unescaped.test(qs.charAt(i)))
					url += qs.charAt(i)
				else if(qs.charAt(i) == "_")
					url += "__"
				else
					url += "_" + qs.charCodeAt(i)  
		}

		return (url + extension).toLowerCase()
	}
	else
		return url
}

function showUserInfo(iUserId)
{
	window.open(resolveUrl('../userlist/viewuser.aspx?userId=' + iUserId),'_blank','status=yes,scrollbars=yes,resizable=yes,width=400,height=350')
}

function showEditProfile(strBaseUrl)
{
	window.open(strBaseUrl + "Admin/Users/EditProfile.aspx", '_blank','status=yes,scrollbars=yes,resizable=yes,width=400,height=500')
}

function setWaitIcon()
{
	if(typeof(setWaitIcon.prototype.setTimes) == "undefined")
		setWaitIcon.prototype.setTimes = 0

	setWaitIcon.prototype.setTimes++

	//Treat like a stack - times called set must match times called unset:	
	if(setWaitIcon.prototype.setTimes > 1)
		return

	////Mask entire document and set the mask to hand, in case user moves cursor quickly after clicking (TODO probably no longer needed):
	_createBodyMasker()
	_calcMaskerSize()
	document.all.bodyMasker.style.display = ""

	_calcMaskerSize.prototype.prevWindowOnResize = window.onresize
	window.onresize = _calcMaskerSize
	
	//TODO: user can still click dropdown form element in HTC
	
}

function _calcMaskerSize()
{
	document.all.bodyMasker.style.width = document.body.clientWidth
	document.all.bodyMasker.style.height = document.body.clientHeight
}

function _createBodyMasker()
{
	if(typeof(document.all.bodyMasker) != "undefined")
		return
	
	var div = document.createElement("div")
	div.id = "bodyMasker"
	div.style.position = "absolute"
	div.style.left = 0
	div.style.top = 0
	div.style.width = "100%"
	div.style.height = "100%"
	div.style.cursor = "wait"
	div.style.zIndex = 2000
	div.onclick = div.oncontextmenu = div.onkeypress = function(){ event.cancelBubble = true; event.returnValue = false }
	div.innerHTML = "&nbsp;" //"<img src='../images/blank.gif' />" // <-- Bad because then IE displays a little toolbar in the upper left of the page
	div.style.backgroundColor = "white"
	div.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
	document.body.appendChild(div)
}

function unsetWaitIcon()
{
	setWaitIcon.prototype.setTimes--
	if(setWaitIcon.prototype.setTimes > 0)
		return

	document.all.bodyMasker.style.display = "none"
	document.all.bodyMasker.style.width = "0px"
	document.all.bodyMasker.style.height = "0px"

	window.onresize = _calcMaskerSize.prototype.prevWindowOnResize
}

function strGetCookie(sName)
{
  // cookies are separated by semicolons
  var aCookie = document.cookie.split("; ");
  strReturn = ""
  for (var i=0; i < aCookie.length; i++)
  {
    // a name/value pair (a crumb) is separated by an equal sign
    var aCrumb = aCookie[i].split("=");
    if (sName == aCrumb[0]) 
    {
		//alert("returning cookie '" + sName + "' = '" + unescape(aCrumb[1]) + "'")
		strReturn = unescape(aCrumb[1]);
    }
  }
  
  ////HACKHERE: If a cookie is written at / level and at /xxx level, two
  //  cookies with same name are listed (IE 6.0, Win2k, non-HTTP-mode.) 
  //  Last one seems to be last written...

  // a cookie with the requested name does not exist
  return strReturn;
}

function setCookie(sName, sValue)
{
  document.cookie = sName + "=" + escape(sValue) + ";"
}

/*
IE has an annoying bug with its CSS implementation - if you set an <input type="text">
style to "width:100%", everything works OK, *except* when you also set the value=""
attribute to a long text string. Then IE measures the long text string and uses that
as the width instead of 100% of the parent element. This causes the input to scroll
off the screen. As a very very ugly workaround, we disable the input and set the value
to emptystring so that IE sizes it properly. Then we wait until the window completely
loads (onload event) and then set the value. If we try to set the value any sooner,
IE miscalculates the size. UGLY HACKHERE!!!

Usage:
Once per control:
CssInputHackWorkaround.registerInput(document.all.xxx)
*/
var CssInputHackWorkaround = new Object()
CssInputHackWorkaround.boolHasOutputWindowCode = false
CssInputHackWorkaround.boolHasInit = false
CssInputHackWorkaround.init = function()
{
	if(CssInputHackWorkaround.boolHasInit)
		return
		
	for(var i=0; i < CssInputHackWorkaround.aInputs.length; i++)
	{
		CssInputHackWorkaround.aInputs[i].value = CssInputHackWorkaround.aValues[i]
		CssInputHackWorkaround.aInputs[i].disabled = CssInputHackWorkaround.aDisabled[i]
	}
	
	CssInputHackWorkaround.boolHasInit = true
}
CssInputHackWorkaround.aInputs = new Array()
CssInputHackWorkaround.aValues = new Array()
CssInputHackWorkaround.aDisabled = new Array()
CssInputHackWorkaround.registerInput = function(input, strValue, boolDisabled)
{
	if(!CssInputHackWorkaround.boolHasOutputWindowCode)
	{
		document.write("<script for='window' event='onload'>\n"
			+ " CssInputHackWorkaround.init()\n"
			+ "</script>")
		
		CssInputHackWorkaround.boolHasOutputWindowCode = true
	}
		
	CssInputHackWorkaround.aInputs.push(input)
	
	if(typeof(strValue) == "undefined")
	{
		strValue = input.value
		boolDisabled = input.disabled
		
		input.disabled = true
		input.value = ""
	}

	CssInputHackWorkaround.aValues.push(strValue)
	CssInputHackWorkaround.aDisabled.push(boolDisabled)
}
var tableBuffer = 30
function fieldWidth(element)
{
	var fieldHeaderWidth = 0
	

	var table = elemParentNamed("TABLE", element)
	for(var i=0; i < table.rows.length; i++)
	{
		var fieldHeaderTd = null
		for(var j=0; j < table.rows[i].childNodes.length; j++)
		{
			if(table.rows[i].childNodes[j].className == "fieldHeader")
			{
				fieldHeaderTd = table.rows[i].childNodes[j]
				break
			}
		}
		
		if(fieldHeaderTd != null)
		{
			fieldHeaderWidth = Math.max(fieldHeaderWidth, fieldHeaderTd.offsetWidth)
			//window.status += " | " + fieldHeaderTd.offsetWidth	
		}
	}
	return document.body.offsetWidth - fieldHeaderWidth - tableBuffer
}

function strJs(strInput)
{
	strInput = strInput.replace(/\"/g, "\\\"")
	return "\"" + strInput + "\""
}