/* Browser Detection */
var BrowserDetect={
	init: function () {
		this.browser=this.searchString(this.dataBrowser) || "An unknown browser";
		this.version=this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS=this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString=data[i].string;
			var dataProp=data[i].prop;
			this.versionSearchString=data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index=dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

/* Mis functions */
function isValidObject(objToTest)
{
	if (null==objToTest)
		return false;
	if ("undefined"==typeof(objToTest))
		return false;
	return true;
}
function showElem(sId,bShow)
{
	var elem=document.getElementById(sId);
	if (elem)
		elem.style.display=(bShow?"":"none");
}
function isElemShown(sId)
{
	var bIsShown=true;
	var elem=document.getElementById(sId);
	if (elem&&elem.style&&elem.style.display)
		bIsShown=(elem.style.display!="none");
	return bIsShown;
}
function enableElem(sId,bEnable)
{
	var elem=document.getElementById(sId);
	if (elem)
		elem.disabled=!bEnable;
}
function readOnlyElem(sId,bReadOnly)
{
	var elem=document.getElementById(sId);
	if (elem)
		elem.readOnly=bReadOnly;
}
function elemAddStyle(elem,sStyle)
{
	if ((!elem)||(!sStyle))
		return;
	var sOldStyle=elem.style.cssText;
	if (sOldStyle==null)
		sOldStyle="";
	if (sOldStyle.length>0)
		sOldStyle=sOldStyle+";";
	elem.style.cssText=sOldStyle+sStyle;
}
function elemRemStyle(elem,sStyle)
{
	if ((!elem)||(!sStyle))
		return;
	var sOldStyle=elem.style.cssText;
	if (!sOldStyle)
		return;
	var idx=sOldStyle.toLowerCase().indexOf(sStyle.toLowerCase());
	if (idx>-1)
	{
		var idx2=sOldStyle.indexOf(idx+sStyle.length,";");
		if (idx2>-1)
			sOldStyle=sOldStyle.substring(0,idx)+sOldStyle.substring(idx2+1,sOldStyle.length);
		else
			sOldStyle=sOldStyle.substring(0,idx);
	}
	elem.style.cssText=sOldStyle;
}
function formFocusFirst(f)
{
	var iLen=((f!=null)?f.length:0);
	for (var i=0;i<iLen;i++)
	{
		if (formSafeFocus(f[i],false))
			break;
	}
}
// Returns lower case form input field type, e.g. "text", "checkbox", etc.
function formGetFieldType(elem)
{
	var sType=null;
	if ((elem!=null)&&elem.type)
		sType=elem.type.toLowerCase();
	return sType;
}
function formSafeFocus(f,bSel)
{
	if (!f)
		return false;
	if (f.style&&f.style.display&&f.style.display=='none')
		return false;
	if (!f.type)
		return false;
	if ((f.type=="password")||(f.type=="textarea")||(f.type=="text")
		||(f.type=="file")||(f.type=="checkbox")||(f.type=="radio")
		||(f.type=="select-one")||(f.type=="select-multiple"))
	{
		if (!f.disabled)
		{
			if (bSel&&f.select)
				f.select();
			if (f.focus)
				f.focus();
			return true;
		}
	}
	return false;
}
// Copy value of one form field to another field
function formCopyField(f1,f2)
{
	if ((f1==null)||(f2==null))
		return;

	// Get types
	var t1=f1.type;
	if ((!t1)&&f1.length)
		t1=f1[0].type;
	var t2=f2.type;
	if ((!t2)&&f2.length)
		t2=f2[0].type;
	if ((!t1)||(!t2))
		return;
	t1=t1.toLowerCase();
	t2=t2.toLowerCase();

	// Get values
	var v=new Array();
	if ((t1=="checkbox")||(t1=="radio"))
	{
		if (f1.length)
		{
			for (var i=0;i<f1.length;i++)
			{
				if (f1[i].checked)
					v[v.length]=f1[i].value;
			}
		}
		else
		{
			if (f1.checked)
				v[0]=f1.value;
		}
	}
	else if ((t1=="select-one")||(t1=="select-multiple"))
	{
		for (var i=0;i<f1.options.length;i++)
		{
			if (f1.options[i].selected)
				v[v.length]=f1.options[i].value;
		}
	}
	else
	{
		v[0]=f1.value;
	}

	// Set values
	if ((t2=="checkbox")||(t2=="radio"))
	{
		if (f2.length)
		{
			for (var j=0;j<f2.length;j++)
			{
				f2[j].checked=false;
				for (var i=0;i<v.length;i++)
				{
					if (f2[j].value.toLowerCase()==v[i].toLowerCase())
						f2[j].checked=true;
				}
			}
		}
		else
		{
			f2.checked=false;
			for (var i=0;i<v.length;i++)
			{
				if (f2.value.toLowerCase()==v[i].toLowerCase())
					f2.checked=true;
			}
		}
	}
	else if ((t2=="select-one")||(t2=="select-multiple"))
	{
		for (var j=0;j<f2.options.length;j++)
		{
			f2.options[j].selected=false;
			for (var i=0;i<v.length;i++)
			{
				if (f2.options[j].value.toLowerCase()==v[i].toLowerCase())
					f2.options[j].selected=true;
			}
		}
	}
	else
	{
		var s="";
		for (var i=0;i<v.length;i++)
		{
			if (i>0)
				s+=";";
			s+=v[i];
		}
		f2.value=s;
	}
}
function windowPopup(sUrl,sWinName,sWinProps,iW,iH,parWin)
{
	// return a new window centered over parWin.
	// if parWin null then centered in display.
	// get browser
	var agt=navigator.userAgent.toLowerCase();
	var bIsIE=((agt.indexOf("msie")!=-1)&&(agt.indexOf("opera")==-1));
	// get screen dim
	var xMax=800;
	var yMax=600;
	if (bIsIE)
	{
		xMax=screen.width;
		yMax=screen.height;
	}
	else
	{
		xMax=window.outerWidth;
		yMax=window.outerHeight;
	}
	// get par win coords
	var xL=0;
	var xR=xMax;
	var yT=0;
	var yB=yMax;
	if (parWin!=null)
	{
		if (bIsIE)
		{
			xL=parWin.screenLeft;
			xR=xL+parWin.document.body.clientWidth;
			yT=parWin.screenTop;
			yB=yT+parWin.document.body.clientHeight;
		}
		else
		{
			xL=parWin.screenX;
			xR=xL+parWin.outerWidth;
			yT=parWin.screenY;
			yB=yT+parWin.outerHeight;
		}
	}
	// calc left,top of new win
	var xM=(xL+xR)/2;
	var yM=(yT+yB)/2;
	var iL=xM-(iW/2);
	var iT=yM-(iH/2);
	// pin in screen
	if (iL<10)
		iL=10;
	if (iT<10)
		iT=10;
	// create new win
	var sLocProps='height='+iH+',width='+iW+',top='+iT+',left='+iL;
	if (sWinProps==null)
		sWinProps="";
	if (sWinProps.length>0)
		sWinProps+=",";
	sWinProps+=sLocProps;
	var win=window.open(sUrl,sWinName,sWinProps);
	return win;
}
/* Select the value in the list.
   Returns the index of the new selection, or -1 if val not found.
*/
function selectSetSelection(sel,val)
{
	if (sel==null||val==null)
		return -1;
	var iSel=-1;
	val=val+"";
	var iOpts=sel.options.length;
	for (var i=0;i<iOpts;i++)
	{
		if (sel.options[i].value==val)
		{
			sel.selectedIndex=iSel=i;
			break;
		}
	}
	return iSel;
}
/* Select functions from http://www.babailiica.com/js/sorter/sort.js
   Param: obj -> Either select object or id of select object 
*/
function selectAddItem(obj,text,value,index,selected,id,classname,color,bg)
{
	if (obj.options.length>1000) // Always add to end for long lists
	{
		var opt=new Option(text,value);
		opt.selected=selected;
		obj.options[obj.options.length]=opt;
		return;
	}
	obj=(typeof obj == "string") ? document.getElementById(obj) : obj;
	if (obj.tagName.toLowerCase() != "select")
		return;
	obj.length++;
	if (typeof index == "number" && index < obj.length-1) {
		var i=Number();
		for (i=obj.length-2; i>index-1; i--) {
			obj[i+1].text=obj[i].text;
			obj[i+1].value=obj[i].value;
			obj[i+1].id=obj[i].id;
			obj[i+1].className=obj[i].className;
			obj[i+1].style.color=obj[i].style.color;
			obj[i+1].style.backgroundColor=obj[i].style.backgroundColor;
			obj[i+1].selected=obj[i].selected;
		}
	} else {
		index=obj.length - 1;
	}
	obj=obj[index];
	obj.text=text;
	obj.value=value;
	obj.id=id ? id : '';
	obj.className=classname ? classname : '';
	obj.style.color=color ? color : '';
	obj.style.backgroundColor=bg ? bg : '';
	obj.selected=selected
}
/* Move selected items in select up. Pass in select, it will do rest
   Param: obj -> Either select object or id of select object 
*/
function selectUp(obj) { /*updated from version 1.2*/
	obj=(typeof obj == "string") ? document.getElementById(obj) : obj;
	if (obj.tagName.toLowerCase() != "select" && obj.length < 2)
		return false;
	var sel=new Array();
	for (var i=0; i<obj.length; i++) {
		if (obj[i].selected == true) {
			sel[sel.length]=i;
		}
	}
	for (var i=0; i<sel.length;i++) {
		if (sel[i] != 0 && !obj[sel[i]-1].selected) {
			var tmp=new Array(obj[sel[i]-1].text, obj[sel[i]-1].value, obj[sel[i]-1].style.color, obj[sel[i]-1].style.backgroundColor, obj[sel[i]-1].className, obj[sel[i]-1].id);
			obj[sel[i]-1].text=obj[sel[i]].text;
			obj[sel[i]-1].value=obj[sel[i]].value;
			obj[sel[i]-1].style.color=obj[sel[i]].style.color;
			obj[sel[i]-1].style.backgroundColor=obj[sel[i]].style.backgroundColor;
			obj[sel[i]-1].className=obj[sel[i]].className;
			obj[sel[i]-1].id=obj[sel[i]].id;
			obj[sel[i]].text=tmp[0];
			obj[sel[i]].value=tmp[1];
			obj[sel[i]].style.color=tmp[2];
			obj[sel[i]].style.backgroundColor=tmp[3];
			obj[sel[i]].className=tmp[4];
			obj[sel[i]].id=tmp[5];
			obj[sel[i]-1].selected=true;
			obj[sel[i]].selected=false;
		}
	}
}
/* Move selected items in select down. Pass in select, it will do rest
   Param: obj -> Either select object or id of select object 
*/
function selectDown(obj) {
	obj=(typeof obj == "string") ? document.getElementById(obj) : obj;
	if (obj.tagName.toLowerCase() != "select" && obj.length < 2)
		return false;
	var sel=new Array();
	for (var i=obj.length-1; i>-1; i--) {
		if (obj[i].selected == true) {
			sel[sel.length]=i;
		}
	}
	for (var i=0; i<sel.length;i++) {
		if (sel[i] != obj.length-1 && !obj[sel[i]+1].selected) {
			var tmp=new Array(obj[sel[i]+1].text, obj[sel[i]+1].value, obj[sel[i]+1].style.color, obj[sel[i]+1].style.backgroundColor, obj[sel[i]+1].className, obj[sel[i]+1].id);
			obj[sel[i]+1].text=obj[sel[i]].text;
			obj[sel[i]+1].value=obj[sel[i]].value;
			obj[sel[i]+1].style.color=obj[sel[i]].style.color;
			obj[sel[i]+1].style.backgroundColor=obj[sel[i]].style.backgroundColor;
			obj[sel[i]+1].className=obj[sel[i]].className;
			obj[sel[i]+1].id=obj[sel[i]].id;
			obj[sel[i]].text=tmp[0];
			obj[sel[i]].value=tmp[1];
			obj[sel[i]].style.color=tmp[2];
			obj[sel[i]].style.backgroundColor=tmp[3];
			obj[sel[i]].className=tmp[4];
			obj[sel[i]].id=tmp[5];
			obj[sel[i]+1].selected=true;
			obj[sel[i]].selected=false;
		}
	}
}
/* Transfer selected items from one sel to the other.
*/
function selectXfer(sel1,sel2,bPrependIfNoSelection)
{
	if (sel1&&sel2)
	{
		var iInsert=sel2.selectedIndex + 1;
		if (iInsert==0)
			iInsert=bPrependIfNoSelection?0:sel2.length;
		sel2.selectedIndex=-1;
		for (var i=0;i<sel1.options.length;i++)//length may change
		{
			var opt=sel1.options[i];
			if (opt.selected)
			{
				selectAddItem(sel2, opt.text, opt.value, iInsert++, true);
				sel1.options[i--]=null;
			}
		}
	}
}
/* Returns how many options are selected.
*/
function selectCountSelected(sel)
{
	var iSels=0;
	for (var i=0;i<sel.options.length;i++)
	{
		var opt=sel.options[i];
		if (opt.selected)
			iSels++;
	}
	return iSels;
}
/* Sets the selection to the first option with this value.
*/
function selectSetSelected(sel,sValue)
{
	for (var i=0;i<sel.options.length;i++)
	{
		var opt=sel.options[i];
		if (opt.value==sValue)
			opt.selected=true;
	}
}
function selectGetSelected(sel)
{
	var sVal=null;
	if (sel!=null)
	{
		var iSel=sel.selectedIndex;
		if (iSel>-1)
			sVal=sel.options[iSel].value;
	}
	return sVal;
}
// Return selected values as an array
function selectGetSelections(sel)
{
	if (sel==null)
		return null;
	var sels=new Array();
	for (var i=0;i<sel.options.length;i++)
	{
		var opt=sel.options[i];
		if (opt.selected)
			sels[sels.length]=opt.value;
	}
	return sels;
}
// Remove selected options, being smart about preserving selection
function selectClearSelection(sel)
{
	if (sel&&(sel.selectedIndex>-1))
	{
		var idx=sel.selectedIndex;
		var iSels=0;
		for (var i=sel.options.length-1;i>=0;i--)
		{
			if (sel.options[i].selected)
			{
				sel.options[i]=null;
				iSels++;
			}
		}
		if (iSels>1)
		{
			sel.selectedIndex=-1;
		}
		else
		{
			if (idx>=sel.options.length)
				idx=sel.options.length-1;
			sel.selectedIndex=idx;
		}
	}
}
// Remove all options
function selectClear(sel)
{
	if (sel==null)
		return;
	while (sel.options.length>0)
		sel.options[0]=null;
}
function strTrim(szStr)
{
	if (szStr==null)
		return null;
	var iLen,i;
	var szTmp;
	iLen=szStr.length;
	if (iLen==0)
		return szStr;
	for (i=0;i<iLen;i++)
	{
		szTmp=szStr.charAt(i);
		if (szTmp!=' '&&szTmp.charCodeAt(0)!=160)
			break;
	}
	if (i<iLen)
		szStr=szStr.substring(i,iLen);
	iLen=szStr.length;
	for (i=iLen-1;i>-1;i--)
	{
		szTmp=szStr.charAt(i);
		if (szTmp!=' '&&szTmp.charCodeAt(0)!=160)
			break;
	}
	if (i>-1)
		szStr=szStr.substring(0,i+1);
	else 
		szStr= ""; // this takes care if empty string is passed.
	return szStr;
}
function strTokenize(sStr,sDelim,bTrim)
{
	if ((sStr==null)||(sDelim==null))
		return null;
	var arr=new Array();
	var iLen=sStr.length;
	var iDelimLen=sDelim.length;
	for (var i=0;i<iLen;)
	{
		var idx=sStr.indexOf(sDelim,i);
		if (idx==-1) // Ended w/o delimiter
		{
			var sTok=sStr.substring(i,iLen);
			if (sTok&&bTrim)
				sTok=strTrim(sTok);
			if (sTok.length>0)
				arr[arr.length]=sTok;
			break;
		}
		var sTok=sStr.substring(i,idx);
		if (sTok&&bTrim)
			sTok=strTrim(sTok);
		if (sTok.length>0)
			arr[arr.length]=sTok;
		i=idx+iDelimLen;
	}
	return arr;
}
function strLowerCaseFirstLetter(sStr)
{
	if ((sStr==null)||(sStr.length<1))
		return sStr;
	sStr=sStr.charAt(0).toLowerCase()+sStr.substring(1,sStr.length);
	return sStr;
}
function strStartsWith(sStr,sVal)
{
	if ((!sStr)||(!sVal))
		return false;
	return (sStr.substr(0, sVal.length)==sVal);
}
/* Returns a float value for the string, where format is a 
	Java-style number format, e.g. "#,##0.0" */
function numParse(sNum,sFormat)
{
	if (sNum==null)
		return null;
	sNum=strTrim(sNum);
	if (sNum.length==0)
		return null;
	if (sFormat)
	{
		// Get decimal point char
		var sDecimal=".";
		for (var i=sFormat.length-1;i>=0;i--)
		{
			var ch=sFormat[i];
			if (ch!='0')
			{
				sDecimal=ch;
				break;
			}
		}
		// Convert to period
		var idx=sNum.indexOf(sDecimal);
		if (idx>-1)
			sNum=sNum.substring(0,idx)+"."+sNum.substring(idx+1,sNum.length);
	}
	return parseFloat(sNum);
}
/* Formats a number as a string using Java-style number format. */
function numFormat(num,sFormat)
{
	if (num==null)
		return "";
	var sNum=num+"";
	if (sFormat)
	{
		// Get decimal point char
		var sDecimal=".";
		for (var i=sFormat.length-1;i>=0;i--)
		{
			var ch=sFormat.charAt(i);
			if (ch!='0')
			{
				sDecimal=ch;
				break;
			}
		}
		// Decimal digits
		var iDecis=0;
		var idx=sFormat.indexOf(sDecimal);
		if (idx>-1)
			iDecis=sFormat.length-idx-1;
		// Format decimal portion
		var whole=Math.round(num*Math.pow(10,iDecis))+"";
		var dp=whole.length-iDecis;
		sNum=whole;
		if (dp>0)
			sNum=whole.substring(0,dp)+sDecimal+whole.substring(dp,whole.length);
		else if (dp==0)
			sNum="0"+sDecimal+whole;
		else if (dp==-1)
			sNum="0"+sDecimal+"0"+whole;
	}
	return sNum;
}
/* Returns a float value for a string, where format is a 
	Java-style number format, e.g. "#,##0.0" or "0:00" */
function hoursParse(sNum,sFormat)
{
	if (sNum==null)
		return null;
	sNum=strTrim(sNum);
	if (sNum.length==0)
		return null;
	if ((sNum.indexOf(":")>-1)||(sFormat&&(sFormat.indexOf(":")>-1)))
	{
		// Get hours
		var hours=0;
		var idx=sNum.indexOf(":");
		if (idx>-1)
		{
			var sHours=sNum.substring(0,idx);
			sNum=sNum.substring(idx+1,sNum.length);
			if (sHours)
			{
				hours=parseFloat(sHours);
				if (isNaN(hours))
					return hours;
			}
		}
		else // Assume all hours
		{
			hours=parseFloat(sNum);
			sNum="";
		}
		// Get minutes
		if (sNum)
		{
			if (sNum.length>2)
				sNum=sNum.substring(0,2);
			var mins=parseFloat(sNum);
			if (isNaN(mins))
				return hours;
			hours+=mins/60;
		}
		return hours;
	}
	return numParse(sNum,sFormat);
}
/* Formats a number as hours using Java-style number format. */
function hoursFormat(num,sFormat)
{
	if (num==null)
		return "";
	if (sFormat&&(sFormat.indexOf(":")>-1))
	{
		var iTotalMins=Math.round(num*60);
		var iHours=Math.floor(iTotalMins/60);
		var iMins=iTotalMins-iHours*60;
		var sNum=iHours+":"+(iMins<10?"0":"")+iMins;
		return sNum;
	}
	return numFormat(num,sFormat);
}
/* Call this instead of innerHTML directly to avoid extraneous taggage from Firefox */
function elemGetText(el)
{
	if (el.textContent) return el.textContent;
	if (el.innerText) return el.innerText;
	return el.innerHTML.replace(/<[^>]*>/g,'');
}
/* Call this to have CSS input subselects (e.g. input.text) work on IE */
function appendInputTypeClasses()
{
	if (BrowserDetect.browser!="Explorer")
		return;
	if (!document.getElementsByTagName)
		return;
	var inputs=document.getElementsByTagName('input');
	var inputLen=inputs.length;
	if (inputLen<1)
		return;
	for (var i=0;i<inputLen;i++) {
		if (inputs[i].getAttribute('type'))
		inputs[i].className+=' '+inputs[i].getAttribute('type');
	}
}
/* String fns */
String.prototype.equalsIgnoreCase=strEqualsIgnoreCase;
String.prototype.equals=strEquals;
function strEquals(arg)
{
	return (this.toString()==arg.toString());
}
function strEqualsIgnoreCase(arg)
{
	return (new String(this.toLowerCase())==(new String(arg)).toLowerCase());
}
/* Misc */
// IE doesn't support this!
if(!Array.indexOf)
{
	Array.prototype.indexOf=
		function(obj)
		{
			for(var i=0;i<this.length;i++)
			{
				if(this[i]==obj)
					return i;
			}
			return -1;
		}
}
// Print function to work around IE bugs
function printIt(win)
{
	if (win)
	{
		win.focus(); // Needed for IE
		if (BrowserDetect.browser=="Explorer")
		{
			win.print();
			/*
			try
			{
				win.execCommand('print', false, null); // Work around IE7 bug in which print dlg doesn't show sometimes
			}
			catch(e)
			{
				win.print();
			}
			*/
		}
		else
		{
			win.print();
		}
	}
}

