var d=new DateFunctions();
var f=new FormFunctions();
var n=new NumberFunctions();
var s=new StringFunctions();
var dd=new DropdownFunctions();
var cb=new CheckBoxFunctions();
var e=new Effects();


//date functions
function DateFunctions() {

	this.New=function(iDay, iMonth, iYear) {
		return new Date(iYear, iMonth-1, iDay);
	}
	
	this.AddDays=function (dDate, iDays) {
		dDate.setDate(dDate.getDate()+iDays);
		return dDate;
	}
	
	this.Year=function (dDate) {
		return dDate.getFullYear();
	}
	
	this.Month=function (dDate) {
		return dDate.getMonth()+1;
	}
	
	this.Day=function(dDate) {
		return dDate.getDate();
	}
	
	this.DisplayDate=function(dDate) {
		dDate=new Date(dDate)
		
		var aMonths=new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')
		
		var sDay=dDate.getDate().toString()
		if (sDay.length==1) {
			sDay='0'+sDay;
		}
		return sDay + ' ' +aMonths[dDate.getMonth()] + ' ' +dDate.getFullYear();
	}
	
	this.DateDiff=function(sStartDate,sEndDate) {
		
		var dStartDate=new Date(sStartDate);
		var dEndDate=new Date(sEndDate);
		var iStartYear;
		var iEndYear;
		var iStartDayOfYear;
		var iEndDayOfYear;
		var iDiff;	
		
		//get the years and day of years, if end date is before start date then swap them round
		if (dStartDate<=dEndDate) {
			iStartYear=dStartDate.getYear();
			iEndYear=dEndDate.getYear();
			iStartDayOfYear=this.DayOfYear(dStartDate);
			iEndDayOfYear=this.DayOfYear(dEndDate);
		} else {
			iStartYear=dEndDate.getYear();
			iEndYear=dStartDate.getYear();
			iStartDayOfYear=this.DayOfYear(dEndDate);
			iEndDayOfYear=this.DayOfYear(dStartDate);
		}	
			
		
		//2 possibilities, same year, different years
		if (iStartYear==iEndYear) {
			
			iDiff=iEndDayOfYear-iStartDayOfYear;
		
		} else {
		
			//one or more years apart starts with same calculation
			iDiff=iEndDayOfYear+(365-iStartDayOfYear);
			
			//if start day of year is 28th feb or before and the year is a leap year than add one
			if ((iStartDayOfYear<=59)&&(this.CheckLeapYear(iStartYear)==1)) {
				iDiff+=1;
			}
			
			//now loop through all (if any years inbetween)
			for (var iLoop=iStartYear+1;iLoop<iEndYear;iLoop++) {			
		
				//add 365 for a normal year, 366 for a leap year
				if (this.CheckLeapYear(iLoop)==1) {
					iDiff+=366;
				} else {
					iDiff+=365;
				}			
			}		
		}
		
		// add one to the datediff as this is an inclusive function
		iDiff+=1;
		
		// if start date > end date invert the difference
		if(dStartDate>dEndDate) {
			iDiff=iDiff*(-1);
		}
		
		return iDiff;
	}
	
	this.CheckLeapYear=function(iYear) {
		return (((iYear % 4 == 0) && (iYear % 100 != 0)) || (iYear % 400 == 0)) ? 1 : 0;
	}
	
	this.DayOfYear=function(dDate) {
		
		//start with current day of month and then add on preivous mointh days
		var iDayOfYear=dDate.getDate();
		var iMonth=dDate.getMonth();
		var iYear=dDate.getYear();
		
		//if it's a leap year and we are past Februrary then add 1
		if((this.CheckLeapYear(iYear)==1)&&(iMonth>=2)) {
			iDayOfYear++;
		}
		
		//now do a huge ugly if statement adding the rest on for the months
		if (iMonth==1) {
			iDayOfYear+=31;
		} else if (iMonth==2) {
			iDayOfYear+=59;
		} else if (iMonth==3) {
			iDayOfYear+=90;
		} else if (iMonth==4) {
			iDayOfYear+=120;
		} else if (iMonth==5) {
			iDayOfYear+=151;
		} else if (iMonth==6) {
			iDayOfYear+=181;
		} else if (iMonth==7) {
			iDayOfYear+=212;
		} else if (iMonth==8) {
			iDayOfYear+=243;
		} else if (iMonth==9) {
			iDayOfYear+=273;
		} else if (iMonth==10) {
			iDayOfYear+=304;
		} else if (iMonth==11) {
			iDayOfYear+=334;
		}
		
		return iDayOfYear;
	}
	
}

