2012-09-25 9 views
37

Ich möchte eine Maske für ein Texteingabefeld implementieren, die ein Datum akzeptiert. Der maskierte Wert sollte direkt in der Eingabe angezeigt werden.So implementieren Sie eine Eingabe mit einer Maske

Etwas wie folgt aus:

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

Ich schrieb die Maske als Wert in diesem Beispiel, aber meine Absicht ist es, Menschen zu ermöglichen, ein Datum zu schreiben, ohne / oder - zu trennen Monate, Jahre und Tage eingeben. Der Benutzer sollte Zahlen in das angezeigte Feld eingeben können, während die Maske das Format automatisch erzwingt, wenn der Benutzer tippt.

Ich habe dieses Verhalten auf anderen Seiten gesehen, aber ich habe keine Ahnung, wie es funktioniert oder wie man es selbst implementiert.

Antwort

28

Eingabemasken können mit einer Kombination aus dem keyup Ereignisse implementiert werden, und die HTMLInputElementvalue, selectionStart und selectionEnd Eigenschaften. Hier ist eine sehr einfache Implementierung, die etwas von dem tut, was Sie wollen. Es ist sicherlich nicht perfekt, aber funktioniert gut genug, um das Prinzip zu demonstrieren:

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)

Es gibt auch eine Reihe von Bibliotheken gibt, die diese Funktion ausführen. Einige Beispiele hierfür sind:

+1

Der Cursor nach links verschiebt, wenn es über einige Zeichen geht in die Maske (zB Bindestrich oder Klammer) – Andree

+0

@Andree Correct , das ist einer der Gründe, warum ich sagte "es ist sicherlich nicht perfekt, aber funktioniert gut genug, um das Prinzip zu demonstrieren". Eine Implementierung in der realen Welt müsste komplizierter sein, um Randfälle wie die, die die Benutzererfahrung beeinträchtigen, zu berücksichtigen. – Ajedi32

+0

Gibt es einen Grund, 'keyup' anstelle von' keydown' zu verwenden? – fbynite

13

Nachdem alle Post zu lesen, habe ich meine eigene Implementierung, ich hoffe, jemandem zu helfen :

Die Idee ist,

  1. Eingabe nur Nummern zulassen. (Keypress Ereignis)
  2. erhalten alle Zahlen in einem Array
  3. ersetzen jedes Zeichen "_" der Maske durch eine Reihe von Array in einer Schleife

Verbesserungen sind willkommen.

/** 
 
* 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

Ich werde den Funktionsnamen generisch machen und ähnliche Logik verwenden, die Ajedi32 verwendet und die Maske aus dem Attribut "data-mask" bezieht. Auf diese Weise maskieren Sie nicht nur die Telefonnummer, sondern jeden Typ, der im Datenmaskenattribut – programmerboy

+0

@programmerboy angegeben ist. Es ist eine gute Idee! –

10

Sie können dies auch erreichen, indem JavaScripts native Methode. Es ist ziemlich einfach und benötigt keine zusätzliche Bibliothek zum Importieren.

<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

Tolle Lösung ... Außer wenn Sie versuchen, Backspace zu verwenden. :) Also eine kleine Änderung ist erforderlich, um damit umzugehen. – derekadk

+0

Geringfügige Änderung für die Griffrücktaste !!! SridharKritha

-6

Mit diesem Code: -

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

Das macht nichts. –

+1

Das macht nichts ohne das jQuery-Masken-Plugin, das Sie hier finden können ... https://igorescobar.github.io/jQuery-Mask-Plugin –

+2

HTML alleine kann so etwas nicht machen, bitte überlegen Sie eine bessere Antwort, vielleicht haben Sie vergessen, einige zusätzliche Komponente oder Javascript zu erwähnen –

2

Hier ist eine 500-Zeilen jQuery-Plugin Masken auf Formularfelder und HTML-Elemente zu machen: DEMO

Sie die Grundlagen durch das Studium verstehen Sein Quellcode: https://github.com/igorescobar/jQuery-Mask-Plugin

+0

btw: Ich schrieb eine ähnliche leichte Implementierung (plain JavaScript), die bei https veröffentlicht ist: // github.com/eugenmihailescu/myinputmask –

2

Sie können auch versuchen, meine Implementierung, die keine Verzögerung nach jedem Tastendruck wann hat Geben Sie den Inhalt ein, und Sie haben volle Unterstützung für Rückschritt und Löschen.

Sie können es versuchen, online: 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

Es wäre hilfreich, wenn Sie einen einleitenden Text schreiben, der Ihren Code erklärt und wie er die Frage beantworten würde. –

Verwandte Themen