I am confused about the various behaviors of keypress, keydown, and keyup. It seems that I have missed an important piece of documentation, one that explains the subtleties and nuances of this trio. Could someone help me to figure out which document I need to read in order to more effectively use these events? In case you want details, see below.
@o.v.: you asked me to show some code, but it's not really a specific problem in the code that I'm trying to solve. I'm trying to get a handle on the behaviors of these event handlers and asking someone who understands them to point me to a good piece of documentation.
I use jQuery to build an input form and insert it into my document. It works just fine, mostly. I want the form to respond to the keyboard like most other input forms I see out there: the esc key should dismiss the form the same as clicking the cancel button, and because the form has a <textarea>
on it, cmd + enter should be the same as clicking the OK button. It seems simple enough to use the keypress event. The problem is that Chrome doesn't call my keypress handler for the esc key or cmd + enter. It fires for ctrl + enter and option + enter and for alphanumerics, but not cmd + enter.
So I'll use keyup instead. I get keyup for esc, and keyup for cmd, and keyup for enter, great. But I don't get keyup for the enter key while I'm holding down cmd.
Third time's the charm, you might think keydown seems to work, but with keydown, you get repeat keys. I know, all you have to do is unbind the handler the first time you're called, but it just seems weird that the three different event types would behave so differently. Why is this? Is there an obvious document out there that I obviously haven't read?
Keypress:
The keypress event is sent to an element when the browser registers
keyboard input. This is similar to the keydown event, except in the
case of key repeats. If the user presses and holds a key, a keydown
event is triggered once, but separate keypress events are triggered
for each inserted character. In addition, modifier keys (such as
Shift) trigger keydown events but not keypress events.
Keydown:
The keydown event is sent to an element when the user first presses a
key on the keyboard. It can be attached to any element, but the event
is only sent to the element that has the focus. Focusable elements can
vary between browsers, but form elements can always get focus so are
reasonable candidates for this event type.
Keyup:
The keyup event is sent to an element when the user releases a key on
the keyboard. It can be attached to any element, but the event is only
sent to the element that has the focus. Focusable elements can vary
between browsers, but form elements can always get focus so are
reasonable candidates for this event type.
Also, this is a handy piece of information that is usually glossed over:
If key presses anywhere need to be caught (for example, to implement
global shortcut keys on a page), it is useful to attach this behavior
to the document object. Because of event bubbling, all key presses
will make their way up the DOM to the document object unless
explicitly stopped.
To determine which character was entered, examine the event object
that is passed to the handler function. While browsers use differing
properties to store this information, jQuery normalizes the .which
property so you can reliably use it to retrieve the character code.
Note that keydown and keyup provide a code indicating which key is
pressed, while keypress indicates which character was entered. For
example, a lowercase "a" will be reported as 65 by keydown and keyup,
but as 97 by keypress. An uppercase "A" is reported as 65 by all
events. Because of this distinction, when catching special keystrokes
such as arrow keys, .keydown() or .keyup() is a better choice.
More information regarding the cmd
key on MACs: jQuery key code for command key
This article is a good resource explaining the differences between keyup
, keydown
and keypress
.
The short answer is there is no easy way to handle them other than to account for the different browsers.
The way I personally handle it in a Bootstrap plugin I wrote is by creating a custom method to check which event is supported. Coincidentally a very similar method showed up in the official Bootstrap version a little while later :P
//------------------------------------------------------------------
//
// Check if an event is supported by the browser eg. 'keypress'
// * This was included to handle the "exhaustive deprecation" of jQuery.browser in jQuery 1.8
//
eventSupported: function(eventName) {
var isSupported = (eventName in this.$element);
if (!isSupported) {
this.$element.setAttribute(eventName, 'return;');
isSupported = typeof this.$element[eventName] === 'function';
}
return isSupported;
}
Later on I use it in my code to attach event handlers:
if (this.eventSupported('keydown')) {
this.$element.on('keydown', $.proxy(this.keypress, this));
}
You have to remember that when validating a KeyboardEvent
on a mac, ⌘
modifier key will not be picked up as event.ctrlKey
but rather an event.metaKey
. Further documentation is available on MDN.
Without seeing any code, my bet is on this being the reason for ⌘+Enter
not being picked up.