/* ====================================================
Standard Form Validation Library

Author: Ryan Anderson <randerson@webvisible.com>
Version: 1.2
Last Revision: October 16th, 2007

TODO: allow user to specify additional symbols
TODO: strict mode for disallowing spaces (maybe hyphens too?)

Dependencies
------------------------------


Method Reference
------------------------------
registerElement(element_id, field_name, data_type, min_length, max_length)
	Register a form element for validaton
	
unRegisterElement(element_id)
	Unregister an element
	
validate()
	Validates the entire collection of registered elements

getErrors() 
	Gets the current errors, as an array

clearErrors() 
	Clears the error array
	
Test Patterns
----------------------------
isAlphaNumeric(value)

isValid(value, pattern)

isValidEmail(value)
isValidUrl(value)
isValidPostalCode(value, country_code)

-------------------------------

======================================================= */

// Validation Object ======================
function Validation(translation) {
	//Members
	this.data_is_valid 		= true;
	this.dataElements		= [];
	this.elementCounter		= 0;
	this.errors				= [];
	this.errorsInline       = new Array();
	
	this.translation        = translation;
	
	//Methods
	this.registerElement	= objRegister;
	this.unRegisterElement	= objUnregister;
	this.validate 			= objValidate;
	this.validateInline		= objValidateInline;
	this.clearErrors		= objClearErrors;
	this.clearErrorsInline	= objClearErrorsInline;
	this.getErrors			= objGetErrors;
	this.getErrorsInline	= objGetErrorsInline;
	
	this.getTypeMessaging   = objGetTypeMessaging;
	
	this._                  = objTranslate;
}

//Validation.registerElement
function objRegister(id, field_name, data_type, min_length, max_length) {
	var element 		= new dataElement();
	element.id 			= id;
	element.field_name	= field_name;
	element.data_type	= data_type;
	element.max_length	= max_length;
	element.min_length	= min_length;
	
	this.dataElements.push(element);
	this.elementCounter++;
}

//Validation.unRegisterElement
function objUnregister(id) {
	
}

//Validation.validate()
function objValidate() {
	this.data_is_valid = true;
	for (var i=0; i<this.dataElements.length; i++) {
		var element = this.dataElements[i];
		if (element.data_type == 'dropdown') {
			if ((document.getElementById(element.id).value == "") && (element.min_length > 0)) {
				this.errors.push(element.field_name + ' ' + this._('required'));
				this.data_is_valid = false;
			}
		} else if (element.data_type == 'listbox') {
			total_selected = document.getElementById(element.id).options.length;
			if (total_selected < element.min_length) {
				this.errors.push("You must select at least "+element.min_length+" "+element.field_name);
				this.data_is_valid = false;	
			} else if (total_selected > element.max_length && element.max_length != 0) {
				this.errors.push("You can select a maximum of "+element.max_length+" "+element.field_name);	
				this.data_is_valid = false;
			}
		} else if (element.data_type == 'checkbox') {
			
		} else {
			var value = idValue(element.id);
			if (isEmpty(value) && element.min_length > 0) {
				this.errors.push(element.field_name + ' ' + this._('required')); 
				this.data_is_valid = false;
			}
			if (!isEmpty(value)) {
				if (!validateByDataType(value, element.data_type)) {
					this.errors.push(element.field_name + ' ' + this.getTypeMessaging(element.data_type)); 
					this.data_is_valid = false;
				}
				if (value.length < element.min_length) {
					this.errors.push(element.field_name +' '+ this._('min') +' '+ element.min_length +' '+ this._('characters'));
					this.data_is_valid = false;	
				}
				if (value.length > element.max_length) {
					this.errors.push(element.field_name +' '+ this._('max') +' '+ element.max_length +' '+ this._('characters'));
					this.data_is_valid = false;	
				}
			}
		}
		
		
	}
	if (!this.data_is_valid) {
		var error_string = "";
		for (var i=0; i<this.errors.length; i++) {
			error_string += "- "+this.errors[i]+"\n";	
		}
		//alert(error_string);	
		//this.errors = [];
		return false;
	} else {
		return true;
	}
	
}


//Validation.validateInline()
function objValidateInline() {
	this.data_is_valid = true;
	for (var i=0; i<this.dataElements.length; i++) {
		var element = this.dataElements[i];
		if (element.data_type == 'dropdown') {
			if ((document.getElementById(element.id).value == "") && (element.min_length > 0)) {
				this.errorsInline[element.id] = element.field_name + ' ' + this._('required');
				this.data_is_valid = false;
			}
		} else if (element.data_type == 'listbox') {
			total_selected = document.getElementById(element.id).options.length;
			if (total_selected < element.min_length) {
				this.errorsInline[element.id] = "You must select at least "+element.min_length+" "+element.field_name;
				this.data_is_valid = false;	
			} else if (total_selected > element.max_length && element.max_length != 0) {
				this.errorsInline[element.id] = "You can select a maximum of "+element.max_length+" "+element.field_name;
				this.data_is_valid = false;
			}
		} else if (element.data_type == 'checkbox') {
			
		} else {
			var value = idValue(element.id);
			if (isEmpty(value) && element.min_length > 0) {
				this.errorsInline[element.id] = element.field_name + ' ' + this._('required');
				this.data_is_valid = false;
			}
			if (!isEmpty(value)) {
				if (!validateByDataType(value, element.data_type)) {
					this.errorsInline[element.id] = element.field_name + ' ' + this.getTypeMessaging(element.data_type);
					this.data_is_valid = false;
				}
				if (value.length < element.min_length) {
					this.errorsInline[element.id] = element.field_name +' '+ this._('min') +' '+ element.min_length +' '+ this._('characters');
					this.data_is_valid = false;	
				}
				if (value.length > element.max_length) {
					this.errorsInline[element.id] = element.field_name +' '+ this._('max') +' '+ element.max_length +' '+ this._('characters');
					this.data_is_valid = false;	
				}
			}
		}
	}
	
	return this.data_is_valid;
}