//number functions
function NumberFunctions() {

	this.SafeInt=function(sInteger) {		
		if ((sInteger==null)||(sInteger=='')||(sInteger=='0')) {
			return 0;
		} else {
		
			//remove any commas
			sInteger+='';
			var aInt = sInteger.split(",");
			var sTotal='';
			for (var loop=0; loop<aInt.length; loop++) {
				sTotal+=aInt[loop];
			}
			return parseInt(parseFloat(sTotal));
		}
	}
	
	
	this.SafeNumeric=function(sNumber) {		
		if ((sNumber==null)||(sNumber=='')||(sNumber=='0')) {
			return 0;
		} else {
		
			//remove any commas
			sNumber+='';
			var aInt = sNumber.split(",");
			var sTotal='';
			for (var loop=0; loop<aInt.length; loop++) {
				sTotal+=aInt[loop];
			}
			return parseFloat(sTotal);
		}
	}
	
	this.Cent=function(nNumber) {
	
		// returns the amount in the .99 format
		return (nNumber == Math.floor(nNumber)) ? nNumber + '.00' : (  (nNumber*10
		== Math.floor(nNumber*10)) ? nNumber + '0' : nNumber);

	}

	this.Round=function(nNumber,X) {

		// rounds number to X decimal places, defaults to 2
		X = (!X ? 2 : X);
		return Math.round(nNumber*Math.pow(10,X))/Math.pow(10,X);

	}
	
	this.FormatMoney=function(nNumber,sCurrency) {
		
		//get the rounded figure
		var nRounded=n.Cent(n.Round(nNumber));
		if (sCurrency!=undefined) {
			
			if (nRounded<0) {
				nRounded=n.Cent(nRounded*(-1));
				return '-'+sCurrency+nRounded;
			} else {
				return sCurrency+nRounded;
			}
		} else {
			return nRounded;
		}
		
	}
}

//string functions
function StringFunctions() {

	this.Left=function(s,i) {
		return s.substring(0,i);
	}
	
	this.Right=function(s,i) {
		return s.substring(s.length - i);
	}
	
	this.Substring=function(s,iStart,iLength) {

		if (iLength == undefined) {
			return s.substring(iStart);
		} else {
			return s.substring(iStart,iLength);
		}
	}
	
	this.Slice=function(s,iStart,iEnd) {
		if (iEnd==undefined) {
			iEnd=iStart;
		}
		return s.substring(iStart,iStart + (iEnd - iStart) + 1);
	}
	
	this.StartsWith=function(sBase, sCompare) {
		return sBase.indexOf(sCompare)==0;
	}
	
	this.Replace=function(sString, sStringToReplace, sReplacement) {
		while (sString.indexOf(sStringToReplace) != -1) {
			sString=sString.replace(sStringToReplace, sReplacement);
		}
		return sString;
	}
	
	this.Trim=function(sBase) {
		return sBase.replace(/^\s*|\s*$/g,'');
	}
}

