34

Is it possible to restrict the input of certain characters in HTML5/JavaScript? For example, could I have an input textbox on the screen and if the user tries to type a letter in it, it wouldn't show up in the box because I've restricted it to only numbers?

I know you can use a pattern which will be checked on submit, but I want the "bad" characters to just never be entered at all.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
user1513171
  • 1,912
  • 6
  • 32
  • 54
  • I'm not sure how you could completely restrict them, but maybe you could add an event on keyup (or keydown even) to check the field's value and remove non-number characters? – gotohales Nov 28 '12 at 14:30
  • Yes, thank you. That is the plan, I was just wondering if there was built in functionality for this. – user1513171 Nov 28 '12 at 15:15

11 Answers11

15

The input textbox

<input type="text" onKeyDown="myFunction()" value="" />

JavaScript

function myFunction() {
    var e = event || window.event;  // get event object
    var key = e.keyCode || e.which; // get key cross-browser

    if (key < 48 || key > 57) { //if it is not a number ascii code
        //Prevent default action, which is inserting character
        if (e.preventDefault) e.preventDefault(); //normal browsers
        e.returnValue = false; //IE
    }
}
Unai Vivi
  • 3,073
  • 3
  • 30
  • 46
jonhopkins
  • 3,844
  • 3
  • 27
  • 39
  • 2
    this also blocks any control keys! – CodeXP Feb 13 '19 at 16:53
  • This should be the accepted answer, although, I do note a little tweak below. – Kevin Waterson Jun 04 '21 at 09:47
  • 1
    I found that using onKeyPress yields the expected results, whereas onKeyDown makes it necessary to check for arrow keys, shift, etc. So try using onKeyPress instead and this solution works as expected. [I added my answer below](https://stackoverflow.com/a/70176712/14624235) – Vlad L Nov 30 '21 at 22:22
  • `KeyboardEvent.keyCode` is deprecated now. Instead, you can use the `element.input` event and a regex replace. See [my answer](https://stackoverflow.com/a/62540570/3437608) below. – Cullub Dec 22 '21 at 17:05
  • This approach does not prevent restricted characters entered with copy&paste or drag&drop, and does not support different keyboard layouts. [My answer explains how the `beforeinput` event encapsulates those different methods.](https://stackoverflow.com/a/74549391) – FWDekker Nov 24 '22 at 14:21
12

Use html5 pattern attribute for inputs:

<input type="text" pattern="\d*" title="Only digits" />

OR

Use html5 number type for input :

<input type="number" />
Akhil Sekharan
  • 12,467
  • 7
  • 40
  • 57
  • 2
    Just a note, according to http://html5pattern.com/ pattern is only this is only supported by "Firefox 4b7 & Chrome 6 & Opera 9 & Safari 5.0.3" and up. – gotohales Nov 28 '12 at 14:34
  • 78
    This allows you to enter anything but then when you submit it tells you it's wrong. Not what I'm looking for. – user1513171 Nov 28 '12 at 15:02
  • 3
    The problem with discarding invalid characters _as you type_ is that users may think their keyboard is broken. It might be better to wait until they submit the input to validate it and then reject it/give a message. Maybe there's something available to reject a key immediately _with_ a persistent message that stays visible until several good characters have been entered? – Phil Perry May 16 '14 at 18:03
  • 3
    like the poster, I want to restrict input to only numbers. Not too concerned if a user entering a telephone number thinks his keyboard is broken because a letter doesn't appear. Bad to assume, but I'm assuming my users know that telephone numbers are made up of numbers. – Jimmy Long Nov 06 '19 at 22:09
  • This is not an answer - please read the question, the OP is already aware of `pattern`. – mikemaccana Sep 10 '22 at 14:47
  • You can [use the `beforeinput` event to stop the data from being entered in the first place](https://stackoverflow.com/a/74549391/3307872). – FWDekker Nov 24 '22 at 14:20
7

To slightly improve off of jonhopkins excellent answer, I added backspace and delete key acceptance like so:

    function inputValidate(){
   var e = event || window.event;  
   var key = e.keyCode || e.which;                              
   if (((key>=48)&&(key<=57))||(key==8)||(key == 46)) { //allow backspace //and delete
           if (e.preventDefault) e.preventDefault(); 
           e.returnValue = false; 
   }
 }
Community
  • 1
  • 1
wbt11a
  • 798
  • 4
  • 12
  • 2
    Nice. I did not think of those being needed. – jonhopkins Jun 27 '14 at 13:51
  • 1
    This should probably include 37 (left-arrow) and 39 (right-arrow) so that the user can move between characters and shift-select the text. – Aaron Newton Nov 06 '15 at 01:00
  • Hmm yeah at that point (2+) I'd say just create an array of allowed characters to check against. – wbt11a Nov 09 '15 at 22:18
  • 2
    also there is a ! missing, that IF is actually checking for the allowed keys and prevent the numbers to be typed – Pablo Pazos Oct 23 '20 at 17:33
  • This approach does not prevent restricted characters entered with copy&paste or drag&drop, and does not support different keyboard layouts. [My answer explains how the `beforeinput` event encapsulates those different methods.](https://stackoverflow.com/a/74549710/) – FWDekker Nov 23 '22 at 16:03
  • This approach does not prevent restricted characters entered with copy&paste or drag&drop, and does not support different keyboard layouts. [My answer explains how the `beforeinput` event encapsulates those different methods.](https://stackoverflow.com/a/74549391) – FWDekker Nov 24 '22 at 14:21
7

For Restricting Characters symbols like '-' and ','

<input type="text" pattern="[^-,]+">

for restricting numbers

<input type="text" pattern="[^0-9]+">

for restricting letters of the alphabet

<input type="text" pattern="[^a-zA-Z]+">
Community
  • 1
  • 1
  • 1
    This is also not an answer, see the question "I know you can use a pattern which will be checked on submit, but I want the "bad" characters to just never be entered at all." – mikemaccana Sep 04 '22 at 16:39
6

KeyboardEvent.keyCode is deprecated, so here's a solution using the HMLElement.input event. This solution uses a simple regex, and handles copy-paste nicely as well by just removing the offending elements from any input.

My regex: /[^\w\d]/gi

  • Matches anything not (^) a word character (\w: a-z) or a digit (\d: 0-9).
  • g modifier makes regex global (don't return after first match)
  • i modifier makes regex case insensitive

With this regex, special characters and spaces won't be allowed. If you wanted to add more, you'd just have to add allowed characters to the regex list.

function filterField(e) {
  let t = e.target;
  let badValues = /[^\w\d]/gi;
  t.value = t.value.replace(badValues, '');
}

let inputElement = document.getElementById('myInput');
inputElement.addEventListener('input', filterField);
<input id="myInput" type="text" style="width: 90%; padding: .5rem;" placeholder="Type or paste (almost) anything...">
Cullub
  • 2,901
  • 3
  • 30
  • 47
  • If you wanted to add a message on bad input for the user, you could check inside the `filderField` function for whether a match was detected, and if so, show the message with a short timeout. – Cullub Dec 22 '21 at 17:07
2
//improved wbt11a function

function numberFieldStrictInput(allowcomma, allownegative) {
    var e = event || window.event;  // get event object
    var key = e.keyCode ||`enter code here` e.which; // get key cross-browser


    if(key==8 || key==46 || key == 9 || key==17 || key==91 || key==18 || 
            key==116 || key==89 || key==67 || key==88 || key==35 || key==36) //back, delete tab, ctrl, win, alt, f5, paste, copy, cut, home, end
        return true;

    if(key == 109 && allownegative)
        return true;

    if(key == 190 && allowcomma)
        return true;

    if(key>=37 && key<=40) //arrows
        return true;

    if(key>=48 && key<=57) // top key
        return true;

    if(key>=96 && key<=105) //num key
        return true;
    console.log('Not allowed key pressed '+key);

    if (e.preventDefault) e.preventDefault(); //normal browsers
        e.returnValue = false; //IE

}   

//on input put onKeyDown="numberFieldStrictInput(1,0)"
2

What about this (it supports special keys, like copy, paste, F5 automatically)?

function filterNumericInput() {
    var e = event || window.event;  // get event object
    if (e.defaultPrevented) {
      return;
    }
    const key = e.key || e.code;
    if ((e.key.length <= 1) && (!(e.metaKey || e.ctrlKey || e.altKey))) {
      if (!((key >= '0' && key <= '9') || (key === '.') || (key === ',') || (key === '-') || (key === ' '))) {
        if (e.preventDefault) {
          e.preventDefault();
        } else {
          e.returnValue = false;
        }
      }
    }
}
AGPX
  • 364
  • 3
  • 10
1

Limit input to letters, numbers and '.' (for React users only)

Here is my simple solution, I couldn't find a better solution for React and made my own. 3 steps.

First, create a state.

const [tagInputVal, setTagInputVal] = useState("");

Then, use the state as input value (value={tagInputVal}) and pass the event to the onChange handler.

<input id="tag-input" type="text" placeholder="Add a tag" value={tagInputVal} onChange={(e) => onChangeTagInput(e)}></input>

Then, set the value of the event inside onChange handler.

function onChangeTagInput(e) {
    setTagInputVal(e.target.value.replace(/[^a-zA-Z\d.]/ig, ""));
}
Mehedi
  • 281
  • 3
  • 5
1

Since many of the answers above didn't satisfy me, I propose my solution which solves the problem of the input event being uncancelable by storing the previous value in a custom attribute, and restoring it in case the pattern is not matched:

const input = document.querySelector('#input-with-pattern')
input.addEventListener('keyup', event => {
  const value = event.target.value;
  if (!/^[a-zA-Z]+$/.test(value) && value !== '') { // it will allow only alphabetic
    event.target.value =  event.target.getAttribute('data-value');
  } else {
    event.target.setAttribute('data-value', value);
  }
});
<input id="input-with-pattern">
0

var keybNumberAndAlpha = new keybEdit(' 0123456789abcdefghijklmnopqrstuvwxyz');

function keybEdit(strValid, strMsg) {
    var reWork = new RegExp('[a-z]','gi');  // Regular expression\
    // Properties
    if(reWork.test(strValid))
            this.valid = strValid.toLowerCase() + strValid.toUpperCase();
    else
            this.valid = strValid;
    if((strMsg == null) || (typeof(strMsg) == 'undefined'))
            this.message = '';
    else
            this.message = strMsg;
    // Methods
    this.getValid = keybEditGetValid;
    this.getMessage = keybEditGetMessage;
    function keybEditGetValid() {
            return this.valid.toString();
    }
    function keybEditGetMessage() {
            return this.message;
    }
}

function editKeyBoard(ev, objForm, objKeyb) {
    strWork = objKeyb.getValid();    
    strMsg = '';       // Error message
    blnValidChar = false;     // Valid character flag
    var BACKSPACE = 8;
    var DELETE = 46;
    var TAB = 9;
    var LEFT = 37 ;
    var UP = 38 ;
    var RIGHT = 39 ;
    var DOWN = 40 ;
    var END = 35 ;
    var HOME = 35 ;
    
    // Checking backspace and delete  
    if(ev.keyCode == BACKSPACE || ev.keyCode == DELETE || ev.keyCode == TAB 
        || ev.keyCode == LEFT || ev.keyCode == UP || ev.keyCode == RIGHT || ev.keyCode == DOWN)  {
            
        blnValidChar = true;
        
    }
    
    if(!blnValidChar) // Part 1: Validate input
            for(i=0;i < strWork.length;i++)
                    if(ev.which == strWork.charCodeAt(i) ) {
                            blnValidChar = true;
                            break;
                    }
                            // Part 2: Build error message
    if(!blnValidChar) 
    {
                //if(objKeyb.getMessage().toString().length != 0)
                    //  alert('Error: ' + objKeyb.getMessage());
            ev.returnValue = false;  // Clear invalid character
            
            
                ev.preventDefault();
        
            objForm.focus();      // Set focus
    }
}
<input type="text"name="worklistFrmDateFltr" onkeypress="editKeyBoard(event, this, keybNumberAndAlpha)" value="">
  • 1
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – kayess Apr 01 '16 at 10:46
  • 1
    Made it little flexible so that you can add which ever character you want to allow for input – Sampathkumar Dhawale Apr 01 '16 at 11:17
0

I found that onKeyDown captures Shift key, arrows, etc. To avoid having to account for this, I could filter out character input easily by subscribing to onKeyPress instead.

Vlad L
  • 1,544
  • 3
  • 6
  • 20