Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   как сделать маску телефона в input c +7(___) без jQuery (https://javascript.ru/forum/dom-window/63870-kak-sdelat-masku-telefona-v-input-c-7-___-bez-jquery.html)

рони 17.10.2017 11:29

Цитата:

Сообщение от Evgeny.Ponamorev
Зачем три input ?

для проверки blur

Loki 22.11.2017 16:06

Здравствуйте, Рони. Спасибо за классный скрипт. Не подскажете, как видоизменить данный скрипт, с учётом записи маски телефонного номера, на двух формах. Дело в том, что, маска телефона в input, работает только в одной форме поля телефон, если на странице находятся две формы, одна из них находится в подвале сайта, то данная маска уже не работает во второй форме поля телефон? Дублировать скрипт из-за var input = document.querySelector("#tel1"); и var input = document.querySelector("#tel2");? Извините за нубский вопрос, в javascript не особо силён

рони 22.11.2017 16:23

Loki,
class="tel" добавить полям ввода

<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>
    <input  value="" class="tel">
    <input  value="" class="tel">
    <input  value="" class="tel" >
    <script>
window.addEventListener("DOMContentLoaded", function() {
    [].forEach.call( document.querySelectorAll('.tel'), function(input) {
    var keyCode;
    function mask(event) {
        event.keyCode && (keyCode = event.keyCode);
        var pos = this.selectionStart;
        if (pos < 3) event.preventDefault();
        var matrix = "+7 (___) ___ ____",
            i = 0,
            def = matrix.replace(/\D/g, ""),
            val = this.value.replace(/\D/g, ""),
            new_value = matrix.replace(/[_\d]/g, function(a) {
                return i < val.length ? val.charAt(i++) || def.charAt(i) : a
            });
        i = new_value.indexOf("_");
        if (i != -1) {
            i < 5 && (i = 3);
            new_value = new_value.slice(0, i)
        }
        var reg = matrix.substr(0, this.value.length).replace(/_+/g,
            function(a) {
                return "\\d{1," + a.length + "}"
            }).replace(/[+()]/g, "\\$&");
        reg = new RegExp("^" + reg + "$");
        if (!reg.test(this.value) || this.value.length < 5 || keyCode > 47 && keyCode < 58) this.value = new_value;
        if (event.type == "blur" && this.value.length < 5)  this.value = ""
    }

    input.addEventListener("input", mask, false);
    input.addEventListener("focus", mask, false);
    input.addEventListener("blur", mask, false);
    input.addEventListener("keydown", mask, false)

  });

});
  </script>
</body>

</html>

Loki 23.11.2017 07:41

Спасибо, за решение Ронни. Пример рабочий. Но к сожалению применительно к моему сайту не подошёл, по данной схеме маски в input перестали работать сразу в двух формах телефонных полей. На сайте стоят формы на Ajax Form (cms Modx Revo), var input = document.querySelector("#tel"); оказался необходим в моём случае.

Решил проблему добавлением (дублем строк с 43- по 53) и как оказалось этот вариант оказался рабочим. Не знаю как на правильность и изящество решения, ибо упоминал, что не особо сильно разбираюсь в javascript. Ниже решение, хотелось бы узнать, Ваше мнение как гуру. Такой вариант решения правильный с точки зрения синтаксиса, или глупость полная? Хотя работает.

<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>

    <input  value="" id="af_tel1" placeholder="Телефон*">   
	<input  value="" id="af_tel2" placeholder="Телефон*">
	
<script>
  window.addEventListener("DOMContentLoaded", function() {
    var keyCode;

    function mask(event) {
        event.keyCode && (keyCode = event.keyCode);
        var pos = this.selectionStart;
        if (pos < 3) event.preventDefault();
        var matrix = "+7 (___) ___-__-__",
            i = 0,
            def = matrix.replace(/\D/g, ""),
            val = this.value.replace(/\D/g, ""),
            new_value = matrix.replace(/[_\d]/g, function(a) {
                return i < val.length ? val.charAt(i++) || def.charAt(i) : a
            });
        i = new_value.indexOf("_");
        if (i != -1) {
            i < 5 && (i = 3);
            new_value = new_value.slice(0, i)
        }
        var reg = matrix.substr(0, this.value.length).replace(/_+/g,
            function(a) {
                return "\\d{1," + a.length + "}"
            }).replace(/[+()]/g, "\\$&");
        reg = new RegExp("^" + reg + "$");
        if (!reg.test(this.value) || this.value.length < 5 || keyCode > 47 && keyCode < 58) this.value = new_value;
        if (event.type == "blur" && this.value.length < 5)  this.value = ""
    }
    var input = document.querySelector("#af_tel1");
    input.addEventListener("input", mask, false);
    input.addEventListener("focus", mask, false);
    input.addEventListener("blur", mask, false);
    input.addEventListener("keydown", mask, false)
	
	var input = document.querySelector("#af_tel2");
    input.addEventListener("input", mask, false);
    input.addEventListener("focus", mask, false);
    input.addEventListener("blur", mask, false);
    input.addEventListener("keydown", mask, false)
});
</script>

</body>

</html>

рони 23.11.2017 08:47

Loki,
а добавить id и class было никак?

Loki 23.11.2017 09:09

Не понял Вас Ронни (проверка в двух input телефонных полей на сайте осуществляется по id="af_tel1" и id-"af_tel2"), но всё равно спасибо за скрипт

рони 23.11.2017 09:26

Loki,
<input  value="" class="tel" id="af_tel1">
 <input  value="" class="tel" id="af_tel2">

и скрипт из поста №43

Loki 23.11.2017 09:39

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

Loki 23.11.2017 09:42

var input = document.querySelector("#af_tel1"); и var input = document.querySelector("#af_tel2"); необходимы на сайте, в такой конструкции пост № 44, всё работает.

Loki 23.11.2017 09:53

Вообще, работоспособность нескольких форм на одной странице сайта, притча во языцех, на двух формах стоят гуглокаптчи - reCAPTCHA2, так вот до недавнего времени тоже наблюдалась проблема совместной работы, работала только одна, буквально 2 дня назад нашёл решение проблемы. Теперь работают обе.

рони 23.11.2017 10:11

Цитата:

Сообщение от Loki
рони,
Нет, таким образом не работает,

чудеса! :)

