Best way to restrict a text field to numbers only?

RobHardgood picture RobHardgood · Sep 21, 2010 · Viewed 153.3k times · Source

I'm using the following Javascript to restrict a text field on my website to only accept numerical input, and no other letters or characters. The problem is, it REALLY rejects all other key inputs, like ctrl-A to select the text, or even any other browser functions like ctrl-T or ctrl-W while the text box is selected. Does anyone know of a better script to only allow numerical input, but not block normal commands (that aren't being directly input into the field)? Thanks Here is the code I'm using now:

function numbersonly(e, decimal) 
{
    var key;
    var keychar;

    if (window.event) 
        key = window.event.keyCode;
    else if (e) 
        key = e.which;
    else 
        return true;

    keychar = String.fromCharCode(key);

    if ((key==null) || (key==0) || (key==8) ||  (key==9) || (key==13) || (key==27))
       return true;     
    else if ((("0123456789").indexOf(keychar) > -1))
       return true;
    else if (decimal && (keychar == "."))
       return true;        
    else
       return false;
}

Edit: None of the solutions provided have solved my problem of allowing commands like ctrl-A while the text box is selected. That was the whole point of my asking here, so I have gone back to using my original script. Oh well.

Answer

Robert picture Robert · Sep 22, 2010

This is something I made another time for just numbers, it will allow all the formatters as well.

jQuery

$('input').keypress(function(e) {
    var a = [];
    var k = e.which;

    for (i = 48; i < 58; i++)
        a.push(i);

    if (!(a.indexOf(k)>=0))
        e.preventDefault();
});​

Try it

http://jsfiddle.net/zpg8k/

As a note, you'll want to filter on submit/server side as well, for sake of pasting/context menu and browsers that don't support the paste event.

Edit to elaborate on multiple methods

I see you're bouncing around the 'accepted' answer, so I'll clear something up. You can really use any of the methods listed here, they all work. What I'd personally do is use mine for live client side filtering, and then on submit and server side use RegEx as suggested by others. However, no client side by itself will be 100% effective as there is nothing stopping me from putting document.getElementById('theInput').value = 'Hey, letters.'; in the console and bypassing any clientside verification (except for polling, but I could just cancel the setInterval from the console as well). Use whichever client side solution you like, but be sure you implement something on submit and server side as well.

Edit 2 - @Tim Down

Alright, per the comments I had to adjust two things I didn't think of. First, keypress instead of keydown, which has been updated, but the lack of indexOf in IE (seriously Microsoft!?) breaks the example above as well. Here's an alternative

$('input').keypress(function(e) {
    var a = [];
    var k = e.which;

    for (i = 48; i < 58; i++)
        a.push(i);

    if (!($.inArray(k,a)>=0))
        e.preventDefault();
});​

New jsfiddle: http://jsfiddle.net/umNuB/