I have some simple code which logs the pressed key code, like this:
window.addEventListener('keypress', function(e) {
console.log(e.keyCode);
})
It seems to work for Alt + pretty much every other on my keyboard. Except for Alt + N.
It seems to not be registering the event at all! Just N (without the Alt) seems to work, and so do other combinations like Ctrl + N. When I type Alt + N nothing else happens, so it's not been reserved by the system as far as I know. I am using Chrome on a Mac.
Is this just something wrong with my computer or does it happen for others too? If it does happen for others, why does it do this and are there ways to detect it?
Try :
window.addEventListener('keydown', function(e) {
if (e.altKey == true && e.keyCode == 78)
console.log('Alt + N');
});
Using keypress event doesn't work for me for Alt+N and for any combination with Alt for that matter. Some combinations are working with Ctrl and some aren't.
However, when I listen for keydown and keyup events, I am able to log these events. So, I guess you could listen for keydown event on Alt and if there is a keydown event for N before Alt generates keyup, you have successfully detected a Alt+N combo.
I am not sure about why this happens though.
EDIT
According to Mozilla documentation,
The keypress event is fired when a key that produces a character value is pressed down. Examples of keys that produce a character value are alphabetic, numeric, and punctuation keys.
Examples of keys that don't produce a character value are modifier keys such as Alt, Shift, Ctrl, or Meta.
As for why some shortcuts work in Chrome, while some do not, Mozilla says
Chrome does not fire the keypress event for known keyboard shortcuts. Which keyboard shortcuts are known depends on the user's system. Use the keydown event to implement keyboard shortcuts.
Related
Some clients have been reporting issues when using their iPad Bluetooth keyboards for entering text into one of our internal sites. Mainly pressing enter on a certain input would work fine when using desktop or the iPad on screen keyboard, but not when using a Bluetooth keyboard connected to the iPad.
Upon investigation it appears that any input to an onKeyUp returns 0 as the keycode when connected to a Bluetooth keyboard on the iPad. The demo works fine, however when using the onscreen keyboard it doesn't work because of the keycode returning 0. I created this jsFiddle to demonstrate. It was tested on both Chrome and Safari for iPad with the same results of working fine with onKeyPress but returning only 0 with onKeyUp.
$('#inputKeyUp').keyup(function (event){
$("#outputKeyUp").text("Key Up Key: " + event.which);
});
$('#inputKeyPress').keypress(function (event){
$("#outputKeyPress").text("Key Press Key: " + event.which);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="inputKeyUp">keyup</textarea>
<div id="outputKeyUp">Key Up Key:</div>
<b/>
<textarea id="inputKeyPress">keypress</textarea>
<div id="outputKeyPress">Key Press Key:</div>
EDIT: just reported the bug to Apple. We will see if anything comes of it.
Testing study
I did some testing on this just now and discovered that on the keyUp event when using a Bluetooth keyboard on iOS Safari, the only keys that give any sort of proper feedback in terms of the properties e.key, e.charCode, e.keyCode and e.which are the following keys:
Escape
Up arrow
Left arrow
Right arrow
Down arrow
All other keys return the following:
{
key: "Dead",
charCode: 0,
keyCode: 0,
which: 0
}
These special keys (escape and arrow keys) only return a different value on the e.key property according to the syntax UIKeyInput{PascalCasedKeyName}:
UIKeyInputEscape
UIKeyInputUpArrow
UIKeyInputLeftArrow
UIKeyInputRightArrow
UIKeyInputDownArrow
Summary
On iOS, the only keys you can identify on the keyUp event, based on my quick study, are Escape and the four Arrow keys, by matching their name on the e.key property. These values also appear on the keyDown event.
If you still need to wait until the keyUp event fires for your applications, and you need to match keys other than these special ones, the only solution I can come up with is to use a keyDown event for capturing the key, but then listen for the keyUp event inside that keyDown event like so:
el.addEventListener("keydown", e => {
if (e.which === 13) // Enter key, or which ever key code you'd like
el.addEventListener("keyup", function keyUp(e) {
el.removeEventListener("keyup", keyUp, false) // Memory clean-up
// Your code here
}, false)
}, false)
Furthermore
After a quick search for "UIKeyInput" I discovered that UIKeyInput is "a set of methods a subclass of UIResponder uses to implement simple text entry". (Apple's Developer Documentation) This would explain the special syntax of these key names.
This is a workaround for the enter key in the keyup event.
if (event.type === 'keyup') {
//this is to handle the enter button on an ipad bluetooth keyboard
if (event.key === 'Enter') {
event.which = event.keyCode = 13;
}
}
CHROME (52):
When turning caps lock ON - only keydown is fired (no event in keyUp or keyPress)
When turning caps lock OFF - only keyup is fired (no event in keyDown or keyPress)
FIREFOX (46):
Only keyDown event is fired for both caps lock ON & OFF (no keyUp or keyPress)
I've read about the keyCodes and events here http://www.quirksmode.org/js/keys.html and in MDN here https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode, aaaand here http://unixpapa.com/js/key.html
But none of the above links talks about this weird behaviour.
Is this expected? If so, any easier way to handle it?
Yes, this is expected.
Chrome treats the CAPS ON as keydown because it treats the on/off as press and hold, like we hold shift key, which turns on caps on behaviour and turns off when we release it. This Caps Lock button also. When you turn on Caps Lock, chrome handles the 'turn on' as a keypress and when you 'turn off' it handles it as a keyup. But, firefox handles everything as keydown which doesn't make sense to me when compared to how chrome handles the same.
Solution
You should use getModifierState() to get the state of the Caps Lock. This is supported in chrome and firefox.
Hope it helps!
$(function() {
$(window).on("keydown", function(e){
if (e.which === 20)
console.log(e.originalEvent.getModifierState('CapsLock'))
});
$(window).on("keyup", function(e) {
if (e.which === 20)
console.log(e.originalEvent.getModifierState('CapsLock'))
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Focus here and press 'Caps Lock'
I had been looking for an answer to a very similar issue. Pranesh's answer pointed me in a direction.
In my case, I wanted to warn users that their capslock is on when they go to log in. Ultimately I settled on the following solution.
Angular Component:
export class AuthenticateComponent {
public capslockOn: boolean;
constructor() {
this.capslockOn = false;
}
public keyup(event: KeyboardEvent): void {
if (event.key === 'CapsLock') {
// Checks / sets when the Caps Lock key is specifically pressed.
this.capslockOn = (!this.capslockOn && event.getModifierState('CapsLock'));
} else {
// Checks all other conditions like the Caps Lock was on before the user
// loaded the form and began typing in it.
this.capslockOn = event.getModifierState('CapsLock');
}
}
}
Then I just call the keyup function from my form:
<form ... (keyup)="keyup($event)">
Any keypress in the form - username or password - will check / set the boolean capslockOn and I can *ngIf that to show an icon or message or both.
Thanks for the explanation Pranesh. It helped quite a bit.
Here's all I'm doing:
$(document).keydown(function(e) {
e.preventDefault();
console.debug(e.keyCode, "down");
});
$(document).keyup(function(e) {
e.preventDefault();
console.debug(e.keyCode, "up");
});
You can see the problem here: http://jsfiddle.net/pJgyu/32530/
If I hold down a letter key, keydown is fired constantly until I let go. Then keyup fires once. That seems like the correct behavior.
If I hold down an arrow key, keydown and keyup alternate constantly. Why is keyup firing?
I've tried it without the "e.preventDefault();".
Also, after holding an arrow key, SOMETIMES letter keys display the same strange behavior.
Your keyboard may be broken. I don't have that issue when I try to replicate it in your jsfiddle.
It is not only the keyboard that has to be broken.
I had the same issue and spent some time googling and debugging it, and only after a couple of painful hours I remembered about my key mapping software that I use. My AutoHotkey scripts do several things with special keys, such as arrows, and this was the reason for the issue.
On a JavaScript page, I pop up an alert if the user hits the enter key by using
if(evt.keyCode == 13){
alert("Return Key Pressed");
}
but the event does not fire when I hit the return key on the iPad. How do I catch the event?
The iPad keyboard does fire the keypress event with a key code of 13 if you press return. This sounds like you've got something else going awry
Here's a quick jsfiddle to verify with: http://jsfiddle.net/359wG/
According to https://api.jquery.com/keypress/
The keypress event is sent to an element when the browser registers
keyboard input. This is similar to the keydown event, except that
modifier and non-printing keys such as Shift, Esc, and delete trigger
keydown events but not keypress events. Other differences between the
two events may arise depending on platform and browser.
A keypress event handler 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 controls can always get focus so are
reasonable candidates for this event type.
I moved my return-key listener to an anchor tag, which on IPad is treated as a 'focusable element' similar to form controls.
I'm trying to add keyboard shortcuts on my website to make fast navigation possible using the keyboard. I'm running into a slight problem, however, with my attempted Alt+X shortcut. The event runs just fine and returns false as it should, but the browser's File menu comes up regardless. I've also tried the preventDefault method, but no change.
The cut-down version of the script is:
document.documentElement.onkeydown = function(e) {
e = e || window.event;
switch( e.keyCode || e.which) {
// some cases here - most notably:
case 116: // F5 key
if( activeFrame) {
activeFrame.contentWindow.location.reload();
// reloads an iframe if one is active
return false;
}
break;
// more cases...
case 88: // X key
if( e.altKey) {
// do something
return false;
}
}
}
As noted above, overriding the default action of the F5 key works just fine - the browser reloads the page only if no iframe is active. I don't quite see how to prevent the menu from appearing when Alt+X is pressed.
use stopPropagation(e); instead of preventDefault method
function stopPropagation(e)
{
e = e || event;/* get IE event ( not passed ) */
e.stopPropagation? e.stopPropagation() : e.cancelBubble = true;
}
Reference link
Another SO question which mentions that preventDefault has issue in IE.
UPDATE
Try using below code as per MSDN Reference
event.returnValue=false;
And some point from Detecting keystrokes
Some general caveats:
Generally, Mac is less reliable than Windows, and some keys cannot be detected.
Explorer doesn't fire the keypress event for delete, end, enter, escape, function keys, home, insert, pageUp/Down and tab.
Onkeypress, Safari gives weird keyCode values in the 63200 range for delete, end, function keys, home and pageUp.Down. The onkeydown and -up values are normal.
Alt, Cmd, Ctrl and Shift cannot be detected on Mac, except in Opera. However, you can always use the altKey, ctrlKey, and shiftKey properties.
I actually had a web app working just fine with CTRL shortcut keys, but then decided I'd be clever and use the accesskey attribute, and ran into this exact issue with IE.
The problem with going to CTRL shortcut keys is that many of those are more standard/useful across many applications (eg: cut, copy, paste, select all).
Ctrl+Alt is fairly safe, but requires more work on the user's part.
I tend to just try to stick to ALT shortcuts IE doesn't stubbornly insist on handling.
Demo of CTRL + A/CTRL + F being cancelled successfully:
http://jsfiddle.net/egJyT/
This answer seems to imply it isn't possible to disable the menu shortcuts without putting IE into kiosk mode.
Beware that if you manage to successfully prevent the browser from detecting a key combination you may make your page unusable for some users. Many screen readers have reserved almost any key you can think of to control the screen reader and if your page was accessible using a screen reader before you added the shortcut key code, it may be completely un-accessible users needing screen readers after you add it.
Read this article about access keys (a bit old but probably still relevant), and this article about Reserved Keystroke Combinations before you invest too much time on this problem.