var oValidation = new validationObj();

addEvent(window,"load",validationObj_onLoadActions);
function validationObj_onLoadActions() {
	oValidation.markRequiredFields();
}

function validationObj() {
	this.typeName = "validationObj";
	return this;
}

validationObj.prototype.getValidationElement = function(fieldname) {
	return document.getElementById("ckvalidate." + fieldname)
	/*
	var sParams, oParams;
	var aEl = document.getElementsByTagName("ckvalidate")
	for (var index=0; index < aEl.length; index++) {
		if (sParams = aEl[index].getAttribute("params")) oParams=eval(sParams);
		if ((oParams) && (oParams.fieldname==fieldname))return aEl[index];
	}
	
	return null;
	*/
}

validationObj.prototype.editValidationElement = function(fieldname,paramName,paramValue) {
	var oEl, oParams;
	var sParams;

	if (paramName=="bReqd") this.markRequiredField(fieldname,(paramValue=="true")); //changes both bReqd and blank validation
	else {
		if (oEl = this.getValidationElement(fieldname)) {
			if (sParams = oEl.getAttribute("params")) oParams=eval(sParams);
			if (oParams) {
				oParams[paramName] = paramValue;
				sParams = getJSON(oParams);
				oEl.setAttribute("params","(" + sParams + ")");
			}
		}
	}
}

validationObj.prototype.markRequiredFields = function() {
	var sParams,oParams, oLabel, oSpanReqd;
	var aEl = document.getElementsByTagName("ckvalidate")
	for (var index=0; index < aEl.length; index++) {
		if (sParams = aEl[index].getAttribute("params")) oParams=eval(sParams);

		if ((oParams) && (oParams.bReqd=="true")) this.__createReqdSpan(oParams); //initial create only if required is true
	}
}

validationObj.prototype.markRequiredField = function(sFieldname) {
	var bReqd = (arguments.length==2 ? arguments[1] : true);
	var oSpanReqd, oEl, oParams;

	if (oEl = this.getValidationElement(sFieldname)) {
	
		var aValidation = Array();
		var sParams = oEl.getAttribute("params");

		if (sParams) oParams=eval(sParams);

		if (oParams.v) {
			oParams.v = oParams.v.replace("blank","");
			aValidation = oParams.v.split(",");
		}
		oParams.v = (bReqd ? "blank" : "");
	
		for (var index=0; index < aValidation.length; index++) {
			if (aValidation[index] != "") oParams.v=oParams.v + (oParams.v != "" ? "," : "") + aValidation[index];
		}
		oParams.bReqd = (bReqd ? "true" : "false");
		sParams = getJSON(oParams);

		oEl.setAttribute("params","(" + sParams + ")");
	} 

	this.__createReqdSpan(oParams);
}

validationObj.prototype.__createReqdSpan = function(oParams) {
	var oLabel,SpanReqd;
	if (oParams) {
		var sLabelID = (oParams.elName ? oParams.elName + "." : ""); 
			
		sLabelID += oParams.fieldname + ".label";
		if (oLabel = document.getElementById(sLabelID)) {
			if (!(oSpanReqd = oDHTML.seekWithin(oLabel,"span",oParams.fieldname + ".reqd"))) {
				oSpanReqd = document.createElement("SPAN");
				oSpanReqd.id = oParams.fieldname + ".reqd";
				oSpanReqd.className="formMandatory";
				oLabel.insertBefore(oSpanReqd,oLabel.firstChild);
			}
			
			oSpanReqd.innerHTML=(oParams.bReqd=="true" ? "*&nbsp;" : "");
		}
	}
}


