jquery-validation.js在前端验证中使用起来非常方便,提供的功能基本上能满足大部分验证需求,例如:1、内置了很多常用的验证方法;2、可以自定义错误显示信息;3、可以自定义错误显示位置;4、可以自定义验证方法;5、ajax提交验证,等等

  但是有时候,我们在做项目的时候总会遇到一些特殊需求,例如,在单个控件验证结束后,根据验证的成功与否,需要调用一些自己定义的方法,这个需求貌似该插件没有提供(可能有只是我没发现),没办法, 只能看源码(这就是开源的好处啊),通过对源码的分析,找到了一种可以给指定控件添加验证回调函数的方法,虽然需要修改一部分源码,但是丝毫不影响对其之前的使用,该方法可以批量添加多个控件的验证回调函数,添加方式与添加自定义规则、自定义错误信息等类似,在阅读源码的过程中,还发现了如何控制控件验证的事件触发,以及如何解决与My97DatePicker日期插件的冲突等问题,所以建议大家多看源码,有时候会有意外收获哦。

  因此,本文包括三个方面:

  1. 添加控件的验证回调函数
  2. 控制控件验证的事件触发
  3. 解决与My97DatePicker日期插件的冲突问题

下面我们来一步步分析:

给指定控件添加自定义回调函数

  首先,要添加回调函数必须找到该插件的验证方法。其实在使用该插件的时候,从直观的操作上我们就可以发现,控件验证的触发有多种方式,包括:控件焦点的失去,控件内容的改变(其实是keyup),以及点击提交按钮等,相信大家都知道,这些只是表象。经查看源码,能触发验证的方法有很多,如:validate、form、checkForm和element等,但这依旧是表象,以我们程序员的嗅觉,真正的验证函数肯定只有一个,经过深入勘察,前面每个方法都调用了check方法,在check方法中发现一句话:

var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters);

可见,这句代码就是真正调用验证逻辑的地方,因此,我们需要将自定义的验证回调函数,放置在check方法中,修改后的代码如下(黄色部分为添加的代码):

check: function(element) {
element = this.validationTargetFor(this.clean(element)); var rules = $(element).rules();
var dependencyMismatch = false;
for (var method in rules) {
var rule = { method: method, parameters: rules[method] };
try {
var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters); // if a method indicates that the field is optional and therefore valid,
// don't mark it as valid when there are no other rules
if (result == "dependency-mismatch") {
dependencyMismatch = true;
continue;
}
dependencyMismatch = false; if (result == "pending") {
this.toHide = this.toHide.not(this.errorsFor(element));
return;
} if (!result) {
this.formatAndAdd(element, rule);
                 //验证失败回调函数  
                if ("invalidEventForElement" in this.settings) {
                    if (element.id in this.settings.validCallbackForElement) {
    this.settings.validCallbackForElement[element.id].fail();
    }
                }
return false;
}
} catch (e) {
this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
+ ", check the '" + rule.method + "' method", e);
throw e;
}
}
if (dependencyMismatch)
return;
if (this.objectLength(rules))
this.successList.push(element);
         //验证成功回调函数
          if ("invalidEventForElement" in this.settings) {
            if (element.id in this.settings.validCallbackForElement) {
this.settings.validCallbackForElement[element.id].success();
}
          }
          return true;
},

在这里,为了和插件的其他自定义属性保持一致,我们定义了一个对象,结构如下:

validCallbackForElement:{
  yourControlId1:{
   success:function(){
//验证成功回调
},
fail:function(){
//验证失败回调
}
},
yourControlId2:{
   success:function(){
//验证成功回调
},
fail:function(){
//验证失败回调
}
},
}

然后将其放入validate方法的参数中,示例如下(修改的时候将"yourControlId1"和"yourControlId2"更换成你自己的控件id):

