Javascript/jQuery: Unable to get proper keyCode when capsLock is ON - javascript

I'm trying to determine the proper key/char code in javascript when a key is pressed.
It seems that when the CapsLock key is on, lowercase letters are not detectable.
Try the combinations:
1. a = a (97) shift:false
2. Shift+A = A (65) shift:true
3. Capslock,A = A (65) shift:false
4. Capslock, Shift+A = A (65) shift:true -- this should be 'a'
Cases 2 & 4 are indistinguishable.
A simple fiddle to illustrate the problem.
http://jsfiddle.net/sramam/pet5G/3/
OUTPUT:
keypress 'a' shift:false charCode97 keyCode:97 which:97
keypress 'A' shift:true charCode65 keyCode:65 which:65
(CAPSLOCK ON)
keypress 'A' shift:false charCode65 keyCode:65 which:65
keypress 'A' shift:true charCode65 keyCode:65 which:65
I only have a MacPro(Lion) to try this on.
Is it even possible to detect character to be rendered correctly?

The keypress detection is in fact "correct." The issue you're running into is that on OS X Lion, if you enable caps lock and press shift, it IGNORES caps lock. On Windows, shift + caps lock will return lower case letters. On your Mac, it will return upper case letters. This is not a matter of how the browser interprets a keypress, it's what the operating system registers.
Try typing in ANY application, i.e. Terminal, and you should see what I mean.
This may be the case for other Mac OS versions, I tested this on my MacBook Air w/ OS X Lion.

The keypress code is correct on windows, returning the correct key codes for the letter as it would be printed on keypress.
CAPS LOCK ON:
PRINTED
CHARACTER keyup/down keypress Modifiers
z 90 122 +Shift
a 65 97 +Shift
Z 90 90
A 65 65
caps lock off:
Z 90 90 +Shift
A 65 65 +Shift
z 90 122
a 65 97

The keydown, keyup, and keypress events are supported by all browsers, but there are some interoperability problems because the values of the keyCode property of the event object have never been standardized.
// The legacy keyCode property of the keydown event object is not standardized
// But the following values seem to work for most browsers and OSes.
Keymap.keyCodeToKeyName = {
// Keys with words or arrows on them
8:"Backspace", 9:"Tab", 13:"Enter", 16:"Shift", 17:"Control", 18:"Alt",
19:"Pause", 20:"CapsLock", 27:"Esc", 32:"Spacebar", 33:"PageUp",
34:"PageDown", 35:"End", 36:"Home", 37:"Left", 38:"Up", 39:"Right", 40:"Down", 45:"Insert", 46:"Del",
// Number keys on main keyboard (not keypad)
48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",
// Letter keys. Note that we don't distinguish upper and lower case
65:"A", 66:"B", 67:"C", 68:"D", 69:"E", 70:"F", 71:"G", 72:"H", 73:"I", 74:"J", 75:"K", 76:"L", ` 77:"M", 78:"N", 79:"O", 80:"P", 81:"Q", 82:"R", 83:"S", 84:"T", 85:"U", 86:"V", 87:"W", 88:"X", 89:"Y", 90:"Z",`
// Keypad numbers and punctuation keys. (Opera does not support these.)
96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9", 106:"Multiply", 107:"Add", 109:"Subtract", 110:"Decimal", 111:"Divide",
// Function keys
112:"F1", 113:"F2", 114:"F3", 115:"F4", 116:"F5", 117:"F6", 118:"F7", 119:"F8", 120:"F9", 121:"F10", 122:"F11", 123:"F12", 124:"F13", 125:"F14", 126:"F15", 127:"F16", 128:"F17", 129:"F18", 130:"F19", 131:"F20", 132:"F21", 133:"F22", 134:"F23", 135:"F24",
// Punctuation keys that don't require holding down Shift
// Hyphen is nonportable: FF returns same code as Subtract
59:";", 61:"=", 186:";", 187:"=", // Firefox and Opera return 59,61 188:",", 190:".", 191:"/", 192:"`", 219:"[", 220:"\\", 221:"]", 222:"'"
};

Related

What is the documented range for TouchEvent#touches?

