The use of navigator.userAgent is not advised as per MDN. In my application I want to have a shortcut for del key.
In mac del key (is backspace) with charCode = 8.
In windows del key charCode = 46.
I want to treat both keyEvents same. I am currently using userAgent but it is unreliable as that property can be spoofed. I am wondering what is the best way to know the client OS otherwise.
More deprecated navigator properties
navigator.appVersion
navigator.platform
/* code objective */
if ((keycode == 8 && os == 'macintosh') || keycode == 46) {
//This is keyboard shortcut to perform delete
}
Relying on KeyboardEvent.metaKey and KeyboardEvent.Backspace solved my problem
Full Key Values - https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
For more details refer: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Key_values
Thanks to #Teoli2003 for twitter reply - https://twitter.com/Teoli2003/status/663995373766221824
Related
Say that I am not using jQuery, and want to support IE8 along with the other mainstream browsers.
In order to normalize events, I am following this pattern:
document.onkeydown = function(e) {
var code;
if (!e) {
var e = window.event;
}
code = e.which || e.keyCode;
// More stuff here...
};
However, I suspect that if I changed the order of my e.which vs e.keyCode check, like so...
code = e.keyCode || e.which;
...then my code might act differently across browsers.
Question: Does the order matter? Is one order "better" than the
other?
Bonus: If I'm only supporting IE8 and up, does e.charCode matter?
Another bonus: Should I use var e = window.event or just e = window.event?
1. Yes, the order matters.
The order you should use is indeed:
code = e.which || e.keyCode;
This is because most browsers support e.which (IE<9 excluded, of course). This way, any browser (IE>=9 and FF, Chrome, Opera, Safari, etc.) that supports e.which will use it, and those that don't will use e.keyCode.
Should you switch the order to:
code = e.keyCode || e.which;
You'll get e.keyCode for virtually every browser (instead of e.which) which will tell you the key that was pressed but not the resulting character (which I suspect is not what you want).
2. No, e.charCode does not matter.
Browser support for e.charCode is spotty at best. Even IE9 documentation states that it's for compatibiity only. Most popular modern browsers return undefined or 0 (or ASCII, or Extended ASCII, if you're lucky and even then it's only on keypress).
Additional reading for both 1 and 2 should probably be done at:
http://www.quirksmode.org/dom/w3c_events.html#link4
http://www.quirksmode.org/js/keys.html
Should you wish to play around with key events, I made a fiddle for you to report the [relevant] properties of the event parameter when you type in the sole input field.
3. You should definitely use var e = window.event;.
If you don't use var, you're effectively declaring window.e = window.event which is silly. Use var to keep e defined in the scope of your handler.
I'd like to have Javascript respond to a keypress or keydown event from only the numeric keypad Enter key, not the usual Enter key. They both seem to generate the same event data according to the demo in the jQuery keypress docs, so I'm not sure it's possible.
They do generate the same keystroke data, at the level of abstraction that JavaScript has access to. Remember, JavaScript lives in a sandbox (the browser) and has no direct access to the underlying hardware (there are plenty of platforms that don't have a numeric keypad at all, but do have a browser).
This cannot be done.
EDIT:
Support for this has been added for some browsers but does not seem to be universal (see the other answer).
it is possible to detect the numpad Enter as seperate key nowadays. With the KeyboardEvent.location property. this way you can firstly check the keycode 13 and after if the key is on the numpad which devines the numpad enter.
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location
example:
window.onkeydown=function(ev)
{
var e= ev || window.event,
key = e.keyCode
if ((key===13) && (e.location===3)) {
console.log("got ya");
console.log(e.location);
}
}
$(document).keydown(function (event)
{
alert(event.which);
});
For the semicolon key, ;, this gives 59 in Firefox and 186 in Chrome. However, from the jQuery reference page for the keydown event, it says
"While browsers use differing properties to store this information, jQuery normalizes the .which property so you can reliably use it to retrieve the key code. This code corresponds to a key on the keyboard, including codes for special keys such as arrows."
Am I missing something?
The which property is a "one stop shop" for which key was pressed, allowing you to ignore the differences between the keyCode and charCode properties. That is the "normalization" that jQuery provides.
The difference in the value of which comes down to a difference between the way the various browsers supply the information - so you'll have to write code to handle the different values that come back. There are a few references to this behavior online.
A quick Google search says you will simply have to test for both. This is a consistent inconsistency with Firefox.
I don't know about jQuery but I'd suggest sticking to keypress events for typing keys and only using keydown events for special keys such as arrows.
Here is the entirety of the "normalization" that jQuery does:
if ( event.which == null ) {
event.which = original.charCode != null ? original.charCode : original.keyCode;
}
Looks like it just gets keyCode if charCode doesn't exist. And charCode is only used if event.which doesn't already exist. It doesn't change the numbers around to make them consistent.
I'm working on a web app that works fine inside the LAN using HTTP but when I test it remotely over SSL it fails for IE (7 & 8). Firefox, Camino and Safari all work perfectly.
I've tracked down the issue to key being undefined. The relevant bit of code is:
function showResult(e,str,num) {
var key = (window.Event) ? e.which : e.keyCode;
if(((key > 32 && key < 58) || (key > 64 && key < 91) || (key > 95 && key < 123)) && (str.length >= num)) {
Any clues as to why key would be undefined for IE over SSL but works fine over HTTP? Better yet, can someone tell me how to overcome this problem? FWIW, I don't need to support IE prior to version 7.
Update:
There was an answer which suggested replacing
var key = (window.event) ? e.which : e.keyCode;
with
var key;
e = e || window.event;
key = e.keyCode || e.which;
That works. The problem now is that I can't accept that answer because it has been deleted.
Ok, I'll re-add that answer, even though it wasn't mine, and add some info along the way so you can feel OK with accepting it even if it wasn't my answer from the beginning.
So, the suggested code is this:
var key;
e = e || window.event;
key = e.keyCode || e.which;
What does || do? For one it's the logical or operator, which would return true if one of the sides evaluate to boolean true.
It also has another use in JS. If you give it two arguments and the first one is undefined, it will return the second argument. This means, in the code above, that if e is undefined, you instead get window.event which is IE's traditional event object.
Same thing goes with e.keyCode || e.which whichever one exists is used. So in the end, you're likely to end up with a valid key code on various browsers. All is good in wonderland.
But wait, doesn't your original code do something similar?
var key = (window.Event) ? e.which : e.keyCode;
Uh-huh. What's that? JavaScript is case-sensisitive, so window.Event is not the same as window.event in the code above. window.event is IE's traditional event object that you would use get information about the event that occurred, while window.Event (which you can see from the initial capital letter) is a constructor, or more specifically in this case an interface.
Point is, in that code it was used to detect Mozilla. If it exists, choose e.which (One of the places where Mozilla stores the key code) otherwise go for e.keyCode where IE would store the key code.
However, this is based on the flawed assumption that IE doesn't have the window.Event constructor defined. It does have it defined as of IE8, at least. This means that e.which is chosen over e.keyCode, on newer versions of IE. e.which has never and will never be supported in IE. That's why key ends up being undefined.
But, uhm, why does it differ between encrypted and unencrypted connections? That's a good question. While I cannot know for sure without access to your development environment, I would assume it has something with IE's compatibility modes.
IE has historically (over the last 10 years) been the most quirky and non-standard browser around. This has lead to people a) programming ignorantly according to IE's standards b) creating workarounds for IE's behaviors. If MS just made IE standards-compliant, that would break many pages which rely on IE's quirky behavior in one way or the other. Microsoft has ackowledged this by making IE8+ emulate older versions of IE so pages won't break, unless told otherwise.
I can only assume that, for whatever reason, in your test environment the page ends up running in the "IE7" mode which might not have the window.Event constructor/interface defined. This would make your old code use e.keyCode which is ey OK. Then perhaps in your production environment, or maybe just because of the encrypted connection (only ghawd knows what MS is doing) you end up with a newer IE mode so window.Event is actually defined and e.which is chosen. This makes IE a cheeky monkey.
Bottom line: Use the new code.
Most probably, you've included a script over http (rather than https), which will fail to load because the page itself is secure and the included file insecure.
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