Валидация input на лету

302
19 октября 2017, 10:29

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

В качестве примера возьму ввод месяца в формате «число и 3 символа месяца». В таком случае регулярка такая:

/^[\d]{1,2}[ ]{0,1}[а-я]{0,3}$/i

Если взять событие keydown и делать return false при несовпадении с регуляркой, то проверяется прошлое значение input-а. Если использовать keyup, то его уже не перехватить — return false не сработает.

Попробовал совместить и промежуточно запоминать строку при keydown и возвращать её, если после keyup строка не прошла проверку:

$strOld = '';
$reg = /^[\d]{1,2}[ ]{0,1}[а-я]{0,3}$/i;
$('.ok').on('keydown', function(e) {
    $strOld = $(this).val();
});
$('.ok').on('keyup', function(e) {
    $val = $(this).val();
    $match = ($reg.test($val));
    if (!$match)
    {
        $(this).val($strOld);
    }
});

Но в таком случае можно нажать клавишу и держать. Проверка произойдет только в конце, на последнем символе.

Как решить такую проблему и сделать валидацию по регулярке на лету?

Answer 1

Для этого проверку стоит делать прямо в обработчике события keydown и проверять не только текущее значение input-а, но и вводимый символ. И, в зависимости от результата проверки, либо разрешать добавление символа в input, либо нет.
В простейшем случае это будет выглядеть так:

var reg = /^[\d]{1,2}[ ]{0,1}[а-я]{0,3}$/i; 
 
$(".ok").on("keydown", function(e) { 
  var newValue = this.value + e.key; 
  return reg.test(newValue); 
});
<input class="ok" /> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Дабы у пользователя был шанс исправить введённое значение, код можно усложнить (разрешить обработку backspace):

var reg = /^[\d]{1,2}[ ]{0,1}[а-я]{0,3}$/i; 
 
$(".ok").on("keydown", function(e) { 
  if (e.which == 8) 
    return true; 
  var newValue = this.value + e.key; 
  return reg.test(newValue); 
});
<input class="ok" /> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Если нужна обработка copy-paste, или возможности перемещаться по значению с помощью стрелок, или ещё что-то в том же духе, то проще и лучше воспользоваться какой-нибудь существующей библиотекой, чем, по сути, создавать свою.

Answer 2

Плагин jQuery Masked Input делает именно то, что вам нужно https://plugins.jquery.com/maskedinput/

Вы задаете маску и нельзя ввести ничего не соответствующего ей. Для вашего примера с датой можно так:

$.mask.definitions['m']='[а-я]'; 
$("#date").mask("99 mmm");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.maskedinput/1.4.1/jquery.maskedinput.min.js"></script> 
<input type="text" id="date">

READ ALSO
Ajax response есть, а данных в базе нет

Ajax response есть, а данных в базе нет

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

279
Ползунок треугольником JQuery CSS

Ползунок треугольником JQuery CSS

ЗдравствуйтеСтолкнулся с проблемой

215
не отображается блок в ios [требует правки]

не отображается блок в ios [требует правки]

Тестирую верстку сайта в browserstackНа iPhone У меня внутри подвала два div'а, при этом один не отображается совсем, пишет, что height: 0

269
Python MySQL запрос с подстановкой значений

Python MySQL запрос с подстановкой значений

Пытаюсь создать во Flask sql запрос с подстановкой параметраТакой код выдает ошибку:

266