如何实现带有掩码的input

我想实现一个接受date的文本input字段的掩码。 屏蔽值应直接显示在input内部。

像这样的东西:

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

在这个例子中,我把面具作为一个值来写,但是我的意图是允许人们写一个date,而不用input/-来分隔几个月,几年和几天。 用户应该能够在显示的字段中input数字,而掩码在用户键入时自动执行格式。

我在其他网站上看到过这种行为,但我不知道它是如何工作的,或者如何自己实现它。

input掩码可以使用keyup事件和HTMLInputElement valueselectionStartselectionEnd属性的组合来实现。 这是一个非常简单的实现,它可以完成一些你想要的function。 这当然不是完美的,但足以certificate这一原则:

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

阅读完所有post后,我做了我自己的实现,希望对有人帮助:

这个想法是,

  1. 只允许input数字。 (按键事件)
  2. 获取数组中的所有数字
  3. 用循环中的数组replace掩码的每个“_”字符

欢迎改进。

 /** * charCode [48,57] Numbers 0 to 9 * keyCode 46 "delete" * keyCode 9 "tab" * keyCode 13 "enter" * keyCode 116 "F5" * keyCode 8 "backscape" * keyCode 37,38,39,40 Arrows * keyCode 10 (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="eg (123) 456-7890" pattern="^\([0-9]{3}\)\s[0-9]{3}-[0-9]{4}$"> 

你也可以通过使用JavaScript的本地方法来实现这一点。 它非常简单,不需要任何额外的库来导入。

 <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"> 

下面是一个500行的jQuery插件,用于在表单字段和html元素上创build蒙版: DEMO

你可以通过学习它的源代码来理解基础: https : //github.com/igorescobar/jQuery-Mask-Plugin

你也可以尝试一下我的实现,在每次按键input内容后都没有延迟,并且完全支持退格和删除。

您可以在线试用: 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> 
 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/> 

使用此代码: –

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