当前位置:嗨网首页>书籍在线阅读

07-讨论

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

11.1.3 讨论

验证插件推广客户端验证的一种特殊方法:在浏览器中进行尽可能多的工作,仅在特殊情况下寻求服务器的帮助,这些情况(如检查用户名是否仍然可用)需要用到远程方法(http://jquery-cookbook.com/go/plugin-validation-remote-method)。

另一种不同的方法是不在客户端和服务器端重复验证规则和方法,而是通过Ajax将整个表单发送到服务器(通常是在表单提交的时候),然后在服务器端使用已经编写好的相同逻辑。这样做的缺点是用户反馈较慢,因为每次击键都发送一个请求是不现实的。编写服务器验证的时候也不太会考虑Ajax验证,所以也不容易重用它。在这种情况下,你必须预先进行规划。

验证插件可在以后添加到表单上,和远程验证不同,没有必要以某种方式改写应用程序。这对于博客上的简单评论表单和一些内联网应用上更加复杂的表单以及两者之间的任何表单都很实用。

这个插件最重要的组成部分是规则和方法。方法包含验证逻辑,如使用正则表达式确定一个值是不是有效电子邮件地址的E-mail方法。规则将字段与方法连接起来,一条规则就是一个输入字段和一个方法的配对。电子邮件地址字段有一条将其标记为必需字段的规则,以及一条将其标记为电子邮件地址的规则。

1.方法

验证插件有19个内置方法。最重要的方法是 required ——它指定必须填写的字段。如果省略它,在空字段上的大部分其他方法将被忽略。唯一的例外是 equalTo 方法,该方法检查字段内容是否与其他字段相同,即使空字段也适用,这条规则本身最常用于“确认密码”字段。

emailurldatedateISOdateDEnumbernumberDEdigitscreditcard 方法都检查某些数据类型,对不同地区有简单的变种。例如, number 要求美国数字格式(如1,000.00),而numberDE要求德国数字格式(如1.000,00)。

minmax 以及 range 方法检查数字值,而 minlengthmaxlengthrangelength 检查字符数量。

在选择列表或者复选框中, minmaxrange 验证选中的选项或者复选框的数量。

在文件输入字段中, accept 方法可以很方便地检查文件扩展名,默认情况下查找 .gif.png.jpg 或者 .jpeg

remote 方法是将其他地方的验证逻辑委托给服务器端的唯一方法。它以指向某个服务器端资源的URL作为参数,该URL可以是一个进行数据库查询的脚本,例如,检查用户名是否已经存在或者指定电子邮件地址是否已经注册的脚本。使用远程方法验证用户名和电子邮件地址的注册表单例子可以在http://jquery-cookbook.com/go/plugin-validation-remote-demo上找到。

自定义方法是按照应用程序相关需求扩展插件的好手段。你可能有一个表单,用户输入的URL必须以某个公司域名开始。自定义方法可以封装必要的验证:

jQuery.validator.addMethod("domain", function(value, element) {
   return this.optional(element) || /^http:\/\/mycorporatedomain.com/.test(value);
}, "Please specify the correct domain for your documents");

jQuery.validator.addMethod 的第一个参数是自定义方法的名称,必须是有效的JavaScript标识符。第二个参数是实现真正验证的一个函数。如果它返回真值,就认为输入是有效的。它使用 this.optional(element) 确定输入是否有值以及是否应该跳过——所有默认方法都使用相同的调用。第三个参数指定新方法的默认信息。

接受参数的方法的写法非常类似:

jQuery.validator.addMethod("math", function(value, element, params) {
   return this.optional(element) || value == params[0] + params[1];
}, jQuery.format("Please enter the correct value for {0} + {1}"));

在这个例子中,默认的信息在该插件提供的模板助手 jQuery.format 的帮助下指定。圆括号中的索引占位符在验证运行时由实际参数替代。

自定义方法也可以重用现有的方法,这对为单个方法指定不同的默认信息很有用。在这个例子中, required 方法用不同的默认信息化名为 customerRequired

$.validator.addMethod("customerRequired", $.validator.methods.required,
"Customer name required");

插件中的 additionalMethods.js 捆绑了一组现成的自定义方法。

2.规则

指定规则有4种不同的方法:两种采用代码形式,另两种作为元数据嵌入。前一个例子使用了类和属性等元数据,这是插件默认支持的方式。在元数据插件(http://jquery-cookbook.com/go/plugin-metadata)可用时,规则可以各种方式迁入,例如,在 class 属性中:

<input type="text" name="email" class="{required:true, email:true}" />

这段代码中的类在圆括号中包含了JavaScript文本,语法与在代码中通过 rules 选项指定规则非常相似:

$("#myform").validate({
   rules: {
     name: {
        required: true,
        minlength: 2
     },
     email: {
        required: true,
        email: true
     },
     url: "url",
     comment: "required"
   }
});

nameemailurlcomment 等对象键值始终引用的是元素名称而不是ID。

注意, urlcomment 使用了简写,其中只需要一条规则。当用 minlength 等参数指定规则时不能使用这种方法。

有些规则需要在以后添加,这是第4种方法——rules插件方法:

//首先初始化验证
$("#myform").validate();
// 以后的某个时刻,添加更多的规则
$("#username").rules("add", { minlength: 2});

规则也可以这样删除:

$("#username").rules("remove", "required");

当在登录表单上实现“忘记密码”链接时,这个方法很方便:

$("#loginform").validate({
   username: "required",
   password: "required"
});
$("a#forgotPassword").click(function(e) {
   $("#password").rules("remove", "required");
   $("#loginform").submit();
   $("#password").rules("add", "required");
   return false;
});

单击事件代码从密码中删除“required”规则,试图提交表单(触发验证),并重新添加规则。这样,用户名字段仍然得到验证,如果验证失败,密码字段再次变成必填字段(在正常表单提交的情况下)。

依赖性 。字段的验证行为往往取决于单击链接之外的一些因素。使用 required 方法的参数能够处理这些情况。参数可以是一个选择器或者一个回调函数。选择器在依赖性可用简单的表达式编写的时候很有用。电子邮件字段只在时事通信复选框选中的时候才是必填的:

email: {
   required: "#newsletter:checked"
}

回调可用于任意复杂性的表达式,例如,字段依赖于多个其他字段的状态:

email: {
   required: function(element) {
     return $("#newsletter:checked").length && $("#telephone:blank");
   }
}

自定义表达式 。前一个例子使用 :blank 表达式,只选择根本没有值或者空白的元素。该插件还提供了 :filled 表达式,它和 :blank 意义相反。jQuery本身提供了 :checked ,验证插件添加了与此相反的 :unchecked。 在指定按钮或者复选框的依赖性时,这两者都很有用。

虽然也可以使用 :not 表达式获得 :filled:checked 的相反意义,但是 :blank:unchecked 使选择器更易读,从而更容易理解。

3.错误消息

和规则类似,指定各种消息也有几种方法,既可以通过代码也可以采用内联方式。内联消息从 title 属性中读取:

<input name="email" class="required email" title="A valid email address is
required" />

这将为每条规则生成一条错误消息。备选的内联方法是使用元数据插件(参见前面的“规则”小节):

<input name="email" class="{required:true, email:true, messages:{required:"Required",
email: "Not a valid email address"}}"/>

