/*	
	Validations.js v 2.9 - Custom Validation Script	
	Author:  Nitin Menon
	Email: 	 nitin@bigbuzz.com
	Date:	 1/6/2007 1:18 PM 	
	
	Validates Following:
	 - Empty Input Fields
	 - Check boxes [checkbox]
	 - Radio buttons [radio]
	 - Email Format [email]
	 - Date Format [date]
	 - Zipcode Format (US/CA) [zipcode]
	 - Phone Number Format [phone]
	 - Social Security [social]
	 - IP Address [ip]
	 - URL Format [url]
	 - String Format [string]
	 - Number Format [number]
	 - Money Format [money]
	 - Compares two strings [compare]
	 - Alpha Characters [alpha]
	 - Alphanumeric Characters [alphanumeric]
	 - XSS Malicious Code [xsscode]
	 - Username Taken Verification (SPRY must be installed) [un_availablity]
	 - Age Verification [checkage]
	 - Regular Expression [regexp]
*/

// Version number
var ScriptVersion = 2.9;

// CSS Style for the required text
var RequiredTextStyle = "color:red;padding-left:5px;font-family:arial;vertical-align:top;font-size:12px;";

function _$() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string') element = document.getElementById(element);
		if (arguments.length == 1) return element;
		elements.push(element);
	}
	return elements;
}

function trim(strValue){
	var objRegExp = /^(\s*)$/;
	if(objRegExp.test(strValue)){
	   strValue = strValue.replace(objRegExp, '');
	   if(strValue.length == 0) return strValue;
	};
	objRegExp = /^(\s*)([\W\w]*)(\b\s*$)/;
	if(objRegExp.test(strValue)) strValue = strValue.replace(objRegExp, '$2');
	return strValue;
};

