Quick background:
- when a key is pressed in a browser, three events are generated: keyDown, keyPress and keyUp.
- keyDown and keyUp have a keyCode property which is approximately the physical key pressed.
- keyPress also has charCode property set which takes into account modifier keys and keyboard layout (A and a have same keyCode but a different charCode).
- all three events have properties that indicate which modifier keys were pressed during those events.
I'm the main noVNC developer and I have a tough problem: noVNC needs the translated charCode value without using the keyPress event for the following reasons:
- noVNC needs to send the keyDown and keyUp events separately to the VNC server (otherwise it's not a completely functional VNC client).
- more importantly, noVNC needs to prevent the default keyboard actions while connected which means calling the preventDefault() method of the keyDown event. This has the side-effect of also preventing the keyPress event from firing.
Due to differences in keyboard layouts (i.e. different keyCode to charCode mappings) I've determine that noVNC will need a lookup table for different keyboard layouts.
But here is the real problem: on alternate layouts, some different physical keys have the SAME keyCode. For example, with an azerty (French) keyboard layout the '-' (dash) and '_' underscore keys both generate keyCode 189. Ack!!!
So ... how do I get proper keyCode to charCode mapping and prevent default browser actions at the same time?
BTW, I suspect the solution to this will be applicable to other interactive web applications and HTML5 games since you often want to be able to know full information about the key pressed without triggering any additional browser response to that keypress.
Useful links:
- Here is an useful test page that show the three events and some other useful properties.
- Summary of the crazy state of key events in Javascript (thanks @Tim)
- Quirksmode Detecting keystrokes
- Quirksmode Events - key events
- noVNC issue with more discussion of the problem.
Solution: see my post below.