Allow to enter particular characters only

Allow to enter particular characters only

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  
    );  
 }

Demo 👨‍💻

Did you find this article valuable?

Support Aniket Jha by becoming a sponsor. Any amount is appreciated!