我想爲接受日期的文本輸入字段實現掩碼。屏蔽值應直接顯示在輸入內部。如何實現帶有掩碼的輸入
事情是這樣的:
<input type='text' value='____/__/__'>
我寫的屏蔽,這個例子的值,但我的目的是讓人們寫的日期,而無需輸入/
或-
分隔月,年和天數。用戶應該能夠在顯示的字段中輸入數字,而掩碼在用戶輸入時自動執行格式。
我在其他網站上看到過這種行爲,但我不知道它是如何工作的或如何自己實現它。
我想爲接受日期的文本輸入字段實現掩碼。屏蔽值應直接顯示在輸入內部。如何實現帶有掩碼的輸入
事情是這樣的:
<input type='text' value='____/__/__'>
我寫的屏蔽,這個例子的值,但我的目的是讓人們寫的日期,而無需輸入/
或-
分隔月,年和天數。用戶應該能夠在顯示的字段中輸入數字,而掩碼在用戶輸入時自動執行格式。
我在其他網站上看到過這種行爲,但我不知道它是如何工作的或如何自己實現它。
輸入掩碼可使用keyup
事件的組合來實現,並且HTMLInputElement
value
,selectionStart
,和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/>
也有許多圖書館在那裏它們執行這一功能的。一些例子包括:
閱讀所有的文章後,我做了我自己的實現,我希望能幫助到別人:
想法是,
改進,歡迎更換面具的每一個「_」字符。
/**
* 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}$">
我將使函數名稱具有通用性,並使用Ajedi32所使用的類似邏輯,並從「data-mask」屬性中獲取掩碼。這樣你不僅可以屏蔽電話號碼,而且可以在data-mask屬性中提供任何類型 – programmerboy
@programmerboy這是一個好主意! –
您可以通過使用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">
偉大的解決方案...除非你嘗試使用退格。 :) 所以需要一個小修改來處理。 – derekadk
處理退格的小修改! – SridharKritha
使用此代碼: -
<input type="text" placeholder="" data-mask="9999/99/99">
這並不做任何事情。 –
但這離不開的jQuery插件面膜什麼,你可以在這裏找到... https://igorescobar.github.io/jQuery-Mask-Plugin –
HTML不能單獨做這樣的事情,請考慮更好的響應,也許你忘了提一些額外的組件或Javascript –
這裏是500行jQuery插件,使在表單字段和HTML元素口罩: DEMO
您可以通過研究瞭解的基礎知識它的源代碼:https://github.com/igorescobar/jQuery-Mask-Plugin
BTW:我寫了一個類似的輕量級實現(普通的JavaScript),這是在HTTPS發佈:// github.com/eugenmihailescu/myinputmask –
你也可以嘗試我的實現,在每次按下按鍵之後沒有延遲輸入內容,並完全支持退格和刪除。
你可以在線試用: 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/>
如果您將介紹性文字解釋爲您的代碼以及它如何回答問題,那將會很有幫助。 –
光標移動時,它越過一些字符在掩模(例如連字符或支架) – Andree
@Andree正確向左,這就是爲什麼我說「這當然不是完美的,但足以證明這個原則」的原因之一。爲了解決像降低用戶體驗那樣的邊緣情況,真實世界的實現將需要更復雜。 – Ajedi32
是否有使用'keyup'而不是'keydown'事件的原因? – fbynite