// CROSS BROWSER FUNCTIONS ###############################################################

var JS_LIB_VER = "1.0";

function GetByID(id)
{
	return document.getElementById(id);
}

function GetByIDs(id, tag)
{
	var oTag;
	var i;
	var aryElement;

	if (document.all)
		return document.all[id];
	else
	{
		oTag = document.getElementsByTagName(tag);
		aryElement = new Array();
		for (i=0; i<oTag.length; i++)
			if (oTag[i].id == id)
				aryElement[aryElement.length] = oTag[i];
		return aryElement;
	}
}

function SetTextContent(obj, text)
{
	if (obj.innerText != null)
		obj.innerText = text;
	else
	if (obj.textContent != null)
		obj.textContent = text;
}
function GetTextContent(obj)
{
	return obj.innerText != null ? obj.innerText : obj.textContent;
}

// BROWSER DETECTION #####################################################################

function IsMSIE()
{
	return (navigator.userAgent.indexOf("MSIE") != -1);
}

// STRING FUNCTIONS ######################################################################

function TrimContent(s)
{
	var ts = LTrim(s, true);

	for (var i=ts.length-1; i>0; i--)
		if (ts.charAt(i) != " " && ts.charCodeAt(i) != 9 && ts.charCodeAt(i) != 13 && ts.charCodeAt(i) != 10)
			break;
	return ts.substring(0, i+1);
}

function RTrimContent(s)
{
	for (var i=s.length-1; i>0; i--)
		if (s.charAt(i) != " " && s.charCodeAt(i) != 9 && s.charCodeAt(i) != 13 && s.charCodeAt(i) != 10)
			break;
	return s.substring(0, i+1);
}

function LTrim(s, trimContent)
{
	for (var i=0; i<s.length; i++)
		if (s.charAt(i) != " " && (!trimContent || (s.charCodeAt(i) != 9 && s.charCodeAt(i) != 13 && s.charCodeAt(i) != 10)))
			break;
	return s.substring(i, s.length);
}

function Trim(s, trimContent)
{
	var ts = LTrim(s);
	for (var i=ts.length-1; i>0; i--)
		if (ts.charAt(i) != " ")
			break;
	return ts.substring(0, i+1);
}

function TrimLeadingZero(s)
{
	for (var i=0; i<s.length; i++)
		if (s.charAt(i) != "0")
			break;
	return s.substring(i, s.length);
}

function Left(s, l)
{
	return s.substr(0, l);
}

function Right(s, l)
{
	return s.substr(s.length-l, l);
}


// DECISION FUNCTIONS ####################################################################

function IsEmpty(str)
{
	return (Trim(str).length == 0);
}

function testtest(s)
{
	return ((s == null) || (s.length == 0));
}

function IsDigit(d)
{
	return ((d >= "0") && (d <= "9"));
}

function IsAlpha(c)
{
	return ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z"));
}

function IsINT(str)
{
	var ptn = /^[+|-]?[\d]+$/;

	if (str.match(ptn))
		return true;
	else
		return false;
}

function IsUINT(str)
{
	var ptn = /^[\d]+$/;

	if (str.match(ptn))
		return true;
	else
		return false;
}

function IsFloat(str)
{
	var ptn = /^[+|-]?[\d]*[.]?[\d]+$/;

	if (str.match(ptn))
		return true;
	else
		return false;
}

function IsUFloat(str)
{
	var ptn = /^[\d]*[.]?[\d]+$/;

	if (str.match(ptn))
		return true;
	else
		return false;
}

function IsEmail(str)
{
	var ptn = /^(([\w-])+(\.))*([\w-])+(@)([\w-])+((\.)([\w-])+)+$/;

	if (str.match(ptn))
		return true;
	else
		return false;
}

function IsHKID(str)
{
	var iSum = 0;
	var iPos = 0;
	var i;
	var iMod;
	var iVChar;

	str = Trim(str.toUpperCase());

	if (str.length == 8 || str.length == 9 && (str.charAt(0) == " " || str.charAt(0) == "X"))
	{
		if (str.length == 9)
		{
			if (str.charAt(0) == "X")
				iSum += 6;
			iPos++;
		}
		iSum += (str.charCodeAt(iPos++) - 64) * 8;

		for (i=0; i<6; i++)
		{
			if (!IsDigit(str.charAt(iPos)))
				return false;
			else
				iSum += (str.charCodeAt(iPos++)-48) * (7-i);
		}

		iMod = 11 - (iSum % 11);
		iVChar = (iMod == 10 ? 65 : (iMod == 11 ? 48 : iMod+48));

		return (iVChar == str.charCodeAt(iPos));
	}
	else
		return false;
}

function IsStudentID(str)
{
	return (IsUINT(str) && str.length == 8);
}


// CONVERT FUNCTIONS #####################################################################

function IsHex(str)
{
	var i;
	var c;
	var s = str.toUpperCase();
	if (str.length)
	{
		for (i=0; i<s.length; i++)
		{
			c = s.charAt(i);
			if (!((c >= "0" && c <= "9") || (c >= "A" && c <= "F")))
				return false;
		}
		return true;
	}
	else
		return false;
}

