I'm not asking this because I need a work-a-around. I have one that works fine, but I want to know WHY it doesn't. Is this bug in Javascript (or JQuery because I was using the JQuery .keypress handler) or is there a specific reason why this is so?
The keypress event is designed for handling a character typed by the user rather than detecting keyboard activity and the delete and backspace keys do not generate characters. Some browsers blur this line somewhat but the general principle is that the keyup and keydown events are there to detect any key being pressed and telling you about which key it is while keypress is for detecting an actual character being typed.
The short answer is that the onkeypress event is not fired for all key types in all browsers. Check the manual for your browser.
Why?
Probably not a comprehensive answer, but consider Shift, when it goes down and when it comes up relative to other keys is significant. And different keyboard hardware has different key rollover characteristics which you might want to know about in detail.
Related
I understand that in Javascript, the 'keypress' event fires when a character gets inserted into the screen and the 'input' event fires when the input field of yours changes. I've seen many good explanations of the different types of events like here, but I was more wondering about the difference between those two events since they seem so similar. Specifically:
What, if at all, is the difference between keypress and input events? In my quick testing, it seems like keypress happens first, but is that it?
Under what circumstances would I use one over the other?
So actually those two events are not the same at all. Let me break it down for you.
keypress event triggers when any of your keyboard keys are pressed independently of the element you are focusing. If you press a key on a blank html page, the event will be triggered. This event is mostly used to trigger events like when there is a popup and you press escape, it hides it.
input event is specific to the case where you are currently typing or pressing keys while focusing an input element. With it, you can actually get the input value and do stuff with it like in a form, check if the password has symbols, a caps letter, and numbers.
This is the difference between those two events. They don't have the same use at all.
To answer your question about when you would use keyDown or keyUp versus input:
Navigation controls for games
Keys that don't change the text. For instance, using keyDown to detect 'esc' or 'F1' pressed. I commonly use keyDown detection of 'esc' to close popup windows
I'm creating a basic search app and on keypress in the search input textbox I want to go back to the server to get results for a javascript autosuggestion dropdown. Is there any value to adding event handlers for both keyup and keydown? It seems like the keydown seems to work fine. Also, I noticed there is a keypress event as well. Should I be using that instead?
There is no need for a simple search input to fire events every keyup and keydown. This would not be very efficient, you also would be making a bunch of unnecessary calls to the server. I would definitely suggest using one or the other. I prefer keyup so that the user may finish typing there letter before the event is fired. So if you are not using the others for a specific reason use KEYUP for a search input.
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.
I have solved my own question. It's not a 100% solution but it should cover most of what is needed. Hopefully there will be a cleaner solution when browser vendors start integrating DOM Level 3 Events.
Just to re-iterate the main constraints:
The key down and key up events should be reported/sent at the time they actually happen. I.e. sending a key down and key up together during the keyPress event is insufficient.
Many key combinations must be fully handled during the keyDown event either because they never trigger a keyPress event (i.e. Ctrl key) or because the default action must be stopped in keyDown (WebKit) and doing so prevents the keyPress event from happening.
The key down and key events should report the translated character code and not keyCode value.
Without some out-of-the-box epiphany, the current browser implementations appear to prevent all three constraints from being fulfilled completely. So I have decided to relax constraint #3 just a bit.
On browser keyDown event add the event to a key down list and check to see if it is a safe (no undesirable browser default behavior) key combination:
Safe: do nothing until the keyPress.
Unsafe: report/send a key down event immediately. This is where constraint #3 is relaxed because these limited key combinations are not translated to a character code (many of them don't have them though anyways).
On browser keyPress event (which happens immediately after the keyDown event) check to see if it is a safe key combination:
Safe: report/send a key down event. Update the key down list using the translated character code (event.which).
Unsafe: do nothing since it was already reported/sent during keyDown.
On browser keyUp event, find and remove the matching event from the key down list and use the translated code to report/send the key up event.
Some additional links for those interesting:
The noVNC commit with the change.
Some wiki notes on the issues as related to noVNC.
This solution has been adopted in RedHat's Broadway project (HTML5 GTK+ backend).
This is an absolute minefield and I would urge you not to attempt this if you can possibly avoid it. Not only is there a long and tangled history of browser manufacturers not agreeing on key event behaviour, there is also the fact that they still don't agree and are still regularly changing the key behaviour of their browsers.
The following is the best I can offer and the definitive resource on browser key events: http://unixpapa.com/js/key.html
If you have to do this, I think you're going to end up with loads of key code mapping tables that will go out of date very quickly. Good luck.
Currently, I listen on the Enter key to start sending a message.
But for multi-byte characters, the Enter key is supposed to choose a certain character.
The problem is that I've no idea how to detect whether a user is in the middle of inputting a multi-byte character, and even if he's in that process, the message will be sent the first time he presses the Enter key.
So the user experience is really strange.
Does anyone have a solution to this?
If you don't get what I mean above, can try to chat here, and once you started a conversation, switching to multi-byte mode, then you'll know what I mean.
The link is here:
http://maishudi.com/OMegle.php
I'm assuming your reference to multibyte input is a reference to "Input Methods" (or "Input Method Editors" on Windows).
Unfortunately, there isn't any real solution at the moment -- DOM3 was going to add mechanisms for this but it seems to have dropped this due to the complexity.
Part of the complexity comes from the vastly different behaviour of individual input methods before you even consider the behaviour discrepancy between browsers. A good example is to just check what key events you receive for a set of behaviour with Japanese, Korean, and (traditional and simplified) Chinese. The browsers cannot avoid this as they are responding to events fired directly by the input editors.
The only things you can really rely on are keyDown events, and even then not so much in opera and Firefox -- Safari and IE both provide keyDown events during IME composition, with a charCode of 229, and a keyUp event with a charCode corresponding to the actual key that was pressed.
There is a textInput event, but that is only supported by Safari (and by proxy Chrome should support it as well), but it's not substantially better than standard events anyway :-/
I have a question regarding the onkeypress event on JavaScript.
Is it possible to detect just Cntl key or Alt Key? At the moment if both Cntl and m are pressed the onkeypress event can trigger a click. Is it possible to do just Cntl key by itself?
Looking forward to your comments
onkeypress just catches character keys. Use onkeydown and/or onkeyup for the other keys. See Peter-Paul Koch on key events.
From the looks of it, no, you can't just capture the Ctrl key. The hotkeys jQuery plugin which focuses exclusively on capturing keys doesn't capture the straight "Ctrl" key either, so I'm guessing it's not possible. You can catch it with the mouse events, but that's not quite the same thing.
http://jshotkeys.googlepages.com/test-static-01.html