Маска ввода номера телефона на js

Очень часто на сайтах необходимо контролировать, что ввел пользователь в поле input ввода номера телефона. Существует множество вариантов, для каждого сайта подойдет свой. Все зависит от требований к маске ввода телефона.

Сегодня рассмотрим несколько вариантов:

  • На чистом js
  • С использованием jQuery

Маска телефона на чистом JS

На легких веб-ресурсах, где не используется фреймворк jquery, подойдет вариант на чистом javascript. Это позволяется минимизировать затраты использования ресурсов браузера и объем загружаемых ресурсов.

Более того, такой скрипт можно вставить непосредственно в сам Html документ, без необходимости подключения лишних js файлов и библиотек.

Требования к скрипту:

  1. Скрипт должен работать без лишних библиотек.
  2. Скрипт должен быть  максимально гибким.
  3. Скрипт должен быть легко подключаемым.

Демонстрация работы скрипта:

Код скрипта на js

Данный код написан на vanilla javascript, без использования дополнительных библиотек и фреймворков.

document.addEventListener("DOMContentLoaded", function () {
    var eventCalllback = function (e) {
        var el = e.target,
        clearVal = el.dataset.phoneClear,
        pattern = el.dataset.phonePattern,
        matrix_def = "+7(___) ___-__-__",
        matrix = pattern ? pattern : matrix_def,
        i = 0,
        def = matrix.replace(/\D/g, ""),
        val = e.target.value.replace(/\D/g, "");
        if (clearVal !== 'false' && e.type === 'blur') {
            if (val.length < matrix.match(/([\_\d])/g).length) {
                e.target.value = '';
                return;
            }
        }
        if (def.length >= val.length) val = def;
        e.target.value = matrix.replace(/./g, function (a) {
            return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" : a
        });
    }
    var phone_inputs = document.querySelectorAll('[data-phone-pattern]');
    for (let elem of phone_inputs) {
        for (let ev of ['input', 'blur', 'focus']) {
            elem.addEventListener(ev, eventCalllback);
        }
    }
});

В сжатом виде код выглядит более компактно:

var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};$jscomp.arrayIterator=function(a){return{next:$jscomp.arrayIteratorImpl(a)}};$jscomp.makeIterator=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):$jscomp.arrayIterator(a)};
document.addEventListener("DOMContentLoaded",function(){var a=function(e){var c=e.target,n=c.dataset.phoneClear;c=(c=c.dataset.phonePattern)?c:"+7(___) ___-__-__";var g=0,k=c.replace(/\D/g,""),d=e.target.value.replace(/\D/g,"");"false"!==n&&"blur"===e.type&&d.length<c.match(/([_\d])/g).length?e.target.value="":(k.length>=d.length&&(d=k),e.target.value=c.replace(/./g,function(l){return/[_\d]/.test(l)&&g<d.length?d.charAt(g++):g>=d.length?"":l}))},b=document.querySelectorAll("[data-phone-pattern]");
b=$jscomp.makeIterator(b);for(var f=b.next();!f.done;f=b.next()){f=f.value;for(var m=$jscomp.makeIterator(["input","blur","focus"]),h=m.next();!h.done;h=m.next())f.addEventListener(h.value,a)}});

Как подключить

Самый простой вариант подключения, это пряма вставка кода в html страницу между тегами <head>

<!doctype html>
<html lang="en">
<head>
    ...
    <!-- Подключение нашего скрипта -->
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            var eventCalllback = function (e) {
                var el = e.target,
                    clearVal = el.dataset.phoneClear,
                    pattern = el.dataset.phonePattern,
                    matrix_def = "+7(___) ___-__-__",
                    matrix = pattern ? pattern : matrix_def,
                    i = 0,
                    def = matrix.replace(/\D/g, ""),
                    val = e.target.value.replace(/\D/g, "");
                if (clearVal !== 'false' && e.type === 'blur') {
                    if (val.length < matrix.match(/([\_\d])/g).length) {
                        e.target.value = '';
                        return;
                    }
                }
                if (def.length >= val.length) val = def;
                e.target.value = matrix.replace(/./g, function (a) {
                    return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" : a
                });
            }
            var phone_inputs = document.querySelectorAll('[data-phone-pattern]');
            for (let elem of phone_inputs) {
                for (let ev of ['input', 'blur', 'focus']) {
                    elem.addEventListener(ev, eventCalllback);
                }
            }
        });
    </script>
    ...