function HexToInteger(str)
{
	var v = parseInt("0x" + str);

	if (!isNaN(v))
		return v;
	else
		return null;
}

function IntegerToHex(val)
{
	var hex = "0123456789ABCDEF";
	var n = val;
	var res = "";
	var smod;

	if (val > 0)
	{
		while (n > 0)
		{
			smod = n % 16;
			res = hex.charAt(smod) + res;
			n = (n - smod) / 16;
		}
	}
	else
		res = "0";

	return res;
}

// LIST FUNCTIONS ########################################################################

function ListLen(inlist, separator)
{
	var lst = inlist.split(separator ? separator : ",");

	if (Trim(inlist) != "")
		return lst.length;
	else
		return 0;
}

function ListFind(list, str, separator)
{
	return ArrayFind(list.split(separator ? separator : ","), str);
}

function ListFindNoCase(list, str, separator)
{
	return ArrayFindNoCase(list.split(separator ? separator : ","), str);
}

function ListGetAt(list, pos, separator)
{
	var lst = list.split(separator ? separator : ",");
	return (pos < lst.length ? lst[pos] : null);
}

function ListFirst(list, separator)
{
	return ListGetAt(list, 0, separator);
}

function ListLast(list, separator)
{
	var iLen = ListLen(list, separator);
	if (iLen)
		return ListGetAt(list, iLen-1, separator);
	else
		return null;
}

function ListAppend(list, str, separator)
{
	return (list + (list == "" ? "" : (separator ? separator : ",")) + str);
}

function ListToArray(list, separator)
{
	return list.split(separator ? separator : ",");
}

function ListDeleteAt(list, pos, separator)
{
	var lst = list.split(separator ? separator : ",");
	var i, res = "";
	for (i=0; i<lst.length; i++)
	{
		if (i != pos)
			res = ListAppend(res, lst[i], separator);
	}
	return res;
}

function ListRemoveItem(list, item, separator)
{
	var lst = list.split(separator ? separator : ",");
	var i, res = "";
	for (i=0; i<lst.length; i++)
	{
		if (lst[i].toUpperCase() != item.toUpperCase())
			res = ListAppend(res, lst[i], separator);
	}
	return res;
}

// URL FUNCTIONS #########################################################################

function GetURLParam(param, name)
{
	var i;

	for (i=0; i<ListLen(param, "&"); i++)
	{
		if (ListGetAt(ListGetAt(param, i, "&"), 0, "=").toUpperCase() == name.toUpperCase())
		{
			if (ListLen(ListGetAt(param, i, "&"), "=") == 2)
				return ListGetAt(ListGetAt(param, i, "&"), 1, "=");
			else
				return "";
		}
	}
}

function SetURLParam(param, name, value)
{
	var rp = "";
	var fnd = false;
	var i;

	for (i=0; i<ListLen(param, "&"); i++)
	{
		if (ListGetAt(ListGetAt(param, i, "&"), 0, "=").toUpperCase() == name.toUpperCase())
		{
			if (rp.length)
				rp = rp + "&" + name + "=" + value;
			else
				rp = name + "=" + value;
			fnd = true;
		}
		else
		{
			if (rp.length)
				rp = rp + "&" + ListGetAt(param, i, "&");
			else
				rp = ListGetAt(param, i, "&");
		}
	}
	if (!fnd)
	{
		if (param.length)
			rp = param + "&" + name + "=" + value;
		else
			rp = name + "=" + value;
	}
	return rp;
}

function RemoveURLParam(param, nameList)
{
	var i, j;
	var rp = "";
	var iP = ListLen(param, "&"), iN = ListLen(nameList);

	for (i=0; i<iP; i++)
	{
		for (j=0; j<iN; j++)
		{
			if (ListFindNoCase(ListGetAt(nameList, j), ListGetAt(ListGetAt(param, i, "&"), 0, "=")) != -1)
				break;
		}
		if (j == iN)
		{
			if (rp.length)
				rp += "&" + ListGetAt(param, i, "&");
			else
				rp = ListGetAt(param, i, "&");
		}
	}
	return rp;
}


// OBJECT FUNCTIONS ######################################################################

function ObjectClone(obj) {
	var key, newObj;

	if (obj) {
		switch (typeof(obj)) {
			case "object":
				if (typeof(obj.length) != "undefined") {
					newObj = new Array();
					for (key=0; key<obj.length; key++)
						newObj[key] = ObjectClone(obj[key]);
				} else {
					newObj = new Object();
					for (key in obj)
						newObj[key] = ObjectClone(obj[key]);
				}
			break;
			default:
				newObj = obj;
		}
	} else
		newObj = obj;

	return newObj;
}


// ARRAY FUNCTIONS #######################################################################

function ArrayFind(ary, str)
{
	var i;
	for (i=0; i<ary.length; i++)
		if (ary[i] == str)
			return i;
	return -1;
}

