/*
@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' || t=='password')) || (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 'e': email(o); return false;
                    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';
                        h = parseInt(text.split(':', 2)[0]);
                        m = parseInt(text.split(':', 2)[1]);
                        if (h < 24 && m < 60) return 's'; else return 'w';
                    case 'number': if (!validateReg(text, '^\\d+$')) return 'w';
                        else {
                            if (typeof op.min == 'number' && parseInt(text) < op.min) return 'min';
                            if (typeof op.max == 'number' && parseInt(text) > op.max) return 'max';
                            return 's';
                        }
                    case 'email':
                        if (!validateReg(text, '^\\w+([-+.\']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$')) return 'e';
                        //'^\\w+([-+.\']\\w*)*@\\w+([-.]\\w*)*\.\\w+([-.]\\w*)*$'
                        //'\\w+([-+.\Т]\\w+)*@\\w+([-.]\\w+)*\.\\w+([-.]\\w+)*'
                        //^([a-z0-9_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,4}\$
                        //'[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\b'
                        ///^\w+([\.-]?\w+)*@(((([a-z0-9]{2,})|([a-z0-9][-][a-z0-9]+))[\.][a-z0-9])|([a-z0-9]+[-]?))+[a-z0-9]+\.([a-z]{2}|(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum))$/i; 

                        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);
            }
            function email(o) {
                o.validSet.lastMSG = 'Wrong Email Format';
                if (typeof o.validSet.onEmail === "function") o.validSet.onEmail(o);
            }


            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);
