Html 使用掩码实现输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12578507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:01:53  来源:igfitidea点击:

Implement an input with a mask

htmldateinputmaskdata-masking

提问by Stanislas Piotrowski

I would like to implement a mask for a text inputfield which accepts a date. The masked value should display directly inside of the input.

我想为input接受日期的文本字段实现掩码。掩码值应直接显示在input.

Something like this:

像这样的东西:

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

I wrote the mask as a value in that example, but my intent is to allow people to write a date without typing /or -to separate months, years and days. The user should be able to enter numbers into the displayed field, while the mask enforces the format automatically as the user types.

我在那个例子中将掩码写为一个值,但我的目的是让人们不用打字就可以写出日期,/或者-将月、年和日分开。用户应该能够在显示的字段中输入数字,而掩码会在用户键入时自动强制执行格式。

I have seen this behavior on other sites, but I have no idea how it works or how to implement it myself.

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

回答by Ajedi32

Input masks can be implemented using a combination of the keyupevent, and the HTMLInputElementvalue, selectionStart, and selectionEndproperties. Here's a very simple implementation which does some of what you want. It's certainly not perfect, but works well enough to demonstrate the principle:

可以使用keyup事件、、 和属性的组合来实现输入掩码。这是一个非常简单的实现,它可以完成您想要的一些操作。它当然不完美,但足以证明其原理:HTMLInputElementvalueselectionStartselectionEnd

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)

在 JSFiddle 中查看

There are also a number of libraries out there which perform this function. Some examples include:

还有一些库可以执行此功能。一些例子包括:

回答by Rodney Salcedo

After reading all post, I did my own implementation, I hope to help to someone:

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

The idea is,

这个想法是,

  1. allow entry only numbers. (keypress event)
  2. get all numbers in a array
  3. replace every "_" character of mask by a number from array in a loop
  1. 只允许输入数字。(按键事件)
  2. 获取数组中的所有数字
  3. 用循环中数组中的数字替换掩码的每个“_”字符

Improvements are welcome.

欢迎改进。