function ArrayFindNoCase(ary, str)
{
	var i;
	for (i=0; i<ary.length; i++)
		if (ary[i].toUpperCase() == str.toUpperCase())
			return i;
	return -1;
}

// DATE-TIME FUNCTIONS ###################################################################

/*
function CreateDate(inpara)
{
	var dteToCompare_A = /^(\d+)([-\/])(\d\d)(\2)(\d\d)$/.exec(inpara);
	var dteISODate_A = new Date(dteToCompare_A[1], dteToCompare_A[3]-1, dteToCompare_A[5]);

	return dteISODate_A;
}
*/

function CreateDate(strDate)
{
	var datePattern = /^(\d{4})(-)(\d{1,2})(-)(\d{1,2})$/;
	var result;
	var iDay, iMonth, iYear;

	if (IsDateFormat(strDate, "YYYY-MM-DD"))
	{
		result = strDate.match(datePattern);

		if (result && result[2] == result[4])
		{
			iDay   = parseInt(TrimLeadingZero(result[5]));
			iMonth = parseInt(TrimLeadingZero(result[3]));
			iYear  = parseInt(TrimLeadingZero(result[1]));
			return new Date(iYear, iMonth-1, iDay);
		}
		else
			return false;
	}
	else
		return false;
}

function MonthAsString(month)
{
	return ListGetAt("January,February,March,April,May,June,July,August,September,October,November,December", month-1);
}

function DayOfWeekAsString(day)
{
	return ListGetAt("Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", day-1);
}

function DayOfWeek(date)
{
	return date.getDay();
}

function DateDiff(part, date1, date2)
{
	var dif = Date.parse(date1) - Date.parse(date2);
	switch (part.toUpperCase())
	{
		case "D": return dif / (24*60*60*1000);
		case "H": return dif / (60*60*1000);
		case "N": return dif / (60*1000);
		case "S": return dif / (1000);
	}
	return null;
}

function DateSub(part, date, unit)
{
	var pd = Date.parse(date);
	switch (part.toUpperCase())
	{
		case "Y":
			pd = new Date(pd);
			return new Date(pd.setFullYear(pd.getFullYear()-unit));
		case "M":
			pd = new Date(pd);
			return new Date(pd.setMonth(pd.getMonth()-unit));
		case "D":
			return new Date(pd-(unit*24*60*60*1000));
		case "H":
			return new Date(pd-(unit*60*60*1000));
		case "N":
			return new Date(pd-(unit*60*1000));
		case "S":
			return new Date(pd-(unit*1000));
	}
}

function DateAdd(part, date, unit)
{
	var pd = Date.parse(date);
	switch (part.toUpperCase())
	{
		case "Y":
			pd = new Date(pd);
			return new Date(pd.setFullYear(pd.getFullYear()+unit));
		case "M":
			pd = new Date(pd);
			return new Date(pd.setMonth(pd.getMonth()+unit));
		case "D":
			return new Date(pd+(unit*24*60*60*1000));
		case "H":
			return new Date(pd+(unit*60*60*1000));
		case "N":
			return new Date(pd+(unit*60*1000));
		case "S":
			return new Date(pd+(unit*1000));
	}
}

function IsLeapYear(year)
{
	return (((year % 4 == 0) && (year % 100 != 0)) || year % 400 == 0);
}

function DaysInMonth(year, month)
{
	var d = -1;

	if (month >= 1 && month <= 12)
	{
		d = (month == 4 || month == 6 || month == 9 || month == 11) ? 30 : 31;

		if (month == 2)
			d = (IsLeapYear(year) ? 29 : 28);
	}
	return d;
}

function DaysInYear(year)
{
	return (IsLeapYear(year) ? 29 : 28) + 337;
}

function DateFormat(indate, mask)
{
	var d = " " + mask.toUpperCase() + " ";
	d = d.replace(/([^a-zA-Z])(YYYY)([^a-zA-Z])/g, "$1"+indate.getFullYear()+"$3");
	d = d.replace(/([^a-zA-Z])(YY)([^a-zA-Z])/g, "$1"+indate.getYear()+"$3");
	d = d.replace(/([^a-zA-Z])(MMMM)([^a-zA-Z])/g, "$1"+MonthAsString(indate.getMonth()+1)+"$3");
	d = d.replace(/([^a-zA-Z])(MMM)([^a-zA-Z])/g, "$1"+MonthAsString(indate.getMonth()+1).substr(0, 3)+"$3");
	d = d.replace(/([^a-zA-Z])(MM)([^a-zA-Z])/g, "$1"+(indate.getMonth()+1<10?"0":"")+(indate.getMonth()+1)+"$3");
	d = d.replace(/([^a-zA-Z])(M)([^a-zA-Z])/g, "$1"+(indate.getMonth()+1)+"$3");
	d = d.replace(/([^a-zA-Z])(DDDD)([^a-zA-Z])/g, "$1"+DayOfWeekAsString(indate.getDay())+"$3");
	d = d.replace(/([^a-zA-Z])(DDD)([^a-zA-Z])/g, "$1"+DayOfWeekAsString(indate.getDay())+"$3");
	d = d.replace(/([^a-zA-Z])(DD)([^a-zA-Z])/g, "$1"+(indate.getDate()<10?"0":"")+indate.getDate()+"$3");
	d = d.replace(/([^a-zA-Z])(D)([^a-zA-Z])/g, "$1"+indate.getDate()+"$3");
	return Trim(d);
}

