/*
@author   AFar        

@change: 17.03.2009  AFar add validationGroup

Exampel:
set validatior 

  $('#id1').validator({groupName:'sendJob', type: 'number', min:1, max:60, requiredMSG:'Please select "Related To".', wrongMSG:'Please select "Related To".'})
  $('#id2').validator({groupName:'sendJob', type: 'time'});
  $('#id3').validator({groupName:'sendJob', reg: '^(\\d+)$'});  

  //set falidation of tow object
    $("#from, #to").validator({groupName:'sendJob', type: 'time', required:false,
    onSuccess: function (o){ 
        o.validateTow($('#from',win)[0],$('#to',win)[0], $("#from",win).val() <= $("#to",win).val());
    }
  });

use Validator

   var res = $.Validator.validate('sendJob');
   if (!res.valid) {
       s = '';
       $(res.msg).each(function() { if (!this.valid) s += this.msg + "<br />"; })
       $('#ErrorDiv').html(s);
   }


default  groupName = ''
т.е. можешь писать 
$('#id1').validator()
.......              
var res = $.Validator.validate();


если функции не переопределять то выполняеться стандартные, addClass(errorCSS) и removeClass(errorCSS)
соответственно надо в css определить класс для ошибок errorCSS (по умолчанию  inputError)
.inputError { border:1px solid red; background: #ffcccc;}
*/

$.Validator = new Validator();

function Validator(){
    this.list= new Array();
    this.validate = function (groupName){
      var MSG = new Array();
      var valid = true;    
      $(this.list).each( function (){
        if(typeof groupName== "undefined") groupName='';       
        if(this.validSet.groupName != groupName) return;

        var v = this.validate();
        if(valid && !v){ try{this.focus();}catch(e){}}
        MSG.push({valid: v, msg: this.validSet.lastMSG});
        valid &= v; 
      })
      return {valid: valid, msg: MSG};
    };
}

