9

I need to set up an <input type="text" /> so that it will accept only numeric chars, backspace, delete, enter, tabs and arrows.

There's a lot of exemple around there, i started with something similar to this:

function isNumericKeyCode (keyCode){
    return ( (keyCode >= 48 && keyCode <= 57) //standard keyboard
           ||(keyCode >= 96 && keyCode <= 105)) //Numpad
}

$('#myTextBox').keydown(function(e){
         var handled = true;
         var keyCode = e.keyCode;
         switch(keyCode){
            //Enter and arrows
            case 13:
            case 37:
            case 38:
            case 39:
            case 40:
               doSomethingSpecialsWithThesesKeys();
               break;
            default:
               handled = false;
               break;
         }

         if (  !handled
            && keyCode !== 8 //backspace
            && keyCode !== 9 //tab
            && keyCode !== 46 //del
            && !isNumericKeyCode(keyCode)){

            handled = true;
         }

         return handled;
});

All that worked perfectly until I hit the "#" key. In my french canadian keyboard, the "#" has his own key (no shift implied) that returns keyCode 51, the same as the number "3".

I think that in US keyboard, the "#" is obtained by pressing shift+3, that may be why they have the same keycode.

Now I realize that I have to handle the shift and alt keys too, but that's another story.

It works differently with the jquery keypress event, which offer the charCode property, but I did not used it at first because of what the documentation says :

as the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms.

Also, I would need a workaround in that case to handle tabs, arrows and other special keys since they don't provide a charCode.

So the question is : is there a way to allow only some specifics chars using the keydown event? And that, in a way that will work independently of the keyboard layout?

As a side quest : Which browsers may be problematics with the keypress event? I mean, currently I don't really care if my website does not support IE6. I am targetting recent browsers.

Edit


As someone pointed out in the comments, this method does not allow user to "ctrl+v" a number in the input. In my particular case this is really not a requirement to be able to paste a number. But this popped something in my head, the user still can right-clic > copy some text in the input, and in that case that could be anything. The more I think of it, the more it seems to me that I will need the keydown event to handle tabs and arrows, and another event to handle the input itself.

Edit2


A lot of beautiful answers here, but the award goes to mrtsherman for the use of input and propertychange events. I will use a combination of this answer for the numeric validation, plus the keyCode event as before for the special use of arrows, tabs and enter keys.

Johnny5
  • 6,664
  • 3
  • 45
  • 78
  • 1
    You know that you can check for NaN(data) and save all those troubles, right? – gdoron Jan 18 '12 at 03:25
  • 1
    Also, what happens when the poor user tries to paste a number with CTRL+V? – Cameron Jan 18 '12 at 03:29
  • @gdoron : I suppose you mean checking the value of the textbox in the keyup event? I remembered doing something similar a couple of years ago, resulting in flashing text in the input when non numeric char where entered. I really want to _block_ other chars to be entered. – Johnny5 Jan 18 '12 at 03:30
  • @Cameron : Good catch, but in the context of my application, there's really no reason I user would want to do that. – Johnny5 Jan 18 '12 at 03:32
  • Please check e.keyCode, e.charCode and e.which. http://unixpapa.com/js/key.html – Diode Jan 18 '12 at 03:39
  • @Cameron, Don't worry about flashing text, There is nothing wrong if the user experience isn't the best when he does something wrong... – gdoron Jan 18 '12 at 03:39
  • @Diode : e.charCode is only available with the keypress event, which the jquery doc recommend _not_ to use. As for e.which, in the test I've made it returns the same as e.keyCode. – Johnny5 Jan 18 '12 at 04:02

4 Answers4

3

How about something like this. This should cover cut/paste and also rmb content. We monitor the textbox for any change in content. Then we use a regex to filter out characters based on a whitelist. This won't handle non-character key, but I think that is okay.

The \d flag says that only digits should be accepted.

http://jsfiddle.net/UXeva/1

$('#myTextBox').bind('input propertychange', function() {
    var text = $(this).val();
    if (isNaN(text)) {
       $(this).val(text.replace(/[^\d]/gi, ''));
    }
});

We bind to two events here. input for FireFox and propertychange for other browsers.

