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?
Advertisement
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