function TimeFormat(date, mask)
{
	var d = " " + mask + " ";
	var hour12 = date.getHours() % 12 + (date.getHours() == 12 ? 12 : 0);
	var i;

	d = d.replace(/([^a-zA-Z])(HH)([^a-zA-Z])/g, "$1"+(date.getHours()<10?"0":"")+date.getHours()+"$3");
	d = d.replace(/([^a-zA-Z])(H)([^a-zA-Z])/g, "$1"+date.getHours()+"$3");
	d = d.replace(/([^a-zA-Z])(hh)([^a-zA-Z])/g, "$1"+(hour12<10?"0":"")+hour12+"$3");
	d = d.replace(/([^a-zA-Z])(h)([^a-zA-Z])/g, "$1"+hour12+"$3");
	d = d.replace(/([^a-zA-Z])(MM)([^a-zA-Z])/ig, "$1"+(date.getMinutes()<10?"0":"")+date.getMinutes()+"$3");
	d = d.replace(/([^a-zA-Z])(M)([^a-zA-Z])/ig, "$1"+date.getMinutes()+"$3");
	d = d.replace(/([^a-zA-Z])(SS)([^a-zA-Z])/ig, "$1"+(date.getSeconds()<10?"0":"")+date.getSeconds()+"$3");
	d = d.replace(/([^a-zA-Z])(S)([^a-zA-Z])/ig, "$1"+date.getSeconds()+"$3");
	d = d.replace(/([^a-zA-Z])(TT)([^a-zA-Z])/ig, "$1"+(date.getHours()<12?"AM":"PM")+"$3");
	d = d.replace(/([^a-zA-Z])(T)([^a-zA-Z])/ig, "$1"+(date.getHours()<12?"A":"P")+"$3");
	return Trim(d);
}

function IsDateFormat(date, mask)
{
	var d, m, s, i, tmp;
	var dm = new Array();

	if (ListLen(mask, "-") == 3)
	{
		m = ListToArray(mask, "-");
		s = "-";
	}
	else
	if (ListLen(mask, "/") == 3)
	{
		m = ListToArray(mask, "/");
		s = "/";
	}
	else
		return false;

	if (ListLen(date, s) == 3)
	{
		d = ListToArray(date, s);
		dm = new Object();
		dm.y = 0;
		dm.m = 0;
		dm.d = 0;
		for (i=0; i<3; i++)
		{
			if (IsUINT(d[i]))
			{
				switch (m[i].toUpperCase())
				{
					case "Y": case "YYYY":
						if (d[i].length == 4)
							dm.y = parseInt(d[i]);
						else
							return false;
					break;
					case "MM":
					case "DD":
						if (d[i].length == 2)
						{
							if (d[i].substr(0, 1) == "0")
								d[i] = d[i].substr(1, 1);
						}
						else
							return false;
					case "M":
					case "D":
						tmp = parseInt(TrimLeadingZero(d[i]));
						switch (m[i].toUpperCase())
						{
							case "MM":
							case "M":
								if (tmp >= 1 && tmp <= 12)
									dm.m = tmp;
								else
									return false;
							break;
							case "DD":
							case "D":
								if (tmp >= 1 && tmp <= 31)
									dm.d = tmp;
								else
									return false;
							break;
						}
					break;
					default: return false;
				}
			}
			else
				return false;
		}
		tmp = new Date(dm.y, dm.m-1, dm.d);
		return (tmp.getFullYear() == dm.y && tmp.getMonth() == dm.m-1 && tmp.getDate() == dm.d);
	}
	else
		return false;
}


function IsTimeFormat(t, mask)
{
	/*
		Mask example:
		HH:mm            ---- 24 hour format
		hh:mm tt / hh:mm ---- 12 hour format
		hh:mm:sstt       ---- e.g. 12:24:00am

		Hour, minute & second must separate by ":"...
	*/

	var strTime = Trim(t).toUpperCase();
	var strMask = Trim(mask).toUpperCase();
	var ptn;
	var res;
	var oP1, oP2;
	var i;
	var iPart;

	ptn = strMask.replace("HH", "\\d{2}");
	ptn = ptn.replace("H", "\\d{1,2}");
	ptn = ptn.replace("MM", "\\d{2}");
	ptn = ptn.replace("M", "\\d{1,2}");
	ptn = ptn.replace("SS", "\\d{2}");
	ptn = ptn.replace("S", "\\d{1,2}");
	ptn = ptn.replace("TT", "(AM|PM)");

	res = strTime.match(ptn);

	if (res && strTime == res[0])
	{
		res = strTime.match("\\d{1,2}((:)\\d{1,2})*");

		for (i=0; i<ListLen(res[0], ":"); i++)
		{
			iPart = parseInt(TrimLeadingZero(ListGetAt(res[0], i, ":")));
			if (iPart < 0 || iPart > 59)
				return false;
		}
		mask = Trim(mask);
		oP1 = strTime.match("\\d{2}");
		oP2 = strTime.match("\\d{1,2}");
		if (oP2)
			iPart = parseInt(TrimLeadingZero(oP2[0]));

		if ((mask.search("hh") == 0 && oP1 != null || mask.search("h") == 0 && oP2 != null) && iPart >= 1 && iPart <= 12)
			return true;
		else
		if ((mask.search("HH") == 0 && oP1 != null || mask.search("H") == 0 && oP2 != null) && iPart >= 0 && iPart <= 23)
			return true;
	}
	return false;
}

