Маскируем и проверяем поле телефона с помощью jQuery

Здравствуйте, дорогие читатели!

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

Маскируем и проверяем поле телефона с помощью jQuery

Что такое маскировка поля? Наверняка Вы уже сталкивались с такой штукой, что у поля телефона есть такая вот подсказка +38 (___) ___ __ __ — именно она и называется маскировкой. Преимущество маскировки над обычным тегом placeholder заключается в том, что она не исчезает после клика по заполняемому полю. Для реализации такой штуки новый велосипед мы изобретать не будем а используем готовое решение в виде jQuery плагина Masked Input — этот плагин реально крутой и получил очень широкое распространение во всем мире.

Разметка формы

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

<form action="#" method="post" class="phone_form">
	
	<div class="user_phone">
		<input type="text" placeholder="(___) ___ __ __" id="user_phone" class="rfield" />
	</div>
	
	<input type="submit" class="btn_submit" />
	
</form>

Стилизация формы

Полю для телефона я присвоил идентификатор #user_phone, и обернул его дополнительным дивом, чтобы добавить с помощью псевдоэлемента :before код страны (в моем случае Украины +38, Вы можете добавить свой, но учтите что тогда нужно увеличить или уменьшить отступ слева у поля телефона, см. ниже стили). Сразу пропишем пару строк стилей для нашей формы:

.phone_form {
	width: 300px;
	margin: 50px auto;
	position: relative;
}
#user_phone {
	width: 300px;
	box-sizing: border-box;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	padding: 8px 8px 8px 36px;
	height: 40px;
	border: 1px solid #ccc;
	font-size: 16px;
	color: #363636;
}
#user_phone:focus {
	outline: none;
	border-color: #363636;
}
input#user_phone:-moz-placeholder {
	color: #363636;
}
input#user_phone::-webkit-input-placeholder {
	color: #363636;
}
.user_phone {
	position: relative;
}
.user_phone:before {
	content: "+38";
	display: block;
	height: 40px;
	color: #363636;
	position: absolute;
	top: 6px;
	left: 7px;
	font-size: 16px;
}
.btn_submit {
	height: 30px;
	position: absolute;
	top: 5px;
	right: 5px;
	background: #363636;
	color: #fff;
	border: none;
	width: 120px;
	cursor: pointer;
	transition: all 0.5s;
	-webkit-transition: all 0.5s;
	-moz-transition: all 0.5s;
}
.btn_submit.disabled {
	color: #363636;
	background: #ccc;
}

Как Вы видите я оформил так же тег placeholder, вобще он нужен потому, что обычное поведение плагина это появление маскировки при клике по полю, когда поле теряет фокус то и маскировка тоже исчезает, чтобы такого не происходило я добавил тег placeholder. Здесь ничего сверхъестественного я не написал, поэтому идем дальше и напишем простой jQuery скрипт.

jQuery скрипт

Перед закрывающим тегом body подключим библиотеку jQuery, плагин Masked Input, ну и наш скрипт:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="jquery.maskedinput.min.js"></script>
<script src="script.js"></script>

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

(function( $ ){
	
//// ---> Проверка на существование элемента на странице
jQuery.fn.exists = function() {
   return jQuery(this).length;
}

//	Phone Mask
$(function() {
  
  if($('#user_phone').exists()){
    
    $('#user_phone').each(function(){
      $(this).mask("(999) 999-99-99");
    });
    
  }
  
  if($('.phone_form').exists()){
    
    var form = $('.phone_form'),
      btn = form.find('.btn_submit');
    
    form.find('.rfield').addClass('empty_field');
  
    setInterval(function(){
    
      if($('#user_phone').exists()){
        var pmc = $('#user_phone');
        if ( (pmc.val().indexOf("_") != -1) || pmc.val() == '' ) {
          pmc.addClass('empty_field');
        } else {
            pmc.removeClass('empty_field');
        }
      }
      
      var sizeEmpty = form.find('.empty_field').size();
      
      if(sizeEmpty > 0){
        if(btn.hasClass('disabled')){
          return false
        } else {
          btn.addClass('disabled')
        }
      } else {
        btn.removeClass('disabled')
      }
      
    },200);

    btn.click(function(){
      if($(this).hasClass('disabled')){
        return false
      } else {
        form.submit();
      }
    });
    
  }

});

})( jQuery );

Как Вы смогли заметить, у скрипта добавился такой вот блок:

 if($('#user_phone').exists()){
   var pmc = $('#user_phone');
   if ( (pmc.val().indexOf("_") != -1) || pmc.val() == '' ) {
     pmc.addClass('empty_field');
   } else {
     pmc.removeClass('empty_field');
   }
 }