/**
 * 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="e.g (123) 456-7890" pattern="^\([0-9]{3}\)\s[0-9]{3}-[0-9]{4}$">

回答by trincot

A solution that responds to the inputevent instead of key events (like keyup) will give a smooth experience (no wiggles), and also works when changes are made without the keyboard (context menu, mouse drag, other device...).

响应input事件而不是键事件(如keyup)的解决方案将提供流畅的体验(无摆动),并且在不使用键盘(上下文菜单、鼠标拖动、其他设备...)进行更改时也能正常工作。

The code below will look for input elements that have both a placeholderattribute and a data-slotsattribute. The latter should define the character(s) in the placeholder that is/are intended as input slot, for example, "_". An optional data-acceptattribute can be provided with a regular expression that defines which characters are allowed in such a slot. The default is \d, i.e. digits.

下面的代码将查找同时具有placeholder属性和data-slots属性的输入元素。后者应定义占位符中用作输入槽的字符,例如“_”。data-accept可以使用正则表达式提供可选属性,用于定义此类插槽中允许使用哪些字符。默认为\d,即数字。

// This code empowers all input tags having a placeholder and data-slots attribute
document.addEventListener('DOMContentLoaded', () => {
    for (const el of document.querySelectorAll("[placeholder][data-slots]")) {
        const pattern = el.getAttribute("placeholder"),
            slots = new Set(el.dataset.slots || "_"),
            prev = (j => Array.from(pattern, (c,i) => slots.has(c)? j=i+1: j))(0),
            first = [...pattern].findIndex(c => slots.has(c)),
            accept = new RegExp(el.dataset.accept || "\d", "g"),
            clean = input => {
                input = input.match(accept) || [];
                return Array.from(pattern, c =>
                    input[0] === c || slots.has(c) ? input.shift() || c : c
                );
            },
            format = () => {
                const [i, j] = [el.selectionStart, el.selectionEnd].map(i => {
                    i = clean(el.value.slice(0, i)).findIndex(c => slots.has(c));
                    return i<0? prev[prev.length-1]: back? prev[i-1] || first: i;
                });
                el.value = clean(el.value).join``;
                el.setSelectionRange(i, j);
                back = false;
            };
        let back = false;
        el.addEventListener("keydown", (e) => back = e.key === "Backspace");
        el.addEventListener("input", format);
        el.addEventListener("focus", format);
        el.addEventListener("blur", () => el.value === pattern && (el.value=""));
    }
});
[data-slots] { font-family: monospace }
<label>Date time: 
    <input placeholder="dd/mm/yyyy hh:mm" data-slots="dmyh">
</label><br>
<label>Telephone:
    <input placeholder="+1 (___) ___-____" data-slots="_">
</label><br>
<label>MAC Address:
    <input placeholder="XX:XX:XX:XX:XX:XX" data-slots="X" data-accept="[\dA-H]">
</label><br>
<label>Signed number (3 digits):
    <input placeholder="±___" data-slots="±_" data-accept="^[+-]|(?!^)\d" size="4">
</label><br>
<label>Alphanumeric:
    <input placeholder="__-__-__-____" data-slots="_" data-accept="\w" size="13">
</label><br>

回答by shubhamkes

You can achieve this also by using JavaScripts's native method. Its pretty simple and doesn't require any extra library to import.

您也可以通过使用 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">

回答by Cecilk Cao

You can also try my implementation, which doesn't have delay after each key press when typing the contents, and has full support for backspace and delete.

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

You can try it online: https://jsfiddle.net/qmyo6a1h/1/

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

回答by Slavik Meltser

I wrote a similar solution some time ago.
Of course it's just a PoC and can be improved further.

前段时间我写了一个类似的解决方案。
当然,这只是一个 PoC,可以进一步改进。

This solution covers the following features:

此解决方案涵盖以下功能:

  • Seamless character input
  • Pattern customization
  • Live validation while you typing
  • Full date validation (including correct days in each month and a leap year consideration)
  • Descriptive errors, so the user will understand what is going on while he is unable to type a character
  • Fix cursor position and prevent selections
  • Show placeholder if the value is empty
  • 无缝字符输入
  • 图案定制
  • 输入时进行实时验证
  • 完整日期验证(包括每个月的正确天数和闰年考虑)
  • 描述性错误,因此用户在无法输入字符时会理解发生了什么
  • 修复光标位置并防止选择
  • 如果值为空则显示占位符

const pattern = "__/__/____";
const patternFreeChar = "_";
const validDate = [
  /^[0-3]$/,
  /^(0[1-9]|[12]\d|3[01])$/,
  /^(0[1-9]|[12]\d|3[01])[01]$/,
  /^((0[1-9]|[12]\d|3[01])(0[13578]|1[02])|(0[1-9]|[12]\d|30)(0[469]|11)|(0[1-9]|[12]\d)02)$/,
  /^((0[1-9]|[12]\d|3[01])(0[13578]|1[02])|(0[1-9]|[12]\d|30)(0[469]|11)|(0[1-9]|[12]\d)02)[12]$/,
  /^((0[1-9]|[12]\d|3[01])(0[13578]|1[02])|(0[1-9]|[12]\d|30)(0[469]|11)|(0[1-9]|[12]\d)02)(19|20)/
]

/**
 * Validate a date as your type.
 * @param {string} date The date in format DDMMYYYY as a string representation.
 * @throws {Error} When the date is invalid.
 */