function IsTime(s, is12Hr) // ********* Private function, please do not use it directly, use IsTime12 or IsTime24 instead!!!!!!
{
	var ptn, h, m, s;

	if (is12Hr)
		var ptn = /^(\d{1,2})(:)(\d{1,2})(:)(\d{1,2})( )*(AM|PM)?$/;
	else
		var ptn = /^(\d{1,2})(:)(\d{1,2})(:)(\d{1,2})$/;

	var res = s.toUpperCase().match(ptn);

	if (res)
	{
		var h = parseInt(res[1]) == 0 ? 0 : parseInt(TrimLeadingZero(res[1]));
		var m = parseInt(res[3]) == 0 ? 0 : parseInt(TrimLeadingZero(res[3]));
		var s = parseInt(res[5]) == 0 ? 0 : parseInt(TrimLeadingZero(res[5]));

		if (h <= (is12Hr ? 12 : 23) && m <= 59 && s <= 59)
			return true;
		else
			return false;
	}
	else
		return false;
}

function IsTime12(s)
{
	return IsTime(s, true);
}

function IsTime24(s)
{
	return IsTime(s, false);
}

// LAYOUT FORMAT FUNCTIONS ###############################################################

/* Reserved ---------------------------------*/
/*
function LinkContent()
{
	var oClient = arguments;
	var i;
	var strContent;

	if (oClient.length)
	{
		strContent = oClient[0].innerHTML;
		oClient[0].innerHTML = "";

		alert(oClient[0].clientWidth + ", " + oClient[0].clientHeight);
	}
}
*/

// COOKIE FUNCTIONS ######################################################################

function SetCookie(name, value, expiresTime, path)
{
	var t, tu;
	var now = new Date();

	if (expiresTime)
	{
		tu = expiresTime.charAt(expiresTime.length - 1);

		if (tu.toUpperCase() == "D")
			t = parseInt(TrimLeadingZero(expiresTime)) * 24 * 3600 * 1000;
		else
		if (tu.toUpperCase() == "H")
			t = parseInt(TrimLeadingZero(expiresTime)) * 3600 * 1000;
		else
		if (tu.toUpperCase() == "M")
			t = parseInt(TrimLeadingZero(expiresTime)) * 60 * 1000;
		else
			t = parseInt(TrimLeadingZero(expiresTime));

		now.setTime(now.getTime() + t);
	}
	document.cookie = name + "=" + escape(value) + (expiresTime ? "; expires=" + now.toGMTString() : "") + (path ? "; path=" + path : "");
	return GetCookie(name);
}

function DeleteCookie(name)
{
	if (GetCookie(name))
		document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT";
}

function GetCookie(name)
{
	var s1, s2;
	if (document.cookie)
	{
		s1 = document.cookie.indexOf(name + "=");

		if (s1 >= 0)
		{
			s1 += name.length + 1;
			s2 = document.cookie.indexOf(";", s1);

			if (s2 == -1)
				s2 = document.cookie.length;
			return unescape(document.cookie.substring(s1, s2));
		}
	}
	return null;
}

// LAYOUT FUNCTIONS ######################################################################

function GetObjectX(obj)
{
	/*
	var p = obj;
	var d = 0;

	if (p)
		while (p != document.body)
		{
			d += p.offsetLeft;
			if (p != obj)
				d += (p.offsetWidth - p.clientWidth) / 2;

			p = p.offsetParent;
		}
	return d;
	*/
	// copy from the new framework...
	var p = obj;
	var b, d = 0;
	while (p) {
		d += p.offsetLeft - (p.scrollLeft != null ? p.scrollLeft : 0);
		b = parseInt(p.style.borderLeftWidth);
		if (!isNaN(b))
			d += b;
		p = p.offsetParent;
	}
	return d+document.body.scrollLeft;
}

function GetObjectY(obj)
{
	/*
	var p = obj;
	var d = 0;

	if (p)
		while (p != document.body)
		{
			d += p.offsetTop;
			if (p != obj)
				d += (p.offsetHeight - p.clientHeight) / 2;

			p = p.offsetParent;
		}
	return d;
	*/
	// copy from the new framework...
	var p = obj;
	var b, d = 0;
	while (p) {
		d += p.offsetTop - (p.scrollTop != null ? p.scrollTop : 0);
		b = parseInt(p.style.borderTopWidth);
		if (!isNaN(b))
			d += b;
		p = p.offsetParent;
	}
	return d+document.body.scrollTop;
}

