2023 here, I've been using a different solution to this for a long time.
It involves using a hidden textarea to get the typed character. It is a bit of a hack, but it works flawlessly in all major browsers and saves the headache of working with e.key or e.keyCode etc.
I'll just post the code here. It's fairly self-explanatory. If you're wanting this to work in ALL mobile browsers including opera mini etc then you'll have to change the fixed positioning to absolute positioning and make sure the textarea is always positioned around the middle of the visible part of the page to avoid scrolling whenever a character is typed.
Basically, create a hidden textarea, add a keydown event to the window object that focuses the textarea, get the value of the textarea, clear the textarea, focus the previously focused element again...and optionally then generate the typed character in the previously focused element.
/*create a hidden textarea*/
var keyGrabber = document.createElement('textarea');
keyGrabber.style.border = '0';
keyGrabber.style.margin = '0';
keyGrabber.style.padding = '0';
keyGrabber.style.outline = 'none';
keyGrabber.style.position = 'fixed';
keyGrabber.style.top = '0';
keyGrabber.tabIndex = '-1';
document.body.appendChild(keyGrabber);
/*Avoid confusion for screen readers*/
keyGrabber.setAttribute('aria-hidden','true');
/*Init the variables here so they are global and easy to access*/
var oldActiveElement = document.activeElement;
var oldStart = 0;
var oldEnd = 0;
/*Catch the keydown event and store the active elements selection start and end in case you still want the character to be typed*/
window.addEventListener('keydown',function(e){
oldActiveElement = document.activeElement;
oldStart = oldActiveElement.selectionStart;
oldEnd = oldActiveElement.selectionEnd;
keyGrabber.focus();
/*If you need to capture keys that don't generate written characters, you'll have to do that here using e.key || e.keyCode */
});
keyGrabber.addEventListener('input',function(){
var character = keyGrabber.value;
if(character == ':'){
alert('You typed a colon!');
/*replace alert with whatever code you want to execute when a colon is typed*/
}
keyGrabber.value = '';
oldActiveElement.focus();
/*This part is optional, in case you want to still have the typed character generate in an input and also fire the event. You would then also replace "window.addEventListener..." with "yourInput.addEventListener..."*/
var part1 = oldActiveElement.value.slice(0,oldStart);
var part2 = oldActiveElement.value.slice(oldEnd,oldActiveElement.value.length);
oldActiveElement.value = part1 + character + part2;
oldActiveElement.selectionStart = oldStart + 1;
oldActiveElement.selectionEnd = oldActiveElement.selectionStart;
});
Please don't copy/paste this code and expect it to work flawlessly. I'm typing this from memory and not copying it from a working file. I can't remember if setting the tabIndex to -1 stops the .focus() from working. I think it's fine but please double check this.