//form functions
function FormFunctions() {

	this.GetObject=function(sID) {
		return document.getElementById(sID);		
	}
	
	this.GetObjectsByIDPrefix=function(sPrefix,sTagName) {
	
		var aObjects=new Array();		
		
		if (sTagName==undefined) {
			sTagName='input';
		}
		
		var aElements=document.getElementsByTagName(sTagName);		
		for (var i=0;i<aElements.length;i++) {
			if (s.StartsWith(aElements[i].id,sPrefix)) {
				aObjects.length=aObjects.length+1;
				aObjects[aObjects.length-1]=aElements[i];
			}
		}
		
		return aObjects;		
	}
	
	
	this.GetValue=function(o) {
		var oControl=this.SafeObject(o);
		if (oControl!=null) {
			return oControl.value;
		} else {
			return '';
		}
	}
	
	this.SetValue=function(o, sValue) {
		var oControl=this.SafeObject(o);
		if (oControl!=null) {
			oControl.value=sValue;
		}
	}

	this.SafeObject=function(o) {
		if (typeof(o)=='object') {
			return o;
		} else if (typeof(o)=='string') {
			return this.GetObject(o);
		} else {
			return null;
		}
	}
	
	this.Toggle=function(o) {
		var oControl=this.SafeObject(o);
		oControl.style.display=oControl.style.display=='none' ? 'block' : 'none';
	}
	
	this.Show=function(o) {
		var oControl=this.SafeObject(o);
		if (oControl!=null) {
			oControl.style.display=oControl.style.display='';
		}
	}
	
	this.Hide=function(o) {
		var oControl=this.SafeObject(o);
		if (oControl!=null) {
			oControl.style.display=oControl.style.display='none';
		}
	}
	
	this.Visible = function(o) {
		var oControl=this.SafeObject(o);
		return oControl.style.display!='none';
	}
	
	this.SetClass = function(o,s) {
		var oControl=this.SafeObject(o);
		oControl.className=s;
	}
	
	this.GetClass = function(o) {
		var oControl=this.SafeObject(o);
		return oControl.className;
	}
	
	this.GetElementsByClassName=function(sElement, sClassName) {
		
		var aElements=document.getElementsByTagName(sElement);
		var aReturn=new Array();
		for (var i=0;i<aElements.length;i++) {
		
			if (aElements[i].className.indexOf(sClassName)>-1) {
				aReturn[aReturn.length]=aElements[i];
			}
		}
		
		return aReturn;		
	}
	
	this.ShowIf=function(o,bCondition) {
		var oControl=this.SafeObject(o);
		if (bCondition) {
			this.Show(o);
		} else {
			this.Hide(o);
		}
	}
	
	this.BuildList=function(aListItems) {
		
		var sList='<ul>';
		for (var i=0;i<aListItems.length;i++) {
			sList+='<li>'+aListItems[i]+'</li>';
		}
		sList+='</ul>';
		return sList;
	}



}

//checkbox functions 
function CheckBoxFunctions() {

	this.Checked=function(o) {
		o=f.SafeObject(o);
		return iif(o!=null,o.checked,false);
	}
}



//dropdown functions
function DropdownFunctions() {

	this.GetText=function(o) {
		o=f.SafeObject(o);
		if (o!=null) {
			return o.options[o.selectedIndex].text;
		} else {
			return '';
		}
	}

	this.GetValue=function(o) {
		o=f.SafeObject(o);
		return iif(o!=null,o.options[o.selectedIndex].value,'');
	}
	
	this.SetIndex=function(o,iIndex) {
		o=f.SafeObject(o);
		if (o!=null) {o.selectedIndex=iIndex;}
	}
	
	this.SetValue=function(o,iValue) {
		o=f.SafeObject(o);
		if (o!=null) {
			for (var i=0;i<=o.options.length-1;i++) {
				if (o.options[i].value==iValue) {
					o.selectedIndex=i;
					break;
				}	
			}
		}
	}
	
	this.SetText=function(o,sText) {
		var o=f.SafeObject(o);
		if (o!=null) {
			for (var i=0;i<=o.options.length;i++) {
				
				if (o.options[i].text==sText) {
					o.selectedIndex=i;
					break;
				}	
			}
		}
	}
	
	this.Clear=function(o,sText) {
		var o=f.SafeObject(o);
		if (o!=null) {
			o.options.length=0;		
		}
	}
	
	this.AddOption=function(o,sText,iValue,sClass) {
		var o=f.SafeObject(o);
		if (o!=null) {
			o.options[o.length] = new Option(sText,iValue);
			if (sClass!=undefined) {
				o.options[o.length - 1].className=sClass;
			}
		}
	}
}