function validateStartTypingDate(date) {
  if ( !date ) return "";
  
  date = date.substr(0, 8);
  
  if ( !/^\d+$/.test(date) )
   throw new Error("Please type numbers only");
  
 if ( !validDate[Math.min(date.length-1,validDate.length-1)].test(date) ) {
    let errMsg = "";
    switch ( date.length ) {
     case 1:
       throw new Error("Day in month can start only with 0, 1, 2 or 3");
        
     case 2:
       throw new Error("Day in month must be in a range between 01 and 31");
        
     case 3:
       throw new Error("Month can start only with 0 or 1");
        
     case 4: {
       const day = parseInt(date.substr(0,2));
       const month = parseInt(date.substr(2,2));
        const monthName = new Date(0,month-1).toLocaleString('en-us',{month:'long'});
        
        if ( month < 1 || month > 12 )
         throw new Error("Month number must be in a range between 01 and 12");
          
        if ( day > 30 && [4,6,9,11].includes(month) )
         throw new Error(`${monthName} have maximum 30 days`);
          
        if ( day > 29 && month === 2 )
         throw new Error(`${monthName} have maximum 29 days`);
        break; 
      }
         
      case 5:
      case 6:
       throw new Error("We support only years between 1900 and 2099, so the full year can start only with 19 or 20");
    }
  }
  
  if ( date.length === 8 ) {
   const day = parseInt(date.substr(0,2));
    const month = parseInt(date.substr(2,2));
    const year = parseInt(date.substr(4,4));
    const monthName = new Date(0,month-1).toLocaleString('en-us',{month:'long'});
    if ( !isLeap(year) && month === 2 && day === 29 )
      throw new Error(`The year you are trying to enter (${year}) is not a leap year. Thus, in this year, ${monthName} can have maximum 28 days`);
  }
  
  return date;
}

/**
 * Check whether the given year is a leap year.
 */
function isLeap(year) {
  return new Date(year, 1, 29).getDate() === 29;
}

/**
 * Move cursor to the end of the provided input element.
 */
function moveCursorToEnd(el) {
 if (typeof el.selectionStart == "number") {
  el.selectionStart = el.selectionEnd = el.value.length;
 } else if (typeof el.createTextRange != "undefined") {
  el.focus();
  var range = el.createTextRange();
  range.collapse(false);
  range.select();
 }
}

/**
 * Move cursor to the end of the self input element.
 */
function selfMoveCursorToEnd() {
 return moveCursorToEnd(this);
}

const input = document.querySelector("input")

input.addEventListener("keydown", function(event){
 event.preventDefault();
  document.getElementById("date-error-msg").innerText = "";
  
  // On digit pressed
  let inputMemory = this.dataset.inputMemory || "";
  
  if ( event.key.length === 1 ) {
    try {
      inputMemory = validateStartTypingDate(inputMemory + event.key);
    } catch (err) {
      document.getElementById("date-error-msg").innerText = err.message;
    }
  }
  
  // On backspace pressed
  if ( event.code === "Backspace" ) {
   inputMemory = inputMemory.slice(0, -1);
  }
  
  // Build an output using a pattern
  if ( this.dataset.inputMemory !== inputMemory ) {
   let output = pattern;
   for ( let i=0, digit; i<inputMemory.length, digit=inputMemory[i]; i++ ) {
     output = output.replace(patternFreeChar, digit);
    }
    this.dataset.inputMemory = inputMemory;
    this.value = output;
  }
  
  // Clean the value if the memory is empty
  if ( inputMemory === "" ) {
   this.value = "";
  }
}, false);

input.addEventListener('select', selfMoveCursorToEnd, false);
input.addEventListener('mousedown', selfMoveCursorToEnd, false);
input.addEventListener('mouseup', selfMoveCursorToEnd, false);
input.addEventListener('click', selfMoveCursorToEnd, false);
<input type="text" placeholder="DD/MM/YYYY" />
<div id="date-error-msg"></div>

A link to jsfiddle: https://jsfiddle.net/d1xbpw8f/56/

jsfiddle 的链接:https://jsfiddle.net/d1xbpw8f/56/

Good luck!

祝你好运!

回答by Solo.dmitry

I taken from this thread decision Implement an input with a maskand adapted it for IE10, and added setter- and getter- functions.

