JavaScript实战-JavaScript、jQuery、HTML5、Node.js实例大全(第2版)
上QQ阅读APP看书,第一时间看更新

2.2 处理各种类型的表单元素

表单(Form)是在HTML1.0草案时代就被支持的古老概念,因为HTML没有1.0版,所以表单元素最早在HTML2.0中被规范,这么古老的对象至今依然被广泛使用,这就证明其意义所在。

2.2.1 input、textarea、hidden和button

随着网站的发展,需求会不断发生变化,比如要在【范例2-4】基础上增加“简介”字段,可以为空,但是最长不超过60个字符,同时要统计一下,用户输入错误的次数,输入超过3次,就锁定“注册”按钮,然后要“解锁”才能重新使用,根据业务需求基于【范例2-4】增加的代码如【范例2-5】所示。

【范例2-5 处理各种类型的表单一】

    1.   <! DOCTYPE html>
    2.   <html>
    3.    <head>
    4.     <title>处理各种类型的表单一</title>
    5.    </head>
    6.    <body>
    7.       <form method="post" action="" onsubmit="return eg.regCheck(); ">
    8.                <input type="hidden" name="" id="errnum" value="0"/>
    9.              账户:<input type="text" name="" id="userid" /><br /><br />
    10.             密码:<input type="password" name="" id="userpwd" /><br /><br />
    11.             确认:<input type="password" name="" id="userpwd2" /><br /><br />
    12.             简介:<textarea name="" rows="4" cols="18" id="about"></textarea>
                      <br /><br />
    13.             <input  type="submit"  value=" 注 册 "  id="regBtn"  />  <input  type=
                  "button" value="解锁" onclick="eg.unlock()" style="display:none; "
                  id="regUnlock" />
    14.     </form>
    15.     <script>
    16.               var eg = {};
                  //声明一个对象,当作命名空间来使用,本书默认的范例都会以此来方便管理
    17.             //定义一个公共函数来获取指定id 元素,减少代码量,提高代码复用率
    18.               eg.$ = function(id){
    19.                         return document.getElementById(id);
    20.               };
    21.             //主要的验证方法
    22.               eg.regCheck = function(){
    23.                         var uid = eg.$("userid");
    24.                         var upwd = eg.$("userpwd");
    25.                         var upwd2 = eg.$("userpwd2");
    26.                     if(uid.value == ''){//value 是元素自带属性
    27.                             alert(’账户不能为空!');
    28.                                  eg.err();
    29.                                  return false;
    30.                         }
    31.                         if(upwd.value == ''){
    32.                             alert(’密码不能为空!');
    33.                                  eg.err();
    34.                                  return false;
    35.                         }
    36.                         if(upwd.value ! = upwd2.value){
    37.                             alert(’两次密码输入不相同!');
    38.                                  eg.err();
    39.                                  return false;
    40.                         }
    41.                     //新增的部分
    42.                         var about = eg.$("about");
    43.                     if(about.value.length>60){ //value 是字符串类型的属性
    44.                             alert(’简介太长!');
    45.                                  eg.err();
    46.                                  return false;
    47.                         }
    48.                     return true;                  //返回true 就会提交表单form
    49.               };
    50.             //出错时记录错误次数
    51.               eg.err = function(){
    52.                         var el = eg.$("errnum");
    53.                         var old = el.value;
    54.                         el.value = parseInt(old)+1;
                          //把字符串转换为整数+1,并保存起来
    55.                     eg.lock();                             //用来检查是否应该锁定
    56.               };
    57.             //通过次数判断是否要锁定注册
    58.               eg.lock = function(){
    59.                         var err = eg.$("errnum");
    60.                         if(parseInt(err.value)>2){
    61.                                  eg.$("regBtn").disabled = true;
                                //根据业务需求,输错3 次就锁定
    62.                                  eg.$("regUnlock").style.display="block";
                                  //同时显示解锁按钮
    63.                         }
    64.               };
    65.             //解锁
    66.               eg.unlock = function(){
    67.                         eg.$("regBtn").disabled = false;
                        //根据业务需求,解锁就是让用户可以重新注册
    68.                         eg.$("regUnlock").style.display="none";
                          //元素所有样式都挂载到style 属性下
    69.               }
    70.     </script>
    71.   </body>
    72. </html>

从【范例2-5】的代码可看出,以前直接提示错误信息就行了,现在还要做错误统计,这些统计数据非常有用,可以为后台系统保存起来用于分析用户的错误率,甚至可以分析出用户一般会在哪些字段上出错。记录错误信息的数据不需要给用户看到,可以选择input的type属性是hidden的元素来存储。用户第3次注册出错时的界面如图2-5所示。

图2-5 【范例2-5】用户第3次注册失败的效果图

2.2.2 checkbox、radio和select

永远别期待自己写的代码会运行很久,就算没有bug,需求也总是在变化的。

例如,有人告诉你【范例2-5】收集的信息太少了,需要知道用户“性别”,还需要知道用户“年龄”段,然后还要选择兴趣爱好,最好是让用户必须选择一个。这些需求都必须实现,最终的代码见【范例2-6】。

【范例2-6 处理各种类型的表单二】

    1.   <! DOCTYPE html>
    2.   <html>
    3.    <head>
    4.     <title>处理各种类型的表单二</title>
    5.    </head>
    6.    <body>
    7.       <form method="POST" onSubmit="return eg.regCheck(); ">
    8.                <input type="hidden" name="" id="errnum" value="0"/>
    9.              账户:<input type="text" name="" id="userid" /><br /><br />
    10.             密码:<input type="password" name="" id="userpwd" /><br /><br />
    11.             确认:<input type="password" name="" id="userpwd2" /><br /><br />
    12.             性别:<input type="radio" name="sex" value="1" checked="checked"/>
                    男 <input type="radio" name="sex" value="0"/>女 <br /><br />
    13.             年龄:<select name="" id="age">
    14.                     <option value="0"  selected="selected">请选择年龄段</option>
    15.                     <option value="1">18 岁以下</option>
    16.                     <option value="2">18-24 岁</option>
    17.                     <option value="3">24-30 岁</option>
    18.                     <option value="4">30-35 岁</option>
    19.                     <option value="5">35 岁以上</option>
    20.               </select><br/><br/>
    21.             爱好:<input type="checkbox" name="like" value="1" class="like"/>
                  上网 <input type="checkbox" name="like" value="2" class="like"/>
                  逛街<input type="checkbox" name="like" value="3" class="like"/>
                  看电影  <input type="checkbox" name="like" value="4"class="like"/>
                  其他 <br/><br/>
    22.             简介:<textarea name="" rows="4" cols="18" id="about"></textarea>
                  <br/><br/>
    23.             <input type="submit" value="注册" id="regBtn" /> <input type=
                  "button" value="解锁" onclick="eg.unlock()" style="display:none; "
                  id="regUnlock" />
    24.     </form>
    25.     <script>
    26.               var eg = {};
                  //声明一个对象,当作命名空间来使用,本书默认的范例都会以此来方便管理
    27.             //定义一个公共函数来获取指定id 元素,减少代码量,提高代码复用率
    28.               eg.$ = function(id){
    29.                         return document.getElementById(id);
    30.               };
    31.             //主要的验证方法
    32.               eg.regCheck = function(){
    33.                         var uid = eg.$("userid");
    34.                         var upwd = eg.$("userpwd");
    35.                         var upwd2 = eg.$("userpwd2");
    36.                         if(uid.value == ''){
    37.                             alert(’账户不能为空!');
    38.                                  eg.err();
    39.                                  return false;
    40.                         }
    41.                         if(upwd.value == ''){
    42.                             alert(’密码不能为空!');
    43.                                  eg.err();
    44.                                  return false;
    45.                         }
    46.                         if(upwd.value ! = upwd2.value){
    47.                             alert(’两次密码输入不相同!');
    48.                                  eg.err();
    49.                                  return false;
    50.                         }
    51.                     //新增的部分
    52.                         var about = eg.$("about");
    53.                         if(about.value.length>60){
    54.                             alert(’简介太长!');
    55.                                  eg.err();
    56.                                  return false;
    57.                         }
    58.                     //第二次新增的部分
    59.                     var age = eg.$("age");              //下拉选项框
    60.                         if(age.value == "0"){
    61.                             alert(’请选择年龄段!');
    62.                                  eg.err();
    63.                                  return false;
    64.                         }
    65.
    66.                         var likes = document.getElementsByClassName("like");
    67.                         var likeNum = 0;
    68.                         for(var n=0; n<likes.length; n++){
    69.                                  if(likes[n].checked){
    70.                                            likeNum++;
    71.                                  }
    72.                         }
    73.                         if(likeNum==0){
    74.                             alert(’请至少选择一个爱好!');
    75.                                  eg.err();
    76.                                  return false;
    77.                         }
    78.                         return true;
                                        //返回true 就会提交表单form
    79.               };
    80.             //出错时记录错误次数
    81.               eg.err = function(){
    82.                         var el = eg.$("errnum");
    83.                         var old = el.value;
    84.                         el.value = parseInt(old)+1;
                        //把字符串转换为整数+1,并保存起来
    85.                     eg.lock();                             //用来检查是否应该锁定
    86.               };
    87.             //通过次数判断是否要锁定注册
    88.               eg.lock = function(){
    89.                         var err = eg.$("errnum");
    90.                         if(parseInt(err.value)>2){
    91.                                  eg.$("regBtn").disabled = true;
                                //根据业务需求,输错3 次就锁定
    92.                                  eg.$("regUnlock").style.display="block";
                                //同时显示解锁按钮
    93.                         }
    94.               };
    95.             //解锁
    96.               eg.unlock = function(){
    97.                         eg.$("regBtn").disabled = false;
                            //根据业务需求,解锁就是让用户可以重新注册
        98.                         eg.$("regUnlock").style.display="none";
        99.               }
        100.              </script>
        101.     </body>
        102.    </html>

最让人痛苦的事情是好不容易写好代码,用Firefox调试一切正常,提交测试部门进行测试。这代码怎么不兼容IE 6、IE 7呢?

看看在IE 6下到底是怎么回事呢?图2-6不容易看到,在运行时它会一闪而过,也无任何提示,这也是未达到预期验证效果的原因。

图2-6 IE 6下报错信息

在IE 6下document不支持getElementsByClassName方法,怎么办呢?那就得写一套兼容的代码放到eg.regCheck方法前,见【范例2-7】。

【范例2-7 兼容各浏览器的获取指定class名称元素集合的方法】

    1.      //定义一个公共函数来获取指定class 名称的元素集合,能兼容各个浏览器
    2.       eg.getElementsByClassName = function(className, element) {
    3.              if(document.getElementsByClassName){     //如果浏览器支持,直接返回
    4.                          return(element||document).getElementsByClassName(className);
    5.                }
    6.                var children = (element || document).getElementsByTagName('*');
                  //使用通配符
    7.                var elements = new Array();
    8.
    9.                for (var i = 0; i < children.length; i++) {
    10.                         var child = children[i];
    11.                         var classNames = child.className.split(' ');
                          //分割多个class 样式
    12.                         for (var j = 0; j < classNames.length; j++) {
    13.                                  if (classNames[j] == className) {
    14.                                            elements.push(child);
    15.                                            break;
    16.                                  }
    17.                         }
    18.               }
    19.               return elements;
    20.     };

【范例2-6】原66行也要改为:

          var likes = eg.getElementsByClassName("like");

再次运行后,终于在IE 6中得到了预期的验证效果,如图2-7所示。

图2-7 预期的验证效果

兼容性是令人头疼的历史遗留问题,因此jQuery这类框架才会应运而生,jQuery相关信息可以参看第四篇中的内容,jQuery从2版本开始也放弃了对IE 6的兼容问题,因为目前已经很少有人再使用IE 6,所以本书后面也会更少提及这类兼容问题。