$("#form1").validate({
rules: {
yourControlId1: {
required: true
},
yourControlId2: {
required: true,
maxlength: 500
}
}, //end rule
messages: {
yourControlId1: {
required: "不能为空"
},
yourControlId2: {
required: "不能为空",
maxlength: "内容过长"
}
},
errorPlacement: function(error, element) {
if (element.context.name == "yourControlId1") {
error.appendTo(document.getElementById("yourControlId1_error"));
}
else if (element.context.name == "yourControlId2")
error.appendTo(document.getElementById("yourControlId2_error"));
},
submitHandler: function(form) {
ajaxSubmit();
},
validCallbackForElement: {
yourControlId1: {
success: function() {
//控件yourControlId1的验证成功回调
},
fail: function() {
//控件yourControlId1的验证失败回调
}
},
yourControlId2: {
success: function() {
//控件yourControlId2的验证成功回调
},
fail: function() {
//控件yourControlId2的验证失败回调
}
}
}
}); //end validate function

在构造函数中,会将validCallbackForElement对象合并多this.settings对象中,因此,在调用的时候需要写成:this.settings.validCallbackForElement[element.id].success();

因为我们不一定给所有的验证控件都添加回调函数,因此,在调用的时候需要首先判断该控件有没有对应的毁掉函数,这样,调用代码就改为:

if ("invalidEventForElement" in this.settings) {
  if (element.id in this.settings.validCallbackForElement) {
  this.settings.validCallbackForElement[element.id].fail();
  }
}

到这里,如何给指定控件添加自定义验证回调函数的问题就已经解决了。下面提供一个简单的示例:

添加控件验证回调方法的示例程序

验证触发问题

在使用jquery-validation的时候发现,在调用验证方法之前,控件的keyup和focusout事件是不能触发验证的,比如我们打开一个页面,先不点击提交按钮,这样就不对表单进行过验证,这时候我们把光标放在input控件上,然后什么也不写,在让该input失去焦点,此时我们会发现,并没有提示该input是必填项的错误信息,原因在于,jquery-validation插件在验证表单的时候会将错误信息保存在errorMap这个变量中,errorMap的结构如下:

errorMap{
yourControlId1:"必填项",
yourControlId2:"内容过长",
......
}

然后将errorMap合并到this.submited对象中,在focusout和keyup事件中,会判断this.submited中是否有该控件的id,如果有才会执行验证,代码如下:

onfocusout: function(element, event) {
if (!that.checkable(element) && (element.name in that.submitted || !that.optional(element))) {
that.element(element);
}
},
onkeyup: function(element, event) {
    if (element.name in this.submitted || element == this.lastElement) { 
this.element(element);
}
},

因此,在执行表单验证后才会激活控件的focusout和keyup验证,如果你想一开始就能使focusout和keyup触发验证,可以在这里去掉红色部分的代码。

之前对这一部分的描述有问题,仅仅去掉红色部分的代码并不能达到验证的目的,从源码中可以看出,jquery-validation插件的作者对这里的控制还是比较严格的,不仅依赖submitted属性,还要根据控件的值来做相应判断,可能这款插件的意图就是保证控件在没有值并且没有进行表单验证之前不调用控件的验证方法,这点通过onfocusout和onkeyup事件中的逻辑就能看出来,两处的逻辑不太一样。因此,如果想要在表单验证前就能对空值的控件通过focusout和keyup触发验证方法,那么就需要修改很多地方,这显然不符合该插件的编写思路。

与My97DatePicker日期控件的冲突问题

相信My97DatePicker是很多人都用过的一个日期控件,该控件会与jquery-validation插件冲突,导致jquery-validation插件的focusout事件无法触发验证,可能是因为这两个东西都注册了focusout事件,所以导致了冲突,本来想看看My97DatePicker的源码,打开之后发现是压缩版的,好像还进行了混淆,所以如果在页面中同时使用了这两个东西的话,只能修改jquery-validation了,可以进行如下修改:

onfocusout: function(element, event) {
//修改了此处代码,否则会与My97DatePicker冲突,导致失去焦点的时候不会验证
var that = this;
setTimeout(function() {
if (!that.checkable(element) && (element.name in that.submitted || !that.optional(element))) {
that.element(element);
}
}, 100); },

