4

I'm working on a textfield working with the kind of validation that wouldn't let you enter other than numeric values. As so, my initial code looked quite simple and similar to this:

$(textField).onKeyPress(function(e) {
    if (e.which < 48 && e.which > 57)
        e.preventDefault();
});

This is fairly strightforward, but turns that (in the latest version of all browsers) Firefox will make this also prevent movement with the arrow keys and delete/backspace keys, whereas the other browsers would not.

Looking around I found that I would need to also check for these keys, and check for different properties exposed in the e event reference.

My final code looks something like this:

$(textField).onKeyPress(function(e) {
    var code = e.which || e.keyCode;
    if (code > 31  // is not a control key
        && (code < 37 || code > 40) // is not an arrow key
        && (code < 48 || code > 57) // is not numeric
        && (code != 46) // is not the delete key
    )
        e.preventDefault();
});

However, this feels to be too much to solve a fairly simple problem as just preventing non-numeric.

What am I doing wrong? Which is the best practice in terms of this kind of validation?

Alpha
  • 7,586
  • 8
  • 59
  • 92
  • 1
    do you care if user copy and paste non-number text to the input box? how about decimal and negative numbers? do you allow those? – Ray Cheng Jun 02 '12 at 22:42
  • @RayCheng Good point. It would be really good to take care of those cases as well, and so I see value in the keyUp solutions provided. I'm amazed at seeing that nobody is using the keyPress approach -- which seems more natural to me. Decimals and negative can be taken out of this approach, my range of allowed characters is plainly digits (0-9). – Alpha Jun 02 '12 at 23:10
  • there could be side effects if you use `keypress` or `keydown` because if user keeps the key pressed, the event is repeated and the code gets called multiple times. `keyup` is only executed once. – Ray Cheng Jun 02 '12 at 23:18
  • @RayCheng see my update below: you can use simple `propertychange` to deal with it :) hope that help both of you – Tats_innit Jun 02 '12 at 23:37

3 Answers3

4

We'll respond to both keypresses, and the blur event. When somebody press a key, we check to see if the key entered is a number. If it is, we permit it. Otherwise, we prevent it.

If the field is blurred, we remove any non-numerical values, and all those values that follow. This will prevent the user from pasting in non-numerical strings:

$("#textfield").on("keypress blur", function(e){
    if ( e.type === "keypress" )
        return !!String.fromCharCode(e.which).match(/^\d$/);
    this.value = this.value.replace(/[^\d].+/, "");
});

Demo: http://jsfiddle.net/jonathansampson/S7VhV/5/

Sampson
  • 265,109
  • 74
  • 539
  • 565
  • Thanks! Won't this look "jumpy" to the user? – Alpha Jun 02 '12 at 22:40
  • Exactly. Don't fiddle with blocking the event, just adjust the result after the fact. – tdammers Jun 02 '12 at 22:40
  • @Alpha You're right. I've taken another approach above, and am working on a solution for those who copy/paste a number as well. – Sampson Jun 02 '12 at 23:15
  • after i typed in `123` and then copy and paste `a99` with mouse, i end up `12399`. it'll be nice to have `123` instead. but overall, it's a good approach. – Ray Cheng Jun 02 '12 at 23:27
  • @RayCheng Thank you for the great input. I've updated the solution to cover key-entry, and pasting. – Sampson Jun 03 '12 at 00:16
  • @Johathan Sampson, this is elegant! – Ray Cheng Jun 03 '12 at 00:51
  • @JonathanSampson I agree, this looks really elegant and straightforward. However, I did try it out on Chrome and does not seem to handle the copy/paste scenario. I wonder if we could mix it with Tats_innit solution. – Alpha Jun 04 '12 at 22:00
  • @Alpha I just tested it in Chrome and it worked fine. What were you trying that didn't work? – Sampson Jun 06 '12 at 02:51
  • @JonathanSampson Chrome Dev (21.0.1163.0). Try this scenario: input "12", copy "a" in your clipboard. Paste it between 1 and 2. Tab out of the field. You'll end up with a "1". – Alpha Jun 11 '12 at 22:46
  • @Alpha What use-case would have you pasting between numbers like that? Of course my script fail there since it assumes you will be pasting *after* values already existing. The only other method would be to store the last valid number as a data-attribute and use it whenever a paste results in bad characters. – Sampson Jun 11 '12 at 23:25
  • @JonathanSampson You're right. I'm thinking that a user may paste text not knowing that has text on the clipboard, thus leaving to a invalid result. While this is valid, isn't it easy to fix? What if you changed `/[^\d].+/` to `/[^\d]/g`? – Alpha Jun 11 '12 at 23:28
  • @Alpha I actually had the code working like this in the past, but another user complained about it ;) See Ray's post above where having "123" and then pasting "a99" resulted in "12399" when he would have preferred to see "123," meaning it removes everything after the first legit number. – Sampson Jun 11 '12 at 23:31
  • @JonathanSampson Got it. Still, this is the most elegant code to this matter. I think it is far beyond acceptable. Thank you so much for all the effort. – Alpha Jun 11 '12 at 23:57
  • @Alpha I will try to create another version that stores the last-good number, and falls back on it in the event a paste results in corrupt values. – Sampson Jun 11 '12 at 23:59
  • Great code. The only thing I noticed is that it's preventing the Enter key from pressing. Just add an "if(e.which == 13) return true;" before the match() and everything works. – csdaraujo Nov 07 '12 at 20:22