timlsf 06.10.2018 21:31

Добрый вечер, Рони!

Давно пользуюсь вариантом из поста #5 )) отличный вариант, я считаю, можно выделять весь номер и переписывать. Но не суть.

На сайте после загрузки страницы в поле номера подставляются данные из онлайн-консультанта.
В самой программе консультанта все номера меняются на формат без скобок и пробелов +79999999999, соответственно подставляются в таком же виде. Маска применяется только при фокусе на инпут.

Перебрал все эвентлистенерс, но ничего не помогло, подскажите как решить вопрос?)

рони 06.10.2018 21:49

timlsf,
не особо понял, в чём у вас проблема.
если программа меняет значение инпута, то вызовите фокус на инпуте после этой программы, либо по таймеру.

timlsf 06.10.2018 23:06

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

в стороннем скрипте добавил такое, возможно это было очевидно, но может кому пригодится:
..
var event = new Event("input");
input.dispatchEvent(event);
..


Все заработало. спасибо за подсказку

Вадим Вадимыч 30.09.2019 22:37

Доброго времени суток, подскажите как код можно вынести в отдельный файл js ? Который подключается <script src="/assets/components/---.js"></script>

Большое спасибо!

рони 30.09.2019 22:52

Вадим Вадимыч,
в чём проблема?

Вадим Вадимыч 30.09.2019 22:59

Рони
Рони, прошу прошения разобрался, сам виноват косяк вышел!

Скрипт просто бомба, маленький не то что всем известный плагин. Спасибо вам за вклад в развитие общего дела!

seroja 03.12.2019 13:46

Приветствую!
Хелп, нужно чтобы при вводе телефона, пробел не подставлялся
<form action="" method="post">
 <input placeholder="Telefono" name="phone" type="tel" class="wv_phone" required id="phone1">
    <button>go</button>
    </form>
    <script>
