/*
+----------------------------------------------------------------------+
| Input Validation Class						                       |
+----------------------------------------------------------------------+
| Copyright (c) July 2006                                              |
+----------------------------------------------------------------------+
|                                                                      |
|  Easy to use validation class, feel free to update the regex, to     |
|  make it more strict in cases where necessary. If changes are made   |
|  also be sure to make changes to InputValidation.class so that the   |
|  javascript and PHP versions stay in sync                            |
|                                                                      |
|  Implemented the same way the PHP class is, just change your -> to . |
|  remove your $ from your variable names, and change your input       |
|												                       |
+----------------------------------------------------------------------+
| Authors: Erik St. Martin                                             |
+----------------------------------------------------------------------+
*/

/* Usage
*
* input = new InputValidation(document.getElementById("Email").value);
*
* if( !input.IsValidEmail() ){
*     alert('Please Supply A Valid Email');
* }
*
*/


/******************************************************************************
* Class Constructor
*
* @param     input         str		data to validate
* @param     trim          bool	optionally trim data before running validation checks
* @access    public
* @return    void
*/
function InputValidation(input,trim){
	if(trim == true){
		input = input.replace(/^\s+/g, '').replace(/\s+$/g, '');
	}
	
        // Stores Input
	this.input = input;

	// Methods
	this.SetInput=IV_SetInput;
	this.IsValidRange=IV_IsValidRange;
	this.IsValidLength=IV_IsValidLength;
	this.IsValidEnum=IV_IsValidEnum;
	this.IsValidNum=IV_IsValidNum;
	this.IsValidAlpha=IV_IsValidAlpha;
	this.IsValidAlphaNum=IV_IsValidAlphaNum;
	this.IsNotBlank=IV_IsNotBlank;
	this.IsValidStreet=IV_IsValidStreet;
	this.IsValidCity=IV_IsValidCity;
	this.IsValidState=IV_IsValidState;
	this.IsValidZip=IV_IsValidZip;
	this.IsValidSSN=IV_IsValidSSN;
	this.IsValidRegex=IV_IsValidRegex;
	this.IsValidDate=IV_IsValidDate;
	this.IsValidDateRange=IV_IsValidDateRange;
	this.IsValidEmail=IV_IsValidEmail;
	this.IsValidFirstName=IV_IsValidFirstName;
	this.IsValidLastName=IV_IsValidLastName;
	this.IsValidPhone=IV_IsValidPhone;
}

/******************************************************************************
* Available so that you do not have to reinstantiate this class
*
* @param     input         str		data to validate
* @param     trim          bool	optionally trim data before running validation checks
* @access    public
* @return    void
*/
function IV_SetInput(input,trim){
	if(trim == true){
		input = input.replace(/^\s+/g, '').replace(/\s+$/g, '');
	}

	this.input = input;
}

/******************************************************************************
* Determines if an integer falls between 2 values
*
* @param     int_start       int		start value
* @param     int_end         int		end value
* @access    public
* @return    bool
*/
function IV_IsValidRange(int_start,int_end){
	if(this.input >= int_start && this.input <= int_end){
		return true;
	} else {
		return false;
	}
}

/******************************************************************************
* Determines if input is the proper number of characters. If only paramater
* supplied value must be exactly specified characters, optionally you may
* supply a maximum length
*
* @param     int_length_min       int		minimum value (or required value for 1 paramater)
* @param     int_length_max       int		optional maximum value
* @access    public
* @return    bool
*/
function IV_IsValidLength(int_length_min,int_length_max){
	if(int_length_max > 0){
		if(this.input.length >= int_length_min && this.input.length <= int_length_max){
			return true;
		} else {
			return false;
		}
	} else {
		return ((this.input.length >= int_length_min) ? true : false);
	}
}

/******************************************************************************
* Determines if input is one of the specified values, when one paramater is given
* it does not enforce case. You may supply true to the optional paramater for case
* sensative match.
*
* @param     arr_options       	array		allowed values
* @param     int_length_max    	bool		optional case sensitive match
* @access    public
* @return    bool
*/
function IV_IsValidEnum(arr_options,case_sensative){

	var valid = false;

	for(var i = 0; i < arr_options.length; i++){
		if(!case_sensative){
			if(this.input.toLowerCase() == arr_options[i].toLowerCase()){
				valid = true;
				break;
			}
		} else {
			if(this.input == arr_options[i]){
				valid = true;
				break;
			}
		}
	}

	return valid;
}