В этом куске кода с помощью условий мы проверяем: если в поле есть знак «_» или оно пустое, то полю телефона добавляется класс empty_field, в противном случае это класс удаляется, функция setInterval() подхватывает это изменение практически мгновенно и кнопка сабмита формы стает активной.

Мобильная проверка поля телефона

Казалось все реально круто и красиво. Но как говорится мечтать не вредно, на сцену выходя мобильные браузеры и кто еще не сталкивался, тот столкнется с той проблемой, что javascript в них работает не ахти, тоесть нифига нормально не работает и это печально, однако не все потеряно. Благодаря HTML5 в арсенале верстальщика есть браузерные средства проверки полей формы и радует то, что мобильные браузеры их поддерживают!

Браузерная проверка очень простая, не нужно писать никаких скриптов, достаточно в разметке формы указать аттрибут required полю, которое обязательно для заполнения, стандартно это выглядит так:

<form action="#" method="post" class="phone_form">
	
	<div class="user_phone">
		<input type="tel" placeholder="(___) ___ __ __" id="user_phone" required />	
	</div>
	
	<input type="submit" class="btn_submit" />
	
</form>

Тоесть дело остается за малым, нужно организовать проверку откуда пользователь просматривает Ваш проект/сайт, это можно осуществить еще одним очень маленьким jQuery плагином, который называется is.mobile.js (он есть в папке с архивом урока), подключим его там же где и остальные скрипты:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="jquery.maskedinput.min.js"></script>
<script src="is.mobile.js"></script>
<script src="script.js"></script>

Финальный этап

Чтобы не было никаких конфликтов, разметку формы мы сразу пишем для мобильных браузеров:

<form action="#" method="post" class="phone_form">
	
	<div class="user_phone">
		<input type="tel" required pattern="[0-9_-]{10}" title="Формат: (096) 999 99 99" placeholder="(___) ___ __ __" id="user_phone" />	
	</div>
	
	<input type="submit" class="btn_submit" />
	
</form>

В форме все достаточно просто:

  • type="tel" — указываем что это поле для ввода телефона
  • required — обязательное поле
  • pattern="[0-9_-]{10}" — паттерн поля, цифры 0-9 указывают на то что вводимые символы должны быть цифрами, а {10} — на то что этих цифр должно быть 10
  • title="Формат: (096) 999 99 99" — это пожалуй самое крутое, мало того что подсказка показывается при наведении, она также вылазит если кликнули по кнопке когда ничего не заполнено(см. картинку ниже)

Маскируем и проверяем поле телефона с помощью jQuery, всплывашка HTML5

Туда-сюда, наконец-то мы добрались до того момента, что нужно грамотно оформить наш скрипт, привожу полный листинг файла script.js:

(function( $ ){
	
	//// ---> Проверка на существование элемента на странице
	jQuery.fn.exists = function() {
	   return jQuery(this).length;
	}
	
	//	Phone Mask
	$(function() {
		
    if(!is_mobile()){
    
      if($('#user_phone').exists()){
        
        $('#user_phone').each(function(){
          $(this).mask("(999) 999-99-99");
        });
        $('#user_phone')
          .addClass('rfield')
          .removeAttr('required')
          .removeAttr('pattern')
          .removeAttr('title')
          .attr({'placeholder':'(___) ___ __ __'});
      }
      
      if($('.phone_form').exists()){
        
        var form = $('.phone_form'),
          btn = form.find('.btn_submit');
        
        form.find('.rfield').addClass('empty_field');
      
        setInterval(function(){
        
          if($('#user_phone').exists()){
            var pmc = $('#user_phone');
            if ( (pmc.val().indexOf("_") != -1) || pmc.val() == '' ) {
              pmc.addClass('empty_field');
            } else {
                pmc.removeClass('empty_field');
            }
          }
          
          var sizeEmpty = form.find('.empty_field').size();
          
          if(sizeEmpty > 0){
            if(btn.hasClass('disabled')){
              return false
            } else {
              btn.addClass('disabled')
            }
          } else {
            btn.removeClass('disabled')
          }
          
        },200);

        btn.click(function(){
          if($(this).hasClass('disabled')){
            return false
          } else {
            form.submit();
          }
        });
        
      }
    }

	});

})( jQuery );

Как Вы смогли заметить у нас добавилась проверка if(!is_mobile()) — тоесть когда пользователь зашел на сайт не с мобильного устройства в разметке происходят следующие изменения: удаляются атрибуты title, pattern, required, добавляется класс rfield (проверяемое поле).

Результат

Результат наших усилий можно просмотреть кликнув по кнопке «Демо», чтобы скачать исходники нажмите кнопку «Скачать»:

