Иногда мы хотим сделать валидацию в поле ввода для символов, которые пользователь может вводить. Другие символы не будут приниматься в поле ввода.
Вопрос: Сделайте поле ввода, которое принимает только цифры и пробелы. Также позаботьтесь о копировании-вставке (Ctrl +V ) недопустимых символов.
Первый шаг — зарегистрировать событие на метке ввода. Но какой тип события? 🤔 Мы вводим символы, поэтому keypress
событие выглядит нормально.
<input type="text" id="input"/>
const input = document.getElementById('input');
var currentInputValue = '';
input.addEventListener('keypress', function inputKeypressHandler(e) {
// keypress event on input box is listened here and this function is triggered
// which key is pressed, keyPressed = e.which || e.keyCode;
const key = e.which || e.keyCode;
// key code corresponds to digits 0-9 or space then okay👍🏼
// 0-9 key code is 48-57
// space keycode is 32
const SPACE = 32; // May be just stored somewhere
const ZERO = 48;
const NINE = 57;
// valid digit is b/w 0-9 thus invalid will be lt 0 or gt 9
const isNotValidDigit = key < ZERO || key > NINE;
// if key is not a space or not a digit prevent this event
if (key != SPACE || ( isNotValidDigit ) ) {
e.preventDefault();
}
});
Это довольно хорошее решение, но оно не предотвращает чит пасты. И это потому, что событие keypress
фиксирует только нажатие клавиши внутри поля ввода. Необходим более подходящий тип события. input
он работает для всех способов ввода, включая copy paste и drag.
var currentInputValue = '';
input.addEventListener('input', function inputInputEventHandler(e) {
// use target of event to get value of input
const target = e.target;
// we can use regex to check if current input value
// is valid input
const DIGITS_SPACE_REGEX = /^[0-9s]*$/;
// test if target.value or value of input box now is valid.
// if value is valid then update currentInputValue
// target.value else its is not value and we will
// ignore this target.value and replace it with
// previously valid value currentInputValue
DIGITS_SPACE_REGEX.test(target.value)
? ( currentInputValue = target.value )
: ( target.value = currentInputValue );
});
Это решает нашу проблему с вставкой, но здесь есть одна проблема. Если вы вставите что-то Ctrl/Cmd + V
, ваша текущая позиция курсора будет потеряна и перемещена в начало. Этого не должно происходить, и вы должны иметь возможность сохранять положение курсора.
// Track cursor position
// cursor position is changed when you type something
const cursorState = {};
input.addEventListener('keydown', function inputKeydownHandler(e) {
const target = e.target;
// record the start and end
cursorState.selectionStart = target.selectionStart;
cursorState.selectionEnd = target.selectionEnd;
});
теперь в обработчике input
.
// modify
DIGITS_SPACE_REGEX.test(target.value)
? ( currentInputValue = target.value )
: ( target.value = currentInputValue );
// to
if (DIGITS_SPACE_REGEX.test(target.value)) {
currentValue = target.value;
}
else {
target.value = current.value;
// restore cursor state
target.setSelectionRange(
cursorState.selectionStart,
cursorState.selectionEnd
);
}
Демонстрация 👨💻