function createMethodReference(object, methodName) {
	// From http://www.brockman.se/writing/method-references.html.utf8
	return function () {
		object[methodName](object);
	}
}

function yValidate() {
	// This function creates the JavaScript version of the yValidate.php object
	// This is the list of fields and the validations to apply (see 
	// $validations)
	this.validations = [];
	// This is the list of Name:Regular Expression combinations (see 
	//$regValidations)
	this.regValidations = [];
	// When the page has loaded, attach the yValidate validation hooks
	addLoadEvent(createMethodReference(this,'attachHandlers'));
}

yValidate.prototype.addBaseValidation = function(sName, sExp) {
	// Attach the regular expression for a validation to a name
	this.regValidations[sName] = sExp;
}

yValidate.prototype.addValidation = function(sID, sType, sMsgID, sMessage) {
	// Attach a validation type to an ID in an HTML form.
	// sID is the HTML ID of the element
	// sType is the type of validation to attach
	// sMsgID is the ID of the element to display failure messages
	// sMessage is the text to put as the failure message
	this.validations[sID] = {"Type":sType, "MsgID":sMsgID, "Message":sMessage};
}

yValidate.prototype.attachHandlers = function (me) {
	// This function uses the validations array to attach field validation
	// events to onchange, and attaching full-form validation to submitting.
	if (document.getElementById) {
		var forms = document.forms;
		for (var i=0;i<forms.length;i++) {
			var form = forms[i];
			form.onsubmit = function(){
			return me.validateForm(me,this);
			
			} // attach validate() to the form
		}
		for (var j in me.validations) {
			var x = document.getElementById(j);
			if (x && x.type != 'checkbox' && x.type != 'radio') {
				x.onchange = function(){return me.validate(this,'field');}
			} else if (document.getElementsByName(j)) {
				// checkboxes and radio
				var all = document.getElementsByName(j);
				for (k=0;k<all.length;k++) 
				{
					/*
					if(all[k].id == 'chkChildren')
					{
						alert("if");	
					}*/
					//alert(all[k].id);
					document.getElementById(all[k].id).onclick = function() {return me.validate(this,'field');}
			/*		if(x.type == 'checkbox')
					   {
						   document.getElementById(all[k].id).onchange = function() {return me.validate(this,'field');}
					   }*/
				}
			}
		}
		return true;
	} else {
		return false;
	}
}

yValidate.prototype.setFeedback = function(ok,feedback,sFeedbackMsg, objInput) {
	// Sets the feedback appearance and text depending on validation.
	// If OK, we get the validateOK class, if broken we get the validateBAD
	// class and a message
		if (ok) {
			feedback.className = 'validateCLEAR';
			feedback.innerHTML = '&nbsp;';
			//feedback.style.display = "none";
			// Sets the input object class 
			objInput.className = 'InputText';
		} else {
			feedback.className = 'validateBAD';
			feedback.innerHTML = sFeedbackMsg;
			//feedback.style.display = "block";
			// Sets the input object class
			objInput.className = 'ErrorInputText';
		}
}

