Реализуйте ввод с помощью маски

Я хотел бы реализовать маску для текста input поле, которое принимает дату. Маскированное значение должно отображаться непосредственно внутри input,

Что-то вроде этого:

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

Я написал маску в качестве значения в этом примере, но я хочу позволить людям писать дату без ввода / или же - отделить месяцы, годы и дни. Пользователь должен иметь возможность вводить числа в отображаемое поле, в то время как маска автоматически вводит формат при вводе пользователем.

Я видел такое поведение на других сайтах, но я понятия не имею, как это работает или как реализовать это самостоятельно.

7 ответов

Решение, которое отвечает на input событие вместо ключевых событий (например, keyup) даст плавный опыт (без покачиваний), а также работает, когда изменения вносятся без клавиатуры (контекстное меню, перетаскивание мышью, другое устройство...).

Код ниже будет искать элементы ввода, которые имеют как 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>

Маски ввода могут быть реализованы с использованием комбинации keyup событие, а HTMLInputElementvalue, 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/>

( Посмотреть в JSFiddle)

Существует также ряд библиотек, которые выполняют эту функцию. Вот некоторые примеры:

Прочитав все посты, я сделал собственную реализацию, надеюсь, кому-то помогу:

Идея в том,

  1. разрешить ввод только номеров. (событие нажатия клавиши)
  2. получить все числа в массиве
  3. заменить каждый символ "_" маски на число из массива в цикле

Улучшения приветствуются.

/**
 * 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}$">

Вы можете достичь этого также с помощью нативного метода JavaScripts. Это довольно просто и не требует дополнительной библиотеки для импорта.

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

Вы также можете попробовать мою реализацию, которая не имеет задержки после каждого нажатия клавиши при наборе содержимого, и имеет полную поддержку возврата и удаления.

Вы можете попробовать это онлайн: 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>

Используйте это для реализации маски:

https://rawgit.com/RobinHerbots/jquery.inputmask/3.x/dist/jquery.inputmask.bundle.js

<input id="phn-number" class="ant-input" type="text" placeholder="(XXX) XXX-XXXX" data-inputmask-mask="(999) 999-9999">


jQuery( '#phn-number[data-inputmask-mask]' ).inputmask();

Я написал подобное решение некоторое время назад.
Конечно, это просто PoC и может быть улучшено в дальнейшем.

Это решение охватывает следующие функции:

  • Бесшовный ввод символов
  • Настройка шаблона
  • Живая проверка во время ввода
  • Полная проверка даты (включая правильные дни в каждом месяце и рассмотрение високосного года)
  • Описательные ошибки, поэтому пользователь поймет, что происходит, пока не может набрать символ
  • Исправить положение курсора и предотвратить выбор
  • Показать заполнитель, если значение пустое

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>

Ссылка на jsfiddle: https://jsfiddle.net/d1xbpw8f/56/

Удачи!

Ниже я опишу свой метод. Я устанавливаю событие на входе в input, чтобы вызвать метод Masking(), который вернет отформатированную строку, которую мы вставим в input,

Html:

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

JQ: Здесь мы устанавливаем событие на входе:

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

JS: функция, которая будет форматировать строку по шаблону;

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

Я взял из этого потока решение. Реализовать ввод с маской и адаптировал его для IE10, а также добавил функции установки и получения.

НО Я ТЕСТИРОВАЛ ТОЛЬКО НА ТЕЛЕФОН-маску

$(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=""); });
    }

});   

Используйте этот код:-

<input type="text" placeholder="" data-mask="9999/99/99">
Другие вопросы по тегам