/**
 * Title: Javascript Form Validator Class
 * Created: Jan 25th 2006
 * Contributers: Andy Peatling, Navjote Sandhu
 *
 * Usage: On your submit button use:
 *					onclick="return new Validator(this.parentNode).validate();"
 *			 where this.parentNode represents the FORM node.
 *			
 *			 For each form element you must include a <span> with and ID of the input element name + "_errors" 
 *			 to show error feedback.
 *			
 *			 Here is a valid example:
 *			
 *			 <label for="first_name">First Name:</label>
 *			 <span id="first_name_errors"></span>
 *			 <input type="text" name="first_name" id="first_name" required="true" />
 *			
 *			 Validation attributes that are allowed for form elements are as follows:
 *			
 *			 1. required="true|false" --> is the element required?
 *			 2. maxvalue="0..n" --> Checks that value is numeric and doesn't exceed this value.
 *			 3. minvalue="0..n" --> Checks that value is numeric and isn't less than this value.
 *			 4. datatype="numeric" --> Checks that the value is numeric.
 *			 5. format="email|tel" --> Validates an email address, or checks a telephone number is numeric.
 *			 
 * 		 You must use the XHTML 1.0 Extended doctype in /project/includes/dtd/ otherwise
 *			 the extra attributes are invalid code.
 *
 *
 *	21 Mar 2006:  	Added evalElement function to allow recognition of DIV tag and processing of its
 * 					children.
 *			
 **/


function Validator(form_obj)
{
	this.setFormObject(form_obj);
}

Validator.prototype.evalElement = function(element)
{
	var retVal = false;
	var errorFeedback = '';
	switch(element.nodeName)
	{
		
		case "INPUT":
		case "TEXTAREA":
		case "SELECT":
		
			var elementError = element.name + '_errors'
			
			errorFeedback += this.checkRequired(element);
			errorFeedback += this.checkDataType(element);
			errorFeedback += this.checkFormatting(element);
			errorFeedback += this.checkValueRange(element);
                        
			if(errorFeedback != "" && errorFeedback != "undefined")
			{
				retVal = true;
				error_element = document.getElementById(elementError);
				if (null != error_element)
				{
					error_element.innerHTML = errorFeedback;
				}
				element.style.background = "#FFEBEB";
				errorFeedback = "";
			}
			else
			{
				if(document.getElementById(elementError))
				{
					document.getElementById(elementError).innerHTML = "";
					element.style.background = "#fff";
				}
			}

		break;
	}	
	return retVal;
}

Validator.prototype.validate = function()
{

	form_obj = this.getFormObject();
	var elements = form_obj.childNodes;

	var errorFeedback = "";
	var hasErrors = false;
	for(var i = 0; i < elements.length; i++)
	{
		
		var element = elements[i];
		if (element.nodeName == "DIV")
		{
			// process child nodes if the current node is a DIV
			var elementChildren = element.childNodes;
			for (var j = 0; j < elementChildren.length; j++)
			{
				var elementChild = elementChildren[j];
				if (this.evalElement(elementChild) && !hasErrors)
				{
					hasErrors = true;	
				}	
			}
		}
		else
		{		
			if (this.evalElement(element) && !hasErrors)
			{
				hasErrors = true;	
			}
		}
	}

	if(hasErrors)
	{
		return false;
	}
	return true;
}


Validator.prototype.checkRequired = function(element)
{
	var error = "";
	
	var formElementName = this.strCapitalize(element.name.replace("_"," "));
	if(element.getAttribute("required") == "true")
	{
		if(element.value == "")
		{
			error = "<p>" + formElementName + " must not be left blank.</p>\n";
		}
	}
	
	return error;
}

Validator.prototype.checkDataType = function(element)
{
	var error = "";
	var formElementName = this.strCapitalize(element.name.replace("_"," "));
	
	if(element.getAttribute("datatype") && element.value != "")
	{
		switch(element.getAttribute("datatype"))
		{
			case "numeric":
			
				var elementValue = parseFloat(element.value);
				
				if(isNaN(elementValue))
				{
					error = "<p>" + formElementName + " must be numeric.</p>\n";
				}
								
			break;

		}
	}
	
	return error;
}

Validator.prototype.checkFormatting = function(element)
{
	var error = "";
	
	if(element.getAttribute("format") && element.value != "")
	{
		switch(element.getAttribute("format"))
		{
			case "tel":
			
				// For now, just check that tel numbers are numeric. Formatting can be done in PHP.
				var elementValue = parseFloat(element.value);
				
				if(isNaN(elementValue))
				{
					error = "<p>" + element.value + " is not numerical.</p>\n";
				}

			break;
			
			case "email":
			
				var regExp = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;

			   if (element.value.search(regExp) == -1) 
			   {
					error = "<p>" + element.value + " is not a valid email address.</p>\n";					
				}
				
			break;
		}
	}
	
	return error;
}

Validator.prototype.checkValueRange = function(element)
{
	var error = "";
	var errorAddon = "";
	
	var minValue = parseFloat(element.getAttribute("minvalue"));
	var maxValue = parseFloat(element.getAttribute("maxvalue"));
	var elementValue = parseFloat(element.value);
	var formElementName = this.strCapitalize(element.name.replace("_"," "));
	
	if(maxValue)
	{
		if(isNaN(elementValue) && element.value != "")
		{
			error = "<p>" + formElementName + " must be numeric.</p>\n";
		}
		
		if(elementValue > maxValue)
		{
			if(minValue)
			{
				error = "<p>" + formElementName + " must have a value between " + minValue + " and " + maxValue + ".</p>\n";
			}
			else
			{
				error = "<p>" + formElementName + " must have a value of " + maxValue + " or less.</p>\n";
			}
		}
	}
	
	if(minValue)
	{
		if(isNaN(elementValue) && element.value != "")
		{
			error = "<p>" + formElementName + " must be numeric.</p>\n";
		}
		
		if(elementValue < minValue)
		{
			if(maxValue)
			{
				error = "<p>" + formElementName + " must have a value between " + minValue + " and " + maxValue + ".</p>\n";
			}
			else
			{
				error = "<p>" + formElementName + " must have a value of " + minValue + " or more.</p>\n";
			}
		}
	}
	
	return error;
	
}

Validator.prototype.strCapitalize = function(str)
{
	var tmpStr, tmpChar, preString, postString, strlen;
	tmpStr = str.toLowerCase();
	stringLen = tmpStr.length;
	if (stringLen > 0)
	{
	  for (i = 0; i < stringLen; i++)
	  {
	    if (i == 0)
	    {
	      tmpChar = tmpStr.substring(0,1).toUpperCase();
	      postString = tmpStr.substring(1,stringLen);
	      tmpStr = tmpChar + postString;
	    }
	    else
	    {
	      tmpChar = tmpStr.substring(i,i+1);
	      if (tmpChar == " " && i < (stringLen-1))
	      {
	      tmpChar = tmpStr.substring(i+1,i+2).toUpperCase();
	      preString = tmpStr.substring(0,i+1);
	      postString = tmpStr.substring(i+2,stringLen);
	      tmpStr = preString + tmpChar + postString;
	      }
	    }
	  }
	}
	return tmpStr;
}

Validator.prototype.setFormObject = function(form_obj) {
	this.form_obj = form_obj;
}

Validator.prototype.getFormObject = function() {
	return this.form_obj;
}