window.addEventListener("DOMContentLoaded", function() {
    [].forEach.call( document.querySelectorAll('.wv_phone'), function(input) {
    var keyCode;
    function mask(event) {
        event.keyCode && (keyCode = event.keyCode);
        var pos = this.selectionStart;
        if (pos < 3) event.preventDefault();
       var matrix = "+39 __________",
            i = 0,
            def = matrix.replace(/\D/g, ""),
            val = this.value.replace(/\D/g, ""),
            new_value = matrix.replace(/[_\d]/g, function(a) {
                return i < val.length ? val.charAt(i++) || def.charAt(i) : a
            });
        i = new_value.indexOf("_");

        if (i != -1) {
            i < 5 && (i = 3);
            new_value = new_value.slice(0, i)
        }
        var reg = matrix.substr(0, this.value.length).replace(/_+/g,
            function(a) {
                return "\\d{0," + a.length + "}"
            }).replace(/[+()]/g, "\\$&");
        reg = new RegExp("^" + reg + "$");
        if (!reg.test(this.value) || this.value.length < 5 || keyCode > 47 && keyCode < 58) this.value = new_value;
        if (event.type == "blur" && this.value.length < 5)  this.value = ""
    }

    input.addEventListener("input", mask, false);
    input.addEventListener("focus", mask, false);
    input.addEventListener("blur", mask, false);
    input.addEventListener("keydown", mask, false)

  });

});
  </script>

Убираю пробел в строке
var matrix = "+39__________",

скрипт перестает работать, не дает ничего ввести...

рони 03.12.2019 14:18

seroja,
строка 23, 5 заменить на 3

seroja 03.12.2019 14:41

Цитата:

Сообщение от рони (Сообщение 516685)
seroja,
строка 23, 5 заменить на 3

Спасибо тебе добрый человек!

Alexandr Battlehater 16.01.2020 02:10

Переписал в ооп с возможностью настройки
 
Изменил код так, чтобы его можно было использовать на множестве инпутов(с разными настройками).

На странице несколько инпутов, для каждого зададим дата-атрибутом маску:
<input type="tel" name="tel1" placeholder="+38 (___) ___-__-__" data-mask="+38 (___) ___-__-__">
<input type="tel" name="tel2" placeholder="+7 ___ ___-____" data-mask="+7 ___ ___-____">
<input type="tel" name="tel3" placeholder="8 (___) ___-__-__" data-mask="8 (___) ___-__-__">
<input type="tel" name="tel4" placeholder="+380(___)___ __ __" data-mask="+380(___)___ __ __">
<input type="tel" name="tel5" placeholder="___-__-__" data-mask="___-__-__">


window.addEventListener('DOMContentLoaded', function() {
 
  /* Инициализируем маски для каждого из них */
  var inputs = document.querySelectorAll('input[type="tel"]');

  Array.prototype.forEach.call(inputs, function(input) {
    new InputMask({
      selector: input,
      layout: input.dataset.mask // читаем дата-атрибут, установленный в html и устанавливаем его значение в качестве маски
    })
  })

  /*
  Одиночный вызов может выглядеть так: 
  
  new InputMask({
      selector: '#myInput',
      layout: '+385(___) ___-__-__'
    })
  */

})

function InputMask(options) {
  this.el = this.getElement(options.selector);
  if (!this.el) return console.log('Что-то не так с селектором');
  this.layout = options.layout || '+_ (___) ___-__-__';
  this.maskreg = this.getRegexp();
  this.setListeners();
}

InputMask.prototype.getRegexp = function () {
  var str = this.layout.replace(/_/g, '\\d');
  str = str.replace(/\(/g, '\\(');
  str = str.replace(/\)/g, '\\)');
  str = str.replace(/\+/g, '\\+');
  str = str.replace(/\s/g, '\\s');
  return str;
};

InputMask.prototype.mask = function (e) {
  var _this = e.target,
      matrix = this.layout,
      i = 0,
      def = matrix.replace(/\D/g, ""),
      val = _this.value.replace(/\D/g, "");

  if (def.length >= val.length) val = def;
  _this.value = matrix.replace(/./g, function (a) {
    return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" : a;
  });

  if (e.type == "blur") {
    var regexp = new RegExp(this.maskreg);
    if (!regexp.test(_this.value)) _this.value = "";
  } else {
    this.setCursorPosition(_this.value.length, _this);
  }
};