function HighlightObject(obj, color)
{
	var iGap = 0;
	var iBorderWidth = 2;
	var d;

	if (obj && IsMSIE() && color != "")
	{
		if (!GetByID("XF_FORMFIELD_HLOBJ"))
		{
			d = document.createElement("div");
			d.style.padding = "0px";
			d.style.margin = "0px";
			d.style.borderStyle = "solid";
			d.style.borderWidth = iBorderWidth + "px"
			d.style.position = "absolute";
			d.id = "XF_FORMFIELD_HLOBJ";
			d.onclick = new Function("var obj=GetByID('XF_FORMFIELD_HLOBJ');FocusField(obj.currentObject)");
			document.body.appendChild(d);
		}
		else
		{
			d = GetByID("XF_FORMFIELD_HLOBJ");
			d.style.display = "";
			d.style.visibility = "visible";
		}

		d.currentObject = obj;
		d.style.borderColor = (color ? color : "red");
		d.style.pixelTop = GetObjectY(obj) - (iGap + iBorderWidth);
		d.style.pixelLeft = GetObjectX(obj) - (iGap + iBorderWidth);
		d.style.width = obj.offsetWidth + (iGap + iBorderWidth) * 2;
		d.style.height = obj.offsetHeight + (iGap + iBorderWidth) * 2;
	}
}

function HighlightRange(obj1, obj2, color)
{
	var iGap = 1;
	var iBorderWidth = 2;
	var d;
	var x1, x2, y1, y2;
	var iWidth, iHeight;

	if (obj1 && obj2 && IsMSIE())
	{
		x1 = GetObjectX(obj1);
		y1 = GetObjectY(obj1);
		x2 = GetObjectX(obj2);
		y2 = GetObjectY(obj2);

		HighlightObject(obj1, color);
		d = GetByID("XF_FORMFIELD_HLOBJ");

		if (x1 > x2)
		{
			d.style.pixelLeft = x2 - (iGap + iBorderWidth);
			iWidth = x1 - x2 + obj1.offsetWidth + (iGap + iBorderWidth) * 2;
		}
		else
			iWidth = x2 - x1 + obj2.offsetWidth + (iGap + iBorderWidth) * 2;

		if (y1 > y2)
		{
			d.style.pixelTop = y2 - (iGap + iBorderWidth);
			iHeight = y1 - y2 + obj1.offsetHeight + (iGap + iBorderWidth) * 2;
		}
		else
			iHeight = y2 - y1 + obj2.offsetHeight + (iGap + iBorderWidth) * 2;

		d.style.width = iWidth;
		d.style.height = iHeight;
	}
}

function KillHighlight()
{
	var d = GetByID("XF_FORMFIELD_HLOBJ");
	if (d && IsMSIE())
	{
		d.style.display = "none";
		d.style.visibility = "hidden";
	}
}

/*
function OverlayObject(obj, message)
{
	var d = GetByID("XF_OVERLAY_OBJ");

	if (obj && IsMSIE())
	{
		if (!d)
		{
			d = document.createElement("div");
			d.style.padding = "0px";
			d.style.margin = "0px";
			d.style.position = "absolute";
			d.id = "XF_OVERLAY_OBJ";
			d.innerHTML = message;
			document.body.appendChild(d);
		}

		d.style.display = "";
		d.style.visibility = "visible";

		d.currentObject = obj;
		d.style.pixelTop = GetObjectY(obj);
		d.style.pixelLeft = GetObjectX(obj);
		d.style.width = obj.offsetWidth;
		d.style.height = obj.offsetHeight;
	}
}

function KillOverlay()
{
	var d = GetByID("XF_OVERLAY_OBJ");
	if (d && IsMSIE())
	{
		d.style.display = "none";
		d.style.visibilitiy = "hidden";
	}
}
*/


// FORM-FIELD FUNCTIONS ##################################################################

function GetObjectAsArray(obj, index)
{
	var aryObj = new Array();
	if (GetObjectLengthAsArray(obj) > index)
	{
		if (obj.length == null || (obj.type != null && obj.type == "select-one" && obj.options))
			return obj;
		else
			return obj[index];
	}
	else
		return null;
}

function GetObjectLengthAsArray(obj)
{
	if (obj)
	{
		if (obj.length == null || (obj.type != null && obj.type == "select-one" && obj.options))
			return 1;
		else
			return obj.length;
	}
	else
		return -1;

	return (obj ? (obj.length==null?1:obj.length) : -1);
}

function GetFieldType(field)
{
	if (field)
	{
		if (field.type)
			return field.type.toUpperCase();
		else
		if (field.length && field[0].type)
			return field[0].type.toUpperCase();
	}
	else
		return "";
}