И на последок пару бонусов: простая проверка полей формы на заполненость и полная проверка полей формы с валидацией email, телефона и чекбоксов!

Заключение

Теперь мы умеем не напрягаясь проверять поле телефона любой формы. Ваши пожелания, полезные и не очень правки моих скриптов, оставляйте в комментариях! Делитесь статьей в социальных сетях! Спасибо за внимание!

Обновление 26.04.2017

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

Об изменениях: скрипт is-mobile.js я отключил — бесполезная штука, masked input работает и на мобильных устройствах (версию в исходниках обновил до 1.4.1), и код скрипта получился более читаемым и понятным. Также изменилась разметка атрибут pattern у input'ов я убрал за ненадобностью.

Обновленная разметка

<form action="#" method="post" class="phone_form">
	
	<div class="user_phone">
  		<input type="tel" required placeholder="+38 (___) ___-__-__" id="user_phone" class="user-phone" title="Формат: +38 (096) 999 99 99"/>
	</div>
	
	<input type="submit" class="btn_submit" disabled />
	
</form>

Обновленный скрипт

(function( $ ){
	
  var $body;

  $(document).ready(function(){
    $body = $('body');

    $body
      .find('.user-phone').each(function(){
          $(this).mask("+38 (999) 999-99-99", {autoсlear: false});
      });

    $body.on('keyup','.user-phone',function(){
      var phone = $(this),
          phoneVal = phone.val(),
          form = $(this).parents('form');

      if ( (phoneVal.indexOf("_") != -1) || phoneVal == '' ) {
        form.find('.btn_submit').attr('disabled',true);
      } else {
        form.find('.btn_submit').removeAttr('disabled');
      }
    });

  });

})( jQuery );

Чуть объяснений: задаем переменную $body; находим все инпуты с телефонами — задаем им маску и указываем параметр не очищать при потере фокуса; отслеживаем событие нажатия кнопок в поле телефона — если заполнено то у кнопки отправки формы удаляется атрибут disabled, в противном случае добавляется.

Заключение 2

Спасибо, Вам, мои читатели и комментаторы по возможности я буду обновлять и добавлять новый контент

Добавить комментарий:

