你的位置:首页 > 网页设计

[网页设计]实现跨浏览器html5表单验证


      html5表单添加了很多类型的表单,而且还自带验证的功能。在移动端,手机等设备能够根据不同的input类型弹出不同的键盘,例如iphone弹的键盘

<input type="mail">


<input type="number">


<input type="tel">


iphone弹不同类型的键盘,方便输入


      但是由于不同的浏览器对不合法输入提示文案不一致,样式也不一样,并且老的浏览器不兼容(IE9及以下),导致了在生产环境中比较少见到。例如对于邮箱格式的检验,不同浏览器的效果如下:

Chrome


Firefox


IE


safari


html5的表单跨浏览器有很大的问题


    具体来说存在三个问题:

    (1) 输入框blur的时候不会触发检查,只有在点提交时才触发,但是一般是希望用户一旦离开这个输入框就对其输入进行检查

    (2)  提示控件的UI差异很大,safari还不会触发提示控件,一些浏览器如IE会给非法的输入框添加一个红色的边框

    (3) 文案是写死的,并且不同浏览器的文案不一致,其中应该以Chrome的提示最好
   

一、跨浏览器的表单验证插件

    为解决这些问题,网上有一些插件,如html5 Form,做了跨浏览器的处理,但是使用起来效果并不是十分让人满意,html5 Form在safari下面就失效了。在多方查找和尝试未果之下,笔者自已写了一个跨浏览器的表单检测插件,效果如下:

Chrome


Firefox


IE


safari


插件效果示例:解决跨浏览器问题


1. 统一UI

      这个插件解决了上面的问题,首先是统一了UI,模拟了Chrome的提示效果,UI的样式和显示位置都是一致的,并且可以自定义。对于文案问题提供了是否使用浏览器默认文案的选项,因为考虑到有些浏览器如Chrome的提示比较智能,例如上面的邮箱文案,如果不使用则自定义文案。

2. 支持异步验证

另外一个强大的功能是支持异步验证,如验证用户名是否存在:

插件支持异步验证


3. 支持多重类型规则验证

      还有,支持不同类型的规则验证,如必填/格式/自定义,例如对电话号码的验证有两个要求,一个是必填,另外一个是符合电话号码的格式:

支持不同规则类型的验证


4. 能够中英文切换

    还考虑到了双语站中英文切换的问题:

支持中英文切换


二、插件使用方法

1. 最简单的使用

      插件已经上传到github,里面包含了一个demo,demo的效果如下:

        form的html结构:

 1   <form class="sign-up"> 2     <label>邮箱地址</label> 3     <input type="email" name="account" t="email" required=""> 4     <label>密码</label> 5     <input type="password" name="password" pattern=".{6,20}" pm="密码要在6到20位之间" required=""> 6     <label>确认密码</label> 7     <input type="password" name="confirm-pwd"> 8     <input id="confirm-sign" type="submit" value="注册"> 9     <p></p>10   </form>

     上面第3行,定义了input的type="email",还要再写多一个t="email"主要是因为IE10以下的浏览器会把不认识的type强制改成text。

     无关的CSS略。有了上面的html结构之后,只需要初始化插件就可以了

