/* Creates a nifty validator object 

To use just add the function 

function validateForm(frm){
	v = new validator(frm);
	return v.validate();
}

above and the validator.js file, 
<script src='validator.js' type="text/javascript"></script>

set forms onSubmit action to onsubmit="return validateForm(this)"
and add the tags below as needed in a fields class attribute eg.
<input type='text' name='Last Name' class='jsRequired'/>

===Validation Options====

===Text and Textarea fields===
jsRequired  //input value cant be empty
jsMinLength(5) 
jsMaxLength(15)//not really needed but its there
jsEmail // basic email validation, could do with a reg exp just checking for @ and . at the moment
jsCheckSame(NameofElementToCheck) //checks that this field and the field in paramater match


===Checkboxes===
jsAtLeast(2) //At least two checkboxes with this name must be ticked, see example below
<input type='checkbox' name='OneOrMore[]' class='jsAtLeast(1)'/><br/>
<input type='checkbox' name='OneOrMore[]' class='jsAtLeast(1)'/><br/>
<input type='checkbox' name='OneOrMore[]' class='jsAtLeast(1)'/><br/>

===Combine Options with : ===
for example class='jsRequired:jsMinLength(5)' will check for both conditions on the text field

===Labels===

If you add a label for a input tag, an error message will refer to the
field by its label, which is nicer


===Extending The Script===

to extend you should only need to add to the doAction function

*/


function validator(form){
	//Properties
	this.frm = form;
	this.errorMessage = "The following errors occured with your submission;\n\n";
	this.isValid = true;
	
	this.ticks = new Array('min','num'); //ticks is for jsAtLeast(num) tags
	this.ticks['min']= new Array();//min ticks required
	this.ticks['num']= new Array();//number so far
	//Methods	
	this.validateIt = validateIt; //validater the form, any fields that arent optional and are empty produce an error
	this.validate = validate;
	this.alertUser = alertUser;
	this.addToErrorMessage = addToErrorMessage;
	this.getErrorMessage = getErrorMessage; 
	this.checkEmail = checkEmail; //(email)check an email element is valid
	this.fillForm = fillForm; //fill the form with test data
	this.displayNameNice = displayNameNice;//make the name look good
	this.checkIsSame = checkIsSame;//check to make sure two fields have the same value
	this.doAction = doAction;
	this.getElName = getElName;
	this.getParam = getParam;
}


//Code for Methods ...
function addToErrorMessage(message){
	if(this.errorMessage.match(message) == null)
	this.errorMessage += message +"\n";
}
function getErrorMessage(){
	return this.errorMessage;	
}
function alertUser(){
	alert(this.errorMessage);
}
function validate(){
	this.validateIt()
	
	if(!this.isValid){
		this.alertUser();
	}
	
	return this.isValid;
}
function displayNameNice(str){
	return str.replace('[]','');
}
function getElName(el){
	if(el.previousSibling){
		if(el.previousSibling.nodeName == "LABEL" && el.previousSibling.htmlFor == el.name){
			return el.previousSibling.innerHTML;
		}
	}else if(el.parentNode.nodeName == "DD"){
	  dd = el.parentNode
    dt = dd.previousSibling
    return dt.firstChild.innerHTML;
	}
	return this.displayNameNice(el.name);
}
function checkEmail(email){
	//this needs a reg expression
	if(email.indexOf('@')==-1||email.indexOf('.')==-1){
		this.addToErrorMessage("- you have not supplied a valid email address.");
		this.isValid = false;
	}
}
function checkIsSame(el1name, el2name){
	if(this.frm.elements[el1name].value != this.frm.elements[el2name].value){
		this.addToErrorMessage("- the fields "+ this.getElName(this.frm.elements[el1name]) + " and "+ this.getElName(this.frm.elements[el2name]) + " dont match.");
		this.isValid = false;
	}
}

function validateIt(){
	for(var x=0; x<this.frm.length; x++) {
		
		className = this.frm.elements[x].className;
		if(className == '' || className.match('js')==null)
		continue;
		
		if(className.indexOf(':')>0){//two names
		
		classArray = className.split(':');
		for(i in classArray){
		this.doAction(classArray[i],this.frm.elements[x]);
		}
		
		}else{
			this.doAction(className,this.frm.elements[x])
		}
		
	}
	//check min ticks array
	
	for(i in this.ticks['min']){
		//if(!this.ticks['min'][i])
		if(isNaN(this.ticks['num'][i]))
		this.ticks['num'][i]=0;
		if(isNaN(this.ticks['min'][i]))
		this.ticks['min'][i]=0;
		
		if(parseInt(this.ticks['num'][i])<parseInt(this.ticks['min'][i])){
			this.addToErrorMessage("- you need to choose at least "+ this.ticks['min'][i] +" options ");//+ this.getElName(this.frm.elements[i]));
			this.isValid = false;
		}
	}
	
	return this.isValid;
	
}

function doAction(className,el){
	switch (className){
			case 'jsRequired':
			if (el.value==''){
				this.isValid = false;
				this.addToErrorMessage("- the field " + this.getElName(el) + " is required.");
			}
			break;
			case 'jsEmail':	
				this.checkEmail(el.value);
			break;
			default:
			if(className.match("jsCheckSame")){
				//alert('in jsCheckSame with '+ this.frm.elements[x].className);}
				param = this.getParam(className);
				//alert(param);
				this.checkIsSame(el.name, param);
				
			}else if(className.match("jsAtLeast")){
				
				param = this.getParam(className);
				this.ticks['min'][el.name] = parseInt(param);
				if(el.checked==true)
				isNaN(this.ticks['num'][el.name])?this.ticks['num'][el.name]=1:this.ticks['num'][el.name]+= 1;
				
			}else if(className.match("jsMinLength")){
				
				param = this.getParam(className);
				if(el.value.length < parseInt(param)){
					this.isValid = false;
					this.addToErrorMessage("- the field " + this.getElName(el) + " needs to be at least "+ param +" charecters long.");
				}
			}else if(className.match("jsMaxLength")){
				
				param = this.getParam(className);
				if(el.value.length > parseInt(param)){
					this.isValid = false;
					this.addToErrorMessage("- the field " + this.getElName(el) + " needs to be less than "+ param +" charecters long.");
				}
			}
			break;
		}
}
//curently only gets one
function getParam(str){
	param = str.substr(str.indexOf('(')+1,str.length);
	param = param.substr(0,(param.length-1));
	return param;
}

function fillForm(){
	var els = this.frm.elements;
	//alert("els" + els);
	for(var i=0; i<els.length; i++) {
		switch(els[i].type){
			case "select-one" :
			els[i].options[els[i].selectedIndex].value == ""
			els[i].selectedIndex = 1;
			break;
			case "text":
			els[i].value= "AT"+ els[i].id;
			break;
			case "textarea":
			els[i].value= "AdminTest for" + els[i].id;
			break;
			case "checkbox":
			els[i].checked = true;
			break;
			case "radio":
			els[i].checked = true;
			break;
		}
	}
}
function isArray(a) {
    return isObject(a) && a.constructor == Array;
}
function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
}