2012-09-25 61 views
37

我想爲接受日期的文本輸入字段實現掩碼。屏蔽值應直接顯示在輸入內部。如何實現帶有掩碼的輸入

事情是這樣的:

<input type='text' value='____/__/__'> 

我寫的屏蔽,這個例子的值,但我的目的是讓人們寫的日期,而無需輸入/-分隔月,年和天數。用戶應該能夠在顯示的字段中輸入數字,而掩碼在用戶輸入時自動執行格式。

我在其他網站上看到過這種行爲,但我不知道它是如何工作的或如何自己實現它。

回答

28

輸入掩碼可使用keyup事件的組合來實現,並且HTMLInputElementvalueselectionStart,和selectionEnd性質。這是一個非常簡單的實現,它可以完成一些你想要的功能。這當然不是完美的,但效果很好,足以證明一個道理:

Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask); 
 

 
function applyDataMask(field) { 
 
    var mask = field.dataset.mask.split(''); 
 
    
 
    // For now, this just strips everything that's not a number 
 
    function stripMask(maskedData) { 
 
     function isDigit(char) { 
 
      return /\d/.test(char); 
 
     } 
 
     return maskedData.split('').filter(isDigit); 
 
    } 
 
    
 
    // Replace `_` characters with characters from `data` 
 
    function applyMask(data) { 
 
     return mask.map(function(char) { 
 
      if (char != '_') return char; 
 
      if (data.length == 0) return char; 
 
      return data.shift(); 
 
     }).join('') 
 
    } 
 
    
 
    function reapplyMask(data) { 
 
     return applyMask(stripMask(data)); 
 
    } 
 
    
 
    function changed() { 
 
     var oldStart = field.selectionStart; 
 
     var oldEnd = field.selectionEnd; 
 
     
 
     field.value = reapplyMask(field.value); 
 
     
 
     field.selectionStart = oldStart; 
 
     field.selectionEnd = oldEnd; 
 
    } 
 
    
 
    field.addEventListener('click', changed) 
 
    field.addEventListener('keyup', changed) 
 
}
ISO Date: <input type="text" value="____-__-__" data-mask="____-__-__"/><br/> 
 
Telephone: <input type="text" value="(___) ___-____" data-mask="(___) ___-____"/><br/>

View in JSFiddle

也有許多圖書館在那裏它們執行這一功能的。一些例子包括:

+1

光標移動時,它越過一些字符在掩模(例如連字符或支架) – Andree

+0

@Andree正確向左,這就是爲什麼我說「這當然不是完美的,但足以證明這個原則」的原因之一。爲了解決像降低用戶體驗那樣的邊緣情況,真實世界的實現將需要更復雜。 – Ajedi32

+0

是否有使用'keyup'而不是'keydown'事件的原因? – fbynite

13

閱讀所有的文章後,我做了我自己的實現,我希望能幫助到別人:

想法是,

  1. 只允許輸入數字。 (按鍵事件)
  2. 得到所有數字的排列
  3. 在由數量從 陣列在一個循環

改進,歡迎更換面具的每一個「_」字符。

/** 
 
* charCode [48,57] \t Numbers 0 to 9 
 
* keyCode 46 \t \t \t "delete" 
 
* keyCode 9 \t \t \t "tab" 
 
* keyCode 13 \t \t \t "enter" 
 
* keyCode 116 \t \t \t "F5" 
 
* keyCode 8 \t \t \t "backscape" 
 
* keyCode 37,38,39,40 \t Arrows 
 
* keyCode 10 \t \t \t (LF) 
 
*/ 
 