/*--------------------------------------------------------------------------------
 As you Type Validation
--------------------------------------------------------------------------------*/
validationObj.prototype.allowRegExp = function(oEvent,strRegExp) {
	var key,keychar;
	if (window.event) key = window.event.keyCode;
	else if ((oEvent) && (oEvent.charCode != 0 && !oEvent.ctrlKey)) key = oEvent.charCode; //checking charCode for non-zero allows backspace, CTRL+V and other functional keys to pass through and always go to next statement to return true
	else return true;

	var reg = new RegExp(strRegExp)
	keychar = String.fromCharCode(key);
	var matchedArr = keychar.match(reg)
	//alert("keyChar=" + keychar + "\nstrRegExp=" + strRegExp + "\nmatchedArr=" + matchedArr);
	return (matchedArr != null);
}
validationObj.prototype.disallowRegExp = function(oEvent,strRegExp) {
	//opposite of above. We can just return the negative result of allowRegExp() function because that would also block backspace, delete, etc
	var key,keychar;
	if (window.event) key = window.event.keyCode;
	else if ((oEvent) && (oEvent.charCode != 0 && !oEvent.ctrlKey)) key = oEvent.charCode; //checking charCode for non-zero allows backspace, CTRL+V and other functional keys to pass through and always go to next statement to return true
	else return true;

	var reg = new RegExp(strRegExp)
	keychar = String.fromCharCode(key);
	var matchedArr = keychar.match(reg)

	return (matchedArr == null);
}