// checked data list
function CheckedDatalist(o) {

	this.List=f.SafeObject(o);

	this.HasCheckedItems=function() {
		
		var aCheckboxes=f.GetObjectsByIDPrefix(this.List.id+'chk');
		
		for (var i=0;i<aCheckboxes.length;i++) {
			if (f.SafeObject(aCheckboxes[i]).checked==true) {
				return true;
			}
		}
		
		return false;
		
	}

}

// validator
function Validator(oButton) {

	this.Validations=new Array();
	this.Button=f.GetObject(oButton);

	
	this.AddValidation=function(Control, FieldName, ValidationType) {
		this.Validations[this.Validations.length]=['Custom',Control,FieldName,ValidationType];
	}

	this.Validate=function() {
		
		aValidation=this.Validations;
		ClientValidation(this.Button,'Custom');
	}
}



//webservice
var oRequest, oResponseObject, bResponseTextOnly, oPopulateList;
var oWebService=new WebService();
function WebService() {

	//getlist 
	this.PopulateList=function(URL, sNamespace, oList, SourceSQL) { 
	
		// get the data
		aParams=new Array(['SourceSQL',SourceSQL]);
		oPopulateList=f.SafeObject(oList);
		this.RunWebService(URL, sNamespace, 'GetList', aParams, oPopulateList);
	}

	this.FillList=function(oXML) {
	
		var bHasAll=iif(oPopulateList.options.length>0 && oPopulateList.options[0].text=='All', true, false);
		var iOffsetForAll=0;
		
		// clear the list
		dd.Clear(oPopulateList);
		
		//add all if required
		if (bHasAll) {
			oPopulateList[0]=new Option('All',-1);
			iOffsetForAll=1;
		}
		
		var oListItems=oXML.getElementsByTagName('ListItem');
		for (var i=0;i<oListItems.length;i++) {
			oPopulateList[i+iOffsetForAll] = new Option(this.GetNodeText(oListItems[i].childNodes[0]), 
				this.GetNodeText(oListItems[i].childNodes[1]));
		}
	}
	

	//support functions
	this.GetTagValue=function(oLocalXML, sTag) {
		var aItems=oLocalXML.getElementsByTagName(sTag);
		if (aItems.length==1 && aItems[0].childNodes[0]) {
			if (aItems[0].textContent) {
				return aItems[0].textContent;
			} else {
				return aItems[0].childNodes[0].data;
			}
		} else {
			return '';
		}
	}	
	
	
	this.GetNodeText=function(oNode) {
		return oNode.text ? oNode.text : oNode.textContent;
	}
	
	this.SafeParam=function(sParam) {
		if (sParam.replace) {
			return sParam.replace(/&/g,'&amp;');
		} else {
			return sParam;
		}
	}	
	
	
	this.RunWebService=function(sUrl, sNamespace, sFunction, aParameters, oCallingObject, bTextOnly) {
		
		var sRequest=
			'<?xml version="1.0" encoding="utf-8"?>'+
			'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '+
			'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+
			'<soap:Body>'+
			'	<'+sFunction+' xmlns="'+sNamespace+'">'
			
		for (var i=0;i<aParameters.length;i++) {
			sRequest=sRequest+'<'+aParameters[i][0]+'>'+
				this.SafeParam(aParameters[i][1])+'</'+aParameters[i][0]+'>';
		}
		
		sRequest=sRequest+'	</'+sFunction+'>'+'</soap:Body>'+'</soap:Envelope>';

		// branch for native XMLHttpRequest object
		if (window.XMLHttpRequest) {
			oRequest = new XMLHttpRequest();
			oRequest.open("POST", sUrl,true);
		} else {
			oRequest = new ActiveXObject("Microsoft.XMLHTTP");
			oRequest.open("POST", sUrl,true);	
		}
		
		oResponseObject=oCallingObject;
		bResponseTextOnly=bTextOnly==undefined ? false : bTextOnly;
		
		oRequest.onreadystatechange=function() {
			
			if (oRequest.readyState==4) {
				if (oResponseObject==oPopulateList) {
					oWebService.FillList(oRequest.responseXML);
				} else if (bResponseTextOnly==false) {
					oResponseObject.Done(oRequest.responseXML); 
				} else {
					oResponseObject.Done(oRequest.responseText);
				}
			}
		}
		
		oRequest.setRequestHeader("Content-Type", "text/xml")
		oRequest.setRequestHeader("MessageType", "CALL")
		oRequest.setRequestHeader('SOAPAction',sNamespace+'/'+sFunction)
		oRequest.send(sRequest);
		
	}	
}	



