Javascript Regex to limit Text Field to only Numbers (Must allow non-printable keys)
Asked Answered
R

6

9

I have received PHP/JS code from previous developer and I need to add number validation to a Mobile Number field. I already have the HTML validation in place but I need to add that if someone presses an invalid key, that it doesn't get displayed only to highlight the field later in red because it contains invalid input.

I've seen many regex's used and tried them but they had an either/or effect from what I need which is: If a letter or special character is entered, do not accept and do not display, all other input (digits, keys) is accepted (I need the invalid character not be displayed at all, not displayed and then erased). The regex that is working the most now is this:

function filterNonDigits(evt)
{
  var event = evt || window.event;
  var keyentered = event.keyCode || event.which;
  keyentered = String.fromCharCode(keyentered);

  //var regex1 = /[0-9]|\./;
  var regex2 = /^[a-zA-Z.,;:|\\\/~!@#$%^&*_-{}\[\]()`"'<>?\s]+$/;

  if( regex2.test(keyentered) ) {
    event.returnValue = false;
    if(event.preventDefault) event.preventDefault();
  }

When I used the commented regex1 (with the IF condition reversed), naturally it limited input to only digits thus preventing all keys such as Delete, BackSpace, etc. When using regex2, I still can't press Delete or the digits from the numpad.

So my question is, can the above code be modified to accept only digits but also allow keys? Another important point is that I need a method that doesn't use keycodes (8, 24 etc) for those key, in order to make sure all keyboard types can be used.


New Update:

So my solution is as follows: If the "oninput" property exists, I use the solution provided by Ehtesham and if it doesn't, the backup uses the solution provided by Rohan Kumar. So it's something like this:

if (obj.hasOwnProperty('oninput') || ('oninput' in obj)) 
{
    $('#mobileno').on('input', function (event) { 
        this.value = this.value.replace(/[^0-9]/g, '');
    });
} 
else 
{
    $('#mobileno').on('keypress',function(e){
        var deleteCode = 8;  var backspaceCode = 46;
        var key = e.which;
        if ((key>=48 && key<=57) || key === deleteCode || key === backspaceCode || (key>=37 &&  key<=40) || key===0)    
        {    
            character = String.fromCharCode(key);
            if( character != '.' && character != '%' && character != '&' && character != '(' && character != '\'' ) 
            { 
                return true; 
            }
            else { return false; }
         }
         else   { return false; }
    });
}

Thanks.

Rosol answered 30/9, 2013 at 11:31 Comment(1)
so i ran this on IE9, and looks good. If i simulate IE8 via Browser/DocumentMode though it fails... like $('#mobileno').get(0).hasOwnProperty('oninput') returns a javascript error "Object doesn't support property or method 'hasOwnProperty'". Anyway to make the check work on IE7/8?Decapolis
G
35

The best method here is to use input event which handles all your concerns. It is supported in all modern browsers. With jQuery you can do like following. Handles all cases pasting the value with mouse/keyboard backspace etc.

$('.numeric').on('input', function (event) { 
    this.value = this.value.replace(/[^0-9]/g, '');
});

See it here

You can check if input event is supported by checking if the input has this property if not you can use onkeyup for older browsers.

if (inputElement.hasOwnProperty('oninput')) {
    // bind input
} else {
    // bind onkeyup
}
Graecize answered 1/10, 2013 at 8:45 Comment(3)
Thanks for the reply, this actually looks promising for what I need. How would I get "inputElement"? Would "document.getElementById" work ? Edit1: I tried it and it's returning False in FF24.0 and IE10. Is that normal behaviour? Edit2: I think adding (hasOwnProperty || 'property' in inputElement) might be a good idea for browsers where hasOwnProperty is not supported. Does that work?Rosol
Okay great thanks, this seems to be working great so far. One small issue, if I have my cursor in the middle of the filed value and I press on an invalid character, the cursor moves to the end of field. This also happens in Chrome when I try to delete a character in the middle. Can anything be done about that or is it normal?Rosol
@Ehtesham, I tried your code there is a bug with respect to mobile browser usage. Can u help me resolve it? Problem: after typing numbers, if i press spacebar it erases the typed number!. how to fix this?Handshake
F
9

A nice solution is described in a previous post:

jQuery('.numbersOnly').keyup(function () { 
    this.value = this.value.replace(/[^0-9\.]/g,'');
});
Fetterlock answered 30/9, 2013 at 11:53 Comment(4)
The regex includes a \., which OP explicitly listed in the disallow regex. Also, usually I wouldn't recommend a jQuery solution if the original post does not include jQuery in the question or tags.Eusebiaeusebio
Thanks for the reply to both of you. I actually have tried this approach but was asked to find a way without the letter displaying and then erased which had me looking into other ways. Also jQuery is okay but I didn't include it since my question was more about the JS function to use.Rosol
Ah, that calls for a different approach. Could you add that to your original question? It might prevent people from adding more answers that don't fit your needs.Eusebiaeusebio
Thanks for the hint. I actually thought I had by mentioning that I don't want the invalid letter to display but I can see that it can be taken as it being ok if it displays and then is removed. I'll edit that now.Rosol
J
3

Try it like,

CSS

.error{border:1px solid #F00;}

SCRIPT

$('#key').on('keydown',function(e){
    var deleteKeyCode = 8;
    var backspaceKeyCode = 46;
    if ((e.which>=48 && e.which<=57) ||
         (e.which>=96 && e.which<=105)  || // for num pad numeric keys
         e.which === deleteKeyCode || // for delete key,
             e.which === backspaceKeyCode) // for backspace
         // you can add code for left,right arrow keys
    {
        $(this).removeClass('error');
        return true;
    }
    else
    {
        $(this).addClass('error');
        return false;
    }
});

Fiddle: http://jsfiddle.net/PueS2/

Jair answered 30/9, 2013 at 11:50 Comment(9)
Thanks for the reply. My only issue with using keyCodes is if someone is using a non-US keyboard which may have different keyCodes for certain keys. I was looking into RegEx to avoid that issue.Rosol
Oh but if that is the case, look at this: #10532477. Just use the keypress event instead of keyup/downEusebiaeusebio
Ah hadn't thought of that (newbie to JS and jQuery here). So would just substituting "keydown" with "keypress" in the code that Rohan Kumar has provided do the trick?Rosol
I have another issue now though which is that the dot, % and & characters have the same codes as backspace and 2 of the arrow keys (which I allow) so dot, % and & are also accepted.. And one more thing which is in Mozilla FF, I can't type at all in the field. Any thoughts?Rosol
Okay the FF issue is fixed, I had used "e.keyCode" instead of "e.which" which FireFox seems to have an issue with. Now I just have the problem of certain invalid characters that have the same code as non-printable keys. Ones I've noticed so far are (%,&,.,') Any idea how to work around that? Thanks.Rosol
You can find the codes from api.jquery.com/event.which or cambiaresearch.com/articles/15/javascript-char-codes-key-codes with shift key and add them in if condition and if the keys is valid then it will shown in input box otherwise the input box would be red as shown in fiddle also e.which works in FF and e.keyCode works in some browsers like IE You cn use it like var keyunicode=e.charCode || e.keyCode and use keyunicode in if conditionJair
Thanks for the links and the tips about browser compatibility. So I'll add what I have so far to the OP, it works well on first testing, any improvements or optimizations?Rosol
I've used this method as backup in my solution so I will upvote as soon as I have enough reputation. Thanks.Rosol
@Rosol use input event instead of keyup or keydownJotunheim
E
2

Instead of checking for the event keyCode, why don't you just check for changes inside the actual input and then filter out non-numbers?

This example uses keyup so that it can read what was actually entered, which means the character is briefly displayed and then removed, but hopefully you get my gist. It might even give the user feedback that the character is not allowed. Either way I think this is the easiest setup, let me know if you need more help fleshing this out.

function filterNonDigits(evt)
{
  var event = evt || window.event;
  var val = event.target.value;
  var filtered = val.replace(/[^0-9]/g, '');

    if(filtered !== val) {
      event.target.value = filtered;
      event.target.className += " error";
    }
}

http://jsfiddle.net/mEvSV/1/

(jquery used solely to easily bind the keyup function, you won't need it for your actual script)

Eusebiaeusebio answered 30/9, 2013 at 11:52 Comment(2)
Thanks for the reply. As I mentioned in my comment on the previous reply, I have tried this approach but am looking for another precisely because of that "the character is briefly displayed and then removed" consequence.Rosol
Thank you for your help in the different issues that came up while I was trying out the different solutions provided :)Rosol
S
1

/\d/ is equivalent to the above described /[0-9]/. src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#special-digit

Spur answered 21/3, 2019 at 22:2 Comment(0)
P
0

This is a bit more concise...

this.value = this.value.replace(/\D/gm, '');
Porosity answered 3/3, 2020 at 21:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.