48-讨论
10.11.3 讨论
这个解决方案中的验证相当简单,检查项目如下:
<input type="text">、<input type="password">和<textarea>有空格之外的某些数据。<select>元素有默认选项之外的选择。请注意,<select>元素有两类:“select-one”(单选)和 “selectmultiple”(多选)(参见本节的第二个代码段中的HTML代码和前一个代码段中的JavaScript验证)。“单选”<select>中的第一个<option>元素必须有value="",验证才能正常工作。“多选”<select>没有这种要求,因为它的<option>元素可以反选。- 对应
name组内的<input type="radio">和<input type="checkbox">至少有一个元素选中。
使用 switch(){} 语句是因为它比多条 if(){}else if(){} 语句更高效,而且允许集中处理共享验证的元素,而用 break; 语句分隔不同的组。
validateElement 对象处于全局作用域,其意图是在其他表单上重用。通过包含验证方法,它还保持了全局作用域的整齐——未来,可以为 validateElement 对象添加助手方法,而不要担心全局命名冲突。例如,可以这样实现 stripWhitespace() 方法:
var validateElement = {
stripWhitespace : function(str){
return str.replace(/\s/g,'');
},
isValid : function(element){
//... snipped code ...//
case 'text':
case 'textarea':
case 'password':
//如果文本长度在去掉空格之后为0,它就是无效的
if ( this.stripWhitespace(value).length == 0 ){ isValid = false; }
break;
//...省略的代码...//
} // 结束validateElement.isValid()
}; // 结束validateElement object对象
当显示和隐藏错误消息时,使用方括号记法调用jQuery的 .addClass() 和 .removeClass() 方法:
//用$(selector)[method]代替$(selector).method
//明智地选择正确的方法
var method = isValid ? 'removeClass' : 'addClass';
//显示错误消息[addClass]
// 隐藏错误消息[removeClass]
$('#errorMessage_' + name)[method]('showErrorMessage');
$('label[for="' + id + '"]')[method]('error');
上述代码中的方括号记法在功能上与点记法相同:
if (isValid) {
$('#errorMessage_' + name).removeClass('showErrorMessage');
$('label[for="' + id + '"]').removeClass('error');
} else {
$('#errorMessage_' + name).addClass('showErrorMessage');
$('label[for="' + id + '"]').addClass('error');
}
当进行提交验证时,点记法更加清晰易读。但是,扩展方括号记法的解决方案,可以用 change 事件(在初始验证之后)重新验证元素。这使得当用户的新答案实际上有效时可以立刻得到反馈,而不要求他们单击提交按钮。下列代码无法像预期那样工作(真正的解决方案参见下一段),但是说明了在何处 .unbind() 和 .bind() change 事件:
// 用$(selector)[method]代替$(selector).method
//明智地选择正确的方法
var method = isValid ? 'removeClass' : 'addClass';
//显示错误消息[addClass]
//显示错误消息[removeClass]
$('#errorMessage_' + name)[method]('showErrorMessage');
$('label[for="' + id + '"]')[method]('error');
//在初始验证之后,允许元素在修改后重新验证
$element
.unbind('change.isValid')
.bind('change.isValid',function(){ validateElement.isValid(this); });
注意
因为在每次验证的时候解除绑定和绑定
change事件,所以添加了.isValid事件命名空间,更加直接地针对具体的事件函数。这样,如果表单元素绑定了另一个change事件,它们将会保留。
前一段代码的问题不是语法而是逻辑。你会注意到,HTML中的单选按钮有 class="required" 属性。这意味着,当验证整个表单的时候,每个单选按钮都验证,而且(更重要的是)每个单选按钮的 <label> 添加或者删除一个类来表示错误的情况。但是,如果允许用元素专用的 change 事件进行重新验证,只有特定单选按钮的 <label> 将更新——其他都保持错误状态。为了处理这种情况, change 事件必须查看同一 name 组中的所有单选按钮和复选框,同时影响所有的 <label> 类:
// 用$(selector)[method]代替$(selector).method
// 明智地选择正确的方法
var method = isValid ? 'removeClass' : 'addClass';
// 显示错误消息[addClass]
// 显示错误消息[removeClass]
$('#errorMessage_' + name)[method]('showErrorMessage');
if ( type == 'checkbox' || type == 'radio' ) {
//如果是单选按钮或者复选框,寻找同名的所有输入字段
$('input[name="' + name + '"]').each(function(){
//更新每个输入元素的<label>标记(this==<input>)
$('label[for="' + this.id + '"]')[method]('error');
});
} else {
//其他所有元素只要更新一个<label>
$('label[for="' + id + '"]')[method]('error');
}
// 在初始验证之后,允许元素在修改后重新验证
.unbind('change.isValid')
.bind('change.isValid',function(){ validateElement.isValid(this); });
如果上述代码用点记法重写,就需要重写两倍的代码。此外,将这一新逻辑应用到合适的地方, name 组中只有一个单选按钮(或者复选框)需要有 class="required" 属性,就能使该组的其他所有元素得到正确的调整。
当禁用JavaScript的时候会发生什么情况?将提交表单而不进行客户端验证。一定要在服务器端验证代码。不要依靠JavaScript提供干净的数据。如果服务器端代码返回带有错误的表单,可以用相同方式使用相同元素上的同一个类。没有必要使用内联样式标记或者编写自定义代码对服务器端错误做出不同的处理。