InputMask.prototype.setCursorPosition = function (pos, elem) {
  elem.focus();
  if (elem.setSelectionRange) elem.setSelectionRange(pos, pos);else if (elem.createTextRange) {
    var range = elem.createTextRange();
    range.collapse(true);
    range.moveEnd("character", pos);
    range.moveStart("character", pos);
    range.select();
  }
};

InputMask.prototype.setListeners = function () {
  this.el.addEventListener("input", this.mask.bind(this), false);
  this.el.addEventListener("focus", this.mask.bind(this), false);
  this.el.addEventListener("blur", this.mask.bind(this), false);
};

InputMask.prototype.getElement = function (selector) {
  if (selector === undefined) return false;
  if (this.isElement(selector)) return selector;

  if (typeof selector == 'string') {
    var el = document.querySelector(selector);
    if (this.isElement(el)) return el;
  }

  return false;
};

InputMask.prototype.isElement = function (element) {
  return element instanceof Element || element instanceof HTMLDocument;
};


ссылка на jsfiddle: https://jsfiddle.net/battlehater/0oaf16bv/

рони 16.01.2020 02:44

Alexandr Battlehater,
:)

Виталикк 02.06.2020 17:22

Здравствуйте. Скажите пожалуйста, что нужно исправить в коде, для получения маски вида "+999 (___) ___ ____" если просто поправить маску, получается "+999 (" при начале заполнения. Как сделать так, чтобы скобка добавлялась не одновременно с первыми тремя цифрами?
И, можете объяснить, что нужно менять, чтобы, при изменении количества начальных цифр (например: +99; +9999) или формы маски (например: (__) ___ ____; (__) ___ __ __;) скобка появлялась не одновременно с первыми цифрами. Спасибо.

<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>
    <input  value="" class="tel">
    <input  value="" class="tel">
    <input  value="" class="tel" >
    <script>
window.addEventListener("DOMContentLoaded", function() {
    [].forEach.call( document.querySelectorAll('.tel'), function(input) {
    var keyCode;
    function mask(event) {
        event.keyCode && (keyCode = event.keyCode);
        var pos = this.selectionStart;
        if (pos < 3) event.preventDefault();
        var matrix = "+999 (__) ___ __ __",
            i = 0,
            def = matrix.replace(/\D/g, ""),
            val = this.value.replace(/\D/g, ""),
            new_value = matrix.replace(/[_\d]/g, function(a) {
                return i < val.length ? val.charAt(i++) || def.charAt(i) : a
            });
        i = new_value.indexOf("_");
        if (i != -1) {
            i < 5 && (i = 3);
            new_value = new_value.slice(0, i)
        }
        var reg = matrix.substr(0, this.value.length).replace(/_+/g,
            function(a) {
                return "\\d{1," + a.length + "}"
            }).replace(/[+()]/g, "\\$&");
        reg = new RegExp("^" + reg + "$");
        if (!reg.test(this.value) || this.value.length < 5 || keyCode > 47 && keyCode < 58) this.value = new_value;
        if (event.type == "blur" && this.value.length < 5)  this.value = ""
    }

    input.addEventListener("input", mask, false);
    input.addEventListener("focus", mask, false);
    input.addEventListener("blur", mask, false);
    input.addEventListener("keydown", mask, false)

  });

});
  </script>
</body>

</html>


https://ibb.co/TWyH87K

Если одна цифра до скобок, то открывающая скобка не захватывается.

Если больше одной цифры, получается вместе с открывающей скобкой.

https://ibb.co/6gvxZrt

От чего это зависит? И как это исправить, чтобы скобка не захватывалась при более чем одной цифре? Еще раз, спасибо.

рони 03.06.2020 15:54

Цитата:

Сообщение от Виталикк
i < 5 && (i = 3);

заменить на
i < 7 && (i = 5);
для var matrix = "+999 (__) ___ __ __",
(__) ___ __ __
i < 6 && (i = 4);
для +99 (__) ___ __ __

Пожалуйста, отформатируйте свой код!

Для этого его можно заключить в специальные теги: js/css/html и т.п., например:
[html run]
... минимальный код страницы с вашей проблемой
[/html]