validationObj.prototype.allowAlphaNumeric = function()  {
	var strChars = '';
	if (arguments.length >= 1) strChars += arguments[0];
	var oEvent = (arguments.length >= 2 ? arguments[1] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[a-zA-Z0-9' + strChars + ']');
}
validationObj.prototype.allowNumeric = function()  {
	var strChars = '';
	if (arguments.length >= 1) strChars += arguments[0];
	var oEvent = (arguments.length >= 2 ? arguments[1] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[0-9' + strChars + ']');
}
validationObj.prototype.allowEmail = function()  {
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowAlphaNumeric(';@\._\-',oEvent);
}
validationObj.prototype.allowPhone = function()  {
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[0-9\\.\\-]');
}

validationObj.prototype.allowCurrency = function()  {
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[\b,0-9\.,\-]');
}

validationObj.prototype.allowDate = function()  {
	//option exists to pass in event object so this function can be called from within another function instead of just used as a direct event handler
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[\b,0-9\/]');
}
validationObj.prototype.allowTime = function()  {
	//option exists to pass in event object so this function can be called from within another function instead of just used as a direct event handler
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[0-9,\:apmAPM ]');
}
validationObj.prototype.allowDateTime = function()  {
	//option exists to pass in event object so this function can be called from within another function instead of just used as a direct event handler
	var oEvent = (arguments.length==1 ? arguments[0] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.allowRegExp(oEvent,'[0-9,\:apmAPM\/ \-]');
}

validationObj.prototype.allowAllExcept = function(strRegExp) {
	var oEvent = (arguments.length >= 2 ? arguments[1] : (window.event || arguments.callee.caller.arguments[0]));
	return oValidation.disallowRegExp(oEvent,strRegExp);
}


/*--------------------------------------------------------------------------------------------------
isBlank
--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isBlank = function(oEl) {
	var bBlank;
	if (oEl) {
		if (!oEl.type) {
			switch (oEl[0].type) {
				case "radio" :
				case "checkbox":
					bBlank = true;
					for (var i=0; i < oEl.length && bBlank; i++) {
						bBlank = (!oEl[i].checked);
					}
					break;
				case "select-one": //will occur if two select boxes with same name on page
					bBlank = true;
					for (var i=0; i < oEl.length && bBlank; i++) {
						bBlank = (oEl[i].value == "");
					}
					break;
			}
			//for (var i=0; i < oEl.length; i++) indicateFieldStatus(oEl[i],!bBlank)
		} else {
			switch (oEl.type) {
				case "checkbox" : //will get here instead of above if there is only one checkbox with this name on the page
					bBlank = !oEl.checked;
					break;
				case "select-one" :
					//if the select box size is > 1 then we're assuming the first element is a valid selection
					if (oEl.size > 1) bBlank = oEl.selectedIndex < 0
					else {
						//if the value of the first field is an empty string, assume that it is a blank ([Select...]) type option
						bBlank = ((oEl.selectedIndex == -1) || (trim(oEl.options[0].value).length==0 && oEl.selectedIndex <=0));
					}
					break;
				case "text" :
				case "textarea" :
				case "hidden" :
				case "password" :
				case "file":
					bBlank = trim(oEl.value).length == 0;
					break;
				case "select-multiple" : //return false if select list is empty...unless special attribute set since this mainly applies to the multiple selects in Reports
					bBlank = (oEl.options.length == 0);
					if ((!bBlank) && (oEl.validateIndex)) bBlank = oEl.selectedIndex < 0;
					break;
				default: 
					alert("Encountered a "+oEl.type+" data type that is not handled.  Name:"+oEl.name);
			}
				
		}
			
	}

	return (bBlank);
}
/*--------------------------------------------------------------------------------------------------
isValid : auto-decision field validation based on field name
--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValid = function(oEl) {
	var bValid = false;
	if (oEl){
		if (oEl.type != "text") {
			bValid = true; //can't handle anything other than text form fields right now
		} else {
			sFieldname = oEl.getAttribute("fieldname"); //key on this first since most unique;
			if (!sFieldname) sFieldname = oEl.name;
			if (!sFieldname) sFieldname = oEl.id;
			if (!sFieldname) throwConsoleError("validationObj.isValid","Unable to make an auto-decision based on fieldname");
			
			sValue = oEl.value;	
						
			if (sValue != "") {
				if (sFieldname.search(/areacode/i) >=0) {
					bValid = this.isValidAreaCode(sValue);
				} else if (sFieldname.search(/phonenumber|faxnumber|cellularnumber|faximportnumber/i) >=0) {
					bValid = this.isValidPhoneNumber(sValue);
					if (bValid) oEl.value = formatPhoneNumber(sValue);
				} else if (sFieldname.search(/email/i) >=0) {
					var aReturn = this.validateEmail(sValue);
					bValid = aReturn[0];
				} else if (sFieldname.search(/zip/i) >=0) {
					bValid = this.isValidZipCode(sValue);
				} else if (sFieldname.search(/date/i) >=0) {
					bValid = this.isValidDate(sValue);
				} else {
					bValid = true;
				}
			} else {
				bValid = true;
			}
			
		}
		
	} 
	
	return (bValid);
}


/*--------------------------------------------------------------------------------------------------
Utilities
--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isMatchRegExp = function(sValue,sRegExp) {
	var bValid = true; //only validates if not a blank value!
	if (sValue != "") {
		var reg = new RegExp(sRegExp);
		bValid = (sValue.match(reg) != null)
	}
	return bValid;
}
validationObj.prototype.isValidNumericRange = function(sValue,sRange) {
	//expecting sRange in semi regexp format... -1,[1-10] allows either a -1 or any number from 1 to 10.  [ ] required for range
	var bValid = true;
	sValue = trim(sValue);
	
	if (sValue != "") {
		bValid = !isNaN(sValue);
		if (bValid) {
			sValue = parseFloat(sValue);
			var sCheck = "";
			var aChecks = sRange.split(",");
			
			var min, max, aRange;
			for (var index=0;index < aChecks.length; index++) {
				sCheck = aChecks[index];
				if (sCheck.indexOf('[')==0) {
					sCheck = sCheck.replace("[","").replace("]","");
					aRange = sCheck.split("-");
					min = parseFloat(aRange[0]);
					max = parseFloat(aRange[1]);
					bValid = ((sValue >= min) && (sValue <=max));
				} else {
					bValid = (sValue==parseFloat(sCheck));
				}
				if (bValid) break;
			}
		}
	}
	
	return bValid;
}
/*--------------------------------------------------------------------------------------------------
Custom data types or functions to call directly when not automatically handled by name search
	within isValid()
--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidURL = function(sValue) {
	if ((sValue != "") && (sValue.slice(0,7)=="mailto:")) {
		var sEmail = sValue.replace("mailto:","");
		var aReturn = this.validateEmail(sEmail);
		return aReturn[0];
	}
	else return this.isMatchRegExp(sValue,/^(http|https):\/\/([\w-]+\.)+([\w-]{2,6})(\/[\w- .\/?%&=]*)?/);

}
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidZipCode = function(sValue) {
	if (sValue.indexOf(".") != -1) return false;
	if (sValue.indexOf(",") != -1) return false;
		
	var len =  sValue.length;	
	if (len == 5) return !isNaN(sValue);
	else {		
	    if (len == 10) return (!isNaN(sValue.substr(0,5))) && (!isNaN(sValue.substr(6,4))) && (sValue.substr(5,1)=="-");
		else return false;	
	}
	return false;
}
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidAreaCode = function(sValue) {
	if (sValue.indexOf(".") != -1) return false;
	if (sValue.indexOf(",") != -1) return false;
	if (sValue.length == 3) return !isNaN(sValue);
	return false;
}
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidPhoneNumber = function(sValue) {
	if (sValue.indexOf(",") != -1) return false;
	var len = sValue.length;	
	if (len == 7) return !isNaN(sValue);
	else {
		var delimiter = sValue.substr(3,1);
	    if (len == 8) return (!isNaN(sValue.substr(0,2))) && (!isNaN(sValue.substr(4,4))) && (delimiter=="-" || delimiter==".");
		else return false;	
	}
	return false;
}
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidDate = function(sValue) {
	var oEl = (arguments.length==2 ? arguments[1] : null);
	
	//requires date to be in mm/dd/yyyy, mm/dd/yy, mm-dd-yy, mm-dd-yyyy, or mmddyyyy format
	var datePat = /^(\d{1,2})([\/-]*)(\d{1,2})([\/-]*)(\d{2,4})$/;
	var matchArray = sValue.match(datePat); 

	if ((matchArray == null) || ((sValue.indexOf("/") == -1) && (sValue.length != 8)) ) {
		return false;
	} else {
		//now validate the values
		var month = matchArray[1]*1;
		var day = matchArray[3]*1;
		var year = parseInt(matchArray[5]);
		if ((month < 1) || (month > 12)) return false;
		if ((day < 1) || (day > 31)) return false;
		if ((month == 4 || month == 6 || month == 9 || month == 11) && (day == 31)) return false;
		if (month == 2) {
			var bLeap = (year % 4 == 0 && (year % 100 !=0 || year % 400 == 0));
			if (day > 29 || (day == 29 && !bLeap)) return false
		}
		if ((year >= 100) && (year <= 999)) return false; //do not allow three digit year
		
		if ((oEl) && (oEl.type=="hidden" || oEl.type=="text")) { //do not try to reformat a select control value
			oEl.value = month + "/" + day + "/" + year; //corrects any problems with people entering something like 8/1//2011
		}

		return true;
	}
}
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.isValidTime = function(sValue) {

	//requires date to be in hh:mm AM/PM
	var timePat = /^(\d{1,2}):(\d{1,2}) *(AM|PM)$/i;
	var matchArray = sValue.match(timePat); 
	if ((matchArray == null) || ((sValue.indexOf(":") == -1) && (sValue.length != 8)) ) {
		return false;
	} else {
		//now validate the values
		var hour = matchArray[1]*1;
		var min = matchArray[2]*1;
		if ((hour < 1) || (hour > 12)) return false;
		if (min > 59) return false;
		
		return true;
	}
}

/*--------------------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------------------*/
validationObj.prototype.validateEmail = function(sEmail) {
	var objReturn = Array();
	var emailPat=/^(.+)@(.+)$/
	var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]"
	var validChars="\[^\\s" + specialChars + "\]"
	var quotedUser="(\"[^\"]*\")"
	var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/
	var atom=validChars + '+'
	var word="(" + atom + "|" + quotedUser + ")"
	var userPat=new RegExp("^" + word + "(\\." + word + ")*$")
	var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$")
	var matchArray=sEmail.match(emailPat)
	
	if (matchArray==null) return Array(false,"Format is incorrect (check @ and .'s)");

	var user=matchArray[1];
	var domain=matchArray[2];
	if (user.match(userPat)==null) return Array(false,"The user name doesn't seem to be valid");

	var IPArray=domain.match(ipDomainPat)
	if (IPArray!=null) { // this is an IP address
		for (var i=1;i<=4;i++) {
			if (IPArray[i]>255) return Array(false,"Destination IP address is invalid");
	    }
	    return Array(true)
	}

	var domainArray=domain.match(domainPat)
	if (domainArray==null) return Array(false,"The domain name doesn't seem to be valid");

	var atomPat=new RegExp(atom,"g")
	var domArr=domain.match(atomPat)
	var len=domArr.length
	if (domArr[domArr.length-1].length<2 ||  domArr[domArr.length-1].length>4) return Array(false,"The address must end in a three or four letter domain, or two letter country");

	if (len < 2) return Array(false,"This address is missing a hostname");

	return Array(true);
}