我从这个线程决定中获取了用掩码实现输入并将其调整为 IE10,并添加了 setter 和 getter 函数。

BUT I TESTED FOR PHONE-mask ONLY

但我只测试了电话面罩

$(document).ready(function(){
    var el_arr = document.querySelectorAll("[placeholder][data-slots]");
    for (var el_ind=0; el_ind < el_arr.length; el_ind++ ){
        var el = el_arr[el_ind];
        var pattern = el.getAttribute("placeholder"),
            slots = new Set(el.getAttribute("data-slots") || "_"),
            prev = function(j){return Array.from(pattern, function(c,i){ return slots.has(c)? j=i+1: j;});}(0),
            first = pattern.split('').findIndex(function(c){return slots.has(c);} ),
            accept = new RegExp(el.getAttribute("data-accept") || "\d", "g"),
            clean = function(input){input = input.match(accept) || [];return Array.from(pattern, function(c){return input[0] === c || slots.has(c) ? input.shift() || c : c;});},
            format = function(){
                var elem = this;
                var i_j_arr = [el.selectionStart, el.selectionEnd].map(function(i){
                    i = clean(el.value.slice(0, i)).findIndex(function(c){ return slots.has(c);});
                    return i<0? prev[prev.length-1]: elem.back? prev[i-1] || first: i;
                });
                el.value = clean(el.value).join('');
                el.setSelectionRange(i_j_arr[0], i_j_arr[1]);
                this.back = false;
            },
            // sdo added
            get_masked_value = function(){
                var input = this.value;
                var ret=[];
                for(var k in pattern){
                    if ( !input[k] )break;
                    if( slots.has(pattern[k]) && input[k]!=pattern[k]){
                        ret.push(input[k]);
                    } 
                } 
                return ret.join('');
            },
            set_masked_value = function(input){
                var ret=[];
                var index_in_value = 0;
                for(var k in pattern){
                    if( slots.has(pattern[k]) && input[index_in_value]){
                        ret.push(input[index_in_value]);
                        index_in_value++;
                    }
                    else{
                        ret.push(pattern[k]);
                    }
                } 
                this.value = ret.join('');
            }                    
        ;
        el.get_masked_value = get_masked_value;
        el.set_masked_value = set_masked_value;
        el.back = false;
        el.addEventListener("keydown", function(event){ this.back = event.key === "Backspace";});
        el.addEventListener("input", format);
        el.addEventListener("focus", format);
        el.addEventListener("blur", function() { return el.value === pattern && (el.value=""); });
    }

});   

回答by Dumitru Boaghi

Below i describe my method. I set event on input in input, to call Masking() method, which will return an formatted string of that we insert in input.

下面我描述一下我的方法。我在输入中设置事件input,以调用 Masking() 方法,该方法将返回我们插入的格式化字符串input

Html:

网址:

<input name="phone" pattern="+373 __ ___ ___" class="masked" required>

JQ: Here we set event on input:

JQ:这里我们在输入上设置事件:

$('.masked').on('input', function () {
    var input = $(this);
    input.val(Masking(input.val(), input.attr('pattern')));
});

JS: Function, which will format string by pattern;

JS:Function,按模式格式化字符串;

function Masking (value, pattern) {
var out = '';
var space = ' ';
var any = '_';

for (var i = 0, j = 0; j < value.length; i++, j++) {
    if (value[j] === pattern[i]) {
        out += value[j];
    }
    else if(pattern[i] === any && value[j] !== space) {
        out += value[j];
    }
    else if(pattern[i] === space && value[j] !== space) {
        out += space;
        j--;
    }
    else if(pattern[i] !== any && pattern[i] !== space) {
        out += pattern[i];
        j--;
    }
}

return out;
}

回答by Vishnu Kant

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

回答by Sasan.R

Use this code:-

使用此代码:-

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

with adding this script https://github.com/RobinHerbots/Inputmask

添加此脚本https://github.com/RobinHerbots/Inputmask