jquery.validfrom.js

/*
    通用表单验证方法
    Validform version 5.3.2
   By sean during April 7, 2010 - March 26, 2013
   For more information, please visit http://validform.rjboy.cn
   Validform is available under the terms of the MIT license.
   
   Demo:
   $(".demoform").Validform({//$(".demoform")指明是哪一表单需要验证,名称需加在form表单上;
      btnSubmit:"#btn_sub", //#btn_sub是该表单下要绑定点击提交表单事件的按钮;如果form内含有submit按钮该参数可省略;
      btnReset:".btn_reset",//可选项 .btn_reset是该表单下要绑定点击重置表单事件的按钮;
      tiptype:1, //可选项 1=>pop box,2=>side tip(parent.next.find; with default pop),3=>side tip(siblings; with default pop),4=>side tip(siblings; none pop),默认为1,也可以传入一个function函数,自定义提示信息的显示方式(可以实现你想要的任何效果,具体参见demo页);
      ignoreHidden:false,//可选项 true | false 默认为false,当为true时对:hidden的表单元素将不做验证;
      dragonfly:false,//可选项 true | false 默认false,当为true时,值为空时不做验证;
      tipSweep:true,//可选项 true | false 默认为false,只在表单提交时触发检测,blur事件将不会触发检测(实时验证会在后台进行,不会显示检测结果);
      label:".label",//可选项 选择符,在没有绑定nullmsg时查找要显示的提示文字,默认查找".Validform_label"下的文字;
      showAllError:false,//可选项 true | falsetrue:提交表单时所有错误提示信息都会显示,false:一碰到验证不通过的就停止检测后面的元素,只显示该元素的错误信息;
      postonce:true, //可选项 表单是否只能提交一次,true开启,不填则默认关闭;
      ajaxPost:true, //使用ajax方式提交表单数据,默认false,提交地址就是action指定地址;
      datatype:{//传入自定义datatype类型,可以是正则,也可以是函数(函数内会传入一个参数);
         "*6-20": /^[^\s]{6,20}$/,
         "z2-4" : /^[\u4E00-\u9FA5\uf900-\ufa2d]{2,4}$/,
         "username":function(gets,obj,curform,regxp){
            //参数gets是获取到的表单元素值,obj为当前表单元素,curform为当前验证的表单,regxp为内置的一些正则表达式的引用;
            var reg1=/^[\w\.]{4,16}$/,
               reg2=/^[\u4E00-\u9FA5\uf900-\ufa2d]{2,8}$/;
            
            if(reg1.test(gets)){return true;}
            if(reg2.test(gets)){return true;}
            return false;
            
            //注意return可以返回true  false 或 字符串文字,true表示验证通过,返回字符串表示验证失败,字符串作为错误提示显示,返回false则用errmsg或默认的错误提示;
         },
         "phone":function(){
            // 5.0 版本之后,要实现二选一的验证效果,datatype 的名称 不 需要以 "option_" 开头;   
         }
      },
      usePlugin:{
         swfupload:{},
         datepicker:{},
         passwordstrength:{},
         jqtransform:{
            selector:"select,input"
         }
      },
      beforeCheck:function(curform){
         //在表单提交执行验证之前执行的函数,curform参数是当前表单对象。
         //这里明确return false的话将不会继续执行验证操作;   
      },
      beforeSubmit:function(curform){
         //在验证成功后,表单提交前执行的函数,curform参数是当前表单对象。
         //这里明确return false的话表单将不会提交;   
      },
      callback:function(data){
         //返回数据datajson格式,{"info":"demo info","status":"y"}
         //info: 输出提示信息;
         //status: 返回提交数据的状态,是否提交成功。如可以用"y"表示提交成功,"n"表示提交失败,在ajax_post.php文件返回数据里自定字符,主要用在callback函数里根据该值执行相应的回调操作;
         //你也可以在ajax_post.php文件返回更多信息在这里获取,进行相应操作;
         //ajax遇到服务端错误时也会执行回调,这时的data{ status:**, statusText:**, readyState:**, responseText:** }
         
         //这里执行回调操作;
         //注意:如果不是ajax方式提交表单,传入callback,这时data参数是当前表单对象,回调函数会在表单验证全部通过后执行,然后判断是否提交表单,如果callback里明确return false,则表单不会提交,如果return true或没有return,则会提交表单。
      }
   });
   
   Validform对象的方法和属性:
   tipmsg:自定义提示信息,通过修改Validform对象的这个属性值来让同一个页面的不同表单使用不同的提示文字;
   dataType:获取内置的一些正则;
   eq(n):获取Validform对象的第n个元素;
   ajaxPost(flag,sync,url):以ajax方式提交表单。flagtrue时,跳过验证直接提交,synctrue时将以同步的方式进行ajax提交,传入了url地址时,表单会提交到这个地址;
   abort():终止ajax的提交;
   submitForm(flag,url):以参数里设置的方式提交表单,flagtrue时,跳过验证直接提交,传入了url地址时,表单会提交到这个地址;
   resetForm():重置表单;
   resetStatus():重置表单的提交状态。传入了postonce参数的话,表单成功提交后状态会设置为"posted",重置提交状态可以让表单继续可以提交;
   getStatus():获取表单的提交状态,normal:未提交,posting:正在提交,posted:已成功提交过;
   setStatus(status):设置表单的提交状态,可以设置normalpostingposted三种状态,不传参则设置状态为posting,这个状态表单可以验证,但不能提交;
   ignore(selector):忽略对所选择对象的验证;
   unignore(selector):将ignore方法所忽略验证的对象重新获取验证效果;
   addRule(rule):可以通过Validform对象的这个方法来给表单元素绑定验证规则;
   check(bool,selector):对指定对象进行验证(默认验证当前整个表单),通过返回true,否则返回false(绑定实时验证的对象,格式符合要求时返回true,而不会等ajax的返回结果),booltrue时则只验证不显示提示信息;
   config(setup):可以通过这个方法来修改初始化参数,指定表单的提交地址,给表单ajax和实时验证的ajax里设置参数;
*/

