Sometimes we want to make validations on an input box for characters that user can type. And other characters will not be entertained in the input box.
Question: Make a input box that accepts digits and spaces only. Also, care for copy-paste (Ctrl +V ) of invalid characters.
The first step is to register an event on the input tag. But what event type? ๐ค We are typing characters into it so keypress
the event looks fine.
<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();
}
});
This is a pretty good solution but this doesnโt prevent paste cheats. And that is because the keypress
event only records key pressed inside the input box. A better event type is required. input
it runs on all input ways including copy paste and 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-9\s]*$/;
// 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 );
});
This solves our problem of paste but there is one problem here. Say you paste something Ctrl/Cmd + V
your current cursor position will be lost and moved to starting. This must not happen and you must be able to retain cursor position.
// 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;
});
now in input
handler
// 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
);
}
Top comments (0)