/*********************************************************************JavaScript 1.2 Validation Script (IE and Netscape)	version 1.02	by matthew frankThere are no warranties expressed or implied.  This script may bere-used and distrubted freely provided this header remains intactand all supporting files are included (unaltered) in the distribution:		nn-validation.js   - this file		nn-validation.htm  - example form		nn-readme.htm      - directions on using this script		(nn-validation.zip contains all files)If you are interested in keeping up with the latest releases of thisscript or asking questions about its implementation, think about joiningthe eGroups discussion forum dedicated to data validation:	http://www.egroups.com/group/validation*********************************************************************//*====================================================================Function: ValidationPurpose:  Custom object constructor.Inputs:   NoneReturns:  undefined====================================================================*/function Validation(){	/*====================================================================	Function: Err	Purpose:  Custom object constructor	Inputs:   None	Returns:  undefined	====================================================================*/	var Err=function()	{		var oSource  = new Object;		var sMessage = new String;		/*********************************************************************		Method:   Err.clear		Purpose:  Clear values from Error object		Inputs:   none		Returns:  undefined		*********************************************************************/		this.clear=function ()		{			oSource  = new Object;			sMessage = new String;		}		/*********************************************************************		Method:   Validation.Err.add		Purpose:  Adds error to Error object		Inputs:   oSource - source element object				  vType   - integer value of error type (or custom string)				  sFormat - optional date format		Returns:  undefined		*********************************************************************/		this.add=function (oSrc,sMsg)		{			oSource  = oSrc;			sMessage = sMsg;		}		/*********************************************************************		Method:   Err.raise		Purpose:  Gives visual warning to user about all errors contained in				  the Error object		Inputs:   none		Returns:  undefined		*********************************************************************/		this.raise=function ()		{			var sName = oSource.NAME;			var sMsg  = oSource.MSG;			// Alert appropriate error message			sMsg = sMsg ? sMsg : sMessage + (sName ? " in the "+sName+" field" : "");			alert(sMsg);			// Give invalid field focus			if(oSource.focus)				oSource.focus();			if(oSource.select)				oSource.select();			// Clear the Err object			this.clear();		}	}	/*********************************************************************	Function: isDate	Purpose:  Check that value is a date of the correct format	Inputs:   sDate   - date as string	          sFormat - string format	Returns:  boolean	*********************************************************************/	var isDate=function (sDate,sFormat)	{		var aDaysInMonth=new Array(31,28,31,30,31,30,31,31,30,31,30,31);		// Fetch the date separator from the user's input		var sSepDate=sDate.charAt(sDate.search(/\D/));		// Fetch the date separator from the format		var sSepFormat=sFormat.charAt(sFormat.search(/[^MDY]/i));		// Compare separators		if (sSepDate!=sSepFormat)			return false;		// Fetch the three pieces of the date from the user's input and the format		var aValueMDY=sDate.split(sSepDate);		var aFormatMDY=sFormat.split(sSepFormat);		// Assign day, month, year based on format		var iMonth,iDay,iYear;		iMonth = aValueMDY[0];		iDay   = aValueMDY[1];		iYear  = aValueMDY[2];		// Validate that all pieces of the date are numbers		if (  !isNum( iMonth )			||!isNum( iDay   )			||!isNum( iYear  ) )			return false;		// Require 4 digit year		if(iYear.length!=4)			return false;		// Check for leap year		var iDaysInMonth=(iMonth!=2)?aDaysInMonth[iMonth-1]:			((iYear%4==0 && iYear%100!=0 || iYear % 400==0)?29:28);		return (iDay!=null && iMonth!=null && iYear!=null				&& iMonth<13 && iMonth>0 && iDay>0 && iDay<=iDaysInMonth);	}	/********************************************	Function: isNum	Purpose:  Check that parameter is a number	Inputs:   v - string value	Returns:  boolean	********************************************/	var isNum=function (v)	{		return (typeof v!="undefined" && v.toString() && !/\D/.test(v));	}	/********************************************	Function: formatNumber	Purpose:  Format an integer for display	Inputs:   i - integer value (as string)	Returns:  string	********************************************/	var formatNumber=function (i)	{		var sEnd="$";		i = i.toString();		if (/\./.test(i))			sEnd="\\.";		var re = new RegExp("(\\d)(\\d{3})(,|"+sEnd+")");		if(re.test(i))			i = formatNumber(i.replace(re, "$1,$2$3"));		return i;	}	/********************************************	Function: getValueOf	Purpose:  Return the value of a form field as seen at server	Inputs:   oElement - form field	Returns:  boolean	********************************************/	var getValueOf=function (oElement)	{		var sReturnValue = null;		switch (oElement.type)		{			case "text" : case "textarea" : case "file" : case "password" : case "hidden" :				sReturnValue = oElement.value;				break;			case "select-one" :				sReturnValue = oElement.options[oElement.selectedIndex].value;				break;			case "select-multiple" :				var i, iOptions = oElement.options.length;				for(i=0; i<iOptions; i++)					if(oElement.options[i].selected && oElement.options[i].value.toString().trim())					{						sReturnValue = true;						break;					}				break;			case "radio" : case "checkbox" :				if(oElement.checked)					sReturnValue = oElement.value ? oElement.value : true;				break;		}		return sReturnValue;	}	/*********************************************************************	Method:   Validation.setup	Purpose:  Set up methods and event handlers for all forms and elements	Inputs:   none	Returns:  undefined	*********************************************************************/	this.setup=function ()	{		// Fan through forms on page to perform initializations		var i,oForm,iForms=document.forms.length;		for(i=0; i<iForms; i++){			oForm=document.forms[i];			if(!oForm.bProcessed)			{				// Capture and replace onsubmit event handler				var fnSubmit=oForm.onsubmit;				// Create new event handlers				oForm.onsubmit=function ()				{					// Execute onbeforevalidate processing					if(typeof this.onbeforevalidate=="function" && this.onbeforevalidate()==false)						return false;					var i, oElement, iElements=this.elements.length;					// Validate individual elements					for(i=0;i<iElements;i++)					{						oElement=this.elements[i];						// Perform default validation for element						if (!oElement.valid())						{							Validation.Err.raise();							return false;						}					}					// Execute onaftervalidate processing					if(typeof this.onaftervalidate=="function" && this.onaftervalidate()==false)						return false;					// Perform original onsubmit event handler					if (fnSubmit && fnSubmit()==false)						return false;				}				oForm.bProcessed=true;			}			// Create Input methods			var j, iElements=oForm.elements.length;			for(j=0; j<iElements; j++)			{				var oElement=oForm.elements[j];				if(!oElement.bProcessed)				{					/**********************************************					Method:   Input.valid					Purpose:  Validate an element based on the					          attributes provided in the HTML text					Inputs:   none					Returns:  boolean					**********************************************/					oElement.valid=function ()					{						// Trim leading and trailing spaces						if(this.value)							this.value = this.value.trim();						var sValue = getValueOf(this);						// REQUIRED						if(this.REQUIRED && !sValue)						{							Validation.Err.add(this, "Please enter a value");					 		return false;						}						// FLOAT						var bSigned=this.SIGNED;						if (this.FLOAT && sValue)						{							var re=new RegExp("^"+((bSigned)?"-?":"")+"(\\d*(,?\\d{3})*\\.?\\d+|\\d+(,?\\d{3})*\\.?\\d*)$");							if (!re.test(sValue))							{								Validation.Err.add(this, "Please enter a number");								return false;							}							// MIN							var iMin = this.MIN;							if(iMin==parseFloat(iMin) && sValue.replace(/,/,"")<iMin)							{								Validation.Err.add(this, "Please enter a value greater than or equal to "+formatNumber(iMin));								return false;							}							// MAX							var iMax = this.MAX;							if(iMax==parseFloat(iMax) && sValue.replace(/,/,"")>iMax)							{								Validation.Err.add(this, "Please enter a value less than or equal to "+formatNumber(iMax));								return false;							}						}						// AMOUNT						if (this.AMOUNT && sValue)						{							var sSigned = "(\\$?-?|-?\\$?)";							var re = new RegExp("^"+((bSigned)?sSigned:"\\$?")+"((\\d{1,3})*(,?\\d{3})*\\.?\\d{2}|\\d{1,3}(,?\\d{3})*\\.?(\\d{2})?)$");							if(!re.test(sValue))							{								Validation.Err.add(this, "Please enter a dollar amount");								return false;							}							// MIN							var iMin = this.MIN;							if(iMin==parseFloat(iMin) && sValue.replace(/[\$,]/,"")<iMin)							{								Validation.Err.add(this, "Please enter a value greater than or equal to $"+formatNumber(iMin));								return false;							}							// MAX							var iMax = this.MAX;							if(iMax==parseFloat(iMax) && sValue.replace(/[\$,]/,"")>iMax)							{								Validation.Err.add(this, "Please enter a value less than or equal to $"+formatNumber(iMax));								return false;							}						}						// INTEGER						if (this.INTEGER && sValue)						{							var re=new RegExp("^"+((bSigned)?"-?":"")+"\\d{1,3}(,?\\d{3})*$");							if (!re.test(sValue))							{								Validation.Err.add(this, "Please enter an integer");								return false;							}							// MIN							var iMin = this.MIN;							if(iMin==parseInt(iMin) && sValue.replace(/,/,"")<iMin)							{								Validation.Err.add(this, "Please enter a value greater than or equal to "+formatNumber(iMin));								return false;							}							// MAX							var iMax = this.MAX;							if(iMax==parseInt(iMax) && sValue.replace(/,/,"")>iMax)							{								Validation.Err.add(this, "Please enter a value less than or equal to "+formatNumber(iMax));								return false;							}						}						// DATE						if (this.DATE && sValue)						{							// Set default date format							var sFormat = "MM/DD/YYYY";							if (!isDate(sValue,sFormat))							{								Validation.Err.add(this, "Please enter a date as MM/DD/YYYY");								return false;							}						}						// REGEXP						var oRegexp=this.REGEXP;						if(oRegexp && oRegexp.constructor==RegExp && sValue)						{							if(!oRegexp.test(sValue))							{								Validation.Err.add(this, "Please enter a valid value");								return false;							}						}						// PHONE						if(this.PHONE && sValue)						{							var sPhone  = sValue.replace(/\D/g,"");							var iDigits = sPhone.length;							if( !(iDigits==10 || iDigits==11 && /^1/.test(sPhone)) )							{								Validation.Err.add(this, "Please enter a valid phone number");								return false;							}						}						// LENGTH						if(sValue && this.LENGTH && isNum(this.LENGTH) && sValue.length>this.LENGTH)						{							Validation.Err.add(this, "Please enter a value with fewer than " + formatNumber(this.LENGTH) + " characters");							return false;						}						// EMAIL						if(this.EMAIL && sValue)						{							if(!/^[\w_-]+(\.[\w_-]+)*@[\w_-]+(\.[\w_-]+)*\.\w{2,3}$/i.test(sValue))							{								Validation.Err.add(this, "Please enter a valid email address");								return false;							}						}						// ZIP Code						if(this.ZIP && sValue)						{							if(!/^\d{5}(-?\d{4})?$/.test(sValue))							{								Validation.Err.add(this, "Please enter a valid ZIP code");								return false;							}						}						// AND						var vAnd=this.AND;						if(vAnd && sValue)						{							// If not an array, create one							if(vAnd.constructor!=Array)								vAnd = vAnd.toString().split(/,/);							// Require each element in the list							var i, iFields=vAnd.length;							for(i=0; i<iFields; i++)							{								var oNewElement =									(vAnd[i].form)									? vAnd[i]									: this.form.elements[vAnd[i].trim()];								if(oNewElement)								{									if(!getValueOf(oNewElement))									{										Validation.Err.add(oNewElement, "Please enter a value");										return false;									}								}							}						}						// OR						var vOr=typeof this.OR=="object";						if(vOr && !sValue)						{							vOr = this.OR["fields"];							if(vOr)							{								// If not an array, create one								if(vOr.constructor!=Array)									vOr = vOr.toString().split(/,/);								// Require each element in the list								var i, iFields=vOr.length;								var bValue=false;								for(i=0; i<iFields; i++)								{									var oNewElement =										(vOr[i].form)										? vOr[i]										: this.form.elements[vOr[i].trim()];									if(oNewElement)										bValue |= !!getValueOf(oNewElement);								}								if(!bValue)								{									Validation.Err.add(this, this.OR["msg"]?this.OR["msg"]:"Please enter a value");									return false;								}							}						}						// NOSPACE						if (this.NOSPACE && this.value)							this.value=this.value.replace(/\s/g,"");						// UPPERCASE						if (this.UPPERCASE && this.value)							this.value=this.value.toUpperCase();						// LOWERCASE						if (this.LOWERCASE && this.value)							this.value=this.value.toLowerCase();						// Perform onvalidate event handler						if(typeof this.onvalidate=="function" && this.onvalidate()==false)							return false;						return true;					}					oElement.bProcessed=true;				}			}		}	}	// Limit use of script to valid environments	if("".replace && window.RegExp)	{		/*********************************************************************		Method:   String.trim		Purpose:  Removing leading and trailing spaces		Inputs:   none		Returns:  string		*********************************************************************/		String.prototype.trim=function ()		{			return this.replace(/^\s+|\s+$/g,"");		}		// Form setup		if(document.forms)		{			this.setup();			this.Err=new Err;		}	}}Validation=new Validation;