表单校验
文章来源:http://www.apple.com.cn/developer/mac/library/documentation/IntelWeb/Conceptual/Webcontent/validation.html
任何可以交互的站点都会有输入表单,用户在这些表单中输入他们是谁,他们想买什么,他们住在哪里等信息。这些数据会被传递到负责后端处理的组件—Perl 的 CGI 脚本,PHP 处理引擎,诸如 Oracle 这样的数据库,或者您投资的其它技术。无论后端是什么样的系统,都不会愿意把时间浪费在一些虚假的信息上,而用户有些时候也不喜欢这样。如果用户提交给 CGI 的信息中包含错误,那么在信息通过英特网传递到服务器,在服务器上进行校验,然后向用户返回一个气人的错误信息之前,将会产生明显的延迟—一般是几秒钟。
如果在提交表单之前,对用户的输入作一些初步的正当性检查,那就不会有等待的时间了。客户端的校验是很快速的,因为这个校验不必通过网络提交任何数据。在转向其它页面之前,JavaScript 可以捕捉到用户输入的任何错误数据。
在服务器端再次对数据进行检查还是有必要的,因为有些时候用户会关掉浏览器对 JavaScript 的支持,有些用户也可能恶意地或者偶然地找到了绕开客户端检查的途径。对于大多数用户来说,基于 JavaScript 的表单校验,会在前端节省很多时间。
脚本的目的
脚本和 HTML 表单相伴出现。当用户在表单上点击 Submit(提交)按键时,表单数据就会被发送给一个 JavaScript 检查函数,这个函数会对用户输入的各个方面进行检查,以确保它们具有正确的格式。程序会根据特定的条件评价每个表单元素。如果发现某个输入域上有错误,脚本就会返回一个警告,来解释字符串应该遵守什么格式。JavaScript 中具有相当强壮的字符串处理和规则表达式技术,可以处理这些检查。
checkWholeForm()
我们把主控函数命名为 checkWholeForm(),放在含有输入表单(form)的页面上方。
function checkWholeForm(theForm) {
var why = "";
why += checkEmail(theForm.email.value);
why += checkPhone(theForm.phone.value);
why += checkPassword(theForm.password.value);
why += checkUsername(theForm.username.value);
why += isEmpty(theForm.notempty.value);
why += isDifferent(theForm.different.value);
for (i=0, n=theForm.radios.length; i<n; i++) {
if (theForm.radios[i].checked) {
var checkvalue = theForm.radios[i].value;
break;
}
}
why += checkRadio(checkvalue);
why += checkDropdown(theForm.choose.selectedIndex);
if (why != "") {
alert(why);
return false;
}
return true;
}
这个函数调用了一系列子函数,每个子函数负责对表单中的某一个元素进行检查,确认其是否遵循特定的字符串格式,并返回一个错误描述信息。如果子函数返回了空字符串,就表示它对应的元素是符合格式约束的。
checkUsername()
这个函数用来检查用户是否在 username(用户名)输入域上输入了字符(我们将使用同样的函数对每个表单输入域进行空白检查)。
function checkUsername (strng) {
var error = "";
if (strng == "") {
error = "You didn't enter a username.\n";
}
我们把 username 域的值传递给该函数,该函数则把这个值和空字符串("")作比较。如果这两个值一样,我们就可以确认 username 域为空,并向主控函数返回警告信息。如果这个域不为空,我们就转向下一个“障碍”。我们只允许用户输入4到10个字符(不包含4和10)的用户名,因此需要检查该字符串的长度,并在该长度太长或者太短时拒绝输入。
if ((strng.length < 4) || (strng.length > 10)) {
error = "The username is the wrong length.\n";
}
下一步,我们希望禁止一些特定的字符,使之不能出现在用户名字符串上。具体地说,我们只允许出现字母,数字,还有下划线。我们可以使用正则表达式和 test() 方法来进行这种检查。在 JavaScript 1.2 中提供的规则表达式函数和 Perl 的正则表达式相类似,只是在语法上作了一点简化。如果您了解 Perl,则对掌握 JavaScript 的规则表达式就不会有任何障碍。在 JavaScript 中,规则表达式/\W/是一个为了方便而预定义的标准字符集,表示“除了字母,数字,和下划线的任何字符”。因此我们把 illegalChars 变量的值设定为这个正则表达式,然后用这个变量对 username 字符串进行检测,看是否可以找到匹配的字符串,如果找到了这种字符串,我们就扔出一个警告信息。
var illegalChars = /\W/;
// allow only letters, numbers, and underscores
if (illegalChars.test(strng)) {
error = "The username contains illegal characters.\n";
}
到此为止,我们对 username 进行三道检查。如果全部通过这三道检查,则这个输入就 OK 了。我们就把 username 的级别设定为通过,然后转向下一个输入域。
checkPassword()
对于密码输入域,我们一样希望限制其长度(这回我们使它的长度保持在6到8个字符之间),并且只允许字符和数字—这次不允许下划线了。因此我们必须使用一个新的规则表达式来定义我们禁止的字符。这个表达式和前一个表达式一样,包含\W —即除了字母,数字,和下划线之外的所有字符,但是我们需要显式说明下划线,以便把输入限制在字母和数字中。因此,我们使用:/[\W_]/。
function checkPassword (strng) {
var error = "";
if (strng == "") {
error = "You didn't enter a password.\n";
}
var illegalChars = /[\W_]/; // allow only letters and numbers
if ((strng.length < 6) || (strng.length > 8)) {
error = "The password is the wrong length.\n";
}
else if (illegalChars.test(strng)) {
error = "The password contains illegal characters.\n";
}
对于密码的本身,我们希望对用户严格一些,这也是为用户自身的利益着想。我们不希望他们选择容易被入侵者猜到的密码,比如字典上的一个词,或者小孩的生日。因此我们希望每个密码都由大小写的字母混合而成,并且最少有一个数字。我们用三个规则表达式来描述这些规则:a-z, A-Z,和0-9,每个规则表达式后面跟着一个+号,表示“一个或者多个”,并且用 search() 方法来确保密码字符串中存在相应的字符:
else if (!((strng.search(/(a-z)+/))
&& (strng.search(/(A-Z)+/))
&& (strng.search(/(0-9)+/)))) {
error = "The password must contain at least one
uppercase letter, one lowercase letter,
and one numeral.\n";
}
checkEmail()
下面我们希望看看用户输入的电子邮件地址是否真实。完成这个任务最有效的办法是看看用户自己声称来自哪里,然后通过网络向相应的域询问这个人是否真的有账户。但是这样会使运行这个检查程序的机器付出很大的代价—而且用 JavaScript 无论如何也不能实现这个功能。通过 JavaScript,我们可以检查用户输入的字符串看起来是否象一个电子邮件地址。我们希望这个字符串遵循如下的格式:一些字符,然后是一个at符号(@),接着又是一些字符,然后是一个点(.),还有两个或者三个字符串,就这些。这种方法并不是完美的—可能会有一些假的,不遵循RFC的地址逃过这种检查—但是通常情况下,这就足够了。如果输入的电子邮件地址没有和这种模式相匹配,我们就拒绝这个输入。
描述上述格式的规则表达式如下所示:/^.+@.+\..{2,3}$/。其中克拉符号(^)表示字符串的开始,而美元符号($)表示字符串的结束。用这些符号把剩下的规则表达式包围起来,我们可以保证程序对整个字符串进行匹配,而不只是其中的一部分。每一个 .+ 符号表示“最少有一个字符”—点(.)表示“任何字符”,后面接一个加号(+),您可能还记得,表示“一个或多个”。.{2,3}部分表示“两个或者三个字符”。如果您希望匹配一个点,则需要用反斜杠来进行转义。这就是我们使用\.的原因。
var emailFilter=/^.+@.+\..{2,3}$/;
if (!(emailFilter.test(strng))) {
error = "Please enter a valid email address.\n";
}
同样地,我们希望通过检查确保输入的字符串中没有禁用的字符。对于电子邮件地址,我们禁用下面这些字符:( ) < > [ ] , ; : \ / "
var illegalChars= /[\(\)\<\>\,\;\:\\\/\"\[\]]/
if (strng.match(illegalChars)) {
error = "The email address contains illegal characters.\n";
}
checkPhone()
在检查电话号码时,我们首先希望清除输入字符串中的间隔字符,比如括号,横杠,和点。我们可以通过规则表达式和 replace() 函数将输入字符串中的匹配字符代替为 null 字符串,从而实现这个目的。在做完这个检查之后,我们把结果传递给 isNaN() 函数(检查一个给定的输入是否不为一个数字),检测经过上述处理后的输入字符串是否为一个整数。如果它包含除了数字外的其它字符,我们就拒绝这个输入。
var stripped = strng.replace(/[\(\)\.\-\ ]/g, '');
//strip out acceptable non-numeric characters
if (isNaN(parseInt(stripped))) {
error = "The phone number contains illegal characters.";
}
然后我们计算一下这个数字的长度,它应该正好是10位—多了或者少了,我们都要拒绝它。
if (!(stripped.length == 10)) {
error = "The phone number is the wrong length.
Make sure you included an area code.\n";
}
isDifferent()
我们还希望多做一些检查。如果您在文本输入框中向用户提供一个许可证,看用户是否接受,则您会希望确认,在提交表单时,许可证的内容没有被改变。这可以通过简单地对用户提交的字符串和您期望的字符串进行比较来实现。
function isDifferent(strng) {
var error = "";
if (strng != "Can\'t touch this!") {
error = "You altered the inviolate text area.\n";
}
还有一种方法,您可以使用 onChange() 方法来捕捉用户修改文本的动作,并在提交表单之前阻止他们。
checkRadio()
为了确定用户是否对收音机按钮做出选择,我们可以遍历收音机按钮的数组,并对被选中的按钮进行记数。我们并没有把整个收音机按钮对象传递给子函数,这样可能会带来问题(因为收音机对象中并没有属性指出哪个值被选中),而是在一个 for 循环中对收音机表单元素进行预处理,然后把结果传递给一个子函数进行评价。
for (i=0, n=theForm.radios.length; i<n; i++) {
if (theForm.radios[i].checked) {
var checkvalue = theForm.radios[i].value;
break;
}
}
why += checkRadio(checkvalue);
function checkRadio(checkvalue) {
var error = "";
if (!(checkvalue)) {
error = "Please check a radio button.\n";
}
return error;
}
check Dropdown()
最后,我们希望确认用户是否在我们提供的下拉式菜单中选择了一个选项(不是第一个选项,它根本不是一个选项,而只是一个“请选择一项”的说明)。为了实现这个目的,我们使用选择对象的 selectedIndex 属性,它返回被选择选项的索引。如果这个索引为0,我们就拒绝这个输入。
function checkDropdown(choice) {
var error = "";
if (choice == 0) {
error = "You didn't choose an option
from the drop-down list.\n";
}
return error;
}
编码的挑战
正当性检查基本上是考虑把一个事物和另一个事物进行比较,这是很容易的,特别是当使用 JavaScript 的时候。需要一点机智的部分是创建一个规则表达式。表达式越复杂,就越难于书写。然而通过一些实践和摸索之后,规则表达式的书写也可以成为一种习惯。
在进行正当性检查时,也会有一些比我们在这里讨论的更加复杂的规则。比如,您可能希望检查一个信用卡号。有一个名为 Luhn modulus-10 方程的算法,可以检查给定信用卡号的正确性。碰到这种问题时,没有必要重新发明轮子了,可以从 brainjar.com 站点上抓取一个简单的脚本,或者从 JavaScript Source 上获得复杂一些的脚本。
使用这些脚本
上述所有的函数都包含在一个名为 validate.js 文件中,可以用表单页面上部的 SCRIPT 标识的 SRC 属性来调用。或者如果您愿意的话,可以把这个文件的内容粘贴到您自己的 HTML 页面的顶部。如果你喜欢,可以通过 onBlur() 这个事件处理函数,在用户移向下一个元素时检查表单上的每一个元素,而不使用 onSubmit() 函数。和我们一贯的做法一样,请记住在后端也要检查重要的表单数据,因为绝大部分的客户端检查都可能被欺骗。

浙公网安备 33010602011771号