yValidate.prototype.validate = function(objInput,from) {
	// This validates the passed field.
	sVal = objInput.value; 
	// The JavaScript version of the validations array is indexed by the
	// field name for quick reference, but doesn't need the name inside the
	// array.

	ok=true;
	
	if(  this.validations[objInput.name])
	{
	sTypeCheck = this.validations[objInput.name].Type; //[0];
	sFeedbackLoc = this.validations[objInput.name].MsgID;
	sFeedbackMsg = this.validations[objInput.name].Message;
	myform = objInput.form;

	feedback = document.getElementById(sFeedbackLoc);

	// See the PHP code for the logic behind these calls.
	if (objInput.type=='checkbox') {
		// Checkboxes can handle required and counts.
		var ccount = 0;
		for (var i=0;i<myform.length;i++) {
			if (myform[i].name == objInput.name && myform[i].checked) {
				ccount++;
			}
		}
		if (sTypeCheck.indexOf('+') == 0 && ccount==0) {
			ok = false;
		} else if (/^\+?\d*-\d*$/.test(sTypeCheck)) {
			var numList = sTypeCheck.split('-');
			if (numList[0]>0) {
				ok = ok && (ccount==0 || ccount>=numList[0]);				
			}
			if (numList[1]>0) {
				ok = ok && (ccount==0 || ccount<=numList[1]);
			}
			if (numList[0][0]=='+') {
				ok = ok && (ccount>0);
			}
		} else if (/^\+?\d+$/.test(sTypeCheck)) {
			var number = parseInt(sTypeCheck,10);
			ok = ok && (ccount == number);
		} 
		else if (/^\+?\d*-\d*-\d*$/.test(sTypeCheck)) 
		{			
			var length = parseInt(sTypeCheck,10);
			var chkCount = 0;
			for(var i=0; i<length; i++)
			{
				//alert("length:" +length + " count:" + ccount);
				var tmpChk = document.getElementById(objInput.name.substring(0, objInput.name.indexOf('[')+1) + i + "]");
				//alert(tmpChk.value + " " + tmpChk.checked);
				if (tmpChk.checked)
				{
					chkCount++;
				}
			}
			ok = ok && (chkCount > 0);
		}
		yValidate.prototype.setFeedback(ok,feedback,sFeedbackMsg, objInput);	
	} else if (objInput.type=='radio') {
		// Radios can only be required
		if (sTypeCheck == '+') {
			ok = false;
			for (var i=0;i<myform.length;i++) {
				if (myform[i].name == objInput.name && myform[i].checked) {
					ok = true;
				}
			}
		yValidate.prototype.setFeedback(ok,feedback,sFeedbackMsg, objInput);	
		}
	} else {
		if (sTypeCheck.substr(0,1)=='+') { // Text Box required field validation
			ok = !(trim(sVal).length==0) || objInput.disabled;
			sTypeCheck = sTypeCheck.substring(1);
		}		
		else if (sTypeCheck.substr(0,1)=='-') 
		{
			// It will check the array of textboxes from which atleast one is required
			ok = false;
			for (var i=0;i<myform.length;i++) {
				if (myform[i].name == objInput.name && myform[i].value.length>0)
				{
					ok = true;
				}
			}
		}
		if (ok && this.regValidations[sTypeCheck]>'') {
			var ok = sVal.match(this.regValidations[sTypeCheck]) || objInput.disabled;	
		} else {
			// If you need more than just a regexp to validate, put it here.
			// Just be sure to set 'ok' to whether the field's OK or not.
		}
		yValidate.prototype.setFeedback(ok,feedback,sFeedbackMsg, objInput);
	}
	}
	if (from=="submit") {
		return(ok);
	}
	return(true);
}
yValidate.prototype.validateForm = function(me,form) {
	// This validates a submit, working through the form and finding any 
	// element with an onchange function - signifies a validation attachment
	// Radio, checkbox and select get onclick rather than onchange
	var ok = true;
	var t = false;
	var x;	
	
	for (var l=0;l<form.elements.length;l++) {
		var element = form.elements[l];
		if (element.onchange && typeof element.onchange == 'function') {
			
			ok2 = me.validate(element,'submit');
			ok = (ok && ok2);
			
			if(!t && !ok)
			{
				t = true;
				x = element.id;
			}
			
		} else if (element.onclick && typeof element.onclick == 'function') {
			ok2 = me.validate(element,'submit');
			ok = (ok && ok2);
			
			if(!t && !ok)
			{
				t = true;
				x = element.id;
			}
		}		
	
	}
	//alert('tet');
	var divErrorSummary = document.getElementById("errorSummary");
	if (ok) 
	{
		divErrorSummary.style.display = "none";
		divErrorSummary.innerHTML = "";
		divErrorSummary.className = "SuccessMsg";
		return ok;
	}
	else
	{
		//alert('Whoops!  There are some submissions that don\'t make sense to us, please go back and change the ones indicated.');
		//alert(document.getElementById("errorSummary").style.display);
		divErrorSummary.style.display = "block";
		divErrorSummary.innerHTML = "Please correct the errors indicated";
		divErrorSummary.className = "ErrorMsg";
		document.getElementById(x).focus();
		return false;
		/*
		alert(x);
		form.elements[x].focus();*/
	}
}

function addLoadEvent(func) {
	// Standard onLoadEvent logic
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

// This function is used to trim the required fields before length check to avoid spaces at the begining
function trim(strInput){
 var strTrimmmed = '';
 for (var i = 0;i<strInput.length; i++)
 {
  	if (strInput.charCodeAt(i)!=32 && strInput.charCodeAt(i)!=9 && strInput.charCodeAt(i)!=10 && strInput.charCodeAt(i)!=13 && strInput.charCodeAt(i)!=11)
  		{
   			strTrimmmed += strInput[i];
  		}
 }
 return strTrimmmed;
}