/*
	This function can be used filter inputs before submitting the form,
	However this function is not used within the Validate() this can be 
	used with 'on' events 
*/
function filter(id,type){
	switch(type){
		case "string":
			var field = _$(id);
			var newVal = field.value.replace(/\d/g,"");
			field.value = newVal;
		break;
		case "number":
			var field = _$(id);
			var newVal = field.value.replace(/[a-zA-Z!@#$%^&*\s?"'._~`:;<=>{}()|+-]/g,"");
			field.value = newVal;
		break;
		case "money":
			var field = _$(id);
			var newVal = field.value.replace(/[a-zA-Z!@#$%^&*\s?"'_~`:;<=>{}()|+-,]/g,"");
			field.value = newVal;
		break;
		case "special":
			var field = _$(id);
			var newVal = field.value.replace(/[!@#$%^&*\s?'._~`:;<=>{}()|+]/g,"");
			field.value = newVal;
		break;
	};	
};

/*
	This function is used to clear all required span tags 
*/
function eraseAllReqSpanTags(){
	var span = document.getElementsByTagName("span"); 
	var re_elmName = new RegExp("_req");
	for (var i = 0; i < span.length; i++) { 
		spID = span[i].getAttribute("id"); 
		if (re_elmName.test(spID)) span[i].innerHTML="";
	};	
};

function validate(params){
	// Script Version detection
	if(!params.id && !params.name &&  ScriptVersion >= 2){
		alert('ERROR: You maybe using a calling function for an older version of the Validations script. The current version you have installed is v '+ ScriptVersion + '. The proper calling function syntax for this version is: \
			   \n \n if(!validate({id:"[fieldid]"})) return false; \n \n To view the complete list of parameters that can be passed into the validate function refer to the developer comment in the validation.js file.');
		return false;
	}
	
	// Default Params
	if(!params.type) params.type = "";
	if(!params.required) params.required = "yes";
	if(!params.alerts) params.alerts = null;
	if(!params.minlength) params.minlength = null;

	/* 
		Firefox throws an exception error when focus() is called;
		To avoid this error, you have to turn off autocomplete
	*/
	var inputElements = document.getElementsByTagName("input");
	for (i=0; inputElements[i]; i++){
		inputElements[i].setAttribute("autocomplete","off");
	}
	
	// If field is a radio or checkbox get the name of the field not the id
	if(params.type.toLowerCase() == "radio" || params.type.toLowerCase() == "checkbox"){
		if(!params.name){ // Must pass in field name
			alert("ERROR: You must specify a Field name in your calling function. Please check your code."); 
			return false;
		}		
		var fieldname = document.getElementsByName(params.name);
		if(!fieldname){
			alert("ERROR: An input field with the Name= " + params.name + " does not exist. Please make sure that all input fields are labeled with the correct name. Please check your code."); 
			return false;
		}
		var FieldId = fieldname[0];
	}else{
		if(!params.id && !params.name){ // Must pass in field id
			alert("ERROR: You must specify a Field ID in your calling function. Please check your code."); 
			return false;
		}
		
		if(params.id){
			 var FieldId = _$(params.id);
		}else if(params.name){
			 var FieldId = document.getElementsByName(params.name)[0];
		}

		
		if(!FieldId){
			alert("ERROR: An input field with the ID= " + params.id + " does not exist. Please make sure that all input fields are labeled with the correct ID and that it matches the field Name. Please check your code."); 
			return false;
		}
	}
	
	var FieldVal = trim(FieldId.value);

	if(!params.alerts){ // If alerts is not defined, it will use alert message instead of spans
		var newSpan = _$(params.id + "_req");
		if( newSpan == null ){ 
			newSpan = document.createElement("span"); 
			newSpan.setAttribute('id',params.id + '_req'); 
			newSpan.style.cssText = RequiredTextStyle;  // IE
			newSpan.setAttribute('style',RequiredTextStyle); // FireFox 
		};
		var parent = FieldId.parentNode; 
		parent.insertBefore(newSpan,FieldId.nextSibling); 
		eraseAllReqSpanTags();
	}else{
		var required_message = params.alerts;	
	}
	
	if(!FieldVal.length && params.required != "no"){
		if(!params.alerts){
			newSpan.innerHTML = "Required";	
		}else{
			alert(required_message);
		}
		
		if(params.type.toLowerCase() != "hidden"){ // Hidden Fields Do Not Allow Focus In Internet Explorer
			FieldId.focus();
		}
		return false;
	}else if(FieldVal.length){ 
		if(params.minlength && FieldVal.length < params.minlength){
			if(!params.alerts){
				newSpan.innerHTML = "Must Have Atleast " + params.minlength + " Characters";
			}else{
				alert(params.id + " Must Have Atleast " + params.minlength + " Characters");	
			}
			FieldId.focus();
			return false;
		};
		switch(params.type.toLowerCase()){
			
			// Validate Check boxes and Radio buttons	
			case "checkbox": case "radio":
				var checked = -1;
				for (i=0; i < fieldname.length; i++){
					if(fieldname[i].checked) checked = i;
				};
				if(checked == -1){
					if(!params.alerts){
						newSpan.innerHTML = "Required";
					}else{
						alert(required_message);	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
				  	return true;
				};
			break;
			
			// Validate Email Addresses ( e.g: username@domain.com )
			case "email":
				if(!(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid E-mail";
					}else{
						alert("Please Enter a Valid E-mail.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
				  	return true;
				};
			break;
			
			// Validate Date ( e.g: mm/dd/yyyy )
			case "date":
				if(!(/^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Date Format: [ mm/dd/yyyy ]";
					}else{
						alert("Please Enter Date Format: [ mm/dd/yyyy ].");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
				  	return true;
				};
			break;
			
			// Validate US & Canadian Zipcodes
			case "zipcode":
				var USZip = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
				var CAZip = /^((\d{5}-\d{4})|(\d{5})|([AaBbCcEeGgHhJjKkLlMmNnPpRrSsTtVvXxYy]\d[A-Za-z]\s?\d[A-Za-z]\d))$/;

				if(!(USZip.test( FieldVal )) && !(CAZip.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid Zipcode";
					}else{
						alert("Please Enter a Valid Zipcode.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate Phone Number
			case "phone":
				if(!(/(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid Phone Number";
					}else{
						alert("Please Enter a Valid Phone Number With Area Code.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate Social Security
			case "social":
				var USSS = /^\d{3}\-?\d{2}\-?\d{4}$/;
				var CASS = /^\d{9}$/;
				
				if(!(USSS.test( FieldVal )) && !(CASS.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid Social Security";
					}else{
						alert("Please Enter a Valid Social Security.");	
					}	
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate IP Address
			case "ip":
				if(!(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid IP Address";
					}else{
						alert("Please Enter a Valid IP Address.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate URL
			case "url":

				/*
				var emailRegxp = /^([\w]+)(.[\w]+)*@([\w]+)(.[\w]{2,3}){1,2}$/;
				var urlRegxp = /^(http:\/\/www.|https:\/\/www.|ftp:\/\/www.|www.){1}([\w]+)(.[\w]+){1,2}$/;
				
				followed by any word character displayed one or more times,
				followed by a dot and two or three word characters repeated at least once but no more than twice,
				so email addresses ending in .com or .co.uk will pass, whereas .co.uk.com would fail.
				Similarly, the URL may begin with either 
				http://www. or https://www. or ftp://www. or just www.
				once followed by any word character one or more times,
				followed by a dot and any number of word characters at least once but no more than twice. 
				*/

				if(!(/^((http:\/\/|https:\/\/|ftp:\/\/){1})?([\w].+)?([\w]+)(.com|.edu|.org){1}$/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Enter Valid URL";
					}else{
						alert("Please Enter a Valid URL.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate String Format
			case "string":
				if((/[\d]/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Invalid! Only Letters Allowed";
					}else{
						alert("Invalid! Only Letters Allowed.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate Number Format
			case "number":
				if((/\D/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Invalid! Only Numbers Allowed";
					}else{
						alert("Invalid! Only Numbers Allowed.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}return true;
				};
			break;
			
			// Validate Money Format
			case "money":
				if((/[$]/.test( FieldVal ))){
					if(!params.alerts){
						newSpan.innerHTML = "Please Remove The $";
					}else{
						alert("Please Remove The $.");	
					}
					FieldId.focus();
					return false;
				}else if((/[a-zA-Z!@#%^&*\s?'_~`:;<=>{}()|+-]/.test(FieldVal))){
					if(!params.alerts){
						newSpan.innerHTML = "Invalid! Only Numbers Allowed";
					}else{
						alert("Invalid! Only Numbers Allowed..");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Compare two string
			case "compare":
				if(!params.id2){ alert("ERROR: You must specify a second Field ID in your calling function if your type is 'compare'."); return false;}
				var FieldId_2 = _$(params.id2);
				if(FieldVal != trim(FieldId_2.value)){
					if(!params.alerts){
						newSpan.innerHTML = "Confirmation Mismatch";
					}else{
						alert("Confirmation Entry Does Not Match.");	
					}
					FieldId.focus();
					return false;		
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate Alpha Characters ONLY
			case "alpha":
				if(!(/^[a-zA-Z]+$/.test(FieldVal))){
					if(!params.alerts){
						newSpan.innerHTML = "Invalid! Only Alpha Characters Allowed";
					}else{
						alert("Invalid! Only Alpha Characters Allowed.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate Alphanumeric character ONLY
			case "alphanumeric":
				if(!(/^[a-zA-Z0-9]+$/.test(FieldVal))){
					if(!params.alerts){
						newSpan.innerHTML = "Invalid! Only Alpha Numeric Characters Allowed";
					}else{
						alert("Invalid! Only Alpha Numeric Characters Allowed.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Validate XSS Malicious Code
			case "xsscode":
				var strRegex = "(-- )|(' )|(script)|(<)|(>)|(%3c)|(%3e)|(select)|(update)|(insert)|(delete)|(drop)|(grant)|(revoke)|(union)|(&lt;)|(&gt;)";
				var re = new RegExp(strRegex);
				var str = FieldVal.toLowerCase();
				if(str.match(re)){
					if(!params.alerts){
						newSpan.innerHTML = "XSS (malicious) code detected!";
					}else{
						alert("XSS (malicious) code detected!");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Check if user name is available (SPRY FRAMEWORK REQUIRED) 
			case "un_availablity":
				if(!params.urlpath){ 
					alert("Please pass in a url path to the file that Spry will read."); 
					return false; 
				}
				try{
					// This Validation can only be done if the Spry Files are being referenced
					request = Spry.Utils.loadURL("GET", params.urlpath + encodeURIComponent(FieldVal), false);
					var result = request.xhRequest.responseText;
 				}catch(err){
				   alert("There was an error using Spry. Please make sure that the Spry files are set up correctly.");
				   return false;
				}				
				
   				if(result==0){
					if(!params.alerts){
						newSpan.innerHTML = "Username Taken";
					}else{
						alert("Username Taken.");	
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			// Age Verification
			case "checkage":
				if(!params.minage) params.minage = 13; // Default Age

				var Today = new Date();
				Today.setHours(0,0,0,0); 
				// Must pass in date in mm/dd/yyyy format
				if(!validate({id:params.id,type:"date",required:"yes"})) return false;
				// Format field to be exactly in mm/dd/yyyy format
				FieldVal = FieldVal.replace(/^(\d{1}\/)/,"0$1").replace(/(\d{2}\/)(\d{1}\/)/,"$10$2");
				// Get Date using '/' as a delimiter  
				var splitDate = FieldVal.split("/");
				// Creates Date from the value passed in an parsed [mm/dd/yyyy]
				var bDay = new Date(splitDate[2]+"/"+splitDate[0]+"/"+splitDate[1]);
				var age = Today.getFullYear() - bDay.getFullYear();
				var currYrbDay = new Date(Today.getFullYear(), bDay.getMonth(), bDay.getDate());
				if (currYrbDay > Today && age > 0) age--;
				
				if(age <  params.minage){
					alert("Sorry. You Are Not Old Enough To Continue.");	
					return false;
				}else{
					return true;
				};
			break;
			
			// Validate any regExp
			case "regexp":
				if(!params.regexp){ 
					alert("Please pass in a regular expression to validate. Check your code."); 
					return false; 
				}
				var re = new RegExp(params.regexp);
				if(!(re.test(FieldVal))){
					if(!params.alerts){
						if(!params.errortext){
							newSpan.innerHTML = "Invalid Format";
						}else{
							newSpan.innerHTML = params.errortext;
						}
					}else{
						if(!params.errortext){
							alert("Invalid Format.");	
						}else{
							alert(params.errortext);
						}
					}
					FieldId.focus();
					return false;
				}else{
					if(!params.alerts){
						newSpan.innerHTML = "";
					}
					return true;
				};
			break;
			
			default: // Default Passed all validations
				if(!params.alerts){
					newSpan.innerHTML = "";
				}
				return true;
			break;
		};
	}else{
		if(!params.alerts){
			newSpan.innerHTML = "";
		}
		return true;
	};
};