/* effects */
function Effects() {
		
	this.SetOpacity=function(o,iOpacity) {
		var oControl=f.SafeObject(o);
		oControl.style.opacity = iOpacity/100;		
		oControl.style.filter = 'alpha(opacity=' + iOpacity + ')';
	}

	this.FadeOut=function(oObject, FadeTime, Opacity) {
		this.FadeOutObject=f.SafeObject(oObject);
		FadeTime=FadeTime==undefined ? 1 : FadeTime;
		this.FadeInterval=FadeTime/20*800;
		this.Opacity=Opacity==undefined ? 100 : Opacity;

		this.Opacity-=5;
			
		if (this.Opacity<0) {
			e.SetOpacity(this.FadeOutObject,0);
		} else {
			e.SetOpacity(this.FadeOutObject,this.Opacity);
			setTimeout('e.FadeOut(\''+this.FadeOutObject.id +'\','+FadeTime+','+this.Opacity+')',
				this.FadeInterval);
		}
	}
	
	this.FadeIn=function(oObject, FadeTime, Opacity) {
		this.FadeInObject=f.SafeObject(oObject);
		FadeTime=FadeTime==undefined ? 1 : FadeTime;
		this.FadeInterval=FadeTime/20*800;
		this.Opacity=Opacity==undefined ? 0 : Opacity;

		this.Opacity+=5;
			
		if (this.Opacity>100) {
			e.SetOpacity(this.FadeInObject,100);
		} else {
			e.SetOpacity(this.FadeInObject,this.Opacity);
			setTimeout('e.FadeIn(\''+this.FadeInObject.id +'\','+FadeTime+','+this.Opacity+')',
				this.FadeInterval);
		}
	}
	
	
	this.ImageRotator=function(IDBase, ItemCount, RotateTime, CurrentIndex) {

		if (ItemCount>1) {
			RotateTime = RotateTime == undefined ? 2 : parseInt(RotateTime);
			CurrentIndex = CurrentIndex == undefined ? 0 : CurrentIndex;

			if (CurrentIndex==0) {
			
				CurrentIndex=1;
				
			} else { 
				
				var oFadeOut=f.GetObject(IDBase+CurrentIndex);

				CurrentIndex+=1;
				CurrentIndex= CurrentIndex>ItemCount ? 1 : CurrentIndex;
			
				var oFadeIn=f.GetObject(IDBase+CurrentIndex);
			
				e.FadeOut(oFadeOut);
				e.FadeIn(oFadeIn);
			
			}

			setTimeout('e.ImageRotator(\''+IDBase+'\','+ItemCount+','+RotateTime+','+CurrentIndex+')', RotateTime*1000);
		}
		
	}	

}