function validate_int(myEvento) { 
 
    if ((myEvento.charCode >= 48 && myEvento.charCode <= 57) || myEvento.keyCode == 9 || myEvento.keyCode == 10 || myEvento.keyCode == 13 || myEvento.keyCode == 8 || myEvento.keyCode == 116 || myEvento.keyCode == 46 || (myEvento.keyCode <= 40 && myEvento.keyCode >= 37)) { 
 
    dato = true; 
 
    } else { 
 
    dato = false; 
 
    } 
 
    return dato; 
 
} 
 

 
function phone_number_mask() { 
 
    var myMask = "(___) ___-____"; 
 
    var myCaja = document.getElementById("phone"); 
 
    var myText = ""; 
 
    var myNumbers = []; 
 
    var myOutPut = "" 
 
    var theLastPos = 1; 
 
    myText = myCaja.value; 
 
    //get numbers 
 
    for (var i = 0; i < myText.length; i++) { 
 
    if (!isNaN(myText.charAt(i)) && myText.charAt(i) != " ") { 
 
     myNumbers.push(myText.charAt(i)); 
 
    } 
 
    } 
 
    //write over mask 
 
    for (var j = 0; j < myMask.length; j++) { 
 
    if (myMask.charAt(j) == "_") { //replace "_" by a number 
 
     if (myNumbers.length == 0) 
 
     myOutPut = myOutPut + myMask.charAt(j); 
 
     else { 
 
     myOutPut = myOutPut + myNumbers.shift(); 
 
     theLastPos = j + 1; //set caret position 
 
     } 
 
    } else { 
 
     myOutPut = myOutPut + myMask.charAt(j); 
 
    } 
 
    } 
 
    document.getElementById("phone").value = myOutPut; 
 
    document.getElementById("phone").setSelectionRange(theLastPos, theLastPos); 
 
} 
 

 
document.getElementById("phone").onkeypress = validate_int; 
 
document.getElementById("phone").onkeyup = phone_number_mask;
<input type="text" name="phone" id="phone" placeholder="(123) 456-7890" required="required" title="e.g (123) 456-7890" pattern="^\([0-9]{3}\)\s[0-9]{3}-[0-9]{4}$">

+0

我將使函數名稱具有通用性,並使用Ajedi32所使用的類似邏輯,並從「data-mask」屬性中獲取掩碼。這樣你不僅可以屏蔽電話號碼,而且可以在data-mask屬性中提供任何類型 – programmerboy

+0

@programmerboy這是一個好主意! –

10

您可以通過使用Java腳本的本地方法也能達到這一點。它非常簡單,不需要任何額外的庫來導入。

<input type="text" name="date" placeholder="yyyy-mm-dd" onkeyup=" 
    var date = this.value; 
    if (date.match(/^\d{4}$/) !== null) { 
    this.value = date + '-'; 
    } else if (date.match(/^\d{4}\-\d{2}$/) !== null) { 
    this.value = date + '-'; 
    }" maxlength="10"> 
+2

偉大的解決方案...除非你嘗試使用退格。 :) 所以需要一個小修改來處理。 – derekadk

+0

處理退格的小修改! SridharKritha

-6

使用此代碼: -

<input type="text" placeholder="" data-mask="9999/99/99"> 
+9

這並不做任何事情。 –

+1

但這離不開的jQuery插件面膜什麼,你可以在這裏找到... https://igorescobar.github.io/jQuery-Mask-Plugin –

+2

HTML不能單獨做這樣的事情,請考慮更好的響應,也許你忘了提一些額外的組件或Javascript –

2

這裏是500行jQuery插件,使在表單字段和HTML元素口罩: DEMO

您可以通過研究瞭解的基礎知識它的源代碼:https://github.com/igorescobar/jQuery-Mask-Plugin

+0

BTW:我寫了一個類似的輕量級實現(普通的JavaScript),這是在HTTPS發佈:// github.com/eugenmihailescu/myinputmask –

2

你也可以嘗試我的實現,在每次按下按鍵之後沒有延遲輸入內容,並完全支持退格和刪除。

你可以在線試用: https://jsfiddle.net/qmyo6a1h/1/

