// =================================================================================================
//	validate.js - Runs validation routine on submit. This module is part of the J namespace.
// -------------------------------------------------------------------------------------------------
/*
	REQUIRES:
		* YUI 2 Core-DOM-Events
		
	
	SETUP:
	This will set up all forms to listen for the submit event. No other configuration or setup is 
	needed. Multiple forms can be used with no additional configuration.
	
	By default, the script checks for special characters. To turn this off, set the 
	checkForSpecialCharacters variable below to false.
	
	
	USEAGE:
	To use the routine simply add the proper class as outlined below. If you need an error message, 
	include the error message in the title attribute. The class required can be chained with any 
	other validation class
	
	ex: <input name="email" type="text" class="required validate-email" title="Please Enter an Email Address" />
	
	The following validations are available:
	-------------------------------------------------------------------------------------	
		Class Name					Validation
	-------------------------------------------------------------------------------------
		required					Field is not empty
		validate-number				Numbers only
		validate-digits				Number digits only
		validate-alpha				Alpha characters only
		validate-alphanum			Alpha-Numeric characters only
		validate-date				Valid Date
		validate-email				Valid Email Address
		validate-phone				Valid Phone Number
		validate-zip				Valid Zip Code (Accepts +4)
		validate-url				Valid URL
		validate-currency-dollar	Valid dollar value
		validate-one-required		At least one radio / textbox element checked
		validate-not-first			Verifies first item in select box is not selected
		validate-not-empty			Verifies select box contains value
	-------------------------------------------------------------------------------------
*/
var J = J || {};