I'm looking at the TouchEvent#touches documentation from MDN web docs, and the code sample provided only supports up to 3 touches.
someElement.addEventListener('touchstart', (e) => {
// Invoke the appropriate handler depending on the
// number of touch points.
switch (e.touches.length) {
case 1: handle_one_touch(e); break;
case 2: handle_two_touches(e); break;
case 3: handle_three_touches(e); break;
default: console.log("Not supported"); break;
}
}, false);
That being said, I'm pretty sure that there are 3+ finger touches, but I was wondering if there was a min/max range for these touches (e.g. can there be "0" touches in any scenario?)
Practically speaking, the W3C standard for TouchEvent does not define a maximum number of touches. Instead, the maximum is going to be the maximum number of consecutive touch points supported by the device's touch screen. In a virtual environment, this could presumably be infinite. Older devices seem to have been less than 20 consecutive touch points, however this could have increased with more modern technology.
Technically speaking, the spec defines the TouchList#length property as an unsigned long, so the absolute maximum within the spec will be 4,294,967,295 consecutive touch points:
interface TouchList {
readonly attribute unsigned long length;
getter Touch? item (unsigned long index);
};
As for the minimum, the spec does not say that there must be at least one item in the list of active touches. However, if you are listening to the touchstart event, then the received TouchList will always contain the touch which triggered the event:
touches of type TouchList, readonly
a list of Touches for every point of contact currently touching the surface.
and:
changedTouches of type TouchList, readonly
a list of Touches for every point of contact which contributed to the event.
For the touchstart event this must be a list of the touch points that just became active with the current event. [...]

Incorrect keystroke dwell/hold time if typed fast