(function($,win,undef){
   var errorobj=null,//指示当前验证失败的表单元素;
      msgobj=null,//pop box object 
      msghidden=true;//msgbox hidden?

   var tipmsg={//默认提示文字;
      tit:"提示信息",
      w:{
         "*":"不能为空!",
         "*6-16":"请填写616位任意字符!",
         "*1-20":"最多只能填写20位字符!",
         "n":"请填写数字!",
         "nd":"请填写数字!", //包括小数点
         "n6-16":"请填写616位数字!",
         "s":"不能输入特殊字符!",
         "s6-18":"请填写618位字符!",
         "p":"请填写邮政编码!",
         "m":"请填写手机号码!",
         "e":"邮箱地址格式不对!",
         "url":"请填写网址!"
      },
      def:"请填写正确信息!",
      undef:"datatype未定义!",
      reck:"两次输入的内容不一致!",
      r:"通过信息验证!",
      c:"正在检测信息…",
      s:"{填写|选择}{0|信息}",
      v:"所填信息没有经过验证,请稍后…",
      p:"正在提交数据…"
   }
   $.Tipmsg=tipmsg;
   
   var Validform=function(forms,settings,inited){
      var settings=$.extend({},Validform.defaults,settings);
      settings.datatype && $.extend(Validform.util.dataType,settings.datatype);
      
      var brothers=this;
      brothers.tipmsg={w:{}};
      brothers.forms=forms;
      brothers.objects=[];
      
      //创建子对象时不再绑定事件;
      if(inited===true){
         return false;
      }
      
      forms.each(function(){
         //已经绑定事件时跳过,避免事件重复绑定;
         if(this.validform_inited=="inited"){return true;}
         this.validform_inited="inited";
         
         var curform=this;
         curform.settings=$.extend({},settings);
         
         var $this=$(curform);
         
         //防止表单按钮双击提交两次;
         curform.validform_status="normal"; //normal | posting | posted;
         
         //让每个Validform对象都能自定义tipmsg;   
         $this.data("tipmsg",brothers.tipmsg);

         //bind the blur event;
         $this.delegate("[datatype]","blur",function(){
            //判断是否是在提交表单操作时触发的验证请求;
            var subpost=arguments[1];
            Validform.util.check.call(this,$this,subpost);
         });
         
         $this.delegate(":text","keypress",function(event){
            if(event.keyCode==13 && $this.find(":submit").length==0){
               $this.submit();
            }
         });
         
         //点击表单元素,默认文字消失效果;
         //表单元素值比较时的信息提示增强;
         //radiocheckbox提示信息增强;
         //外调插件初始化;
         Validform.util.enhance.call($this,curform.settings.tiptype,curform.settings.usePlugin,curform.settings.tipSweep);
         
         curform.settings.btnSubmit && $this.find(curform.settings.btnSubmit).bind("click",function(){
            $this.trigger("submit");
            return false;
         });
                  
         $this.submit(function(){
            var subflag=Validform.util.submitForm.call($this,curform.settings);
            subflag === undef && (subflag=true);
            return subflag;
         });
         
         $this.find("[type='reset']").add($this.find(curform.settings.btnReset)).bind("click",function(){
            Validform.util.resetForm.call($this);
         });
         
      });
      
      //预创建pop box;
      if( settings.tiptype==1 || (settings.tiptype==2 || settings.tiptype==3) && settings.ajaxPost ){       
         creatMsgbox();
      }
   }
   
   Validform.defaults={
      tiptype:1,
      tipSweep:false,
      showAllError:false,
      postonce:false,
      ajaxPost:false
   }
   
   Validform.util={
      dataType:{
         "*":/[\w\W]+/,
         "*6-16":/^[\w\W]{6,16}$/,
         "n":/^\d+$/,
         "n6-16":/^\d{6,16}$/,
         "s":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]+$/,
         "s6-18":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]{6,18}$/,
         "p":/^[0-9]{6}$/,
         "m":/^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$|17[0-9]{9}$/,
         "e":/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
         "url":/^(https?|ftp):\/\/(\w+:\/\/)?\w+(\.\w+)+.*$/,
         "nd":/^\d+(\.\d+)?$/
      },
      
      toString:Object.prototype.toString,
      
      isEmpty:function(val){
         return val==="" || val===$.trim(this.attr("tip"));
      },
      
      getValue:function(obj){
         var inputval,
            curform=this;
            
         if(obj.is(":radio")){
            inputval=curform.find(":radio[name='"+obj.attr("name")+"']:checked").val();
            inputval= inputval===undef ? "" : inputval;
         }else if(obj.is(":checkbox")){
            inputval="";
            curform.find(":checkbox[name='"+obj.attr("name")+"']:checked").each(function(){ 
               inputval +=$(this).val()+','; 
            })
            inputval= inputval===undef ? "" : inputval;
         }else{
            inputval=obj.val();
         }
         inputval=$.trim(inputval);
         
         return Validform.util.isEmpty.call(obj,inputval) ? "" : inputval;
      },
      
      enhance:function(tiptype,usePlugin,tipSweep,addRule){
         var curform=this;
         
         //页面上不存在提示信息的标签时,自动创建;
         curform.find("[datatype]").each(function(){
            if(tiptype==2){
               if($(this).parent().next().find(".Validform_checktip").length==0){
                  $(this).parent().next().append("<span class='Validform_checktip' />");
                  $(this).siblings(".Validform_checktip").remove();
               }
            }else if(tiptype==3 || tiptype==4){
               if($(this).siblings(".Validform_checktip").length==0){
                  $(this).parent().append("<span class='Validform_checktip' />");
                  $(this).parent().next().find(".Validform_checktip").remove();
               }
            }
         })
         
         //表单元素值比较时的信息提示增强;
         curform.find("input[recheck]").each(function(){
            //已经绑定事件时跳过;
            if(this.validform_inited=="inited"){return true;}
            this.validform_inited="inited";
            
            var _this=$(this);
            var recheckinput=curform.find("input[name='"+$(this).attr("recheck")+"']");
            recheckinput.bind("keyup",function(){
               if(recheckinput.val()==_this.val() && recheckinput.val() != ""){
                  if(recheckinput.attr("tip")){
                     if(recheckinput.attr("tip") == recheckinput.val()){return false;}
                  }
                  _this.trigger("blur");
               }
            }).bind("blur",function(){
               if(recheckinput.val()!=_this.val() && _this.val()!=""){
                  if(_this.attr("tip")){
                     if(_this.attr("tip") == _this.val()){return false;}    
                  }
                  _this.trigger("blur");
               }
            });
         });
         
         //hasDefaultText;
         curform.find("[tip]").each(function(){//tip是表单元素的默认提示信息,这是点击清空效果;
            //已经绑定事件时跳过;
            if(this.validform_inited=="inited"){return true;}
            this.validform_inited="inited";
            
            var defaultvalue=$(this).attr("tip");
            var altercss=$(this).attr("altercss");
            $(this).focus(function(){
               if($(this).val()==defaultvalue){
                  $(this).val('');
                  if(altercss){$(this).removeClass(altercss);}
               }
            }).blur(function(){
               if($.trim($(this).val())===''){
                  $(this).val(defaultvalue);
                  if(altercss){$(this).addClass(altercss);}
               }
            });
         });
         
         //enhance info feedback for checkbox & radio;
         curform.find(":checkbox[datatype],:radio[datatype]").each(function(){
            //已经绑定事件时跳过;
            if(this.validform_inited=="inited"){return true;}
            this.validform_inited="inited";
            
            var _this=$(this);
            var name=_this.attr("name");
            curform.find("[name='"+name+"']").filter(":checkbox,:radio").bind("click",function(){
               //避免多个事件绑定时的取值滞后问题;
               setTimeout(function(){
                  _this.trigger("blur");
               },0);
            });
            
         });
         
         //select multiple;
         curform.find("select[datatype][multiple]").bind("click",function(){
            var _this=$(this);
            setTimeout(function(){
               _this.trigger("blur");
            },0);
         });
         
         //plugins here to start;
         Validform.util.usePlugin.call(curform,usePlugin,tiptype,tipSweep,addRule);
      },
      
      usePlugin:function(plugin,tiptype,tipSweep,addRule){
         /*
            plugin:settings.usePlugin;
            tiptype:settings.tiptype;
            tipSweep:settings.tipSweep;
            addRule:是否在addRule时触发;
         */

         var curform=this,
            plugin=plugin || {};
         //swfupload;
         if(curform.find("input[plugin='swfupload']").length && typeof(swfuploadhandler) != "undefined"){
            
            var custom={
                  custom_settings:{
                     form:curform,
                     showmsg:function(msg,type,obj){
                        Validform.util.showmsg.call(curform,msg,tiptype,{obj:curform.find("input[plugin='swfupload']"),type:type,sweep:tipSweep}); 
                     }  
                  }  
               };

            custom=$.extend(true,{},plugin.swfupload,custom);
            
            curform.find("input[plugin='swfupload']").each(function(n){
               if(this.validform_inited=="inited"){return true;}
               this.validform_inited="inited";
               
               $(this).val("");
               swfuploadhandler.init(custom,n);
            });
            
         }
         
         //datepicker;
         if(curform.find("input[plugin='datepicker']").length && $.fn.datePicker){
            plugin.datepicker=plugin.datepicker || {};
            
            if(plugin.datepicker.format){
               Date.format=plugin.datepicker.format; 
               delete plugin.datepicker.format;
            }
            if(plugin.datepicker.firstDayOfWeek){
               Date.firstDayOfWeek=plugin.datepicker.firstDayOfWeek; 
               delete plugin.datepicker.firstDayOfWeek;
            }

            curform.find("input[plugin='datepicker']").each(function(n){
               if(this.validform_inited=="inited"){return true;}
               this.validform_inited="inited";
               
               plugin.datepicker.callback && $(this).bind("dateSelected",function(){
                  var d=new Date( $.event._dpCache[this._dpId].getSelected()[0] ).asString(Date.format);
                  plugin.datepicker.callback(d,this);
               });
               $(this).datePicker(plugin.datepicker);
            });
         }
         
         //passwordstrength;
         if(curform.find("input[plugin*='passwordStrength']").length && $.fn.passwordStrength){
            plugin.passwordstrength=plugin.passwordstrength || {};
            plugin.passwordstrength.showmsg=function(obj,msg,type){
               Validform.util.showmsg.call(curform,msg,tiptype,{obj:obj,type:type,sweep:tipSweep});
            };
            
            curform.find("input[plugin='passwordStrength']").each(function(n){
               if(this.validform_inited=="inited"){return true;}
               this.validform_inited="inited";
               
               $(this).passwordStrength(plugin.passwordstrength);
            });
         }
         
         //jqtransform;
         if(addRule!="addRule" && plugin.jqtransform && $.fn.jqTransSelect){
            if(curform[0].jqTransSelected=="true"){return;};
            curform[0].jqTransSelected="true";
            
            var jqTransformHideSelect = function(oTarget){
               var ulVisible = $('.jqTransformSelectWrapper ul:visible');
               ulVisible.each(function(){
                  var oSelect = $(this).parents(".jqTransformSelectWrapper:first").find("select").get(0);
                  //do not hide if click on the label object associated to the select
                  if( !(oTarget && oSelect.oLabel && oSelect.oLabel.get(0) == oTarget.get(0)) ){$(this).hide();}
               });
            };
            
            /* Check for an external click */
            var jqTransformCheckExternalClick = function(event) {
               if ($(event.target).parents('.jqTransformSelectWrapper').length === 0) { jqTransformHideSelect($(event.target)); }
            };
            
            var jqTransformAddDocumentListener = function (){
               $(document).mousedown(jqTransformCheckExternalClick);
            };
            
            if(plugin.jqtransform.selector){
               curform.find(plugin.jqtransform.selector).filter('input:submit, input:reset, input[type="button"]').jqTransInputButton();
               curform.find(plugin.jqtransform.selector).filter('input:text, input:password').jqTransInputText();       
               curform.find(plugin.jqtransform.selector).filter('input:checkbox').jqTransCheckBox();
               curform.find(plugin.jqtransform.selector).filter('input:radio').jqTransRadio();
               curform.find(plugin.jqtransform.selector).filter('textarea').jqTransTextarea();
               if(curform.find(plugin.jqtransform.selector).filter("select").length > 0 ){
                   curform.find(plugin.jqtransform.selector).filter("select").jqTransSelect();
                   jqTransformAddDocumentListener();
               }
               
            }else{
               curform.jqTransform();
            }
            
            curform.find(".jqTransformSelectWrapper").find("li a").click(function(){
               $(this).parents(".jqTransformSelectWrapper").find("select").trigger("blur");   
            });
         }

      },
      
      getNullmsg:function(curform){
         var obj=this;
         var reg=/[\u4E00-\u9FA5\uf900-\ufa2da-zA-Z\s]+/g;
         var nullmsg;
         
         var label=curform[0].settings.label || ".Validform_label";
         label=obj.siblings(label).eq(0).text() || obj.siblings().find(label).eq(0).text() || obj.parent().siblings(label).eq(0).text() || obj.parent().siblings().find(label).eq(0).text();
         label=label.replace(/\s(?![a-zA-Z])/g,"").match(reg);
         label=label? label.join("") : [""];

         reg=/\{(.+)\|(.+)\}/;
         nullmsg=curform.data("tipmsg").s || tipmsg.s;
         
         if(label != ""){
            nullmsg=nullmsg.replace(/\{0\|(.+)\}/,label);
            if(obj.attr("recheck")){
               nullmsg=nullmsg.replace(/\{(.+)\}/,"");
               obj.attr("nullmsg",nullmsg);
               return nullmsg;
            }
         }else{
            nullmsg=obj.is(":checkbox,:radio,select") ? nullmsg.replace(/\{0\|(.+)\}/,"") : nullmsg.replace(/\{0\|(.+)\}/,"$1");
         }
         nullmsg=obj.is(":checkbox,:radio,select") ? nullmsg.replace(reg,"$2") : nullmsg.replace(reg,"$1");
         
         obj.attr("nullmsg",nullmsg);
         return nullmsg;
      },
      
      getErrormsg:function(curform,datatype,recheck){
         var regxp=/^(.+?)((\d+)-(\d+))?$/,
            regxp2=/^(.+?)(\d+)-(\d+)$/,
            regxp3=/(.*?)\d+(.+?)\d+(.*)/,
            mac=datatype.match(regxp),
            temp,str;
         
         //如果是值不一样而报错;
         if(recheck=="recheck"){
            str=curform.data("tipmsg").reck || tipmsg.reck;
            return str;
         }
         
         var tipmsg_w_ex=$.extend({},tipmsg.w,curform.data("tipmsg").w);
         
         //如果原来就有,直接显示该项的提示信息;
         if(mac[0] in tipmsg_w_ex){
            return curform.data("tipmsg").w[mac[0]] || tipmsg.w[mac[0]];
         }
         
         //没有的话在提示对象里查找相似;
         for(var name in tipmsg_w_ex){
            if(name.indexOf(mac[1])!=-1 && regxp2.test(name)){
               str=(curform.data("tipmsg").w[name] || tipmsg.w[name]).replace(regxp3,"$1"+mac[3]+"$2"+mac[4]+"$3");
               curform.data("tipmsg").w[mac[0]]=str;
               
               return str;
            }
            
         }
         
         return curform.data("tipmsg").def || tipmsg.def;
      },

      _regcheck:function(datatype,gets,obj,curform){
         var curform=curform,
            info=null,
            passed=false,
            reg=/\/.+\//g,
            regex=/^(.+?)(\d+)-(\d+)$/,
            type=3;//default set to wrong type, 2,3,4;
            
         //datatype有三种情况:正则,函数和直接绑定的正则;
         
         //直接是正则;
         if(reg.test(datatype)){
            var regstr=datatype.match(reg)[0].slice(1,-1);
            var param=datatype.replace(reg,"");
            var rexp=RegExp(regstr,param);

            passed=rexp.test(gets);

         //function;
         }else if(Validform.util.toString.call(Validform.util.dataType[datatype])=="[object Function]"){
            passed=Validform.util.dataType[datatype](gets,obj,curform,Validform.util.dataType);
            if(passed === true || passed===undef){
               passed = true;
            }else{
               info= passed;
               passed=false;
            }
         
         //自定义正则;   
         }else{
            //自动扩展datatype;
            if(!(datatype in Validform.util.dataType)){
               var mac=datatype.match(regex),
                  temp;
                  
               if(!mac){
                  passed=false;
                  info=curform.data("tipmsg").undef||tipmsg.undef;
               }else{
                  for(var name in Validform.util.dataType){
                     temp=name.match(regex);
                     if(!temp){continue;}
                     if(mac[1]===temp[1]){
                        var str=Validform.util.dataType[name].toString(),
                           param=str.match(/\/[mgi]*/g)[1].replace("\/",""),
                           regxp=new RegExp("\\{"+temp[2]+","+temp[3]+"\\}","g");
                        str=str.replace(/\/[mgi]*/g,"\/").replace(regxp,"{"+mac[2]+","+mac[3]+"}").replace(/^\//,"").replace(/\/$/,"");
                        Validform.util.dataType[datatype]=new RegExp(str,param);
                        break;
                     }  
                  }
               }
            }
            
            if(Validform.util.toString.call(Validform.util.dataType[datatype])=="[object RegExp]"){
               passed=Validform.util.dataType[datatype].test(gets);
            }
               
         }
         
         
         if(passed){
            type=2;
            info=obj.attr("sucmsg") || curform.data("tipmsg").r||tipmsg.r;
            
            //规则验证通过后,还需要对绑定recheck的对象进行值比较;
            if(obj.attr("recheck")){
               var theother=curform.find("input[name='"+obj.attr("recheck")+"']:first");
               if(gets!=theother.val()){
                  passed=false;
                  type=3;
                  info=obj.attr("errormsg")  || Validform.util.getErrormsg.call(obj,curform,datatype,"recheck");
               }
            }
         }else{
            info=info || obj.attr("errormsg") || Validform.util.getErrormsg.call(obj,curform,datatype);
            
            //验证不通过且为空时;
            if(Validform.util.isEmpty.call(obj,gets)){
               info=obj.attr("nullmsg") || Validform.util.getNullmsg.call(obj,curform);
            }
         }
         
         return{
               passed:passed,
               type:type,
               info:info
         };
         
      },
      
      regcheck:function(datatype,gets,obj){
         /*
            datatype:datatype;
            gets:inputvalue;
            obj:input object;
         */
         var curform=this,
            info=null,
            passed=false,
            type=3;//default set to wrong type, 2,3,4;
            
         //ignore;
         if(obj.attr("ignore")==="ignore" && Validform.util.isEmpty.call(obj,gets)){             
            if(obj.data("cked")){
               info="";   
            }
            
            return {
               passed:true,
               type:4,
               info:info
            };
         }

         obj.data("cked","cked");//do nothing if is the first time validation triggered;
         
         var dtype=Validform.util.parseDatatype(datatype);
         var res;
         for(var eithor=0; eithor<dtype.length; eithor++){
            for(var dtp=0; dtp<dtype[eithor].length; dtp++){
               res=Validform.util._regcheck(dtype[eithor][dtp],gets,obj,curform);
               if(!res.passed){
                  break;
               }
            }
            if(res.passed){
               break;
            }
         }
         return res;
         
      },
      
      parseDatatype:function(datatype){
         /*
            字符串里面只能含有一个正则表达式;
            Datatype名称必须是字母,数字、下划线或*号组成;
            datatype="/regexp/|phone|tel,s,e|f,e";
            ==>[["/regexp/"],["phone"],["tel","s","e"],["f","e"]];
         */

         var reg=/\/.+?\/[mgi]*(?=(,|$|\||\s))|[\w\*-]+/g,
            dtype=datatype.match(reg),
            sepor=datatype.replace(reg,"").replace(/\s*/g,"").split(""),
            arr=[],
            m=0;
            
         arr[0]=[];
         arr[0].push(dtype[0]);
         for(var n=0;n<sepor.length;n++){
            if(sepor[n]=="|"){
               m++;
               arr[m]=[];
            }
            arr[m].push(dtype[n+1]);
         }
         
         return arr;
      },

      showmsg:function(msg,type,o,triggered){
         /*
            msg:提示文字;
            type:提示信息显示方式;
            o:{obj:当前对象, type:1=>正在检测 | 2=>通过, sweep:true | false}, 
            triggered:blur或提交表单触发的验证中,有些情况不需要显示提示文字,如自定义弹出提示框的显示方式,不需要每次blur时就马上弹出提示;
            
            tiptype:1\2\3时都有坑能会弹出自定义提示框
            tiptype:1时在triggered bycheck时不弹框
            tiptype:2\3时在ajax时弹框
            tipSweeptrue时在triggered bycheck时不触发showmsg,但ajax出错的情况下要提示
         */
         
         //如果msgundefined,那么就没必要执行后面的操作,ignore有可能会出现这情况;
         if(msg==undef){return;}
         
         //tipSweeptrue,且当前不是处于错误状态时,blur事件不触发信息显示;
         if(triggered=="bycheck" && o.sweep && (o.obj && !o.obj.is(".Validform_error") || typeof type == "function")){return;}

         $.extend(o,{curform:this});
            
         if(typeof type == "function"){
            type(msg,o,Validform.util.cssctl);
            return;
         }
         
         if(type==1 || triggered=="byajax" && type!=4){
            msgobj.find(".Validform_info").html(msg);
         }
         
         //tiptypt=1时,blur触发showmsg,验证是否通过都不弹框,提交表单触发的话,只要验证出错,就弹框;
         if(type==1 && triggered!="bycheck" && o.type!=2 || triggered=="byajax" && type!=4){
            msghidden=false;
            msgobj.find(".iframe").css("height",msgobj.outerHeight());
            msgobj.show();
            setCenter(msgobj,100);
         }

         if(type==2 && o.obj){
            o.obj.parent().next().find(".Validform_checktip").html(msg);
            Validform.util.cssctl(o.obj.parent().next().find(".Validform_checktip"),o.type);
         }
         
         if((type==3 || type==4) && o.obj){
            o.obj.siblings(".Validform_checktip").html(msg);
            Validform.util.cssctl(o.obj.siblings(".Validform_checktip"),o.type);
         }

      },

      cssctl:function(obj,status){
         switch(status){
            case 1:
               obj.removeClass("Validform_right Validform_wrong").addClass("Validform_checktip Validform_loading");//checking;
               break;
            case 2:
               obj.removeClass("Validform_wrong Validform_loading").addClass("Validform_checktip Validform_right");//passed;
               break;
            case 4:
               obj.removeClass("Validform_right Validform_wrong Validform_loading").addClass("Validform_checktip");//for ignore;
               break;
            default:
               obj.removeClass("Validform_right Validform_loading").addClass("Validform_checktip Validform_wrong");//wrong;
         }
      },
      
      check:function(curform,subpost,bool){
         /*
            检测单个表单元素;
            验证通过返回true,否则返回false、实时验证返回值为ajax;
            bool,传入true则只检测不显示提示信息;
         */
         var settings=curform[0].settings;
         var subpost=subpost || "";
         var inputval=Validform.util.getValue.call(curform,$(this));
         
         //隐藏或绑定dataIgnore的表单对象不做验证;
         if(settings.ignoreHidden && $(this).is(":hidden") || $(this).data("dataIgnore")==="dataIgnore"){
            return true;
         }
         
         //dragonfly=true时,没有绑定ignore,值为空不做验证,但验证不通过;
         if(settings.dragonfly && !$(this).data("cked") && Validform.util.isEmpty.call($(this),inputval) && $(this).attr("ignore")!="ignore"){
            return false;
         }
         
         var flag=Validform.util.regcheck.call(curform,$(this).attr("datatype"),inputval,$(this));
         
         //值没变化不做检测,这时要考虑recheck情况;
         //不是在提交表单时触发的ajax验证;
         if(inputval==this.validform_lastval && !$(this).attr("recheck") && subpost==""){
            return flag.passed ? true : false;
         }

         this.validform_lastval=inputval;//存储当前值;
         
         var _this;
         errorobj=_this=$(this);
         
         if(!flag.passed){
            //取消正在进行的ajax验证;
            Validform.util.abort.call(_this[0]);
            
            if(!bool){
               //传入"bycheck",指示当前是check方法里调用的,当tiptype=1时,blur事件不让触发错误信息显示;
               Validform.util.showmsg.call(curform,flag.info,settings.tiptype,{obj:$(this),type:flag.type,sweep:settings.tipSweep},"bycheck");
               
               !settings.tipSweep && _this.addClass("Validform_error");
            }
            return false;
         }
         
         //验证通过的话,如果绑定有ajaxurl,要执行ajax检测;
         //ignore="ignore"时,为空值可以通过验证,这时不需要ajax检测;
         var ajaxurl=$(this).attr("ajaxurl");
         if(ajaxurl && !Validform.util.isEmpty.call($(this),inputval) && !bool){
            var inputobj=$(this);

            //当提交表单时,表单中的某项已经在执行ajax检测,这时需要让该项ajax结束后继续提交表单;
            if(subpost=="postform"){
               inputobj[0].validform_subpost="postform";
            }else{
               inputobj[0].validform_subpost="";
            }
            
            if(inputobj[0].validform_valid==="posting" && inputval==inputobj[0].validform_ckvalue){return "ajax";}
            
            inputobj[0].validform_valid="posting";
            inputobj[0].validform_ckvalue=inputval;
            Validform.util.showmsg.call(curform,curform.data("tipmsg").c||tipmsg.c,settings.tiptype,{obj:inputobj,type:1,sweep:settings.tipSweep},"bycheck");
            
            Validform.util.abort.call(_this[0]);
            
            var ajaxsetup=$.extend(true,{},settings.ajaxurl || {});
                        
            var localconfig={
               type: "POST",
               cache:false,
               url: ajaxurl,
               data: "param="+encodeURIComponent(inputval)+"&name="+encodeURIComponent($(this).attr("name")),
               success: function(data){
                  if($.trim(data.status)==="y"){
                     inputobj[0].validform_valid="true";
                     data.info && inputobj.attr("sucmsg",data.info);
                     Validform.util.showmsg.call(curform,inputobj.attr("sucmsg") || curform.data("tipmsg").r||tipmsg.r,settings.tiptype,{obj:inputobj,type:2,sweep:settings.tipSweep},"bycheck");
                     _this.removeClass("Validform_error");
                     errorobj=null;
                     if(inputobj[0].validform_subpost=="postform"){
                        curform.trigger("submit");
                     }
                  }else{
                     inputobj[0].validform_valid=data.info;
                     Validform.util.showmsg.call(curform,data.info,settings.tiptype,{obj:inputobj,type:3,sweep:settings.tipSweep});
                     _this.addClass("Validform_error");
                  }
                  _this[0].validform_ajax=null;
               },
               error: function(data){
                  if(data.status=="200"){
                     if(data.responseText=="y"){
                        ajaxsetup.success({"status":"y"});
                     }else{
                        ajaxsetup.success({"status":"n","info":data.responseText});    
                     }
                     return false;
                  }
                  
                  //正在检测时,要检测的数据发生改变,这时要终止当前的ajax。不是这种情况引起的ajax错误,那么显示相关错误信息;
                  if(data.statusText!=="abort"){
                     var msg="status: "+data.status+"; statusText: "+data.statusText;
                  
                     Validform.util.showmsg.call(curform,msg,settings.tiptype,{obj:inputobj,type:3,sweep:settings.tipSweep});
                     _this.addClass("Validform_error");
                  }
                  
                  inputobj[0].validform_valid=data.statusText;
                  _this[0].validform_ajax=null;
                  
                  //localconfig.error返回true表示还需要执行temp_err;
                  return true;
               }
            }
            
            if(ajaxsetup.success){
               var temp_suc=ajaxsetup.success;
               ajaxsetup.success=function(data){
                  localconfig.success(data);
                  temp_suc(data,inputobj);
               }
            }
            
            if(ajaxsetup.error){
               var temp_err=ajaxsetup.error;
               ajaxsetup.error=function(data){
                  //localconfig.error返回false表示不需要执行temp_err;
                  localconfig.error(data) && temp_err(data,inputobj);
               }  
            }

            ajaxsetup=$.extend({},localconfig,ajaxsetup,{dataType:"json"});
            _this[0].validform_ajax=$.ajax(ajaxsetup);
            
            return "ajax";
         }else if(ajaxurl && Validform.util.isEmpty.call($(this),inputval)){
            Validform.util.abort.call(_this[0]);
            _this[0].validform_valid="true";
         }
         
         if(!bool){
            Validform.util.showmsg.call(curform,flag.info,settings.tiptype,{obj:$(this),type:flag.type,sweep:settings.tipSweep},"bycheck");
            _this.removeClass("Validform_error");
         }
         errorobj=null;
         
         return true;
      
      },
      
      submitForm:function(settings,flg,url,ajaxPost,sync){
         /*
            flg===true时跳过验证直接提交;
            ajaxPost==="ajaxPost"指示当前表单以ajax方式提交;
         */
         var curform=this;
         
         //表单正在提交时点击提交按钮不做反应;
         if(curform[0].validform_status==="posting"){return false;}
         
         //要求只能提交一次时;
         if(settings.postonce && curform[0].validform_status==="posted"){return false;}
         
         var beforeCheck=settings.beforeCheck && settings.beforeCheck(curform);
         if(beforeCheck===false){return false;}
         
         var flag=true,
            inflag;
            
         curform.find("[datatype]").each(function(){
            //跳过验证;
            if(flg){
               return false;
            }
            
            //隐藏或绑定dataIgnore的表单对象不做验证;
            if(settings.ignoreHidden && $(this).is(":hidden") || $(this).data("dataIgnore")==="dataIgnore"){
               return true;
            }
            
            var inputval=Validform.util.getValue.call(curform,$(this)),
               _this;
            errorobj=_this=$(this);
            
            inflag=Validform.util.regcheck.call(curform,$(this).attr("datatype"),inputval,$(this));
            
            if(!inflag.passed){
               Validform.util.showmsg.call(curform,inflag.info,settings.tiptype,{obj:$(this),type:inflag.type,sweep:settings.tipSweep});
               _this.addClass("Validform_error");
               
               if(!settings.showAllError){
                  _this.focus();
                  flag=false;
                  return false;
               }
               
               flag && (flag=false);
               return true;
            }
            
            //ignore="ignore"时,为空值可以通过验证,这时不需要ajax检测;
            if($(this).attr("ajaxurl") && !Validform.util.isEmpty.call($(this),inputval)){
               if(this.validform_valid!=="true"){
                  var thisobj=$(this);
                  Validform.util.showmsg.call(curform,curform.data("tipmsg").v||tipmsg.v,settings.tiptype,{obj:thisobj,type:3,sweep:settings.tipSweep});
                  _this.addClass("Validform_error");
                  
                  thisobj.trigger("blur",["postform"]);//continue the form post;
                  
                  if(!settings.showAllError){
                     flag=false;
                     return false;
                  }
                  
                  flag && (flag=false);
                  return true;
               }
            }else if($(this).attr("ajaxurl") && Validform.util.isEmpty.call($(this),inputval)){
               Validform.util.abort.call(this);
               this.validform_valid="true";
            }

            Validform.util.showmsg.call(curform,inflag.info,settings.tiptype,{obj:$(this),type:inflag.type,sweep:settings.tipSweep});
            _this.removeClass("Validform_error");
            errorobj=null;
         });
         
         if(settings.showAllError){
            curform.find(".Validform_error:first").focus();
         }

         if(flag){
            var beforeSubmit=settings.beforeSubmit && settings.beforeSubmit(curform);
            if(beforeSubmit===false){return false;}
            
            curform[0].validform_status="posting";
                     
            if(settings.ajaxPost || ajaxPost==="ajaxPost"){
               //获取配置参数;
               var ajaxsetup=$.extend(true,{},settings.ajaxpost || {});
               //有可能需要动态的改变提交地址,所以把action所指定的url层级设为最低;
               ajaxsetup.url=url || ajaxsetup.url || settings.url || curform.attr("action");
               
               //byajaxajax时,tiptye123需要弹出提示框;
               Validform.util.showmsg.call(curform,curform.data("tipmsg").p||tipmsg.p,settings.tiptype,{obj:curform,type:1,sweep:settings.tipSweep},"byajax");

               //方法里的优先级要高;
               //undefined情况;
               if(sync){
                  ajaxsetup.async=false;
               }else if(sync===false){
                  ajaxsetup.async=true;
               }
               
               if(ajaxsetup.success){
                  var temp_suc=ajaxsetup.success;
                  ajaxsetup.success=function(data){
                     settings.callback && settings.callback(data);
                     curform[0].validform_ajax=null;
                     if($.trim(data.status)==="y"){
                        curform[0].validform_status="posted";
                     }else{
                        curform[0].validform_status="normal";
                     }
                     
                     temp_suc(data,curform);
                  }
               }
               
               if(ajaxsetup.error){
                  var temp_err=ajaxsetup.error;
                  ajaxsetup.error=function(data){
                     settings.callback && settings.callback(data);
                     curform[0].validform_status="normal";
                     curform[0].validform_ajax=null;
                     
                     temp_err(data,curform);
                  }  
               }
               
               var localconfig={
                  type: "POST",
                  async:true,
                  data: curform.serializeArray(),
                  success: function(data){
                     if($.trim(data.status)==="y"){
                        //成功提交;
                        curform[0].validform_status="posted";
                        Validform.util.showmsg.call(curform,data.info,settings.tiptype,{obj:curform,type:2,sweep:settings.tipSweep},"byajax");
                     }else{
                        //提交出错;
                        curform[0].validform_status="normal";
                        Validform.util.showmsg.call(curform,data.info,settings.tiptype,{obj:curform,type:3,sweep:settings.tipSweep},"byajax");
                     }
                     
                     settings.callback && settings.callback(data);
                     curform[0].validform_ajax=null;
                  },
                  error: function(data){
                     var msg="status: "+data.status+"; statusText: "+data.statusText;
                           
                     Validform.util.showmsg.call(curform,msg,settings.tiptype,{obj:curform,type:3,sweep:settings.tipSweep},"byajax");
                     
                     settings.callback && settings.callback(data);
                     curform[0].validform_status="normal";
                     curform[0].validform_ajax=null;
                  }
               }
               
               ajaxsetup=$.extend({},localconfig,ajaxsetup,{dataType:"json"});
               
               curform[0].validform_ajax=$.ajax(ajaxsetup);

            }else{
               if(!settings.postonce){
                  curform[0].validform_status="normal";
               }
               
               var url=url || settings.url;
               if(url){
                  curform.attr("action",url);
               }
               
               return settings.callback && settings.callback(curform);
            }
         }
         
         return false;
         
      },
      
      resetForm:function(){
         var brothers=this;
         brothers.each(function(){
            this.reset && this.reset();
            this.validform_status="normal";
         });
         
         brothers.find(".Validform_right").text("");
         brothers.find(".passwordStrength").children().removeClass("bgStrength");
         brothers.find(".Validform_checktip").removeClass("Validform_wrong Validform_right Validform_loading");
         brothers.find(".Validform_error").removeClass("Validform_error");
         brothers.find("[datatype]").removeData("cked").removeData("dataIgnore").each(function(){
            this.validform_lastval=null;
         });
         brothers.eq(0).find("input:first").focus();
      },
      
      abort:function(){
         if(this.validform_ajax){
            this.validform_ajax.abort();   
         }
      }
      
   }
   
   $.Datatype=Validform.util.dataType;
   
   Validform.prototype={
      dataType:Validform.util.dataType,
      
      eq:function(n){
         var obj=this;
         
         if(n>=obj.forms.length){
            return null;   
         }
         
         if(!(n in obj.objects)){
            obj.objects[n]=new Validform($(obj.forms[n]).get(),{},true);
         }
         
         return obj.objects[n];

      },
      
      resetStatus:function(){
         var obj=this;
         $(obj.forms).each(function(){
            this.validform_status="normal";    
         });
         
         return this;
      },
      
      setStatus:function(status){
         var obj=this;
         $(obj.forms).each(function(){
            this.validform_status=status || "posting"; 
         });
         
         return this;
      },
      
      getStatus:function(){
         var obj=this;
         var status=$(obj.forms)[0].validform_status;
         
         return status;
      },
      
      ignore:function(selector){
         var obj=this;
         var selector=selector || "[datatype]"
         
         $(obj.forms).find(selector).each(function(){
            $(this).data("dataIgnore","dataIgnore").removeClass("Validform_error");
         });
         
         return this;
      },
      
      unignore:function(selector){
         var obj=this;
         var selector=selector || "[datatype]"
         
         $(obj.forms).find(selector).each(function(){
            $(this).removeData("dataIgnore");
         });
         
         return this;
      },
      
      addRule:function(rule){
         /*
            rule => [{
               ele:"#id",
               datatype:"*",
               errormsg:"出错提示文字!",
               nullmsg:"为空时的提示文字!",
               tip:"默认显示的提示文字",
               altercss:"gray",
               ignore:"ignore",
               ajaxurl:"valid.php",
               recheck:"password",
               plugin:"passwordStrength"
            },{},{},...]
         */
         var obj=this;
         var rule=rule || [];
         
         for(var index=0; index<rule.length; index++){
            var o=$(obj.forms).find(rule[index].ele);
            for(var attr in rule[index]){
               attr !=="ele" && o.attr(attr,rule[index][attr]);
            }
         }
         
         $(obj.forms).each(function(){
            var $this=$(this);
            Validform.util.enhance.call($this,this.settings.tiptype,this.settings.usePlugin,this.settings.tipSweep,"addRule");
         });
         
         return this;
      },
      
      ajaxPost:function(flag,sync,url){
         var obj=this;
         
         $(obj.forms).each(function(){
            //创建pop box;
            if( this.settings.tiptype==1 || this.settings.tiptype==2 || this.settings.tiptype==3 ){
               creatMsgbox();
            }
            
            Validform.util.submitForm.call($(obj.forms[0]),this.settings,flag,url,"ajaxPost",sync);
         });
         
         return this;
      },
      
      submitForm:function(flag,url){
         /*flag===true时不做验证直接提交*/
         

         var obj=this;
         
         $(obj.forms).each(function(){
            var subflag=Validform.util.submitForm.call($(this),this.settings,flag,url);
            subflag === undef && (subflag=true);
            if(subflag===true){
               this.submit();
            }
         });
         
         return this;
      },
      
      resetForm:function(){
         var obj=this;
         Validform.util.resetForm.call($(obj.forms));
         
         return this;
      },
      
      abort:function(){
         var obj=this;
         $(obj.forms).each(function(){
            Validform.util.abort.call(this);
         });
         
         return this;
      },
      
      check:function(bool,selector){
         /*
            bool:传入true,只检测不显示提示信息;
         */
         
         var selector=selector || "[datatype]",
            obj=this,
            curform=$(obj.forms),
            flag=true;
         
         curform.find(selector).each(function(){
            Validform.util.check.call(this,curform,"",bool) || (flag=false);
         });
         
         return flag;
      },
      
      config:function(setup){
      /*
         config={
            url:"ajaxpost.php",//指定了url后,数据会提交到这个地址;
            ajaxurl:{
               timeout:1000,
               ...
            },
            ajaxpost:{
               timeout:1000,
               ...
            }
         }
      */
         var obj=this;
         setup=setup || {};
         $(obj.forms).each(function(){
            var $this=$(this);
            this.settings=$.extend(true,this.settings,setup);
            Validform.util.enhance.call($this,this.settings.tiptype,this.settings.usePlugin,this.settings.tipSweep);
         });
         
         return this;
      }
   }

   $.fn.Validform=function(settings){
      return new Validform(this,settings);
   };
   
   function setCenter(obj,time){
      var left=($(window).width()-obj.outerWidth())/2,
         top=($(window).height()-obj.outerHeight())/2,
         
      top=(document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop)+(top>0?top:0);

      obj.css({
         left:left
      }).animate({
         top : top
      },{ duration:time , queue:false });
   }
   
   function creatMsgbox(){
      if($("#Validform_msg").length!==0){return false;}
      msgobj=$('<div id="Validform_msg"><div class="Validform_title">'+tipmsg.tit+'<a class="Validform_close" href="javascript:void(0);">&chi;</a></div><div class="Validform_info"></div><div class="iframe"><iframe frameborder="0" scrolling="no" height="100%" width="100%"></iframe></div></div>').appendTo("body");//提示信息框;
      msgobj.find("a.Validform_close").click(function(){
         msgobj.hide();
         msghidden=true;
         if(errorobj){
            errorobj.focus().addClass("Validform_error");
         }
         return false;
      }).focus(function(){this.blur();});

      $(window).bind("scroll resize",function(){
         !msghidden && setCenter(msgobj,400);
      });
   };
   
   //公用方法显示&关闭信息提示框;
   $.Showmsg=function(msg){
      creatMsgbox();
      Validform.util.showmsg.call(win,msg,1,{});
   };
   
   $.Hidemsg=function(){
      msgobj.hide();
      msghidden=true;
   };
   
})(jQuery,window);
 
 
 
 
 
use:
$("#myform").Validform({
   btnSubmit: "#formsubmit",
   showAllError: true,    
   tiptype: 3,
   ajaxPost: true,
   beforeCheck:function () {
      do something...
   },
   callback: function(json){
     
    do something...
}});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值