


jQuery.fn.validate = function( settings ) {
  
  var validator = new jQuery.validator(settings);
  validator.obj_form = this;
  validator.addEventsToForm();
  validator.checkAjaxQueue();

	if( this.is('form') ) {
		  // validate the form on submit
		 
     return this.submit(validator.validateForm);
	} else {
		// validate all elements immediately
		this.each(function() {
			var element = this;
			validator.validateElement(element);
		});
	}
	return this;
};



//validation per field
jQuery.validator = function( settings ) {

var settings = jQuery.extend({
    error:'error',
    show_hint: 0,
    hint:'hint',
    queue_length: 2,
    poll:1000
  }, settings);
  this.error_list = [];
  this.ajax_queue = [];

  var obj= this;

 

    //cycle through form fields and do stuff
    obj.cycleFormFields = function(fctn,type){
      jQuery("input, select, textarea",obj.obj_form).not("[@type=submit]").not("[@type=reset]").each(function() { 
            obj[fctn](this,type);
          });
    };
 
    //add events to all elements in form
    obj.addEventsToForm = function(){
       obj.cycleFormFields('addEventsToElement');	     
    };
  
   //add events such as clicks etc to from elements
    obj.addEventsToElement = function(element){
      //onfocus
      jQuery(element).focus(function() {
        obj.cycleFormFields('hideElement',settings.hint);
        obj.hideError(element);
        obj.showHint(element);
        //if(!element.clicked){
          //element.value = '';
         // element.clicked = 1;
        //}
     
        });
        //onblur
        jQuery(element).blur(function() {

          if(!obj.validateElement(this)){
            if(!this.className.match('ajax')){
              obj.showErrorMsg(this);
            }
        }
     
     });
    };
    //show element based on id
    obj.hideElement = function(element,type){
      var str_id = element.id;
      if(typeof(element) == 'string'){
        str_id = element;
      }
      jQuery('#'+str_id+'_'+type).hide();
    };
    //hide element based on id
    obj.showElement = function(element,type){

      var str_id = element.id;
      if(typeof(element) == 'string'){
       
        str_id = element;
      }

     jQuery('#'+str_id+'_'+type).fadeIn('fast');

     
    };
    obj.showHint = function(element){
      if(settings.show_hint == 1)
      obj.showElement(element,settings.hint);
    };
    obj.hideHint = function(element){
      obj.hideElement(element,settings.hint);
    };
    obj.showError = function(element){
      obj.showElement(element,settings.error);
    };
    obj.hideError = function(element){
      obj.hideElement(element,settings.error);
    };
    

    obj.showErrorMsg = function(element,msg){
 
      var id = element.id;
      var className = element.className;
    
      obj.hideHint(element);
      //ajax error!
      if(typeof(element) == 'string'){
          id = element;
      }
      if(!msg){
        if(obj.rules[className])
          msg = obj.rules[className].msg;
        if(element.title)
          msg = element.title;
      }
      jQuery('#'+id+'_'+settings.error).empty().append(msg);
      obj.showError(element);
  
    
    
    };
    //onsubmit check
    obj.validateForm = function(){
      obj.cycleFormFields('validateAllElements');
   
        if(obj.error_list.length > 0){
          obj.error_list = [];
              
          return false;
        } else {
             
        return true;
        }
  
    };

    
    obj.validateAllElements = function(element){
     var id        = element.id;
     var obj_error = '#'+id+'_'+settings.error;
    
 
      if(!obj.validateElement(element) && $(obj_error).length > 0){
      
       
        
        
        if(!element.className.match('ajax')){
  
         obj.error_list.push(1);
         obj.cycleFormFields('hideElement',settings.hint);
         obj.showErrorMsg(element);

        }
      } else {
        obj.hideError(element);
      }
    };
    obj.validateElement = function(element){
        if(!element.className)return false;
        var className       = element.className;
        var value           = element.value;
  
      if(element.type != 'checkbox' && obj.rules[className]){
        return !obj.rules[className].test(value,element);

}
    };
    obj.validateAllElementsAjax = function(){
      jQuery.ajax({
        type: "POST",
        url: "errors.js",
        data: obj.ajax_queue,
        dataType: "json",
        success: function(json){
          jQuery.each( json.errors, function(i,n){
            
            obj.showErrorMsg(i,n);
          
 
          });
        }
      });
    };
    
    
    obj.checkAjaxQueue =  function(){
    
      if(obj.ajax_queue.length == settings.queue_length){
        obj.validateAllElementsAjax();
        obj.ajax_queue = [];
      }
      setTimeout(obj.checkAjaxQueue,settings.poll); 
    };
    
 
 
obj.rules = {
  required:
  {
    test:function(value){return((value == null) || (value.length == 0))},
    msg:'This field is required'
  },
  email: 
  {
    test:function(value){ return !value.match(/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i)},
    msg:'This email is not formatted correctly'
  },
  number:{
    test:function(value) {return isNaN(value);},
    msg:'This field is for number only'
  },
  required_email:
  {
    test:function(value) {return obj.rules.email.test(value) | obj.rules.required.test(value);},
    msg:'Email is required and must be formatted correctly'
  },
  required_number:
  {
  test:function(value) {return this.number(value) | this.required(value);},
  msg:'This field is for numbers only'
  },
  ajax:
  {
  test:function(value,element){var obj_id = element.id;obj.ajax_queue.push(obj_id);obj.ajax_queue[obj_id] = value;return true;}
  }
};
    


};