/******************************************************************************
* Determines if input is numeric
*
* @access    public
* @return    bool
*/
function IV_IsValidNum(){
	var regex = new RegExp("^[0-9]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is alpha, no punctuation
*
* @access    public
* @return    bool
*/
function IV_IsValidAlpha(){
	var regex = new RegExp("^[a-zA-Z]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is alphanumeric, no punctuation
*
* @access    public
* @return    bool
*/
function IV_IsValidAlphaNum(){
	var regex = new RegExp("^[a-zA-Z0-9]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is blank
*
* @access    public
* @return    bool
*/
function IV_IsNotBlank(){
	return ((this.input.replace(/^\s+/g, '').replace(/\s+$/g, '')) == '') ? false : true;
}

/******************************************************************************
* Determines if input is in a valid street address format
*
* @access    public
* @return    bool
*/
function IV_IsValidStreet(){
	var regex = new RegExp("^[0-9]{1,}\ [0-9a-zA-Z.-\\\\#\\\\ ]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is in a valid city format ( at least 4 of the following letters, \'s,.'s, spaces
* and starts with at least 3 letters)
*
* @access    public
* @return    bool
*/
function IV_IsValidCity(){
	var regex = new RegExp("^[a-zA-Z]{1,}[a-zA-Z.-\\\\ \\\\\]{3,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is a valid state, assumes it is being passed a state
* abbreviation, optinal paramater can be set to false to check against full state
* name
*
* @param     abbr    	bool		optional check full name, set to false if not an abbreviation
* @access    public
* @return    bool
*/
function IV_IsValidState(abbr){
	var states_array = new Array(54)
	states_array['NA'] = '';
	states_array['AL'] = 'ALABAMA';
	states_array['AK'] = 'ALASKA';
	states_array['AZ'] = 'ARIZONA';
	states_array['AR'] = 'ARKANSAS';
	states_array['CA'] = 'CALIFORNIA';
	states_array['CO'] = 'COLORADO';
	states_array['CT'] = 'CONNECTICUT';
	states_array['DE'] = 'DELAWARE';
	states_array['DC'] = 'DISTRICT OF COLUMBIA';
	states_array['FL'] = 'FLORIDA';
	states_array['GA'] = 'GEORGIA';
	states_array['HI'] = 'HAWAII';
	states_array['ID'] = 'IDAHO';
	states_array['IL'] = 'ILLINOIS';
	states_array['IN'] = 'INDIANA';
	states_array['IA'] = 'IOWA';
	states_array['KS'] = 'KANSAS';
	states_array['KY'] = 'KENTUCKY';
	states_array['LA'] = 'LOUISIANA';
	states_array['ME'] = 'MAINE';
	states_array['MD'] = 'MARYLAND';
	states_array['MA'] = 'MASSACHUSETTS';
	states_array['MI'] = 'MICHIGAN';
	states_array['MN'] = 'MINNESOTA';
	states_array['MS'] = 'MISSISSIPPI';
	states_array['MO'] = 'MISSOURI';
	states_array['MT'] = 'MONTANA';
	states_array['NE'] = 'NEBRASKA';
	states_array['NV'] = 'NEVADA';
	states_array['NH'] = 'NEW HAMPSHIRE';
	states_array['NJ'] = 'NEW JERSEY';
	states_array['NM'] = 'NEW MEXICO';
	states_array['NY'] = 'NEW YORK';
	states_array['NC'] = 'NORTH CAROLINA';
	states_array['ND'] = 'NORTH DAKOTA';
	states_array['OH'] = 'OHIO';
	states_array['OK'] = 'OKLAHOMA';
	states_array['OR'] = 'OREGON';
	states_array['PA'] = 'PENNSYLVANIA';
	states_array['PR'] = 'PUERTO RICO';
	states_array['RI'] = 'RHODE ISLAND';
	states_array['SC'] = 'SOUTH CAROLINA';
	states_array['SD'] = 'SOUTH DAKOTA';
	states_array['TN'] = 'TENNESSEE';
	states_array['TX'] = 'TEXAS';
	states_array['UT'] = 'UTAH';
	states_array['VT'] = 'VERMONT';
	states_array['VA'] = 'VIRGINIA';
	states_array['VI'] = 'VIRGIN ISLANDS';
	states_array['WA'] = 'WASHINGTON';
	states_array['WV'] = 'WEST VIRGINIA';
	states_array['WI'] = 'WISCONSIN';
	states_array['WY'] = 'WYOMING';

	if(abbr != false){
		if(this.input.toUpperCase() == 'NA' || states_array[this.input.toUpperCase()] != undefined){
			return true;
		} else {
			return false;
		}
	} else {
		// Check Full State Name
		var valid = false;
		for(var i in states_array){
			if(this.input.toUpperCase() == states_array[i].toUpperCase()){
				valid = true;
				break;
			}
		}
		return valid;
	}
}

/******************************************************************************
* Determines if input is a valid zip code
* PHP Version Checks Against Database and validate against state,
* This Will Just Validate Syntax
*
* @access    public
* @return    bool
*/
function IV_IsValidZip(){
	// PHP Version Checks Against Database, This Will Just Validate Syntax
	var regex = new RegExp("^[0-9]{5}$");
	return (regex.exec(this.input) != null) ? true : false;
}
/******************************************************************************
* Determines if input is a valid Social Security Number. Can be passed SSN with
* or without punctuation. Checks for blocks and numbers that the administration
* does not issue.
*
* @access    public
* @return    bool
*/
function IV_IsValidSSN(){
	var regex_p = new RegExp("^[0-9]{3}-[0-9]{2}-[0-9]{4}$");
	var regex = new RegExp("^[0-9]{9}$");
	var ssn_parts = new Array();

	if(regex_p.exec(this.input) != null){
		ssn_parts[0] = this.input.substring(0,3);
		ssn_parts[1] = this.input.substring(4,6);
		ssn_parts[2] = this.input.substring(7,11);
	} else if (regex.exec(this.input) != null){
		ssn_parts[0] = this.input.substring(0,3);
		ssn_parts[1] = this.input.substring(3,5);
		ssn_parts[2] = this.input.substring(5,9);
	} else {
		return false;
	}

	if( ssn_parts[0] == "000" 	||
	ssn_parts[0] == "666" 	||
	ssn_parts[0] > "772"	||
	ssn_parts[1] == "00" 	||
	ssn_parts[2] == "0000"){
		return false;
	}

	if(ssn_parts[0] == 987 && ssn_parts[1] == 65 && ssn_parts[2] >= 4320 && ssn_parts <= 4329){
		return false;
	}

	// If we have passed all these checks its as valid as its going to get.
	return true;
}

/******************************************************************************
* Determines if input matches given regular expression. Defaults to case sensitive,
* or you may pass false as the optional paramter to do case insensitive comparison
*
* @param     regex    			str		regular expression
* @param     case_sensitive    bool	optional, case sensitive
* @access    public
* @return    bool
*/
function IV_IsValidRegex(regex,case_sensative){
	var regex = new RegExp(regex,(case_sensative != false ? '' : 'i'));
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is a valid date in the format of m/d/Y, or Y-m-d
*
* @access    public
* @return    bool
*/
function IV_IsValidDate(){
	var regex1 = new RegExp("^[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}$");
	var regex2 = new RegExp("^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$");
	if(regex1.exec(this.input) != null || regex2.exec(this.input) != null){
		// Looks Accurate
		if(Date.parse(this.input) != NaN){
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

/******************************************************************************
* Determines if input is a valid date and falls between supplied dates, provide
* dates in m/d/Y format
*
* @param	 date_start	str	date range begin date (m/d/Y)
* @param	 date_end		str	date range end date (m/d/Y)
* @access    public
* @return    bool
*/
function IV_IsValidDateRange(date_start,date_end){
	if(this.IsValidDate()){
		if(Date.parse(this.input) >= Date.parse(date_start) && Date.parse(this.input) <= Date.parse(date_end)){
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

/******************************************************************************
* Determines if input is a valid email address
*
* @access    public
* @return    bool
*/
function IV_IsValidEmail(){
	var regex = new RegExp("^[a-zA-Z][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is a valid first name
*
* @access    public
* @return    bool
*/
function IV_IsValidFirstName(){
	var regex = new RegExp("^[a-zA-Z]{1,}[a-zA-Z.-\\\\'\\\\ ]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is a valid last name
*
* @access    public
* @return    bool
*/
function IV_IsValidLastName(){
	var regex = new RegExp("^[a-zA-Z]{1,}[a-zA-Z.-\\\\'\\\\ ]{1,}$");
	return (regex.exec(this.input) != null) ? true : false;
}

/******************************************************************************
* Determines if input is a valid phone number with or without hyphens
*
* @param     hyphens    	bool hyphens expected
* @access    public
* @return    bool
*/
function IV_IsValidPhone(hyphens){
	if(hyphens != true){
	    var regex = new RegExp("^[0-9]{10}$");
	} else {
	    var regex = new RegExp("^[0-9]{3}-[0-9]{3}-[0-9]{4}$");
	}
	return (regex.exec(this.input) != null) ? true : false;
}