function objClearErrors() {
	this.errors = [];	
}

function objClearErrorsInline() {
	this.errorsInline = new Array();	
}

function objGetErrors() {
	return this.errors;
}

function objGetErrorsInline() {
	return this.errorsInline;
}

function objGetTypeMessaging(type) {
	if (type == "alpha") {
		return this._('alpha');	
	} else if (type == "num") {
		return this._('numeric');	
	}else if (type == "alpha-num") {
		return this._('alpha_numeric');
	} else if (type == "alpha-num-symbol") {
		return this._('alpha_numeric_symbol');
	} else if (type == "email") {
		return this._('valid_email');
	} else if (type == "url") {
		return this._('valid_url');
	} else if (type == "zip-us") {
		return this._('valid_zip');	
	} else if (type == "zip-ca") {
		return "must be a valid Canadian Postal Code";	
	}
}

function objTranslate(phrase) {
	if (this.translation[phrase] != undefined) {
		return this.translation[phrase];
	} else {
		return phrase;	
	}
}


function formatErrors(errors) {
	var error_string = "";
	for (var i=0; i<errors.length; i++) {
		error_string += "- "+errors[i]+" \n";
	}
	return error_string;
}

// Data Element Object ======================
function dataElement() {
	this.id				= "";
	this.field_name		= "";
	this.data_type		= "";
	this.min_length		= "";
	this.max_length		= "";
}


//Function Reference ==================================
function validateByDataType (value, data_type) {
	if (data_type == 'alpha') {
		return isAlpha(value);
	} else if (data_type == 'alpha-num') {
		return isAlphaNumeric(value);
	} else if (data_type == 'num') {
		return isNumeric(value);
	} else if (data_type == 'alpha-num-symbol') {
		return true;
	} else if (data_type == 'url') {
		return isValidUrl(value);	
	} else if (data_type == 'email') { 
		return isValidEmail(value);	
	} else if (data_type == 'zip-us') {
		return isValidPostalCode(value, 'us');	
	} else if (data_type == 'zip-ca') {
		return isValidPostalCode(value, 'ca');
	}
}
function isNotEmpty(value) {
	if (value.length > 0) {
		return true;	
	} else {
		return false;	
	}
}
function isEmpty(value) {
	return !isNotEmpty(value);
}

//Standard Data Types ==================================
function isNumeric(value) {
	var pattern = /^[0-9]+$/;
	return testPattern(value, pattern);
}
function isNumericSpace(value) {
	var pattern = /^[0-9\s]+$/;
	return testPattern(value, pattern);
}
function isAlpha(value) {
	var pattern = /^[a-zA-Z\s]+$/;
	return testPattern(value, pattern);
}
function isAlphaNumeric(value) {
	var pattern = /^[a-zA-Z0-9\s]+$/;
	return testPattern(value, pattern);	
}
function isValid(value, pattern) {
	return testPattern(value, pattern);	
}
//=======================================================

//Additional Data Types =================================
function isValidEmail(address) {
	var email_filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (email_filter.test(address)) {
		return true;
	} else {
		return false;
	}
}
function isValidUrl(value) {
	var pattern = /^((http|https):\/\/)?([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?$/;
	return testPattern(value, pattern);
}
function isValidPostalCode(value, country_code) {
	if (country_code == 'us') {
		var pattern = /^[0-9]+$/;
	} else if (country_code == 'ca') {
		var pattern = /^[0-9]+$/;
	} else {
		var pattern = "";	
	}
	return testPattern(value, pattern);
}
//=======================================================


//Special Functions =================================
/**
	Checks an array of field ID's to see if data has been entered
	
	@param array fields An array of field ID's to check
	@return true if all fields contain data, false if 1 or more are empty
*/
function fieldsCompleted(fields) {
	var fields_complete = true;
	
	for (var i=0; i < fields.length; i++) {
		if (isEmpty(document.getElementById(fields[i]).value)) {
			fields_complete = false;
		}
	}
	return fields_complete;
}

//Private =================================
function testPattern(value, pattern) {
	if (pattern.test(value)) {
		return true;
	} else {
		return false;
	}	
}


// Other ==================================
function idValue(id) {
	return document.getElementById(id).value;	
}