function GetFieldValue(field)
{
	var strType = GetFieldType(field);
	var strValue = "";

	if (strType.length)
	{
		switch (strType)
		{
			case "TEXT": case "TEXTAREA": case "PASSWORD": case "HIDDEN": case "FILE":
				return field.value;
			break;
			case "CHECKBOX": case "RADIO":
				if (field.length)
				{
					for (i=0; i<field.length; i++)
						if (field[i].checked)
							strValue += (strValue.length ? "," : "") + field[i].value;
					return strValue;
				}
				else
					return (field.checked ? field.value : "");
			break;
			case "SELECT-ONE":
				return field.options[field.selectedIndex].value;
			break;
			case "SELECT-MULTIPLE":
			break;
			default:
				alert("Error occurred in GetFieldValue() - Unsupport field type '"+strType+"'");
				return false;
			break;
		}
	}
}

function FocusField(field)
{
	if (field && (!field.type || field.type != 'hidden'))
	{
		if (field.focus)
			field.focus();

		if (!field.options && field.select)
			field.select();
	}
}

function FieldError(field, errMsg, color)
{
	var iY = GetObjectY(field);
	var strType = GetFieldType(field);

	switch (strType)
	{
		case "BUTTON": break;
		default: FocusField(field);
	}

	if (IsMSIE())
	{
		HighlightObject(field, color);

		if (iY - document.body.scrollTop < 30)
			document.body.scrollTop -= 30 - (iY - document.body.scrollTop);
		else
		if (document.body.scrollTop + document.body.clientHeight < iY + 90)
			document.body.scrollTop = iY + 90 - document.body.clientHeight;
	}
	if (errMsg)
		alert(errMsg);
	if (IsMSIE())
		KillHighlight();

	return false;
}

function FieldErrorRange(field1, field2, errMsg, color)
{
	var iY = GetObjectY(field1);
	var strType = GetFieldType(field1);

	switch (strType)
	{
		case "BUTTON": break;
		default: FocusField(field1);
	}

	if (IsMSIE())
	{
		HighlightRange(field1, field2, color);

		if (iY - document.body.scrollTop < 30)
			document.body.scrollTop -= 30 - (iY - document.body.scrollTop);
		else
		if (document.body.scrollTop +document.body.clientHeight < iY + 90)
			document.body.scrollTop = iY + 90 - document.body.clientHeight;
	}
	if (errMsg)
		alert(errMsg);
	if (IsMSIE())
		KillHighlight();

	return false;
}

function GetSelectedRadioObj(field)
{
	if (field)
	{
		if (field.length)
		{
			for (i=0; i<field.length; i++)
				if (field[i].checked)
					return field[i];
		}
		else
			return (field.checked ? field : null);
	}
	return null;
}

function IsEmptyField(field)
{
	var i;
	var strType = GetFieldType(field);

	if (strType.length)
	{
		if (field.type)
			strType = field.type.toUpperCase();
		else
		if (field.length && field[0].type)
			strType = field[0].type.toUpperCase();
		switch (strType)
		{
			case "TEXT": case "TEXTAREA": case "PASSWORD": case "FILE": case "HIDDEN":
				return IsEmpty(field.value);
			case "CHECKBOX": case "RADIO":
				if (field.length)
				{
					for (i=0; i<field.length; i++)
						if (field[i].checked)
							return false;
				}
				else
					return !field.checked;
			break;
			case "SELECT-ONE": case "SELECT-MULTIPLE":
				return IsEmpty(field.options[field.selectedIndex].value);
			break;
		}
	}
	return true;
}


// CSS / STYLE FUNCTIONS #################################################################

function GetGlobalCSSRule(tagName)
{
	var oRules;
	var i, j;

	for (i=0; i<document.styleSheets.length; i++)
	{
		oRules = document.styleSheets[i].rules;
		for (j=0; j<oRules.length; j++)
		{
			if (oRules.item(j).selectorText.toUpperCase() == tagName.toUpperCase())
				return oRules.item(j);
		}
	}
	return null;
}

function RemoveGlobalCSSRule(htmlTags)
{
	RemoveGlobalCSSSimilarRule(htmlTags, true);
}

function RemoveGlobalCSSSimilarRule(htmlTags, mustExactly)
{
	var iLen = ListLen(htmlTags);
	var oRules;
	var strRuleName;
	var strTagName;
	var i, j, k;

	for (i=0; i<document.styleSheets.length; i++)
	{
		oRules = document.styleSheets[i].rules;
		j = 0;
		while (j < oRules.length)
		{
			strRuleName = oRules.item(j).selectorText.toUpperCase();
			for (k=0; k<iLen; k++)
			{
				strTagName = ListGetAt(htmlTags, k).toUpperCase();

				if (strRuleName == strTagName ||
					!mustExactly &&
					(
					strRuleName.substr(0, strTagName.length+1) == strTagName+"." ||
					strRuleName.substr(0, strTagName.length+1) == strTagName+"#" ||
					strRuleName.substr(0, strTagName.length+1) == strTagName+" " ||
					strRuleName.substr(strRuleName.length-strTagName.length-1, strRuleName.length) == " "+strTagName
					))
				{
					document.styleSheets[i].removeRule(j);
					break;
				}
			}
			if (k == iLen)
				j++;
		}
	}
}