J.validate = function() {
	// Alias YAHOO namespace
	var Dom = YAHOO.util.Dom;
	var Event = YAHOO.util.Event;
	var Element = YAHOO.util.Element;
	
	var checkForSpecialCharacters = true; // Set to false if you do not want to check text fields for special characters.
	
	// ---------------------------------------------------------------------------------------------
	//  Trim String
	// ---------------------------------------------------------------------------------------------
		String.prototype.trim=function(){
			return this.replace(/^\s*|\s*$/g,'');
		}
		String.prototype.ltrim=function(){
			return this.replace(/^\s*/g,'');
		}
		String.prototype.rtrim=function(){
			return this.replace(/\s*$/g,'');
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  checkInputField(element) - Checks the class name and runs the specified valdation.
	// 		* Returns:
	//			- valid.valid (boolean)
	//			- valid.specialCharacters (boolean)
	// ---------------------------------------------------------------------------------------------
		var checkInputField = function(element) {
			var valid = true;
			var specialCharacters = true;
			var testElement = element.value.trim();
			
			// Check required fields
			if (Dom.hasClass(element, 'required') == true && testElement.length == 0) {
				//required found, and not filled in
				valid = false;
			}
		
			//check length
			if (Dom.hasClass(element, 'required') == true) {
				//check for minlength.
				var m = element.getAttribute('minlength');
				if (m && Math.abs(m) > 0){
					if (element.value.length < Math.abs(m)) {
						valid = false;
					}
				}
			}
			
			// Check for special characters
			if(checkForSpecialCharacters == true) {
				if (testElement.match(/[\\\^\$\|\?\*\~#:!'"]/)) { 
					valid = false;
					specialCharacters = false;
				}
			}
		
			// Check if validation classes exist and run Validation Routines. 
			if (Dom.hasClass(element, 'validate-number') == true && isNaN(testElement) && testElement.match(/[^\d]/)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-digits') == true && testElement.replace(/ /,'').match(/[^\d]/)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-alpha') == true && !testElement.match(/^[a-zA-Z\s]+$/)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-alphanum') == true && testElement.match(/\W/)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-date') == true) {
				var tempDate = new Date(testElement);
				
				if (isNaN(tempDate)) {
					valid = false;
				}
			} else if (Dom.hasClass(element, 'validate-email') == true && !testElement.match(/\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/)) {
				valid = false;
				
				if (Dom.hasClass(element, 'required') == false && testElement.length == 0) {
					valid = true;
				}
			} else if(Dom.hasClass(element, 'validate-phone') == true && !testElement.match(/\(?\b[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}\b/)) {
				valid = false;
			} else if(Dom.hasClass(element, 'validate-zip') == true && !testElement.match(/\b[0-9]{5}(?:-[0-9]{4})?\b/)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-url') == true && !testElement.match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i)) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-currency-dollar') == true && !testElement.match(/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/)) {
				valid = false;
			}
		
			return {
				valid:valid,
				specialCharacters:specialCharacters
			}
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  checkRadioField(element, elementArray) - Checks radio elements to see if one is checked.
	// 		* Returns valid (boolean)
	// ---------------------------------------------------------------------------------------------
		var checkRadioField = function(element, elementArray) {
			var valid = true;
		
			// Search for validation class
			if (Dom.hasClass(element, 'validate-one-required') == true) {
				valid = false;
				
				// Check if any radios are selected
				for (var i=0; i < elementArray.length; i++) {
					if(elementArray[i].name.toLowerCase() == element.name.toLowerCase() && elementArray[i].checked) {
						valid = true;
						break;
					}
				}
			}

			return valid;
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  checkSelectField(element) - Checks select elements for class name and 
	//  runs the specified validation.
	// 		* Returns valid (boolean)
	// ---------------------------------------------------------------------------------------------
		var checkSelectField = function(element) {
			var valid = true;
			
			// Search for validation Criterion
			if (Dom.hasClass(element, 'validate-not-first') == true && element.selectedIndex == 0) {
				valid = false;
			} else if (Dom.hasClass(element, 'validate-not-empty') == true && element.options[element.selectedIndex].value.length == 0) {
				valid = false;
			}
			
			return valid;
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  isVisible(element) - Determines if element is visible to user. Returns boolean.
	// ---------------------------------------------------------------------------------------------
		var isVisible = function(element) {
			if(typeof(element) == 'string') {
				element = document.getElementById(element);
			}
			
			while (element.nodeName.toLowerCase() != 'body' && element.style.display.toLowerCase() != 'none' && element.style.visibility.toLowerCase() != 'hidden') {
				element = element.parentNode;
			}
			
			if (element.nodeName.toLowerCase() == 'body') {
				return true;
			} else {
				return false;
			}
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  searchUp(element, findElement, debug) - Searches the DOM tree upwards for the findElm node 
	//  starting from element.
	//  	* Returns element
	// ---------------------------------------------------------------------------------------------
		var searchUpfunction = function(element, findElement, debug) {
			if(typeof(element) == 'string') {
				element = document.getElementById(element);
			}
			
			// Get the parent findElm
			while (element && element.parentNode && element.nodeName.toLowerCase() != findElement && element.nodeName.toLowerCase() != 'body') {
				element = element.parentNode;
			}
			
			return element;
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	// 	checkform(element, type) - Check form for errors
	// ---------------------------------------------------------------------------------------------
		var checkForm = function(element, type) {
			var errs = new Array();
			
			if(type == 'submit') {
				var elm = element.parentNode.parentNode; // The target node of the container you want to check
			} else {
				elm = this.parentNode.parentNode; // The target node of the container you want to check
			}
			
			var all_valid = true;
			var specialCharacters = true;
		
			// Get form elements
			var inputElements = elm.getElementsByTagName('input');
			var selectElements = elm.getElementsByTagName('select');
			var textAreaElements = elm.getElementsByTagName('textarea');
			
			// Validate Input Elements
			for (i=0; i < inputElements.length; i++) {
				// Get the type of element
				var inputElementType = inputElements[i].type.toLowerCase();
				
				if (inputElementType != 'submit' && inputElementType != 'button' && inputElementType != 'hidden') {
					if (isVisible(inputElements[i])) {
						// Get the class attribute
						var cname = ' ' + inputElements[i].className;
						var inv = inputElements[i].value.trim();
						var classNameExtention = '';
						
						// Determine the type of validation to run
						if (inputElementType == 'text' || inputElementType == 'password') {
							var valid = checkInputField(inputElements[i]);
						} else if(inputElementType == 'radio' || inputElementType == 'checkbox') {
							var valid = checkRadioField(inputElements[i], inputElements);
							classNameExtention = '-cr';
						} else {
							var valid = true;
						}
						
						// Determine action if valid
						if(valid.valid == true || valid == true) {
							Dom.removeClass(inputElements[i], 'validation-failed' + classNameExtention);
							Dom.addClass(inputElements[i], 'validation-passed' + classNameExtention);
						} else {
							Dom.removeClass(inputElements[i], 'validation-passed' + classNameExtention);
							Dom.addClass(inputElements[i], 'validation-failed' + classNameExtention);
							
							// Try to get the title for the error message
							if (inputElements[i].getAttribute('title')) {
								errs[errs.length] = inputElements[i].getAttribute('title');
							}
							
							all_valid = false;
							
							// Check for special characters error
							if(valid.specialCharacters == false) {
								specialCharacters = false;
							}
						}
					}
				}
			}
		
			// Validate Text Area Elements
			for (i=0; i < textAreaElements.length; i++) {
				if (isVisible(textAreaElements[i])) {
					
					cname = ' ' + textAreaElements[i].className;
					cname = cname.toLowerCase();
					
					var valid = checkInputField(textAreaElements[i]);
		
					if (valid.valid == true) {
						Dom.removeClass(textAreaElements[i], 'validation-failed');
						Dom.addClass(textAreaElements[i], 'validation-passed');
					} else {
						Dom.removeClass(textAreaElements[i], 'validation-passed');
						Dom.addClass(textAreaElements[i], 'validation-failed');
						
						// Try to get the title for the error message
						if (textAreaElements[i].getAttribute('title')){
							errs[errs.length] = textAreaElements[i].getAttribute('title');
						}
						
						all_valid = false;
						
						// Check for special characters error
						if(valid.specialCharacters == false) {
							specialCharacters = false;
						}
					}
				}
			}
		
			// Validate Select Boxes
			for (i=0; i < selectElements.length; i++) {
				if (isVisible(selectElements[i])) {
					cname = ' ' + selectElements[i].className;
					cname = cname.toLowerCase();
					
					var valid = checkSelectField(selectElements[i]);
					
					if (valid) {
						Dom.removeClass(selectElements[i], 'validation-failed-sel');
						Dom.addClass(selectElements[i], 'validation-passed-sel');
					} else {
						Dom.removeClass(selectElements[i], 'validation-passed-sel');
						Dom.addClass(selectElements[i], 'validation-failed-sel');
						
						// Try to get the title for the error message
						if (selectElements[i].getAttribute('title')){
							errs[errs.length] = selectElements[i].getAttribute('title');
						}
						
						all_valid = false;
					}
				}
			}
			
			// Output error messages if needed
			if (!all_valid) {
				if(specialCharacters == false) {
					alert('Unsupported Special Characters were found. Please only use Alpha Numeric Characters.');
				} else if (errs.length > 0) {
					alert("We have found the following error(s):\n\n  * " + errs.join("\n  * ") + "\n\nPlease check the fields and try again");
				} else {
					alert('Some required values are not correct. Please check the items in red.');
				}
				
				// If there is an error, stop the form from submitting.
				Event.stopEvent(elm);
			} else {
				JoinNPC.pageEvents.movePanel(1);
			}
			
			return all_valid;
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//	submitForm(id, formName) - Submits the form and submits if valid
	//	@public
	// ---------------------------------------------------------------------------------------------
		var submitForm = function(id, formName) {
			var target = document.getElementById(id);
			var valid = checkForm(target, 'submit');

			if(valid == true) {
				// Submit Form
				document.forms[formName].submit();
			}
		}
	// ---------------------------------------------------------------------------------------------
	
	
	// ---------------------------------------------------------------------------------------------
	//  attachToForms(element) - Attaches Event Listener to all next and submit buttons
	// ---------------------------------------------------------------------------------------------
		var attachToForms = function(element) {
			// Get button elements
			var triggers = Dom.getElementsByClassName('nextButton');
			
			// Loop through next buttons
			for(i=0; i<triggers.length; i++) {
				// Set an event listener on the button
				Event.addListener(triggers[i], 'click', checkForm);
			}
		}
	// ---------------------------------------------------------------------------------------------
	
	// On load, attach the event listeners
	Event.addListener(window, "load", attachToForms);
	
	return {
		submitForm:submitForm
	}

}();