О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.

рони 03.06.2020 16:01

Виталикк,
строки this.value.length < 5 если нужно уточните сами (будет 6 или 7 соответственно)

Виталикк 03.06.2020 23:29

Цитата:

Сообщение от рони (Сообщение 525364)
Пожалуйста, отформатируйте свой код!

Для этого его можно заключить в специальные теги: js/css/html и т.п., например:
[html run]
... минимальный код страницы с вашей проблемой
[/html]

О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.

Поправил. Буду знать)

misol 24.10.2020 09:36

А можно сделать так, чтоб знаки кроме "_" или сразу были, или появлялись бы сразу после введения предыдущего перед ними символа, и первая скобка или цифры уже стояли и курсор за ними?

рони 24.10.2020 10:34

Цитата:

Сообщение от misol
А можно сделать так,

не понял.

homie 09.04.2021 11:54

Очень лёгкий и мощный скрипт. Но есть один нюанс, от которого я буду аплодировать стоя - оставлять каретку там же, где пользователь вводит данные, а не сбрасывать её в конец (event.target).value.
Не задумывались об этом, рони?

romveld 15.04.2021 15:35

Привет! Слушай, а как бы сделать, чтобы на +7 нельзя было бы поставить фокус и его изменить, а то сейчас получается меняется, если человек случайно по ошибке кликнет.

рони 15.04.2021 15:53

Цитата:

Сообщение от romveld
а то сейчас получается меняется,

где код?

romveld 15.04.2021 16:01

<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
</head>

<body>
    <input  value="+7(___)___-____">
    <script>
window.addEventListener("DOMContentLoaded", function() {
function setCursorPosition(pos, elem) {
    elem.focus();
    if (elem.setSelectionRange) elem.setSelectionRange(pos, pos);
    else if (elem.createTextRange) {
        var range = elem.createTextRange();
        range.collapse(true);
        range.moveEnd("character", pos);
        range.moveStart("character", pos);
        range.select()
    }
}

function mask(event) {
    var matrix = this.defaultValue,
        i = 0,
        def = matrix.replace(/\D/g, ""),
        val = this.value.replace(/\D/g, "");
        def.length >= val.length && (val = def);
    matrix = matrix.replace(/[_\d]/g, function(a) {
        return val.charAt(i++) || "_"
    });
    this.value = matrix;
    i = matrix.lastIndexOf(val.substr(-1));
    i < matrix.length && matrix != this.defaultValue ? i++ : i = matrix.indexOf("_");
    setCursorPosition(i, this)
}

    var input = document.querySelector("input");
    input.addEventListener("input", mask, false)
});
  </script>
</body>

</html>

рони 15.04.2021 16:16

romveld,
что нужно сделать, чтоб изменить +7?

romveld 15.04.2021 16:43

https://prnt.sc/11g6c1x нужно поставить курсор в самое начало инпута и начать печатать, он изменится.

рони 15.04.2021 18:47

romveld,
ок, понятно.

Alex_medik 06.08.2021 11:00

Добрый день. Скрипт отличный - спасибо. Но подскажите, как сделать так, чтобы в модальном окне также была проверка.

рони 06.08.2021 12:30

Цитата:

Сообщение от Alex_medik
подскажите, как сделать так, чтобы в модальном окне также была проверка.

в функцию открытия окна, добавить установку проверки.

Alex_medik 06.08.2021 13:08

Отлично... теперь бы понять как это)

рони 06.08.2021 13:11

Alex_medik,

[html run]
... минимальный код страницы с вашей проблемой
[/html]

О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.

Alex_medik 06.08.2021 13:23

думаю в эту функцию нужно вставить

qfstartModalform: function(d) {
            var box = QuickForm.qfstartoverlay(d.class);
            $.ajax({
                type: 'POST',
                url: d.url,
                data: {
                    option: "com_qf3",
                    task: "ajax.qfmodal",
                    id: d.project
                },
                success: function(html) {
                    box.append(html);
                    QuickForm.verticallycentr(box, true);
                    var form = $('form', box)[0];
                    QuickForm.initiate(form);
                }
            });


Часовой пояс GMT +3, время: 22:05.