8.7 综合案例:设计表单验证

表单验证在网页设计中经常用到,为了方便读者学习和开发需要,本节将通过一个综合实例演示如何使用正则表达式设计一个表单验证工具Validator。本节实例会涉及后面几章有关面向对象的知识,读者可根据实际情况有选择地学习。

Validator是基于JavaScript的伪静态类和对象的自定义属性,可以对网页中的表单项输入进行相应的验证,允许同一页面中同时验证多个表单,熟悉接口代码之后也可以对特定的表单项,甚至仅是某个字符串进行验证。因为是伪静态类,所以在调用时不需要实例化,直接以“类名+语法+属性或方法名”来调用。此外,Validator还提供3种不同的错误提示模式,以满足不同的需要。

【操作步骤】

第1步,新建文档,保存为index.html。在页面中新建一个表格,设计一个表单框,其中包含多个输入文本框,如图8-1所示。

图8-1 设计表单

第2步,在<body>标签底部插入一个<script type="text/javascript">标签,在其中设计Validator类表单验证脚本。

第3步,在脚本中新建全局对象Validator,在其中定义多个属性值为正则表达式的成员。

      Validator = {
          Require: /.+/,                                //是否为空
          Email: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/, //Email地址
          Phone : /^((\(\d{2,3}\))|(\d{3}\-))? (\(0\d{2,3}\)|0\d{2,3}-)? [1-9]\d{6,7}(\-\d{1,4})? $/, //电话号码
          Mobile: /^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$/, //手机号码
          Url: /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\? %\-&_~`@[\]\':+! ]*([^<>\"\"])*$/, // 使用HTTP协议的网址
          Currency: /^\d+(\.\d+)? $/,                    //货币
          Number: /^\d+$/,                               //数字
          Zip: /^[1-9]\d{5}$/,                           //邮政编码
          QQ: /^[1-9]\d{4,8}$/,                          //QQ号码
          Integer: /^[-\+]? \d+$/,                       //整数
          Double: /^[-\+]? \d+(\.\d+)? $/,               //实数
          English: /^[A-Za-z]+$/,                        //英文
          Chinese: /^[\u0391-\uFFE5]+$/,                 //中文
          Username: /^[a-z]\w{3, }$/i,             //用户名
          UnSafe : /^(([A-Z]*|[a-z]*|\d*|[-_\~! @#\$%\^&\*\.\(\)\[\]\{\}<>\? \\\/\'\"]*)|.{0,5})$|\s/符合安全规则的密码
      }

第4步,为Validator对象定义一个Validate()方法,该方法根据参数theForm指定的表单form,通过for循环语句获取表单中所有包含dataType属性的文本框。然后根据dataType属性值不同,分别调用第3步定义的正则表达式执行表单验证。如果通过验证,说明输入值合法,否则获取该文本框的msg属性值,并显示错误信息。

      //表单验证对象
      Validator = {
          //表单验证方法,参数theForm为需要验证的表单对象,mode指定验证错误提示方式
          Validate : function(theForm, mode) {
            var obj=theForm||event.srcElement;  //如果没有指定表单对象,则使用当前元素
            var count=obj.elements.length;      //获取表单项的个数
            this.ErrorMessage.length=1;         //初始错误信息个数为1
            this.ErrorItem.length=1;            //初始错误项目个数为1
            this.ErrorItem[0]=obj;              //把表单传递给错误信息对象
            for(var i=0; i<count; i++){         //遍历所有表单项
                with(obj.elements[i]){          //操作当前表单项
                    //获取当前表单项dataType属性值
                    var _dataType = getAttribute("dataType");
                    //如果dataType属性值非法,则跳过
                    if ( typeof (_dataType) == "object" || typeof (this[_dataType]) == "undefined")
                        continue;
                    this.ClearState(obj.elements[i]); //清除当前表单项的错误提示信息
                    //如果require属性值为false,或者输入框为空,则跳过
                    if (getAttribute("require") == "false" && value == "")
                        continue;
                    //如果dataType属性值为下列值之一时,则调用验证函数执行验证
                    switch(_dataType) {
                    case"IdCard":               //身份证
                    case"Date":                 //日期
                    case"Repeat":               //某项的重复值
                    case"Range":                //范围
                    case"Compare":              //两数的关系比较
                    case"Custom":               //自定义的正则表达式验证
                    case"Group":                //判断输入值是否在(n, m)区间
                    case"Limit":                //对于具有相同名称的单选按钮的选中判断
                    case"LimitB":               //输入字符长度限制(可按字节比较)
                    case"SafeString":           //符合安全规则的密码
                    case"Filter":               //文件上传格式过滤
                        if (! eval(this[_dataType])) {
                          this.AddError(i, getAttribute("msg"));
                        }
                        break;
                    //对于非上面所列dataType属性值,则直接使用正则表达式进行验证
                    default :
                        if (! this[_dataType].test(value)) {
                          //验证失败后,则调用AddError()函数显示错误信息
                          //获取表单项的msg属性值,并把它作为错误信息源
                          this.AddError(i, getAttribute("msg"));
                        }
                        break;
                    }
                }
            }
            //根据错误信息,以及指定的模式,显示错误信息
            if (this.ErrorMessage.length > 1) {
                mode = mode || 1;
                var errCount = this.ErrorItem.length;
                switch(mode) {
                case 2:                   //本模式是把错误项目的字体颜色设置为红色显示
                  for (var i = 1; i < errCount; i++)
                      this.ErrorItem[i].style.color = "red";
                  break;
                case 1:                   //本模式是通过弹出提示框提示错误信息
                  alert(this.ErrorMessage.join("\n"));
                  this.ErrorItem[1].focus();
                  break;
                case 3:                   //本模式是创建一个span元素,把错误信息显示在文本框后面
                  for (var i = 1; i < errCount; i++) {
                      try {
                          var span = document.createElement("SPAN");
                          span.id = "__ErrorMessagePanel";
                          span.style.color = "red";
                          this.ErrorItem[i].parentNode.appendChild(span);
                          span.innerHTML = this.ErrorMessage[i].replace(/\d+:/, "*");
                      } catch(e) {
                          alert(e.description);
                      }
                  }
                  this.ErrorItem[1].focus();
                  break;
                default :
                  alert(this.ErrorMessage.join("\n"));
                  break;
                }
                return false;
            }
            return true;
        },
      }

第5步,使用自定义属性dataType定义表单项(文本框)验证类型。在表单结构中,为每个文本框设置如下自定义属性:

      <input name="Nick" dataType="English" require="false" msg="英文名只允许英文字母">

其中自定义属性dataType用于设定表单项的输入数据验证类型,值为字符串,必填项目。该属性可选值如下:

      dataType="Require|Chinese|English|Number|Integer|Double|Email|Url|Phone|Mobile|Currency|Zip|IdCard|QQ|Date|SafeString|Repeat|Compare|Range|Limit|LimitB|Group|Custom|Filter"

可选值的验证功能说明如下。

Require:必填项。

Chinese:中文。

English:英文。

Number:数字。

Integer:整数。

Double:实数。

Email:Email地址格式。

Url:基于HTTP协议的网址格式。

Phone:电话号码格式。

Mobile:手机号码格式。

Currency:货币格式。

Zip:邮政编码。

IdCard:身份证号码。

QQ:QQ号码。

Date:日期。

SafeString:安全密码。

Repeat:重复输入。

Compare:关系比较。

Range:输入范围。

Limit:限制输入长度。

LimitB:限制输入的字节长度。

Group:验证单/多选按钮组。

Custom:自定义正则表达式验证。

Filter:设置过滤,用于限制文件上传。

提示:另外,还可以通过如下自定义属性为文本框设置特定验证需求。

accept="string",可选。设定表单项输入过滤,多用于type="file" 的上传控件,以限制允许上传的文件类型。该属性仅当dataType属性值为Filter时起作用。

max="int"。在dataType属性值为Range时必选,为Group且待验证项是多选按钮组时可选(此时默认值为1),为Limit/LimitB时可选(此时默认值为Number.MAX_VALUE的值)。当dataType属性值为Range时,用于判断输入是否在min与max的属性值之间;当dataType属性值为Group,且待验证项是多选按钮组时,用于设定多选按钮组的选中个数,判断选中个数是否在[min, max]区间;当dataType属性值为Limit时,用于验证输入的字符数是否在[min, max]区间;当dataType属性值为LimitB时,用于验证输入字符的字节数是否在[min, max]区间。

min="int"。在dataType属性值为Range时必选,为Group且待验证项是多选按钮组时可选(此时默认值为1),为Limit/LimitB时可选(此时默认值为0)。当dataType属性值为Range时,用于判断输入是否在min与max的属性值之间;当dataType属性值为Group,且待验证项是多选按钮组时,用于设定多选按钮组的选中个数,判断选中个数是否在[min, max]区间;当dataType属性值为Limit时,用于验证输入的字符数是否在[min, max]区间;当dataType属性值为LimitB时,用于验证输入字符的字节数是否在[min, max]区间。

msg="string",必选。在验证失败时要提示的出错信息。

operator="NotEqual | GreaterThan | GreaterThanEqual | LessThan | LessThanEqual | Equal"。在dataType属性值为Compare时可选(默认值为Equal)。

各选值所对应的关系操作符如下。

➢ NotEqual:不等于!=。

➢ GreaterThan:大于>。

➢ GreaterThanEqual:大于等于>=。

➢ LessThan:小于<。

➢ LessThanEqual:小于等于<=。

➢ Equal:等于=。

require="true | false",可选。用于设定表单项的验证方式。当值为false时,表单项不是必填项,但当有填写时,仍然要执行dataType属性所设定的验证方法,值为true或任何非false字符时,可省略此属性。

to="sting | int"。当dataType值为Repeat或Compare时必选。当dataType值为Repeat时,to的值为某表单项的name属性值,用于设定当前表单项的值是否与目标表单项的值一致;当dataType的值为Compare时,to的选值类型为实数,用于判断当前表单项的输入与to的值是否符合operator属性值所指定的关系。

format="ymd | dmy"。在dataType属性值为Date时可选(默认值为ymd)。用于验证输入是否为符合format属性值所指定格式的日期。符合规则的输入示例如2015-11-23、2015/11/23、15.11.23、23-11-2015等。注意,当输入的年份为2位时,如果数值小于30,将使年份看作处于21世纪,否则为20世纪。

regexp="object"。在dataType属性值为Custom时必选,用于验证输入是否符合regexp属性所指定的正则表达式。

第6步,调用Validate()方法进行验证。在提交按钮中绑定Validate()方法,代码如下:

      <input onClick="Validator.Validate(document.getElementById('demo'))" value="检验模式1" type="button">
      <input onClick="Validator.Validate(document.getElementById('demo'),2)" value="检验模式2" type="button">
      <input onClick="Validator.Validate(document.getElementById('demo'),3)" value="检验模式3" type="button">

在调用Validate()方法中,第一个参数为需要验证的表单对象,第二个参数为模式。这个模式指定要显示错误信息的方式,效果如图8-2所示。

图8-2 表单错误提示信息