Skip to content
Advertisement

Best way to detect typed key on different systems and keyboards? Chrome mobile keyCode bug

I’m working on this special input and I need to allow / disallow some keys from being typed by the user.

I’m doing the validation on the onKeyDown handler.

This is what I was doing at first:

const ALLOWED_KEYS = [
  "Ctrl", "Meta", "Shift","Home", "End", 
  "Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab", 
  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 
  ".", ","
];

function onKeyDown(event) {
  if (ALLOWED_KEYS.indexOf(event.key) === -1) {
    event.preventDefault();
  }
}

But I was worried that the string names of the keys were not consistent across browsers, so someone here on SO told me that I should change to event.keyCode instead of event.key.

And on this link I could check each key code: https://www.w3.org/2002/09/tests/keys.html

const DIGITS_COMMA_POINT_KEY_CODES = [
  48,49,50,51,52,53,54,55,56,57,        // 0-9 NORMAL KEYBOARD
  96,97,98,99,100,101,102,103,104,105,  // 0-9 NUMERIC KEYPAD
  110,188,                              // COMMA NORMAL AND NUMERIC KEYPAD
  190,194                               // POINT NORMAL AND NUMERIC KEYPAD
];

function onKeyDown(event) {
  if (DIGITS_COMMA_POINT_KEY_CODES.indexOf(event.keyCode) === -1) {
    event.preventDefault();
  }
}

Anyway, both options were working on Chrome Desktop, but failing in Chrome Mobile.

When I test the keyCodes from my Android mobile device I get completely different numbers:

Example:

KEY CODES FOR THE CHAR "0"

DESKTOP NORMAL KEYBOARD : 48
DESKTOP NUMERIC KEYPAD : 96
ANDROID MOBILE KEYBOARD : 229  (EVERY DIGIT SHOW AS 229)

-----------------

KEY CODES FOR THE CHAR "," (COMMA)

DESKTOP NORMAL KEYBOARD : 188
DESKTOP NUMERIC KEYPAD : 110
ANDROID MOBILE KEYBOARD : 229   (EVERY DIGIT, COMMA AND POINT SHOW AS 229)

PS: On Android Mobile, all the digits, comma and point seem to return keyCode as 229 on https://www.w3.org/2002/09/tests/keys.html

UPDATE1:

Just tested with event.charCode but every key logs as charCode: 0

UPDATE2:

On this link: https://javascript.info/keyboard-events Every key from my Android Chrome Mobile shows up as Unidentified. This is weird.

UPDATE3:

This is an issue with Chrome Mobile. Firefox Mobile handles it perfectly. Haven’t tested on other browsers.

Keycode is always zero in Chrome for Android

And this bug was reported in Chromium in 2012:

https://bugs.chromium.org/p/chromium/issues/detail?id=118639

QUESTION

What is the universal way to detect the typed key that should work on every keyboard, browser or system?

Answer

From all the research that I did, here is the answer:

If you plan to support Chrome Mobile on Android, DO NOT use onKeyDown (and probably other KeyboardEvents such as onKeyPres and onKeyUp) because you will not be able to read the keys that are being typed.

This is a Chromium bug. The same happens on my Samsung Internet, since it’s also Chromium-based.

There’s an issue opened about this topic on Chromium since 2012. And I’m writing this in 2020.

https://bugs.chromium.org/p/chromium/issues/detail?id=118639

And there are heated discussions going on in there for the past 8 years.

This problem does not happen in Android Firefox, but somehow this is not a trivial thing to fix in Chromium. Don’t know why.


I was looking for a solution for this, because when you call event.preventDefault inside the onKeyDown handler, you do not get a caret jump (at least on Mobile Chrome you don’t). While if you are fixing the input value in the onChange handler you will need to deal with caret jumps.

I’ve ended up dealing with the caret jumps.

EDIT: It is not a bug anymore, as in the status of the bug you shared is wontFix

Advertisement