(function($) {
  //Main Method
  $.fn.validator = function(validSet) {     
    //this.getType = function (){return settings.type;}     
    _defaultOprions = {
            groupName:'',    
            type: null,                       
            reg: '',
            required: true,
            successMSG: '',
            requiredMSG: 'This field is required.',
            wrongMSG: 'Wrong format',
            errorCSS:'inputError',
            minMGS: 'Renge error.',
            maxMGS: 'Renge error.',  
            onSuccess: function (o){ $(o).removeClass(o.validSet.errorCSS); },
            onError: function (o){ $(o).addClass(o.validSet.errorCSS); },
            onWrong: function (o){ o.validSet.onError(o);},
            onRange: function (o){ o.validSet.onError(o);},
            onRequired: function (o){ o.validSet.onError(o);},
            lastMSG:''
    };
    this.validatorFn = function (param){
      if(this.length==0 || typeof this[0][param] !== "function") return null; 
      var otherArgs = Array.prototype.slice.call(arguments, 1);    
      return this[0][param].apply(this[0], otherArgs);     
    }
    this.validate = function(){ return (this.length ==0) ? false: this[0].validate();     
} 

    return this.each(function(){
      function isText(tag,t){ return (tag=='INPUT' && (t== 'text' || t== 'hidden')) || (tag=='SELECT') || (tag=='TEXTAREA') }  

      if($($.Validator.list).index(this)==-1)  $.Validator.list.push(this);
      if(typeof this.validSet=== "undefined")
      {
        this.validSet = $.extend(_defaultOprions, validSet);
        this.getType = function (){return this.validSet.type;}     
        this.valid = function (){
          if( isText(this.tagName, this.type)) return validText($(this).val(), this.validSet) === 's'; 
          if(this.tagName =='INPUT' && this.type == "checkbox") return validCheck(this.checked,this.validSet)==='s'; 
          return false;
        };     
        this.validate = function (){                
          if( isText(this.tagName, this.type)) return validateText($(this).val(), this); 
          if(this.tagName =='INPUT' && this.type == "checkbox") return validateCheck(this.checked,this); 
          return false;
        };
        
        //$(this).bind("change",function() { this.validate();});
        $(this).bind("blur",function() { this.validate();});  
      }
      else   
        this.validSet = $.extend(this.validSet, validSet);

      

      function validCheck(chacked,o) { 
        switch(validateCheck(text, o.validSet)){
          case 'w': wrong(o); return false;
          case 'r': required(o); return false;
          case 's': success(o); return true;
        }        
      }

      function validateCheck(chacked,op) { 
        if(op.required && !chacked) return 'r'; else return 's';
      }
      function validateText(text, o) { 
        switch(validText(text, o.validSet)){
          case 'w': wrong(o); return false;
          case 'r': required(o); return false;
          case 's': success(o); return true;
          case 'min': range(o,'min'); return false;
          case 'max': range(o,'max'); return false;

        }  
      }
      function validText(text, op){        
        if(typeof text !== "string" ) return 'w';
        if($.trim(text) ==="")
          if(op.required) return 'r'; else return 's';
        if(typeof op.type!== "string" )//use reg
          if(validateReg(text, op.reg)) return 's'; else return 'w';
        //use type
        switch (op.type) {
            case 'time':
                if (!validateReg(text, '^\\d{1,2}:\\d\\d$')) return 'w'; 
                var h = parseInt(text.split(':', 2)[0], 10);
                var m = parseInt(text.split(':', 2)[1], 10);                
                if(h < 24 && m < 60) return 's'; else return 'w';
            case 'longTime':
                if (!validateReg(text, '^\\d+:\\d\\d$')) return 'w'; 
                var h = parseInt(text.split(':', 2)[0], 10);
                var m = parseInt(text.split(':', 2)[1], 10);                
                if(m >= 60) return 'w'; 
                else {
                 var time = h*60+m;
                 if(typeof op.min == 'number' && time < op.min) return 'min';
                 if(typeof op.max == 'number' && time > op.max) return 'max';
                 return 's';
                }                
            case 'number': 
                if(!validateReg(text, '^\\d+$')) return 'w'; 
                else {
                 if(typeof op.min == 'number' && parseInt(text, 10) < op.min) return 'min';
                 if(typeof op.max == 'number' && parseInt(text, 10) > op.max) return 'max';
                 return 's';
                }
        }
      }
      function validateReg(text, reg) {
        var reChar = new RegExp(reg);
        return text.match(reChar);            
      }  
      function wrong(o){        
        o.validSet.lastMSG = o.validSet.wrongMSG;
        if(typeof o.validSet.onWrong ==="function" ) o.validSet.onWrong(o);
      }
      function required(o){        
        o.validSet.lastMSG = o.validSet.requiredMSG;
        if(typeof o.validSet.onRequired ==="function" ) o.validSet.onRequired(o);
      }
      function success(o){        
        o.validSet.lastMSG = o.validSet.successMSG;
        if(typeof o.validSet.onSuccess ==="function" ) o.validSet.onSuccess(o);
      }
      function range(o,v){        
        o.validSet.lastMSG = v == 'min'? o.validSet.minMGS : o.validSet.maxMGS;
        if(typeof o.validSet.onRange ==="function" ) o.validSet.onRange(o,v);
      }

      
      this.validateTow = function (o1,o2, v){
        if(v){
          if(o1.valid()) $(o1).removeClass(o1.validSet.errorCSS); else $(o1).addClass(o1.validSet.errorCSS);
          if(o2.valid()) $(o2).removeClass(o2.validSet.errorCSS); else $(o2).addClass(o2.validSet.errorCSS);
        }else{
          $(o1).addClass(o1.validSet.errorCSS);
          $(o2).addClass(o2.validSet.errorCSS);
        }
      }
    });    
  };
})(jQuery);