可以用这种方法指定每条规则的消息,也可以使用 messages 选项:

$("#myform").validate({
   messages: {
     email: {
        required: "Required",
        email: "Not a valid email address"
     }
   }
});

这里的键值 email 指的也是输入字段的名称而非ID,和规则的指定方法一样。

对于更动态性的场景,可以使用 rules 插件方法:

$("#myform").validate();
// 稍后
$("#email").rules("add", {
   messages: {
     email: "A valid email address, please!"
   }
});

如果使用 title 属性的替代品,同时使用常规的标题,可以禁止插件检查消息的属性:

$("#myform").validate({
   ignoreTitle: true
});

本地化 。默认的消息采用英语(除了 dateDEnumberDE 以外)。此外,该插件提供(在本书编写的时候)17种本地化信息。用法很简单:将所需的 message_xx.js 文件复制到项目中,在验证插件之后包含它们。例如,下面是瑞典语本地化消息所用的代码:

<script src="assets/jquery-latest.js"></script>
<script src="assets/jquery.validate.js"></script>
<script src="assets/messages_se.js.js"></script>

有了上述代码,“Please enter a valid email address”(请输入有效的电子邮件地址)将会变成“Ange en korrekt e-postadress”。

错误元素 。默认情况下,错误消息将插入DOM中发生错误元素的下一个节点。把错误消息当作标签元素插入,把for属性设置为验证元素的 id。 带有 for 属性使用标签利用了浏览器的特性——单击标签会将焦点设置在输入字段上。所以默认情况下,用户可以单击错误消息,将焦点移到无效字段上。