</head>
<body>
...
<input name="phone" data-phone-pattern />
...
</body>
</html>

Второй вариант. Создать пустой файл с расширением .js и вставит код скрипта в него. Далее подключить уже сам файл между тегами <head>

Допустим мы создали файл mask.js, вставили в него наш код и загрузили на сайт. Тогда подключение скрипта к сайту будет выглядеть примерно так:

<!doctype html>
<html lang="en">
<head>
    ...
    <!-- Подключение нашего скрипта -->
    <script src="/путь до скрипта/mask.js"></script>
    ...
</head>
<body>
...
<input name="phone" data-phone-pattern />
...
</body>
</html>

Как использовать

Скрипт работает с атрибутами элемента input, т.е. для того, чтобы скрипт применил маску к инпуту ввода номера телефона, вам необходимо прописать data атрибут.

data-phone-pattern  - подключает маску к input 
data-phone-pattern = '+7 (___) ___-__-__'  - Задает свою маску для номера телефона.
data-phone-clear = 'false' - отключает сброс значения Input , если пользователь не до конца ввел телефон.

В самом скрипте, уже имеется дефолтная маска вида: '+7 (___) ___-__-__'. Если вам необходим другой вид, то указываем свою в атрибуте data-phone-pattern.

Скрипт автоматически стирает некорректно введеный номер телефона в поле, при потере фокуса.

data-phone-clear = "false" - указывает скрипту, что не надо стирать данные в поле input, даже если пользователь ввел телефон не полностью. (Не знаю зачем это надо, но мало ли).  

Примеры использования атрибутов:

//Простое подключение скрипта
<input type="text" name="" data-phone-pattern>
 
//Подключение скрипта со своей маской
<input type="text" name="" data-phone-pattern = "+7 (___) ___-__-__">
 
//Подключение скрипта со своей маской и отключением стирания
<input type="text" name="" data-phone-pattern 'data-phone-clear = "false" >

Теперь единственное, что необходимо сделать, это очистить данные от мусора на стороне сервера. Так как в поле телефона присутствуют не очень нужные символы (типа скобок и прочерков, пробелов), то когда вы принимаете POST данные в скрипте php, можно применить функцию замены ненужных символов.

К примеру, у нас имя поля input было phone

//Входящие данные от формы POST
 
// пришло + 7(929) 7896-56-56
$phone = $_POST['phone'];
 
// чистим
$phone = str_replace(['(',')','-','+',' '], '', $phone );
 
// на выходе
$phone будет равен 792978965656

Маска телефона на jQuery

Если на сайте уже используется framework jQuery, то можно использовать более компактный код. Он использует функции обертки самого фреймворка, что немного упрощает код.

$(function () {
            $('[data-phone-pattern]').on('input blur focus', (e) => {
                var el = e.target,
                    clearVal = $(el).data('phoneClear'),
                    pattern = $(el).data('phonePattern'),
                    matrix_def = "+7(___) ___-__-__",
                    matrix = pattern ? pattern : matrix_def,
                    i = 0,
                    def = matrix.replace(/\D/g, ""),
                    val = $(el).val().replace(/\D/g, "");
                if (clearVal !== 'false' && e.type === 'blur') {
                    if (val.length < matrix.match(/([\_\d])/g).length) {
                        $(el).val('');
                        return;
                    }
                }
                if (def.length >= val.length) val = def;
                $(el).val(matrix.replace(/./g, function (a) {
                    return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" : a;
                }));
            });
        });

Подключение и использование данного варианта скрипта, аналогично как и у варианта на чистом JS. Смотрите выше.

Компактный вид:

$(function(){$("[data-phone-pattern]").on("input blur focus",function(e){var c=e.target,h=$(c).data("phoneClear"),a=$(c).data("phonePattern");a=a?a:"+7(___) ___-__-__";var d=0,f=a.replace(/\D/g,""),b=$(c).val().replace(/\D/g,"");"false"!==h&&"blur"===e.type&&b.length<a.match(/([_\d])/g).length?$(c).val(""):(f.length>=b.length&&(b=f),$(c).val(a.replace(/./g,function(g){return/[_\d]/.test(g)&&d<b.length?b.charAt(d++):d>=b.length?"":g})))})});

Вот и все. Пользуйтесь.