mrtsherman
  • 39,342
  • 23
  • 87
  • 111
  • Maybe I missed something, but I can enter anything in the fiddle, with firefox 9.0.1. – Johnny5 Jan 18 '12 at 14:25
  • @Johnny5 - Works fine in FF9 for me. You cannot type special characters like @#$%. – mrtsherman Jan 18 '12 at 15:05
  • @Johnny5 - I see. For some reason I read your answer as wanting to accept #'s and letters. But you only want numbers. I changed the regular expression to `\d` so that it only accepts digits. – mrtsherman Jan 18 '12 at 15:07
  • @Johnny5 - I actually changed my answer to borrow some of adeneo's code because his isNaN check prevents unnecessary execution of the regular expression. – mrtsherman Jan 18 '12 at 15:21
  • Can you explain a bit further what is the event "input propertychange"? – Johnny5 Jan 18 '12 at 16:12
  • 1
    @Johnny5 - input is an event for FireFox that occurs when the textbox value changes. The propertychange event is the same, but for other browsers. You need both to handle all browser cases. – mrtsherman Jan 18 '12 at 16:27
2

If older browsers are'nt an issue, the number input type should cover this.

<input type="number" />

If not you could use the isNaN javascript function

$("#number1").on('keyup', function() {
    var myval = $(this).val();
    if (isNaN(myval)) {
        alert('numbers only!');
    }
});

Personally I would do some regex filtering with a check to see if the value has changed, that will allow any character that does not change the value, like tabs, enter and arrows. With a regex you could also add or remove any character, or you could use \d for digits only or as below, [0-9]. Up to you really what your exact needs are?

var P;
$("#number2").on('keyup', function() {
    var V = $(this).val();
    if (V != P) {
        $(this).val(V.replace(/[^0-9]/g,''));
    }
    P=V;
});

They could also be combined to something like this:

$("#number3").on('keyup', function() {
    var V = $(this).val();
    if (isNaN(V)) {
        $(this).val(V.replace(/[^0-9]/g,''));
    }
});

Here's a FIDDLE to test them out!

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • It seems to be the solution, I will test tonight. Thanks. – Johnny5 Jan 18 '12 at 14:23
  • +1 - similar to my answer, but the isNaN check is a better implementation. If you take a look at my answer I use `input propertychange`. This will catch all input method events (typing, ctrl-v and rmb). A very good trick to know. – mrtsherman Jan 18 '12 at 15:23
1

Why not do something like this? It uses a combination of the keyup() event and isNaN(). It'll work whether the user types with the keyboard or pastes a number.

The way it works is, as soon as the text changes, it will check if the value is a number. If not, it will trim the input until it is a number. So, if you enter 25s or 25ss, you will be left with 25.

This will work with ctrl+v paste as well. It won't work with right-click paste and for that reason, I have disabled right-clicking only on the textbox.

Live Demo

The Jquery

$(document).ready(function(){
    $('#number').keyup(function(){    
        var input = this.value;
        while (isNaN(input))
        {
            input = input.substring(0,input.length-1);
            $('#number').val(input);             
        }
    });
    $('#number').bind("contextmenu",function(e){
        return false;
    });
});
Ayush
  • 41,754
  • 51
  • 164
  • 239
0

jQuery also provides a shiftkey boolean on the event object:

$('#myTextBox').keydown(function(e){
  if(e.keyCode === 51 && !e.shiftKey){
     // '3' key pressed while shift was **not** held down (not '#')
  }
});

EDIT I reread your question and changed the code above for !shiftkey

rgthree
  • 7,217
  • 17
  • 21
  • As I said in the question, there's no shift key involved when I type "#". This char has its own key on my keyboard, and no modifier is needed. – Johnny5 Jan 18 '12 at 03:34
  • 1
    @rgthree: so it would seem that your solution keeps Johnny5 in the current situation of not being able to distinguish between a "3" (no shift) and a "#" (no shift, same code as "3") – kaveman Jan 18 '12 at 03:42
  • I see. I'm not quite sure why that would produce the same keyCode. On a US keyboard, the standalone '*' key is a different keyCode than the shift + 8 key (obviously), it would seem to me that a separate '#' key should be a different keyCode than shift + 3 just the same. If I had venture a guess, it would seem that whatever drivers are sitting between your keyboard, the OS and the browser are mapping a '#' key to the 51 keyCode... (though, I'm no international keyboard expert). Could there be anything else on the event object that tells you anything special about this key being pressed? – rgthree Jan 18 '12 at 03:49
  • The more I think of it, the more it seems that keydown + keycode is not the way to go. – Johnny5 Jan 18 '12 at 03:59