new Form($(".sign-up")[0], {  errorMsgClass: "error",     //错误提示框的类名,用于自定义样式  errorInputClass: "invalid",   //input无效的类名,用于自定义样式}, submit);function submit(){  console.log("表单验证成功,准备提交");  //提交操作 }

      执行new From的时候传了3个参数,第一个是form的DOM元素,第二个参数是验证规则的一些配置,第三是验证成功的回调函数。对应如下:

var Form = function(form, checkOpt, submitCallback){    //...}

     第二个参数checkOpt有两个属性errorMsgClass和errorInputClass用来自定义样式。

     最简单的初始化,能够实现required属性、pattern属性和类型检验生效。pattern使用正则表达式,其错误提示信息放在pm属性里,如上面的 pm="密码要在6到20位之间" 。

2. 添加自定义检验

     上面的密码需要保证两次的输入一致,在checkOpt里面添加自定义验证:

 checkOpt.rule = {     "confirm-pwd": {         check: checkPwdIdentity,  //自定义检验函数         msg: "两次密码输入不一致"   //出错提示信息     } }     function checkPwdIdentity(){     if(this.form["password"].value !== this.form["confirm-pwd"].value){       return false;     }     return true; }

      如上所示,添加了一个rule属性,key值为input的name属性,value值包含一个自定义的检验函数和出错信息

3. 自定义异步检验

     有些数据需要向服务请求检验,如检验账户是否存在

checkOpt.rule.account = {    check: checkAccountExist,    msg: "账户已存在!",    async: true             //标志位,说明是异步的检验};function checkAccountExist(failCallback, successCallback){    var input = this;    util.ajax("/register/hasUser", {account: this.value}, function(data){      //如果用户存在则调用failCallback,让插件添加一个错误提示      if(data.isUser === true){        failCallback();      }      //成功则调用成功的回调函数      else{        successCallback();      }    });  }

      在回调函数里面传进两个参数,如果检验失败则执行第一个参数,成功则执行第二个参数,为插件所用。

4. 添加自定义类型出错提示

      Form已经提供了一套默认类型出错提示:

Form.prototype.validationMessage_cn = {  email: '无效的邮箱格式',  number: '无效的数字格式',  url: '无效的网址格式',  password: '格式无效',  text: '格式无效'};

      你也可以自定义一个,将上面的文案换掉即可,暂时没有提供参数

      另外可以取消掉浏览器提供的文案,用上面的默认文案

//如果浏览器的语言不是中文的话,就不要使用英文的文案了,双语站时候适用checkOpt.disableBrowserMsg = !(navigator.language || navigator.userLanguage).match(/cn/i)

      还可以指定Form使用的语言:

//双语站切换时适用checkOpt.lang = "cn"; //或者en

 

三、插件源码解析

      插件的代码并不是很复杂,只是需要考虑很多细节。

1. 为非html5浏览器添加checkValidity函数

      如果没有checkValidity函数的话就给它添加一个,核心代码见Github,这里不进行详细说明。

  var input = document.createElement("input");  if(!input.checkValidity){    HTMLInputElement.prototype.checkValidity = function(){        //详细代码见github    }  }

 

2. 添加错误提示

      重点是计算提示显示的位置,

Form.prototype.addErrorMsg = function(input, msg){}

 

3. 异步检验的实现

      异步检验难点在于,什么时候执行submit回调。解决方案是给每个input添加一个hasCheck属性,如果检查通过则设置为true,一旦focus了就设为false,blur则触发检查。只有所有的input都有了hasCheck为true时才能执行submit回调。下面的checkAsync的第二个参数,点提交时设置成true,而blur验证则为false

 1 Form.prototype.checkAsync = function(input, doesSubmit){ 2   name = input.name; 3   var rule = input.form.Form.checkOpt.rule; 4   rule[name]["check"].call(input,  5   //检验失败回调函数 6   function(){ 7     var Form = input.form.Form; 8     Form.addErrorMsg(input, Form.checkOpt.rule[name].msg); 9   },10   //检验成功回调函数 11   function(){12     input.hasCheck = true;13     if(doesSubmit){14       input.form.Form.tryCallSubmit(input);15     }16   });17 };

      代码的第14行检查除submit外所有的input是否为hasCheck为true,如果有则执行submit callback。

     

      现在这个Form插件只支持text/password/url/email/number这几种input,应该可以满足大部份的表单提交,如果需要,可再继续完善。

 

参考:

1. Making HTML5 Form backwards compatible

2. Building HTML5 Form Validation Bubble Replacements




深圳到爱尔兰旅游深圳去爱尔兰旅游报价深圳到比利时旅游深圳去比利时旅游报价深圳到法国旅游看霾前霾后的津城美景对比照 走进天然的油画世界 新疆五彩滩 西安钟鼓楼的前世今生 晨钟暮鼓的由来 渔港古镇 石浦自驾游攻略(组图) 2015长江水世界中秋节活动?中山长江水世界中秋节门票多少钱? 深圳观澜水上乐园报价多少?观澜水上乐园优惠票怎么买? 深圳观澜水上乐园最新票价?观澜水上乐园要涨价了吗? 观澜水上乐园营业时间?深圳观澜水上乐园9月还有吗? 惠州有什么民风民俗呢? 惠州南昆山有什么好玩的地方?南昆山怎么样 2015年五一假期惠州巽寮湾的烧烤场会不会没位呀? 广州上下九该怎么去? 2015-2015浙江卫视广州跨年演唱会节目单?奔跑吧兄弟跨年演唱会门票预定? 2015-2015浙江卫视跨年演唱会明星有谁?奔跑吧兄弟跨年演唱会在哪里举办? 2015-2015浙江卫视广州跨年演唱会时间?广州跨年演唱会明星名单? 2015圣诞节深圳欢乐谷免费了是真的吗?欢乐谷圣诞节免门票了? LP3891EMRX-1.8 Datasheet LP3891EMRX-1.8 Datasheet LM3674MFX-1.5/NOPB Datasheet LM3674MFX-1.5/NOPB Datasheet LP3891ESX-1.2/NOPB Datasheet LP3891ESX-1.2/NOPB Datasheet 自驾游注意事项 自驾游注意事项 自驾游注意事项 马尔代夫游记 马尔代夫游记 马尔代夫游记 慕尼黑时间 慕尼黑时间 慕尼黑时间