event.preventDefault() not working in the keypress event on Android

Go To StackoverFlow.com

2

Most web developers know that to restrict only numbers to a form input, you can do something like this:

$(function() {
    $("#foobar").keypress(function(e) {
    if($.inArray(e.which, range(48, 57)) == -1) {
        e.preventDefault();
        return false;
    }
    });
});

function range(start, end) {
    var range = [];

    for(var i = start; i <= end; i++) {
        range.push(i);
    }

    return range;
}

Unfortunately, this does not quite get the job done on an Android with the default browser. (iPhone and Other Android browsers have not been tested, so they could suffer from the same issue. Tested on an iPhone 4S, which did not have this issue.)

On an Android, let's say you first type "f". Nothing happens. Awesome. Wait just a minute. You then type "a". What happens? The "f" is put into the input field! You type "c", the "a" is put into the field. And so on. Whatever the previously-entered character is, that's what's put into the field.

Here's a jsFiddle that demonstrates the issue.

The fiddle works fine on a desktop, but try it on Android (phone or emulator). I've tested with Android 2.3.6 and 2.2.

Anyone run into this before? Any direction would be greatly appreciated! For now, the workaround is to remove non-numeric characters immediately afterwards (in the keyup event).

Update: Here is a fiddle that shows that preventDefault() is being reached. The problem seems to be that rather than preventing, it's simply delaying (until the next event).

2012-04-03 22:36
by The Awnry Bear
FYI, this does not allow back forward backspace etc.. - TimWickstrom.com 2012-04-03 22:42
I just posted the bare minimum to reproduce the issue. In our "real" code, we are also allowing backspace, delete, tab, escape, Ctrl+A, home, end, left and right. : - The Awnry Bear 2012-04-03 22:54
From what I can tell, this seems to be caused by the auto-complete/correct. E.g if I type an only a is displayed, I tap Android and it fills in Androi. It would seem only the last letter is seen & processed. Not to dissimilar to the paste event (which also would allow entering invalid characters) - Chris Chilvers 2012-06-13 10:56
The only thing is that we have autocomplete="false" on the field. (It's just not in the jsFiddle.) Perhaps Android is ignoring the attribute - The Awnry Bear 2012-06-13 14:08
Has anyone come up with a solution for this issue? I'm building a mobile site and I'm using a jquery plugin that lets you mask input fields, and checks input values in both the keydown and keypress events. It has similar behavior to what you describe with the autocomplete - Derek 2013-04-30 21:34
@Derek, not really no. In my case I ended up using <input type="number"> as @keystorm describes in his answer below. It's a shame this issue exists. If you end up finding an actual solution please come back and post here - The Awnry Bear 2013-05-02 16:15


2

A completely different approach would be using <input type="number"> and relying on the browser to provide the appropriate interface/filtering (which mobile browsers are prone to). It does not fix the code, but should circumvent the problem, which looks like a bug, to be honest.

2012-04-04 00:10
by keystorm
That's a good idea actually. On Android that gives you a number-only keypad, so this could be a better approach. (Does not prevent invalid input from a hardware keyboard, but that's what server side validation is for.) I'll run it by my team tomorrow. Thanks - The Awnry Bear 2012-04-04 00:39


1

A wild guess: Maybe Androids register the input at the keydown stage. You could try both events.

2012-04-03 23:05
by keystorm
I tried keydown (original code), keypress, and keyup... and every combination thereof - The Awnry Bear 2012-04-03 23:56


0

Ok I played with this a bit and this is running fine on my andriod:

var reserved = [0,8]

$(function()
{
    $("#foobar").keypress(function(e)
    {
        if($.inArray(e.which, reserved) < 0 && ((e.which < 48) || (e.which > 57)))
        {
            e.preventDefault();
            return false;
        }
    });
});

http://jsfiddle.net/HW794/1/embedded/result/

Possible that droid does not like the call to the fn? (range)

2012-04-03 23:34
by TimWickstrom.com
What version of Android did you test with? I just tried on my Nexus One running 2.3.6, and unfortunately the issue remains. The strange thing is it seems to only happen when the first characters entered are letters. If I start with numbers sometimes the issue doesn't happen - The Awnry Bear 2012-04-04 00:00
Updated the question with a link to another fiddle that shows preventDefault() is indeed being reached - The Awnry Bear 2012-04-04 00:48
strange indeed, I have no issues and it works as expected with my samsung galaxy s2 2.3.6.. - TimWickstrom.com 2012-04-04 21:28