<html> 
    <style> 
    input{ 
     font-family:'monospace'; 
    } 
    </style> 
    <body> 
     <input type="text" id="phone" placeholder="123-5678-1234" title="123-5678-1234" input-mask="___-____-____"> 
     <input type="button" onClick="showValue_phone()" value="Show Value" /> 
     <input type="text" id="console_phone" /> 
     <script> 
     function InputMask(element) { 
      var self = this; 

      self.element = element; 

      self.mask = element.attributes["input-mask"].nodeValue; 

      self.inputBuffer = ""; 

      self.cursorPosition = 0; 

      self.bufferCursorPosition = 0; 

      self.dataLength = getDataLength(); 

      function getDataLength() { 
      var ret = 0; 

      for (var i = 0; i < self.mask.length; i++) { 
       if (self.mask.charAt(i) == "_") { 
       ret++; 
       } 
      } 

      return ret; 
      } 

      self.keyEventHandler = function (obj) { 
      obj.preventDefault(); 

      self.updateBuffer(obj); 
      self.manageCursor(obj); 
      self.render(); 
      self.moveCursor(); 
      } 

      self.updateBufferPosition = function() { 
      var selectionStart = self.element.selectionStart; 
      self.bufferCursorPosition = self.displayPosToBufferPos(selectionStart); 
      console.log("self.bufferCursorPosition==" + self.bufferCursorPosition); 
      } 

      self.onClick = function() { 
      self.updateBufferPosition(); 
      } 

      self.updateBuffer = function (obj) { 
      if (obj.keyCode == 8) { 
       self.inputBuffer = self.inputBuffer.substring(0, self.bufferCursorPosition - 1) + self.inputBuffer.substring(self.bufferCursorPosition); 
      } 
      else if (obj.keyCode == 46) { 
       self.inputBuffer = self.inputBuffer.substring(0, self.bufferCursorPosition) + self.inputBuffer.substring(self.bufferCursorPosition + 1); 
      } 
      else if (obj.keyCode >= 37 && obj.keyCode <= 40) { 
       //do nothing on cursor keys. 
      } 
      else { 
       var selectionStart = self.element.selectionStart; 
       var bufferCursorPosition = self.displayPosToBufferPos(selectionStart); 
       self.inputBuffer = self.inputBuffer.substring(0, bufferCursorPosition) + String.fromCharCode(obj.which) + self.inputBuffer.substring(bufferCursorPosition); 
       if (self.inputBuffer.length > self.dataLength) { 
       self.inputBuffer = self.inputBuffer.substring(0, self.dataLength); 
       } 
      } 
      } 

      self.manageCursor = function (obj) { 
      console.log(obj.keyCode); 
      if (obj.keyCode == 8) { 
       self.bufferCursorPosition--; 
      } 
      else if (obj.keyCode == 46) { 
       //do nothing on delete key. 
      } 
      else if (obj.keyCode >= 37 && obj.keyCode <= 40) { 
       if (obj.keyCode == 37) { 
       self.bufferCursorPosition--; 
       } 
       else if (obj.keyCode == 39) { 
       self.bufferCursorPosition++; 
       } 
      } 
      else { 
       var bufferCursorPosition = self.displayPosToBufferPos(self.element.selectionStart); 
       self.bufferCursorPosition = bufferCursorPosition + 1; 
      } 
      } 

      self.setCursorByBuffer = function (bufferCursorPosition) { 
      var displayCursorPos = self.bufferPosToDisplayPos(bufferCursorPosition); 
      self.element.setSelectionRange(displayCursorPos, displayCursorPos); 
      } 

      self.moveCursor = function() { 
      self.setCursorByBuffer(self.bufferCursorPosition); 
      } 

      self.render = function() { 
      var bufferCopy = self.inputBuffer; 
      var ret = { 
       muskifiedValue: "" 
      }; 

      var lastChar = 0; 

      for (var i = 0; i < self.mask.length; i++) { 
       if (self.mask.charAt(i) == "_" && 
       bufferCopy) { 
       ret.muskifiedValue += bufferCopy.charAt(0); 
       bufferCopy = bufferCopy.substr(1); 
       lastChar = i; 
       } 
       else { 
       ret.muskifiedValue += self.mask.charAt(i); 
       } 
      } 

      self.element.value = ret.muskifiedValue; 

      } 

      self.preceedingMaskCharCount = function (displayCursorPos) { 
      var lastCharIndex = 0; 
      var ret = 0; 

      for (var i = 0; i < self.element.value.length; i++) { 
       if (self.element.value.charAt(i) == "_" 
       || i > displayCursorPos - 1) { 
       lastCharIndex = i; 
       break; 
       } 
      } 

      if (self.mask.charAt(lastCharIndex - 1) != "_") { 
       var i = lastCharIndex - 1; 
       while (self.mask.charAt(i) != "_") { 
       i--; 
       if (i < 0) break; 
       ret++; 
       } 
      } 

      return ret; 
      } 

      self.leadingMaskCharCount = function (displayIndex) { 
      var ret = 0; 

      for (var i = displayIndex; i >= 0; i--) { 
       if (i >= self.mask.length) { 
       continue; 
       } 
       if (self.mask.charAt(i) != "_") { 
       ret++; 
       } 
      } 

      return ret; 
      } 

      self.bufferPosToDisplayPos = function (bufferIndex) { 
      var offset = 0; 
      var indexInBuffer = 0; 

      for (var i = 0; i < self.mask.length; i++) { 
       if (indexInBuffer > bufferIndex) { 
       break; 
       } 

       if (self.mask.charAt(i) != "_") { 
       offset++; 
       continue; 
       } 

       indexInBuffer++; 
      } 
      var ret = bufferIndex + offset; 

      return ret; 
      } 

      self.displayPosToBufferPos = function (displayIndex) { 
      var offset = 0; 
      var indexInBuffer = 0; 

      for (var i = 0; i < self.mask.length && i <= displayIndex; i++) { 
       if (indexInBuffer >= self.inputBuffer.length) { 
       break; 
       } 

       if (self.mask.charAt(i) != "_") { 
       offset++; 
       continue; 
       } 

       indexInBuffer++; 
      } 

      return displayIndex - offset; 
      } 

      self.getValue = function() { 
      return this.inputBuffer; 
      } 
      self.element.onkeypress = self.keyEventHandler; 
      self.element.onclick = self.onClick; 
     } 

     function InputMaskManager() { 
      var self = this; 

      self.instances = {}; 

      self.add = function (id) { 
      var elem = document.getElementById(id); 
      var maskInstance = new InputMask(elem); 
      self.instances[id] = maskInstance; 
      } 

      self.getValue = function (id) { 
      return self.instances[id].getValue(); 
      } 

      document.onkeydown = function (obj) { 
      if (obj.target.attributes["input-mask"]) { 
       if (obj.keyCode == 8 || 
       obj.keyCode == 46 || 
       (obj.keyCode >= 37 && obj.keyCode <= 40)) { 

       if (obj.keyCode == 8 || obj.keyCode == 46) { 
        obj.preventDefault(); 
       } 

       //needs to broadcast to all instances here: 
       var keys = Object.keys(self.instances); 
       for (var i = 0; i < keys.length; i++) { 
        if (self.instances[keys[i]].element.id == obj.target.id) { 
        self.instances[keys[i]].keyEventHandler(obj); 
        } 
       } 
       } 
      } 
      } 
     } 

     //Initialize an instance of InputMaskManager and 
     //add masker instances by passing in the DOM ids 
     //of each HTML counterpart. 
     var maskMgr = new InputMaskManager(); 
     maskMgr.add("phone"); 

     function showValue_phone() { 
      //-------------------------------------------------------__Value_Here_____ 
      document.getElementById("console_phone").value = maskMgr.getValue("phone"); 
     } 
     </script> 
    </body> 

    </html> 