Aim: Gather data(dwell time, flight time, down to down time...) for keystroke dynamics.
Things accomplished: Successfully obtained the flight time between two keystrokes.
Problem: When I type fast, I am able to obtain flight time correctly but dwell time messes up.
Minimal, complete and verifiable example: https://jsfiddle.net/nirajpandkar/600orotn/
For example for reproducing the error, you could try typing the word "the" slowly, one word at a time. The dwell times are as follows -
Pressed key 84 for 0.107
Pressed key 72 for 0.091
Pressed key 69 for 0.091
Now try typing letters 't' and 'h' in the word "the" as fast as you can(you won't have to try hard). The dwell times are -
Pressed key 84 for 0.008
Pressed key 72 for 1490285526.868
Pressed key 69 for 0.074
Question: Why is this happening and how should it be fixed?
The reason for the error is that when typing fast it's possible for the keydown to fire before the previous keyup. Hence the dwellTime may not have been reset.
To alleviate the problem you could store the dwellTime on a per-keyCode basis so that it couples the keydown with the keyup for that given key, something like this:
var dwellTimes = {};
$('#inputbox').keydown(function(e) {
if (!dwellTimes[e.which])
dwellTimes[e.which] = new Date().getTime();
});
$('#inputbox').keyup(function(e) {
var dwellTime = new Date().getTime() - dwellTimes[e.which];
delete dwellTimes[e.which];
$('#output').prepend("<p>Pressed key " + e.which + " for " + dwellTime / 1000 + "</p>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="inputbox" type='text'>
<div id="output"></div>
Note that I used prepend() in this example so you don't have to scroll down to see the newly raised events. Also, I changed the logic so that if a key is held down the dwellTime accounts for that, as your previous logic did not. If you don't need that behaviour you can simply remove the if condition from the keydown event handler.

Dealing with bizarrely inverted wheel event deltaX in Microsoft Edge browser?

Today I've discovered some very bizarre behavior in Microsoft's Edge browser, where the deltaX values for wheel events is apparently inverted! This was particularly surprising because this is not consistent with every other browser I've ever tested, including Internet Explorer 11 which returns the expected values.
Seeing this issue in action is rather simple, just run the following code, and use your mouse wheel or trackpad.
window.addEventListener('wheel', function(e) {
console.log(e.deltaX, e.deltaY);
});
For your convenience, I've created a full-page example (snippets are tricky for this):
Fullpage Working Example
Wheeling down gives a positive value and wheeling up gives a negative value as expected in Edge, IE, and other browsers. However, in Edge wheeling left gives a positive value, and right a negative value, the exact opposite of every other browser (IE11 and below included).
I made some GIF videos to show off the issue too, linked for file sizes.
IE11
Edge
The question:
Why is it like this, and is there a solution for handling the browser compatibility issues? Is there a way to feature-detect this? Is this behavior a bug, or is it documented somewhere?
The spec strongly suggests this is in-fact incorrect behavior:
If a user agent scrolls as the default action of the wheel event then the sign of the delta SHOULD be given by a right-hand coordinate system where positive X, Y, and Z axes are directed towards the right-most edge, bottom-most edge, and farthest depth (away from the user) of the document, respectively.
Notes:
I've tested this in both a Windows 10 VM and a native laptop, behavior was the same for both.
I'm reasonably sure this is not related to "natural"/inverted scrolling (off on all systems and VM hosts tested, and only happening on one axis).
On a side note, I don't know if deltaZ is inverted or even supported to begin with, I lack such an input device.
Bug Report:
I've reported the bug to Microsoft here. It has been assigned to someone, so hopefully it will be fixed.
While we await an official response from Microsoft, hopefully in the form of an update that resolves the issue, I have found a way to check if the browser is reporting an incorrectly inverted deltaX.
Edge also added support for the non-standard wheelDeltaX, wheelDeltaY, and wheelDelta properties also found in Chrome. Unlike deltaX, these values are correct, but instead refer to the actual wheel change and not the computed result. While their actual values are of little interest, we can infer the correct sign value from them.
In Chrome, deltaX and wheelDeltaX correctly have different sign values, so when one is negative, the other is positive. This means that if both values are negative or both are positive, the deltaX is incorrectly signed as it is presently in Edge. Therefore we can use this property to detect the incorrectly inverted value and un-invert it.
Here is a wrapper function I created to resolve the issue.
function wheelDeltaX(e) {
// Get the reported deltaX.
var r = e.deltaX;
// In Edge, the deltaX incorrectly matches wheelDeltaX sign.
// If both value signs match then uninvert it.
var wheelDeltaX;
if (
r &&
(wheelDeltaX = e.wheelDeltaX) &&
(
(r < 0 && wheelDeltaX < 0) ||
(r > 0 && wheelDeltaX > 0)
)
) {
r = -r;
}
return r;
}
So long as Edge retains the correct signing for wheelDeltaX when they hopefully fix the issue, this should be future-proof.

Certain key combinations prevent key events in javascript

Working on an app that requires the ability to hold down multiple keys at once to trigger unique functions.
I've run into a situation where certain combinations of keys will prevent 'keydown' from being triggered.
Holding a horizontal row 1 > 2 > 3 > 4 > 5 > 6 or a vertical column 1 > Q > A > Z
(6 keys appears to be the max the browser will recognise at once) will work however - if a user holds corner shape for example 1 > 2 > w the events are prevented.
Can be demonstrated using this fiddle:
http://jsfiddle.net/B1KMusic/U5L2X/light/
Interestingly though this 'shape' of keys appears significant - 2 > 3 > Wand 3 > 4 > R etc. will also be prevented.
Even if this shape is rotated across the keyboard the same shapes like: C -> X -> S and N -> H -> J will do the same.
If a gap is left and the corner is not 'connected' then the events will work properly 3 > E > D > V - but if C is pressed this will not work.
What is going on here? Is this some intentional browser default to prevent key mashing?
Edit: As the answer provided points out, this is a hardware issue so it makes sense to include hardware info: tested on a late 2013 Macbook Pro, apple stackexchange question confirms the answer here: https://apple.stackexchange.com/questions/47699/are-apple-keyboards-multi-key-rollover
This is a hardware limitation of your keyboard, not an issue with the browser. Most keyboards use a matrix arrangement for key switches, and hence cannot detect certain combinations of keys being pressed. The specific combinations which will and will not work are hardware-dependent, but in general, it is not safe to assume that more than two non-modifier keys can be pressed simultaneously.
Some gaming keyboards support n-key rollover (that is, any number of keys being pressed at once), but these are rare.

What preferred way to reconcile keyCode/charCode across browsers?

Based on the properties of the keydown event I would like to ascertain what the current charCode are?
Example.
For the keydown event when the NumPad0, D0, and Colon key is pressed I would like to know what the associated charcode is. Currently I have a map that contains the charcode associated with that keyCode or use the current if charCode is not specified.
keyCode = {
Colon: 186,
D0: 48,
NumPad0: 96,
};
charCodes = {
186: 59,
96: 48,
};
shiftCharCodes = {
186: 58,
48: 41
};
Also in certain cases the keyCodes are different accross browsers?
Example.
The keydown event has different keyCode values across browsers.
Colon Key (:/;)
- keyCode is 59 on firefox
- keyCode is 186 on IE/safari
For more information
http://www.quirksmode.org/js/keys.html
If you're interested in the character code associated with a keypress, you're going to get nowhere with the keydown event. The keypress event is the only place this information is available, and is not too problematic for most printable keys.
document.onkeypress = function(evt) {
evt = evt || window.event;
var charCode = evt.which || evt.keyCode;
alert("Character: " + String.fromCharCode(charCode));
};
There are differences between browser behaviour around "special" non-printable keypresses such as function keys. For more information I consider this article by Jan Wolter to be the definitive reference for JavaScript key handling.
Although I generally loath answers like the one I am about to give, I feel it is appropriate:
This is a perfect use case for a library like jQuery, Prototype, Dojo or MooTools.
You don't want to burden yourself with this work, it has already been done.

Categories