给jquery-validation插件添加控件的验证回调方法的更多相关文章

  1. jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法

    博客分类: jquery-easyui jQueryAjax框架HTML  现象: AJAX返回的html无法做到自动渲染为EasyUI的样式.比如:class="easyui-layout ...

  2. jQuery 自定义插件 (分页控件)

    1.引入jqpage.js 2.html代码 <div id="page"> </div> 3.js 调用 $(function () { $.fn.jqp ...

  3. jquery weui日期选择控件添加取消按钮

    如图: 上图是jQuery weui的时间选择控件,红框处本来应该有个“取消”按钮的,可惜偏偏没有,当用户不想选择的时候就不好处理,虽然插件提供了点击其他区域关闭的功能,但过于隐晦,不容易发现,因此本 ...

  4. jquery插件——日历控件

    今天在网上有看到一个jquery插件——日历控件,不过之前也在柯乐义的网站上看到了(http://keleyi.com/ 推荐下) 这个插件看着比较大气,所以干脆也分享下,以后自己也好用一点儿 1.页 ...

  5. JQuery动态添加控件并取值

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. jquery easyui datebox 时间控件默认显示当前日期的实现方法

    jquery easyui datebox 时间控件默认显示当前日期的实现方法 直接class easyui-datebox后添加一个value="true"就可以

  7. jquery的上传控件uploadly,每行都有一个这样的控件对id选择器的使用

    1.先看看预览图 这个是我的页面,其中如果我没点击添加一行的时候,会把本来有的数据进行循环出来,这个时候每个记录都必须有个上传图片的按钮,但是jquery的uploadly这个控件只是锁定id的,至少 ...

  8. 为什么Jquery对input file控件的onchange事件只生效一次

    今天在做jquery对input file控件的onchange事件进行监听,就一直只生效一次,不知道Jquery为什么对file控件没有做到每次改变触发onchange事件的效果,但是还是有好几种解 ...

  9. Jquery获对HTML控件的控制

    Jquery获对HTML控件的控制 1.获取控件的值 1.1.radio 1.1.1 获取一组radio被选中项的值  var item = $('input[name=items][checked] ...

随机推荐

  1. Js 原型和原型链

    Js中通过原型和原型链实现了继承 Js对象属性的访问,首先会查找自身是否拥有这个属性 如果查到,则返回属性值,如果找不到,就会遍历原型链,一层一层的查找,如果找到就会返回属性值 直到遍历完Object ...

  2. 初步了解nodejs

    什么是Node.js? 很多初学者并没有真正地理解Node.js到底是什么.nodejs.org网站中的描述也没有多大帮助. 首先要清楚Node不是一个Web服务器,这十分重要.它本身并不能做任何事情 ...

  3. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  4. .NET平台开源项目速览(16)C#写PDF文件类库PDF File Writer介绍

    1年前,我在文章:这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)中(第9个项目),给大家推荐了一个开源免费的PDF读写组件 PDFSharp,PDFSharp我2年前就看过 ...

  5. JavaScript自定义媒体播放器

    使用<audio>和<video>元素的play()和pause()方法,可以手工控制媒体文件的播放.组合使用属性.事件和这两个方法,很容易创建一个自定义的媒体播放器,如下面的 ...

  6. JS继承之原型继承

     许多OO语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支 ...

  7. 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap

    一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...

  8. 【uwp】浅谈China Daily 中划词翻译的实现

    学习uwp开发也有一段时间了,最近上架了一个小应用(China Daily),现在准备将开发中所学到的一些东西拿出来跟大家分享交流一下. 先给出应用的下载链接:China Daily , 感兴趣的童鞋 ...

  9. 编译器开发系列--Ocelot语言5.表达式的有效性检查

    本篇将对"1=3""&5"这样无法求值的不正确的表达式进行检查. 将检查如下这些问题.●为无法赋值的表达式赋值(例:1 = 2 + 2)●使用非法的函数 ...

  10. Mysql - 性能优化之子查询

    记得在做项目的时候, 听到过一句话, 尽量不要使用子查询, 那么这一篇就来看一下, 这句话是否是正确的. 那在这之前, 需要介绍一些概念性东西和mysql对语句的大致处理. 当Mysql Server ...