KeyPress malfunction in Opera - javascript

I'm using the following code to detect users' key pressing, in JavaScript:
$(document).bind('keydown', function (event) {
'use strict';
var keyCode = event.keyCode;
switch (keyCode) {
case '{N}':
doSomething();
break;
default:
break;
}
});
Where doSomething is a previously defined function and {N} is any of the JavaScript Char Codes.
It works properly in every major browser, but in Opera even if a key remains pressed, it only calls doSomething once, instead of doing it until the key is released.
What can I do to fix this?
Edit
I solved it using the keypress event instead of keydown (which is not well handled by Opera).

Opera makes a mess, the keydown event does not repeat, and you cannot prevent the default for keydown in opera. For more http://quirksmode.org/dom/events/

this is a known bug which should (finally!) get fixed soon. In short, keydown events are not repeated while keypress events are. Listening to keypress instead if you want repetition (and don't care about keys that do NOT fire keypress in all browsers like most function keys) should be a reasonable cross-browser solution.

Related

Maintaining a map of which keys are down in the presence of Undo, Copy, etc

I'm building a web application with a fullscreen canvas that needs to react to continuous and discrete keyboard input.
My current approach is similar to the one in this question: JavaScript keep track of which keys are down accurately.
I maintain a set of which keys are currently pressed using keyEvent.code to differentiate keys. I query this set in the requestAnimationFrame loop of my application. I update the set in event handlers for the 'keyup' and 'keydown' events attached to window.
The Problem
When pressing and releasing Cmd+Z to undo, the 'keydown' event fires but the 'keyup' event does not (at least in the latest Firefox, Chrome, and Edge on macOS 10.15.6).
Consequently, my set contains an entry for 'KeyZ' even though the Z key on the keyboard is not being held. Similarly, Cmd+C, Cmd+V, and many other system shortcuts seem to hijack the 'keyup' event.
Why am I not getting a 'keyup' event in this case? What can I do to ensure that my set accurately reflects the state of the currently held keys on the keyboard?
What I've Tried
This seems like it could be related to event propagation, so I tried using keyEvent.stopPropagation() and keyEvent.preventDefault() in the keydown event handler.
I've tried pressing Control+Z instead, which does fire a 'keyup' event.
Problem Reproduction
const listenerTarget = window;
const useCapture = false;
const heldKeys = new Set();
listenerTarget.addEventListener('keydown', (keyEvent) => {
const code = keyEvent.code;
if (!keyEvent.repeat) {
console.log(`${code} went down`);
heldKeys.add(code);
} else {
console.log(`${code} went down (repeat)`);
}
keyEvent.stopPropagation();
keyEvent.preventDefault();
}, useCapture);
listenerTarget.addEventListener('keyup', (keyEvent) => {
const code = keyEvent.code;
// Why does this not fire if
// the 'keydown' happened in combination with
// a Meta key?
console.log(`${code} went up`);
heldKeys.delete(code);
}, useCapture);
Workaround Update (11/03/2020)
I found When CMD key is kept pressed, keyup is not triggered for any other key and http://web.archive.org/web/20160304022453/http://bitspushedaround.com/on-a-few-things-you-may-not-know-about-the-hellish-command-key-and-javascript-events/, which indicate that this is known behavior. My current workaround is to not add codes to the set of held keys if keyEvent.metaKey is set. Doing this at least ensures that the set of held keys doesn't contain phantom entries. I'll keep this question open in case someone can think of a better approach.
For me it works just fine on the lates chrome version..
Sorry.
This isn't super helpful, but there's a bunch of good info here: https://unixpapa.com/js/key.html. You've probably already seen that in other answers though.
I say not super helpful because it doesn't really answer your particular question, but it does show that there's definite weirdness between browser versions and both modifier keys and branded keys. I suspect the answer is that the branded keys like the windows key and cmd key just act weird because they tend to trigger system level events. I would just use different keys, but hopefully someone else will know a way around this other than "use different keys".
For windows people, you can produce really similar results by doing Windows Key + Z. You'll only get up event for Z and no down events.

Javascript Keyup isn't called when Command and another is pressed

This is Mac only problem; I've tried this on windows and it works fine.
I have a script that saves which keys are pressed on keydown and deletes them on keyup.
$(function(){
var keys = [];
$(document).keydown(function(event) {
keys[event.which] = true;
});
$(document).keyup(function(event) {
delete keys[event.which];
console.log(keys);
});
});
All I am doing right now is console logging whatever is left after the keyup, which should be nothing. This works as expected when you press any number of keys simultaneously.
HOWEVER, when you press command and any other key, the other key is NOT released! So console.log will show that key to be true. This will remain true until you press that key itself.
This only happens on a Mac, and it only happens when one of the keys pressed is the Command key. Here is a very simple plunker with the above example.
Any ideas?
The Mac is modifying your key whenever you press Command, and thus the normal keyup event never fires.
C = command key and K = non-command key
As you press C and K, they register normally. While they are both simultaneously pressed, the Mac captures K and modifies it. In modifying K, the Mac somehow makes K's keyup event not fire as it is supposed to. C's keyup works as expected, however.
Since K's keyup never actually fires, it won't correctly delete the matching element from keys. Later on when you press K without C, the keydown event overwrites the existing keydown in keys. And when K's keyup correctly fires, it works as expected.
In addition to all the normal keys used to input ASCII characters,
keyboards typically have many special purpose keys that do other
things. These do not necessarily generate the same events as normal
keys, and they show less consistency across browsers.
JavaScript Madness: Keyboard Events. Potentially helpful article for all key-related problems.
I can't fix this Mac issue, but here is my way of getting around it.
This answer will help you if you are trying to have keyboard-shortcut behavior, where the user presses CMD+S to do save, or something like that. This answer does not apply to people who may be building a game or something where their keyboard's keydown states need to be known at each run frame. Sorry!
In the KeyboardEvent returned by keydown, you can do the following
$(document).keydown(function(keyboardEvent) {
if (keyboardEvent.metaKey){
// on Mac, CMD is down ...or Meta key is down on pc
console.log(keyboardEvent.meta + " & command key are down")
switch (keyboardEvent.which) {
...
}
}
});
If your keyboard shortcut overlaps with the browser's, you need to make sure to cancel the propagation of the keyboard event,
keyboardEvent.preventDefault()
I hope this helps people who want keyboard shortcut functionality that is Mac compatible!

keyCode simply giving... the wrong response

I'm not sure why this is happening. Similar things have happened, but they're typically due to keyloggers or something along those lines.
My javascript is simply bugging out, or something.
When I use this link and press W, I get 87 as a response.
However, when I run my own code, which looks simply like this:
var keydown = function(e) {
console.log(e.keyCode); //I've also tried charCode
}
window.addEventListener("keypress", keydown, false);
I get the number 119 when I press W.
This is occurring both in Chrome and in IE.
What gives?
Actually, keyup and keydown for identifying physical keys and keypress(redundant) is for identifying typed character so using keypress event, W/capital(87) and w/lower(119) gives different results but keydown will always give you 87. So, as other answer stated, you should use keydown.
Read more on quirksmode.org.
Therefore, onkeydown/up keyCode always holds the key code. onkeypress
you can find the actual character the user typed by evt.charCode ||
evt.keyCode.
Note: as the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms.
Source: http://api.jquery.com/keypress/
Maybe you should use keydown?

$(window).keypress(function()) does not work in IE7?

This keypress event works fine for me in Chrome and Firefox, but simply isn't being picked up at all in IE7:
$(window).keypress(function(e) {
alert('hello world');
});
Does anyone know alternatives for IE7?
Or is it an error higher up in my JavaScript that means it isn't being picked up in IE7 - in which case, how can I debug it? I have script errors turned on in IE, but nothing is popping up.
IE doesn't support key events on the window.
Place it on the document instead.
$(document).keypress(function(e) {
alert('hello world');
});
Currently I have no IE7 to test it, but I believe you have to assign the event handler to $(document) instead of $(window). Something like:
$(document).keypress(function(e) {
alert("hello world");
});
A couple things to try:
1: Wrap your event code in a document.onready event, like so:
jQuery(function()
{
$(window).keypress(function(e)....
});
This way your event is not attached until the DOM has finished loading.
2: Attach your event to the body or the document instead of the window:
jQuery(function()
{
$("body").keypress(function(e)....
$(document).keypress(function(e)....
});
(I have no reason to think this will work, it's just something I've done when events don't bubble all the way back to document or window for some reason.)
I encountered this problem too. What I discovered is that IE7 has no keyChar member in its implementation of the event object. Thus, it tries to evaluate event.keyChar, gets a null and does nothing. Instead the keyCode is ambiguous returning either the ascii keyChar or the keycode of the key that was pressed... ugh. Since I was having to trap both special keys and keys tied to characters this was my solution.
onkeydown
negate the keyCode and save in a persistent object
myObject.kSave=-event.keyCode;
WHY? because at this point you don't know if the key is a character or a special key !!!
onkeypress
The onkeypress event may not fire if the key is a special key.
For that reason my strategy uses onkeyup to handle special keys and control characters and uses onkeypress to handle characters other than control characters.
When the key is a character, event.keyChar contains the character and its value is greater than 0. However, since IE7 doesn't have an event.keyChar member, use event.keyCode as the character. You can force all control characters (e.g. enter, esc, tab, etc.) to be handled as a special key by preventing the default behavior of control characters and deferring handling to onkeyup. To signal that a character has been handled we must set the saved object to the character we found.
var ch = (event.keyChar == null) ? event.keyCode : event.keyChar;
if (ch >=32) {//ch is a character and not a control character
myObject.kSave = ch; //tells onkeyup that the key was handled
event.preventDefault(); //don't let default processing mess with your handler
switch(ch) {
//your character handler goes here
}
} else if (ch > 0) {//ch is a control character
event.preventDefault();
}
onkeyup
Add the saved value to event.keyCode. If the sum is zero, the onkeypress event did not
handle the keypress because the pressed key was a special key or a control character.
When the sum is positive, there is nothing further to do because the key was a character
and the onkeypress event handler already took care of it.
if (myObject.kSave+event.keyCode == 0) {//this is a special key or control character
event.preventDefault();
switch(event.keyCode) {
//handle special keys here
}
}
One last thing, in your event handler invoke event.preventDefault() if you don't want the default handler to mess with your event handler.

BlackBerry JavaScript support of keycodes/keypresses

I'm new to dealing with BlackBerry devices. I'm currently running into a JavaScript issue on a 9700 and trapping keypress events and getting a proper keycode.
I have this javascript:
function numbersonly(e) {
var key
if(window.event) {
key = window.event.keyCode; // IE
}else{
key = e.which; // Firefox
}
alert('keycode : ' + key);
}
And it's attached to an input field via an unobtrusive addEvent script.
On a standard desktop browser (Firefox and IE), it does what you'd think it does...pressing a key will show the keycode via the alert.
On a blackberry, however, pressing a key does one of two things:
if the key presses is the numbers 1 through 9, nothing happens.
if it's any other key, the keyCode is 'undefined'.
Any idea what's going on? I assume it's a limitation of the BlackBerry JavaScript support.
UPDATE:
Tested this on a 9800 Simulator as well, which is running OS6. Problem doesn't exist there. So this is either an issue with BlackBerry OS5 or BlackBerry's physical keyboard.
I'm not sure if the event variable is set when you add an inline event handler.
Have you tried setting the event-handler from javascript. So something like
document.getElementById('mytextelement').onkeypress = keytest;
Try using e.keyCode instead of e.which

Categories

Resources