實現跨瀏覽器html5表單驗證

shiyan0827 8年前發布 | 13K 次閱讀 HTML5 前端技術

來自: http://www.cnblogs.com/yincheng/p/html5-form.html

html5表單添加了很多類型的表單,而且還自帶驗證的功能。在移動端,手機等設備能夠根據不同的input類型彈出不同的鍵盤,例如iphone彈的鍵盤

<input type="mail">

<input type="number">

<input type="tel">

iphone彈不同類型的鍵盤,方便輸入

</div>

但是由于不同的瀏覽器對不合法輸入提示文案不一致,樣式也不一樣,并且老的瀏覽器不兼容(IE9及以下),導致了在生產環境中比較少見到。例如對于郵箱格式的檢驗,不同瀏覽器的效果如下:

Chrome

Firefox

IE

safari

html5的表單跨瀏覽器有很大的問題

</div>

具體來說存在三個問題:

(1) 輸入框blur的時候不會觸發檢查,只有在點提交時才觸發,但是一般是希望用戶一旦離開這個輸入框就對其輸入進行檢查

(2)  提示控件的UI差異很大,safari還不會觸發提示控件,一些瀏覽器如IE會給非法的輸入框添加一個紅色的邊框

(3) 文案是寫死的,并且不同瀏覽器的文案不一致,其中應該以Chrome的提示最好

一、跨瀏覽器的表單驗證插件

為解決這些問題,網上有一些插件,如 html5 Form ,做了跨瀏覽器的處理,但是使用起來效果并不是十分讓人滿意,html5 Form在safari下面就失效了。在多方查找和嘗試未果之下,筆者自已寫了一個跨瀏覽器的表單檢測插件,效果如下:

Chrome

Firefox

IE

safari

插件效果示例:解決跨瀏覽器問題

</div>

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("表單驗證成功,準備提交"); //提交操作 }</pre>

執行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; }</pre>

如上所示,添加了一個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(); } }); }</pre>

在回調函數里面傳進兩個參數,如果檢驗失敗則執行第一個參數,成功則執行第二個參數,為插件所用。

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){

}</pre>

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

</div>

 本文由用戶 shiyan0827 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!