/*

Form Validation Example
=======================

In form page:
<script language="Javascript">
function validateLoginForm(){
	
	// Create a new JSForm object
	var myForm = new JSForm();
	 
	myForm.addElement(new JSFormElement(document.frmLogin.userName,TEXTBOX,true, "Please enter a user name", TEXT));
	
	return myForm.validate();
}
</script>

<form name="frmValidateLogin" onsubmit="return validateLoginForm()">
	<input type="text" name="userName">
	<input type="submit" value="Submit">
</form>

*/

// Data types
var TEXT=0, EMAIL_ADDRESS=1, NUMBER=2, POS_INT=3, NEG_INT=4, NZ_POS_INT=5, POSTAL_CODE=6, ZIP_CODE=7;

// Element types
var TEXTBOX="textbox", CHECKBOX="checkbox", RADIO="radio";

/*
* Returns true if the value is a valid email address. Otherwise, it returns false.
*/
function isEmailAddress(value) {
	var regex = /^[\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,3}$/;
  	if (!regex.test(value)) {
    	return false;
  	} else {
    	return true;
	}
}

function isPostalCode(value){
	var regex = /^[a-zA-Z]\d[a-zA-Z][\s]*\d[a-zA-Z]\d$/;
  	if (!regex.test(value)) {
    	return false;
  	} else {
    	return true;
	}
}

function isZipCode(value){

	var regex = /^[\d]{5}$/;
  	if (!regex.test(value)) {
    	return false;
  	} else {
    	return true;
	}
}	
	
/*
* Returns true if the value is undefined, null, or an empty string. Otherwise,
* it returns false.
*/
function isEmpty(value) {
	return ((value == undefined) || (value == null) || (value == ""));
}

/*
* Returns true if the value is a valid number (including decimals). Otherwise,
* it returns false.
*/
function isNumber(value) {
	var regex = /^[\d]*[\.]{0,1}[\d]*$/;
	if(!regex.test(value)) {
		return false;
	} else {
		return true;
	}
}

function isInteger(value) {
	var regex = /^[\d]*$/;
	if(!regex.test(value)) {
		return false;
	} else {
		return true;
	}
}

/*
* Trims leading and trailing whitespace.
*/
String.prototype.trim = function() {
  var x=this;
  x=x.replace(/^\s*(.*)/, "$1");
  x=x.replace(/(.*?)\s*$/, "$1");
  return x;
}

/*
* The JSForm class represents a document form's properties and methods.
*/
function JSForm() {

	this.elementList = new Array();

	if(typeof(_jsform_prototype_called) == 'undefined') {
		_jsform_prototype_called = true;
		JSForm.prototype.validate = validate;
		JSForm.prototype.addElement = addElement;
	}

	/*
	* Adds an element to the form.
	*/
	function addElement(element) {
		this.elementList.push(element);
	}

  /*
	* Validates all the elements in the form and returns true if successful.
	* Otherwise, it returns false.
	*/
	function validate() {
		for (i=0; i < this.elementList.length; i++) {
			element = this.elementList[i];
			if(!element.validate())
				return false;
		}
		
		return true;
	}
}

/*
* The JSFormElement class represents an element in a document form. It requires the
* following parameters:
* 	- elementObject : object : a reference to the document form element object
*   - elementType : string : whether it is a TEXTBOX, CHECKBOX, or RADIO
*   - required : boolean : whether it is required or not
*   - errorMessage : string : error message to be displayed
*   - dataType : string : whether it is TEXT, EMAIL_ADDRESS, or NUMBER
*/
function JSFormElement(elementObject, elementType, required, errorMessage, dataType) {

	this.elementObject = elementObject;
	this.elementType = elementType;
	this.required = required;
	this.errorMessage = errorMessage;
	this.dataType = dataType;

	if (typeof(_formelement_prototype_called) == 'undefined') {
		_jsformelement_prototype_called = true;
		JSFormElement.prototype.validate = validate;
		JSFormElement.prototype.displayError = displayError;
	}

	/*
	* Validates the element and returns true if successful. Otherwise, it returns
	* false.
	*/
	function validate() {
		if(this.required) {
			if(this.elementType == RADIO) {
				checked = false;

				for(j=0; j < this.elementObject.length; j++) {
					if(this.elementObject[j].checked == true) {
						checked = true;
					}
				}
				if(!checked) {					
					displayError(this.errorMessage, this.elementObject);
					return false;
				}
			} else if(this.elementType == CHECKBOX) {
				if(!this.elementObject.checked) {
					displayError(this.errorMessage, this.elementObject);
					return false;
				}
			} else {
				switch(this.dataType) {				
					case TEXT:
						if(isEmpty(this.elementObject.value)) {
							displayError(this.errorMessage, this.elementObject);							
							return false;
						}
						break;
					case EMAIL_ADDRESS:
						if(isEmpty(this.elementObject.value) || !isEmailAddress(this.elementObject.value)) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;
					case NUMBER:
						if(isEmpty(this.elementObject.value) || !isNumber(this.elementObject.value)) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;
					case POS_INT:
						if(isEmpty(this.elementObject.value) || !isInteger(this.elementObject.value) || this.elementObject.value < 0) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;
					case NZ_POS_INT:
						if(isEmpty(this.elementObject.value) || !isInteger(this.elementObject.value) || this.elementObject.value < 1) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;
					case NEG_INT:
						if(isEmpty(this.elementObject.value) || !isInteger(this.elementObject.value) || this.elementObject.value > 0) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;
					case NZ_NEG_INT:
						if(isEmpty(this.elementObject.value) || !isInteger(this.elementObject.value) || this.elementObject.value > 1) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;						
					case POSTAL_CODE:
						if(isEmpty(this.elementObject.value) || !isPostalCode(this.elementObject.value)) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;												
					case ZIP_CODE:
						if(isEmpty(this.elementObject.value) || !isZipCode(this.elementObject.value)) {
							displayError(this.errorMessage, this.elementObject);
							return false;
						}
						break;					
					default:
				}
			}
		} else {

		}

		return true;
	}

	/*
	* Displays an alert box with an error message and draws focus to the element.
	*/
	function displayError(errorMessage, element) {
		alert(errorMessage);
		if(!(element.value == undefined))
			element.focus();
	}
}