0
Array.prototype.forEach.call(document.body.querySelectorAll("*[data-mask]"), applyDataMask); 

function applyDataMask(field) { 
    var mask = field.dataset.mask.split(''); 

    // For now, this just strips everything that's not a number 
    function stripMask(maskedData) { 
     function isDigit(char) { 
      return /\d/.test(char); 
     } 
     return maskedData.split('').filter(isDigit); 
    } 

    // Replace `_` characters with characters from `data` 
    function applyMask(data) { 
     return mask.map(function(char) { 
      if (char != '_') return char; 
      if (data.length == 0) return char; 
      return data.shift(); 
     }).join('') 
    } 

    function reapplyMask(data) { 
     return applyMask(stripMask(data)); 
    } 

    function changed() { 
     var oldStart = field.selectionStart; 
     var oldEnd = field.selectionEnd; 

     field.value = reapplyMask(field.value); 

     field.selectionStart = oldStart; 
     field.selectionEnd = oldEnd; 
    } 

    field.addEventListener('click', changed) 
    field.addEventListener('keyup', changed) 
} 
Date: <input type="text" value="__-__-____" data-mask="__-__-____"/><br/> 
Telephone: <input type="text" value="(___) ___-____" data-mask="(___) ___-____"/><br/> 
+0

如果您將介紹性文字解釋爲您的代碼以及它如何回答問題,那將會很有幫助。 –