2014-01-08 51 views
1
  • 以下是根據測試與Chrome 31或
  • TL; DR:如何在this fiddle作品上嘗試來的代碼提交,但不確實在this one手工調用?有沒有更好的方法來做到這一點?

在回答a question asking for a way of validating an <input type="file"> against its accept attribute(本機行爲將生成的文件對話框的工作提出默認過濾器,但它不執行),我想看看有什麼選項都是這個定製驗證融入HTML5的腳本Constraint validation如何將自定義約束驗證作爲本機驗證事件流的一部分進行調用?

API的我最初的脫脂閱讀使我覆蓋本地checkValidity方法,相信這將被默認稱爲每當瀏覽器認爲合適的驗證碼(jsFiddle):

void function enhanceFileInputTypeValidityCheck(){ 
    var inputPrototype  = document.createElement('input').constructor.prototype; 
    var nativeCheckValidity = inputPrototype.checkValidity; 

    // This is my custom validation function 
    function validateFileInputType(input){ 
     var MIMEtype = new RegExp(input.accept.replace('*', '.\*')); 

     return Array.prototype.every.call(input.files, function passesAcceptedFormat(file){ 
      return MIMEtype.test(file.type); 
     }); 
    } 

    // My attempt at getting the behaviour to happen 
    inputPrototype.checkValidity = function enhancedCheckValidity(){ 
     if(this.type === 'file' && this.accept && this.files && this.files.length){ 
      if(!validateFileInputType(this)){ 
       this.setCustomValidity('Please only submit files of type ' + this.accept); 

       return false; 
      } 
     } 

     return nativeCheckValidity.apply(this); 
    } 
}(); 

當我的條件不滿足時,這會有效增強checkValidity以返回false,並且如果它們屬於本機行爲,但setCustomValidity未按預期工作:它不會拋出任何異常,但不會顯示任何錯誤消息。關鍵是,我的return falsecheckValidity不會阻止表單提交。

後一些擺弄我結束了這個事件處理程序,這與上述最後發佈的代碼沿實現期望的目的 - 即,防止根據提交的自定義標準,並反饋給用戶(jsFiddle):

$('input').on('change input', function(event){ 
    this.checkValidity(); 
}); 

我很困惑這是怎麼發生的:根據記錄事件類型,change將執行checkValidity,但不會顯示消息;同時要提交表格確實執行我的setCustomValidity,但不會記錄事件類型:但暗示這是一個input事件,因爲這是處理程序正在監聽的唯一其他事件 - 但(這是它在真的奇怪),解除從change(這是不工作),只留下input作爲我的命令性回調觸發器doesn't prevent submission at all anymore

由於綁定到changeevent以觸發預期的行爲,因爲這兩個事件都沒有實際發生,所以我似乎仍然對將自定義驗證綁定到本機驗證流程的「正確」方式有所損失太習慣於被用於預期的用途。

解釋下列任何加分點:

  • 爲什麼在一個空的輸入調用checkValidity時不我從我的自定義驗證console.log任何反饋?
  • 爲什麼我從事件處理程序中的console.log得到任何反饋?
  • 如何執行代碼作爲change事件的回調不會觸發setCustomValidity
  • 什麼事件 - 如果不是input - 實際上是觸發我的setCustomValidity
  • 我可以在不覆蓋checkValidity的情況下生成相同的期望最終結果嗎?

回答

2

據我所知,checkValidity方法調用瀏覽器的內部驗證,而不是瀏覽器的內部驗證調用。因此,如果您覆蓋它,瀏覽器將不會注意或關心。

根據我的經驗,實現自定義有效性所需的一切就是綁定到更改事件,然後使用正確的值調用setCustomValidity。例如,

myinput.addEventListener('change', function(e) { 
    if (! myCustomValidityCheck()) 
     this.setCustomValidity('Uh oh, that didn\'t work!'); 
    else 
     this.setCustomValidity(''); 
}) 

Whimsical JSFiddle example

0

這裏是你的問題http://jsfiddle.net/trixta/E7VtD/

  1. 輸入事件的使用變化isntead的解決方案。輸入事件很好,但不適用於輸入[type = file]。
  2. 你不應該重寫checkValidity
  3. 使用setCustomValidity DOM的準備+每一個變化
  4. 使用reportValidity,如果有的話,通過單擊提交按鈕

這裏報告錯誤或模擬reportValditity是一個簡單的方法,使setCustomValidity簡單:

//setCustomValidity is stupid so we improve by adding setCustomValidityRule 
$.fn.setCustomValidityRule = function (type, rule) { 
    var testRule = function() { 
     //only if it's valid or we have set the message our own 
     if ($(this).is(':valid') || $.data(this, 'customErrorType' + type)) { 
      var message = rule(this); 
      this.setCustomValidity(message); 
      if (message) { 
       $.data(this, 'customErrorType' + type, message) 
      } else { 
       $.removeData(this, 'customErrorType' + type); 
      } 
     } 
    }; 
    return this 
    //invoke initially 
    .each(testRule) 
    //and on every change 
    .on('customchange.customerror' + type + ' change.customerror' + type, testRule); 
}; 

這裏是使當前的瀏覽器reportValidity工作的方法:

$.fn.reportValidity = function() { 
    return this.each(function() { 
     var form; 
     if (this.reportValidity) { 
      this.reportValidity(); 
     } else { 
      form = $($.prop(this, 'form')).add(this).filter('form'); 
      //checkvalidity is obtrusive sometimes so we use :invalid 
      if($(':invalid', form).length){ 
      $('<input type="submit" />') 
       .css({ 
        position: 'absolute', 
        left: '-99999px' 
       }) 
       .appendTo(form) 
       .click() 
       .remove(); 
      } 
     } 
    }); 
}; 
0

我會試着總結一下我的經驗:

  1. 自定義的驗證檢查應在用戶輸入的數據和表單的提交按鈕,點擊即可實現兩者。
  2. 您需要使用HTML5表單驗證API中的setCustomValiditycheckValidity方法。
  3. 要驗證用戶數據輸入,請在輸入字段元素中添加一個input事件偵聽器,該偵聽器在輸入字段上調用setCustomValidity。在setCustomValidity的參數中,您可以調用合適的檢查函數,如果用戶輸入有效,則返回空字符串,否則返回約束違規消息。
  4. 要驗證表單提交按鈕點擊,您需要在表單元素上調用checkValidity,並且只有在返回true時才繼續提交。

另請參閱my answer to a similar SO questiontry my example solution