2

Working demo http://jsfiddle.net/Pb2eR/23/ Updated Copy/Paste demo: http://jsfiddle.net/Pb2eR/47/ (In this demo wit you copy paste string with characters it won't allow else it will allow number to be copy pasted: tested in safari)

Demo for arrow key to work http://jsfiddle.net/gpAUf/

This will help you.

Note: in this version even if you copy paste it will set it to empty input box, tested in safari lion osx :)

Good Link: [1] How to allow only numeric (0-9) in HTML inputbox using jQuery?

code

$(".hulk").keyup(function(){    
    this.value = this.value.replace(/[^0-9\.]/g,'');    
});
​

html

<input type="text" class="hulk" value="" />
​

Update for copy paste stuff

$(".hulk").keyup(function(){

    this.value = this.value.replace(/[^0-9\.]/g,'');

});

$(".hulk").bind('input propertychange', function() {

     this.value = this.value.replace(/[^0-9\.]/g,'');
});​

code from another demo

$(".hulk").bind('input propertychange', function(event) {
         if( !(event.keyCode == 8    // backspace
        || event.keyCode == 46      // delete
        || (event.keyCode >= 35 && event.keyCode <= 40)     // arrow keys/home/end
        || (event.keyCode >= 48 && event.keyCode <= 57)     // numbers on keyboard
        || (event.keyCode >= 96 && event.keyCode <= 105))   // number on keypad
        ) {
            event.preventDefault();     // Prevent character input
    }
     this.value = this.value.replace(/[^0-9\.]/g,'');
});

​
Community
  • 1
  • 1
Tats_innit
  • 33,991
  • 10
  • 71
  • 77
  • how about copy and paste with mouse? – Ray Cheng Jun 02 '12 at 23:02
  • i was on FF12 and IE9. you code doesn't get executed when i copy and paste with mouse. also, how about users enter `-1.2.3.4`? – Ray Cheng Jun 02 '12 at 23:13
  • @RayCheng cool got you, see my update above you can do it simple way by using `propertyChnage` – Tats_innit Jun 02 '12 at 23:33
  • @Tats_innit Thanks. It is a really good approach and does not look jumpy (specifically, the copy/paste one). Still, it has other quirks. For example, at least in Chrome it won't let you use arrow keys to move through the field. As you see, little quirks make it more complex and more complex, that is why I am asking about the "correct" approach to take. – Alpha Jun 04 '12 at 21:57
  • 1
    O, also. I'm dazzled about the class "hulk". Anything to do with the Marvel character? – Alpha Jun 04 '12 at 21:57
  • Yo @Alpha Cool bruv - will take a look into this - bit busy at the moment :) Yep hulk is used in the reference of the green dude that is a Marvel character :P – Tats_innit Jun 04 '12 at 22:26
  • @Tats_innit Sure, no problem. Sorry if I sounded like hurrying you, I didn't mean to at all. – Alpha Jun 05 '12 at 13:44
  • Hiya @Alpha not a probs man `:)` no sorry taken; okies fixed it Updating my post as well: **DEMO** http://jsfiddle.net/gpAUf/ this will allow arrow keys just fine, cheers :) – Tats_innit Jun 06 '12 at 02:11
-1

this will allow both int. it also removes text if user copy and paste with mouse.

$(document).ready(function () {
    $('#textfield').bind('keyup blur', function (e) {
        if (e.type == 'keyup') {
            if (parseInt($(this).val()) != $(this).val()) {
                $(this).val($(this).val().slice(0, $(this).val().length - 1));
            }
        } else if (e.type == 'blur') {
            $(this).val('');
        }
    });
});
Ray Cheng
  • 12,230
  • 14
  • 74
  • 137