Комментарии
  1. JAH:

    Дмитрий, обновил пост и исходники, пора уже было)

  2. Дмитрий:

    Захожу на вашу ссылку «Демо» с мобильного (Android 6.0, Chrome) — скрипт не работает, когда начинаешь вводить номер — разметка пропадает и можно вбить сколько угодно цифр. Можно проверить даже в десктопном Chrome — в отладчике (F12) режим мобильного — например «Galaxy S5». Обнаружил когда пытался по вашему описанию встроить скрипт на свой сайт.Может у вас предложение, как поправить баг? Буду благодарен.

  3. Максим:

    На мобильном маска работает неправильно — курсор перескакивает на символ назад, когда доходит до разграничителя.

  4. а как сделать, чтоб в поле можно было вводить только вначале цифры?

    Допустим, маска в инпуте такая +7 (___) ___-__-__ По умолчанию скрипт позволяет вводить цифры с любого положения. Например, после скобок или в другом месте, если поставить туда курсор. Это происходит так +7 (___) _45-_6-8_ Необходимо что-то прописать, чтобы при постановке курсора не в начало, он возвращался в начало строки автоматически и не позволял вводить цифры с неположенного места.

    как такое сделать?

  5. zzhanka:

    antracit, нужно добавить код

    jQuery(function($){
    $(«#product»).mask(«99/99/9999»,{autoclear: false});
    });

    об этом можно почитать в документации: https://github.com/digitalBush/jquery.maskedinput

  6. antracit:

    Скажите, как сделать чтобы поле с телефоном не очищалось, когда случайно кликаешь мышкой за его пределами?

  7. Спасибо! Разобрался скачал простой обработчик PHP и все заработало.

  8. Николай, вы путаете валидацию формы с ее отправкой. Обычно этим занимается php-обработчик, например функция mail().

  9. Все понял спасибо, но остался вопрос куда надо вписать адрес своей почты, чтоб приходило письмо с сайта?

  10. JAH:

    в данный момент времени почти ушел с jQuery, вместо него юзаю AngularJs и для таких решений использую маску поля на AngularJs

  11. test:

    Все конечно супер — но де совершенно , у меня в хроме проскакивали при тесте возможность в часть (___) поставить курсор куда угодна если часто клацать именно в разные части этого блока — то получилось написать (_09) надо дорабатывать

  12. Alina:

    А если нужно чтобы вместо х была возможность для всех цифр кроме 7,8 .Для нулей [0-9] +380 (Х00) 000-00-00?

  13. Макс:

    Спасибо за оперативность, JAH. Действительно, это больше подойдет. Я просто неверно подошел к вопросу. Когда явно указываем маску, значит ожидаем получить номер именно в таком формате, а когда форматов море, тогда проще провести валидацию поля.
    Все равно благодарен, возможно пригодится на другом проекте.

  14. JAH:

    Макс, тогда лучше без маски, заюзать скрипт который будет разрешать вводить тока цифры в поле а инпуту добавить атрибут maxlength

    jQuery.fn.ForceNumericOnly = function() {
    	return this.each(function() {
    		$(this).keydown(function(e) {
    			var key = e.charCode || e.keyCode || 0;
    			// Разрешаем backspace, tab, delete, стрелки, обычные цифры и цифры на дополнительной клавиатуре
    			return (
    				key == 8 || 
    				key == 9 ||
    				key == 46 ||
    				key == 107 ||
    				(key >= 37 && key <= 40) ||
    				(key >= 48 && key <= 57) ||
    				(key >= 96 && key <= 105)
    			);
    		});
    	});
    }
    

    ну и на инпут повесить:

    $('.required-num').ForceNumericOnly();
    

    пока ниче другого в голову не лезет

  15. Макс:

    Да, возникла задачка. Номер может быть +7 900 444 44 44, 8 (83342) 4-44-44 или вообще 4-44-44. И я задумался…

  16. JAH:

    Макс, имеешь ввиду что код будет не 3-значным?

  17. Макс:

    Вопрос. А если пользователь захочет указать домашний телефон?

  18. Роман:

    Добрый день! Спасибо!
    а вариант php обработчика можете предложить?

  19. JAH:

    Роман,

    1. +38 заменить на +7 нужно в стилях в строке content: '+38'
    2. форма отправляется или php или ajax обработчиком
    3. если юзать телефон то скрипт не работает в нем, взамен работает стандартная браузерная проверка
  20. Роман:

    Добрый день! как заменить +38 на +7

  21. JAH:

    Дмитрий, возможно я не так выразился в посте)
    +38 имеется ввиду что в скобках пишем обычно 3 символа например: (067) поэтому код +38
    сути это не меняет

  22. Дмитрий:

    Прошу исправить статью.
    Телефонного кода страны +38 не существует. Вот ссылка https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D1%82%D0%B5%D0%BB%D0%B5%D1%84%D0%BE%D0%BD%D0%BD%D1%8B%D1%85_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D1%82%D1%80%D0%B0%D0%BD

    Код Украины +380

  23. Евгений:

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

  24. JAH:

    Евгений, достаточно вместо id юзать класс и перебирать циклом each

  25. Вся проблема в том что данная маска работает корректно только если поле для ввода телефона одно если их на странице более одного второй и последующие уже не обрабатываются это БЕДА.

  26. JAH:

    Perperik, возможно в проверке is_mobile() проверять если это iphone через navigator user agent

  27. Perperik:

    спасибо за статью! один нюанс все таки если не работает на айфоне.. может есть решение?

  28. Дмитрий:

    Да, я бы хотел узнать, как это сделать!

  29. JAH:

    Павел, Дмитрий, могу для Вас написать пост как аяксом отправлять формы (но тока для WordPress), интересно Вам будет?

  30. Да да да, как сделать что бы введенный телефон отправлялся на указанное мыло…?

  31. Дмитрий:

    Есть вопрос: как сделать что бы вводимый телефон дошел на нужную почту? Я так понял что надо .php обработчик вот сюда вставить Но у меня что-то не получается настроить. Подскажите что надо сделать?

  32. Андрей:

    Подскажите, пожалуйста, как все-таки сделать, чтоб работало несколько полей на странице?

  33. Пытался добавить в в готовую форму, чтоб была проверка номера и написание по шаблону, а именно такого вида (999) 999-99-99, но ничего не помогло, скажите почему?

  34. Стар:

    При дублировании на одной странице (лендинг) работает корректно только одна форма (поля) у остальных слетает фокус (поля для цифр)

  35. JAH:

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

  36. ЛЯЛЬКА:

    Херня полная это ваша форма тупо не дает вписать номер телефона произвольно, а нужно что бы принимала запись в любой форме а записывало в базу по шаблону ВОТ ЭТО ДРУГОЕ ДЕЛО. А тупо не давать пользователям региться тупыми скриптами это ИДИОТИЗМ.

  37. Альйоша:

    Красава, автор! Умные вещи в паблике всегда нужны) Даже забыл зачем заходил О_о

  38. JAH:

    Junk, практически в любом интернет магазине нужно такую штуку делать)

  39. Junk:

    Статья конечно полезная, осталось только сайт сделать, где это может пригодиться.