var validator = {
	default_alert : "There are some required fields that you need to complete before submitting this form. We have highlighted them for you  above. Please complete these fields before continuing",
  default_response : "required",

  validate : function(frm){
		var form_validated = true;
		
		for (i=0; i < frm.elements.length; i++){
			validated = true;
			
			if (!frm.elements[i])
				continue;
				
			validations = frm.elements[i].getAttribute("validate");
			if (!validations){
				if (this.$(frm.elements[i].name + "_response"))
					this.hideValidationResponse(frm.elements[i]);
				continue;
			}
			
			// Split by ';' in case there is more than one criteria
			var validation = validations.split(';');

			for (var val in validation){						
				if (typeof validation[val] != 'string')
					continue;
				if (validation[val].indexOf(':') != -1){
					splitPos = validation[val].indexOf(':');
					functionName = validation[val].substring(0,splitPos);
					functionArgs = validation[val].substring(splitPos+1, validation[val].length);
				}else{
					functionName = validation[val];
					functionArgs = false;
				}

				// test to see if field validation is optional (ie only test if there is a value - it is OK to be blank)
				reg = /^optional_/;
				if (reg.test(functionName)){
					functionName = functionName.replace(reg,"");
          if (frm.elements[i].value.length == 0) // if field is null and validation is optional, then skip
            continue;						
				}
        
        functionName = "validator." + functionName;
        
				// allow override if already validated above
				// run the function to validate
				// if (!validated)
        try{
          _function = eval(functionName);
          validated = _function(frm.elements[i],functionArgs);
        } catch(e){
          validated = true; // validate as true on error - don't piss the user off 'cos the programmer messed up...
        }          
          
				if (!validated)
					break;
			}
			if (!validated){
				form_validated = false;
				this.showValidationResponse(frm.elements[i]);
			}else{
				this.hideValidationResponse(frm.elements[i]);
			}
		}
		if (form_validated == false){
			alert(this.default_alert);
			return false;
		}else{
			return true;
		}
	},
	
	showValidationResponse : function (el){
		// create the response (only if not exists)
		if (!el.obj_validate_response){
		  response = el.getAttribute("validate_response");
      if (!response) response = this.default_response;
			r = document.createElement("div");
			r.innerHTML = response;
			r.className = "validate_response";
			//r.id = el.name + "_response";
			el.obj_validate_response = r;
      
			// see if there is a dedicated container for the response
			if(container = this.$("response_container:"+el.id)){
				container.appendChild(r);
			}else if(container = this.$("response_container:"+el.name)){ // legacy - allow use of name or ID\
				container.appendChild(r);
			}else{
				container = el.parentNode
			  this.insertAfter(container,r,el);
      }
		}
	},
	
	hideValidationResponse : function (el){
		// remove the response if it exists
    response = el.obj_validate_response;
    
		if (response){
		    //alert(el.validate_response);
			// see if there is a dedicated container for the response
			if(this.$("response_container:"+el.name))
				container = this.$("response_container:"+el.name)
			else
				container = el.parentNode						
			container.removeChild(response);
			el.obj_validate_response = null;
		}
	},
	
	insertAfter : function(parent, node, referenceNode) {
	  parent.insertBefore(node, referenceNode.nextSibling);
	},
	
	$ : function(el){
		return document.getElementById(el);
	},
	
	minLength : function (form_element,required_length){
		return form_element.value.length >= (+required_length)
	},
	
	maxLength : function(form_element,required_length){
		return form_element.value.length <= (+required_length)
	},
	
	isEmail : function(form_element){
		  var addressPattern = 
			/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]{2,10}$/;
		  return addressPattern.test(form_element.value);
	},
	
	isChecked : function(form_element){
		return form_element.checked == true;
	},
	
	ccNumber : function(form_element){
		// note the function referred to is in a different file
		return CheckCardNumber(form_element.value);
	},
	
	matchField : function(form_element,match_element_id){
		if (form_element.value == d(match_element_id).value)
			return true;
		else
			return false;
	},
	
	isDate : function(form_element){
		  var datePattern = 
			/^[0-9]{1,2}\/[0-9]{1,2}\/([0-9]{2}|[0-9]{4})$/;
		  return datePattern.test(form_element.value);
	},
	
	containsNumbers : function(form_element){
		var addressPattern = /[0-9]+/;
		return addressPattern.test(form_element.value);	
	},
	
	isNumeric : function(form_element){
		var pattern = /^[0-9\.]+$/;
		return pattern.test(form_element.value);	
	},
	
	isRegex : function (form_element,reg_ex){
		var regex = new RegExp(reg_ex);
		return regex.test(form_element.value);
	},
  
  equals : function (form_element,val){
		return form_element.value == val;
	},
  
  notEquals : function (form_element,val){
		return form_element.value != val;
	},
  
  math : function (form_element,equation){
    // supports simple operator like validate="math:>6"
    // Can be used to check if a specific value - use double equals sign as you would normally eg validate="math:==7"
    return eval(form_element.value+equation);
  },
  
  callFunction : function (form_element, _fArgs){
    // Pass through a function like validate="callFunction:myFunction('arg1','arg2',...)"
    // Args will be passed to your function
    // You can also use the 'this' keyword to refer to the form element
    // such as validate="callFunction:myFunction(this,'arg1','arg2',...)"
    
    // Note; as an alternative to using this function, you can simply extend this class with
    // a new function of your own eg. validator.myFunction = function(form_element, args){}
    // This would be called by: validate="myFunction:args"
    
    // replace the 'this' keyword with the form_element object
    _fArgs = _fArgs.replace('this', 'form_element');

    try{
      return eval(_fArgs);
    }catch(e){ 
      return true; 
    }

  }
};