function ReplaceGlobalCSSRuleName(srcName, descName)
{
	var oRules;
	var i, j;
	for (i=0; i<document.styleSheets.length; i++)
	{
		oRules = document.styleSheets[i].rules;
		j = 0;
		while (j < oRules.length)
		{
			if (oRules.item(j).selectorText.toUpperCase() == srcName.toUpperCase())
			{
				document.styleSheets[i].addRule(descName, oRules.item(j).style.cssText);
				document.styleSheets[i].removeRule(j);
			}
			else
				j++;
		}
	}
}

function ListGlobalCSSRule()
{
	var oRules;
	var i, j;

	for (i=0; i<document.styleSheets.length; i++)
	{
		oRules = document.styleSheets[i].rules;
		document.writeln("Stylesheet " + i + "-------------------------------------------" + '<br/>');
		for (j=0; j<oRules.length; j++)
		{
			document.writeln(j + ": " + oRules.item(j).selectorText + '<br/>');
		}
	}
}


// ONLOAD FUNCTIONS ######################################################################

// FOR XFRM 2.0....
function XAddOnLoadFunc(func, priority)
{
	var qry = document.ONLOAD_CONTROL;
	if (!qry)
	{
		qry = { h:new Array(), n:new Array(), l:new Array(), o:window.onload };
		window.onload = function()
		{
			var i, c = qry;
			for (i=0; i<c.h.length; i++) c.h[i]();
			for (i=0; i<c.n.length; i++) c.n[i]();
			if (c.o) c.o();
			for (i=0; i<c.l.length; i++) c.l[i]();
		}
		document.ONLOAD_CONTROL = qry;
	}
	switch (priority.toUpperCase())
	{
		case "HIGH": qry.h[qry.h.length] = func; break;
		case "LOW": qry.l[qry.l.length] = func; break;
		default: qry.n[qry.n.length] = func;
	}
}

// [ BEGIN ] DEPRECIATED FUNCTIONS... DON'T USE IT AND DON'T REMOVE IT!! =============
function AppendOnLoadMethod(func)
{
	if (!document.onLoadFuncQuery)
	{
		document.onLoadFuncQuery = new Array();
		document.oldOnLoadFunc = window.onload;
		window.onload = function()
		{
			if (document.oldOnLoadFunc)
				document.oldOnLoadFunc();
			SYSTEM_AutoOnLoadMethod();
		}
	}
	document.onLoadFuncQuery[document.onLoadFuncQuery.length] = func;
}

function SYSTEM_AutoOnLoadMethod()
{
	var i;
	if (document.onLoadFuncQuery)
	{
		for (i=0; i<document.onLoadFuncQuery.length; i++)
			document.onLoadFuncQuery[i]();
	}
}
// [ END ] ==============================================================================

function AddOnLoadFunc(func, pos)
{
	if (!document.onLoadFuncQuery_BEGIN)
	{
		document.onLoadFuncQuery_BEGIN = new Array();
		document.onLoadFuncQuery_END = new Array();
	}

	if (pos && pos.toUpperCase() == "BEGIN")
		document.onLoadFuncQuery_BEGIN[document.onLoadFuncQuery_BEGIN.length] = func;
	else
		document.onLoadFuncQuery_END[document.onLoadFuncQuery_END.length] = func;
}

function ProcessOnLoadFunc(pos)
{
	var i;
	if (document.onLoadFuncQuery_BEGIN)
	{
		if (pos && pos.toUpperCase() == "BEGIN")
		{
			for (i=0; i<document.onLoadFuncQuery_BEGIN.length; i++)
				document.onLoadFuncQuery_BEGIN[i]();
		}
		else
		{
			for (i=0; i<document.onLoadFuncQuery_END.length; i++)
				document.onLoadFuncQuery_END[i]();
		}
	}
}

function AddOnUnloadFunc(func, pos)
{
	if (!document.onUnloadFuncQuery_BEGIN)
	{
		document.onUnloadFuncQuery_BEGIN = new Array();
		document.onUnloadFuncQuery_END = new Array();
	}
	if (pos && pos.toUpperCase() == "BEGIN")
		document.onUnloadFuncQuery_BEGIN[document.onUnloadFuncQuery_BEGIN.length] = func;
	else
		document.onUnloadFuncQuery_END[document.onUnloadFuncQuery_END.length] = func;
}

function ProcessOnUnloadFunc(pos)
{
	var i;
	if (document.onUnloadFuncQuery_BEGIN)
	{
		if (pos.toUpperCase() == "BEGIN")
		{
			for (i=0; i<document.onUnloadFuncQuery_BEGIN.length; i++)
				document.onUnloadFuncQuery_BEGIN[i]();
		}
		else
		{
			for (i=0; i<document.onUnloadFuncQuery_END.length; i++)
				document.onUnloadFuncQuery_END[i]();
		}
	}
}


// MATHS FUNCTIONS #######################################################################

function RandRange(iStart, iEnd)
{
	var iRandNum = parseInt(Math.random()/1 * (iEnd - iStart + 1)) + iStart;

	return (iRandNum > iEnd ? iEnd : iRandNum);
}