如果需要不同的元素类型,可以使用 errorElement 选项:

$("#myform").validate({
   errorElement: "em"
});

插件仍然使用 for 属性,但是浏览器提供的自动链接失效。

布局 。如果你想要自定义错误消息插入的位置, errorPlacement 选项就能派上用场。假定有一个表单,使用表格布局,第一列包含常规标签,第二列是输入字段,第三列是错误消息:

<form id="signupform" method="get" action="">
   <table>
     <tr>
        <td class="label">
          <label id="lfirstname" for="firstname">First Name</label>
        </td>
        <td class="field">
          <input id="firstname" name="firstname" type="text" value=""
maxlength="100" />
        </td>
        <td class="status"></td>
     </tr>
     <!-- more fields -->
   </table>
</form>
$("#signupform").validate({
   errorPlacement: function(error, element) {
     error.appendTo( element.parent("td").next("td") );
   }
});

另一种常见的需求是将一般的消息显示在表单上方。 errorContainer 选项有助于实现这种功能:

$("#myform").validate({
   errorContainer: "#messageBox1"
});

在这个例子中,ID为 messageBox1 的元素在表单无效的时候显示,在表单有效时隐藏。

errorContainer 选项也可以与 errorLabelContainer 选项合并使用。当指定这两个选项时,错误标签不会放在输入元素的旁边,而是添加到表单上方或者下方的一个元素中。和 errorContainerwrapper 组合使用,信息可以添加到表单上方的一个错误列表中:

<div class="container">
     <h4>There are a few problems, please see below for details.</h4>
     <ul></ul>
</div>
<form id="myform" action="">
<!-- form content -->
</form>
var container = $('div.container');
// validate the form when it is submitted
$("#myform").validate({
   errorContainer: container,
   errorLabelContainer: $("ul", container),
   wrapper: 'li'
});

4.处理提交

一旦表单有效,就必须提交它。默认情况下和任何其他的表单提交一样。要通过Ajax提交表单,可以使用 submitHandler 选项和表单插件(更多细节参见秘诀11.6):

$(".selector").validate({
   submitHandler: function(form) {
     $(form).ajaxSubmit();
   }
});

invalidHandler 回调用于在无效提交时运行代码。下面的例子显示忘记填写的字段的摘要:

$("#myform").validate({
   invalidHandler: function(e, validator) {
     var errors = validator.numberOfInvalids();
     if (errors) {
        var message = errors == 1
          ? 'You missed 1 field. It has been highlighted below'
          : 'You missed ' + errors + ' fields. They have been highlighted below';
        $("div.error span").html(message);
        $("div.error").show();
     } else {
        $("div.error").hide();
     }
   }
});

Maketo演示程序展示了这种行为(http://jquery-cookbook.com/go/plugin-validation-marketo-demo)。

5.局限性

那么,不使用插件而从头开始编写一个验证解决方案在什么时候有意义呢?插件有一些局限性:有些表单中的成组输入字段(如复选框)有不同的 name 属性,难以作为整体来验证。有相同名称的一系列输入字段也无法验证,因为每个单独的输入字段都需要有独特的名称。如果你坚持对于输入字段采用唯一名称的命名约定,对一组复选框或者单选钮只使用一个名称,插件就能工作得很好。

如果应用程序只有一个登录表单,使用插件可能就有些小题大做了,从文件尺寸上也不合理;但是,如果将插件用于网站的其他地方,它也就可以用在登录表单上。