Confused by javascript Keyboard events - javascript

I'm confused at how I'm supposed to handle keyboard events in Javascript. I'm trying to detect meta-z and meta-shift-z to implement undo/redo. What is currently working is to use
let key = String.fromCharCode(e.which || e.keyCode);
if (e.ctrlKey || e.metaKey) {
// Handle ctrl/cmd keypress
if ((key === 'Z' && e.shiftKey) || key === 'Y') {
// Ctrl/Cmd-shift Z or Cmd-Y => Redo
redoGraph();
e.stopPropagation();
}
else if (key === 'Z') { // lower-case z, no shift
// Ctrl/Cmd-Z => Undo
undoGraph();
e.stopPropagation();
}
}
However, both "which" and "keyCode" are deprecated. Though, as usual, the notice I found for the deprecation didn't say what to use instead. If I use "e.key", then according to W3Schools, Safari doesn't support that, so then it seems like I'd need to do both or something. Is there a best practice for detecting keyboard events?
Also, "e.key" always returns lower-case. So then if you wanted to detect typing, do you have to do your own manual conversion from lower to upper (including all diacritics, etc.)? Or is there a way to get a key event that says what the typed character should look like?

Related

Altering the keypress event of certain keys in JavaScript

I am working on a project which shows the character code of each key that is pressed down inside a text box.
My problem is that when certain keys, namely: Shift, Backspace, Space are pressed down, their character codes appear like: 16, 8, 32.
I want these keys to retain their normal behavior when pressed. So that space causes a space in the text box, and backspace deletes the character, and so on...but the rest of the keys to continue outputting their character code.
How can I go about accomplishing this?
You can just check for the keys and handle accordingly. Here's a demo:
document.getElementById("test-textbox").addEventListener("keypress", function(event) {
var code = event.keyCode || event.which;
if(code === 16 || code === 8 || code === 32) //check if space, shift, or backspace
return; //if yes, allow
console.log(code); //if not, log value
event.preventDefault(); //prevent entry
});
<input type="text" id="test-textbox">
This will allow the shift, backspace, and space keys to be pressed, but all others will be logged.
I think this will work for you.
var elementID = document.getElementById('elementID');
elementID.onkeydown = function(event) {
var key = event.keyCode || event.charCode;
if( key == 32 || key == 8 )
event.preventDefault();
};
As long as you…
don’t call the preventDefault method on the event object, and
don’t return false from the event handler
…you should be fine.
In particular, the handler…
function showCharCode(event) {
// NOTE: Don’t call `event.preventDefault()` here.
document.querySelector('.char-code').textContent = event.charCode;
// NOTE: Don't return false here.
}
… will still propagate the event to the default textbox (or input, or contenteditable) element.

Get the keypress code without to care which symbol is clicked using JQuery

I see here is have few questions when is asking for how can get which key is clicked from keyboard. I tested is ok is working if is in English case.
If I change the language and the symbols on keyboard is changed then is not show anything.
So my question is how can I get the keypress code without to care which language is now used the user when is click the key 'G' or 'Г' or something else.
here is my simple jquery code
$(document).keypress(function(e) {
if (e.charCode == 103) {
alert('g');
} else if (e.charCode == 71) {
alert('G');
}
});
If is with english is working, when I change to Bulgarian then is not working. How can I make to working on every language?
Using the keypress event will give you the character typed, regardless of keyboard layout.
For character input, it is suggested you use keypress(), which will report the actual ASCII code for the character pressed. It automatically takes care of letter case, and ignores non-character presses. In either case, you can use fromCharCode() to convert to a string representation. E.g.
document.onkeypress = function(evt) {
evt = evt || window.event;
var charCode = evt.which || evt.keyCode;
var charTyped = String.fromCharCode(charCode);
alert("Character typed: " + charTyped);
};
I find the solution of my problem. Thanks of this article
$(document).on('keydown', function(e) {
if (e.ctrlKey) {
alert('Echo');
} else {
alert(e.which + ' ' + e.key);
}
});
What I'm changing. I change only the event. I replace 'keypress' with 'keydown' and now is the same code without to care which language is used.

How to know if a key is pressed having no charcode value

I want to know if ctrl,space,alt,capslock,shift like keys are pressed in my keyboard.
When i do
String.fromCharCode(e.keyCode)
,it returns blank value for these keys but when I do
alert($.trim(String.fromCharCode(e.keyCode))=='')
Then it return false for all keys except space bar.So it would be great if someone may tell me to get the keydown event of these keys
Vanilla JavaScript:
For other constants, see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
window.onkeydown = function (e) {
switch (e.keyCode) {
case KeyboardEvent.DOM_VK_SPACE:
alert('space bar!');
break;
case KeyboardEvent.DOM_VK_CAPS_LOCK:
alert('CAPS LOCK!');
break;
case KeyboardEvent.DOM_VK_CONTROL:
alert('control!');
break;
case KeyboardEvent.DOM_VK_SHIFT:
alert('shift!');
break;
case KeyboardEvent.DOM_VK_ALT:
alert('alt!');
break;
}
};
UPDATED FOR REQUIREMENT TO AVOID CASES:
Per the following test, the only numeric values that will, after trimming (and not including numbers not corresponding to the average keyboard), be reduced to an empty string are 9,10,11,12,13,32. Looking at https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Virtual_key_codes , the only ones that correspond are tab, clear, return, and space .
// Run in Firefox where trim() is supported (without need for jQuery):
var arr = [];
for (var i=0; i < 0xFFFF; i++) {
if (String.fromCharCode(i).trim() == '') {
arr.push(i);
}
}
In other words, your own test is not going to catch all cases.
So you have to use numeric comparisons based on the info at https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Virtual_key_codes and BASED ON EXACTLY WHAT CHARACTERS YOU NEED TO INCLUDE (or exclude).
For example, if you consider the cancel key, help key, back space, tab, etc. all to be of the type you mentioned, you can do:
window.onkeydown = function (e) {
if (e.keyCode < 0x30) {
alert('Special key pressed!');
}
};
As you can see, this allows for us to find a whole group of characters within a short amount of code (e.g., without using case). (But if we don't know exactly which characters you want to include or exclude, we can't give you a more precise answer.)
NOTE:
charCode is never set in the keydown and keyup events. In these cases, keyCode is set instead.
you can try
$(window).keydown(function (e){
if (e.ctrlKey) { there are e.altKey & e.shiftKey also.
for other keys use hardcoded integer values.
alert("control");
}
});
I'm not sure about the support of keyIdentifier but if you are using the keyup, keydown or keypress events, but you could possibly do the following. However there are no cross-browser guarantees where charcode is not defined or is zero. Not using jquery to keep things as small as possible, and only detecting the keys that you specified. See article.
Javascript
/*jslint maxerr: 50, indent: 4, browser: true */
(function () {
"use strict";
function addEvent(elem, event, fn) {
if (typeof elem === "string") {
elem = document.getElementById(elem);
}
function listenHandler(e) {
var ret = fn.apply(null, arguments);
if (ret === false) {
e.stopPropagation();
e.preventDefault();
}
return ret;
}
function attachHandler() {
window.event.target = window.event.srcElement;
var ret = fn.call(elem, window.event);
if (ret === false) {
window.event.returnValue = false;
window.event.cancelBubble = true;
}
return ret;
}
if (elem.addEventListener) {
elem.addEventListener(event, listenHandler, false);
} else {
elem.attachEvent("on" + event, attachHandler);
}
}
function checkKeys(e) {
if ("Alt,Shift,Control,CapsLock,U+0020".indexOf(e.keyIdentifier) !== -1) {
alert(e.keyIdentifier);
}
console.log(e.keyIdentifier);
}
addEvent(window, "keydown", checkKeys);
}());
On jsfiddle
Update: reading a bit furter, keyIdentifier is not supported by all browsers and so is not fullly cross-browser friendly.
3.4. New Standard Key and Character Events
The DOM3 standard abandons all hope of creating order among
event.keyCode, event.which and event.charCode, and instead defines new
values for keydown and keyup events. For a while it deprecated the
keypress event and replaced it with the textInput event, but that was
undone. Only a few browsers implemented the first version, and, so
far, no browsers have implemented the newest version. Earlier versions
of the specification defined attributes named event.keyIdentifier and
event.keyLocation. The keyIdentifier was a string that in most cases
looked like "U+0041" where the "0041" part is the unicode value of the
character sent by the key when it is typed without modifiers, in this
case the letter "A". For keys that didn't send unicode characters, or
where the unicode value is not standardized, it was a string like
"Enter", "Shift", "Left" or "F9". The keyLocation attribute gave
values to distinguish among multiple keys that had the same
identifier, like the left and right shift keys, or the keypad number
keys. It was 0 for standard keys, 1 or 2 for left or right versions of
a keys like Shift which appear twice on the keyboard, and 3 for keys
on the numeric keypad.
WebKit implemented support for keyIdentifier and got it mostly right.
Older versions conformed to an older version of the standard and
returned two extra zeros (eg, "U+000041") but this was corrected in
version 525. Windows versions of Safari and Linux versions of Chrome
return bad keyIdentifier values for all of the non-number symbol keys
(WebKit Bug 19906 reported in July 2008). The keyLocation attribute is
always 0 or 3, so it does not distinguish between left and right
modifier keys.
Konqueror returns keyIdentifier values like "Shift" and "Enter"
correctly, but instead of returning the Unicode values, it returns the
typed character itself, "a" or "A" instead of "U+0041". All
keyLocation values are zero, except for modifiers key, which are
always one, regardless of whether the left or right one was pressed.
We cannot, however expect any more browsers to implement that
standard, since it has now changed. The DOM 3 standard no longer
mentions event.keyIdentifier or event.keyLocation. Instead we have
event.key, event.char, event.location.. So far as I know, no browser
has yet implemented this new version of the DOM 3 standard.
In this standard event.char is defined only when you type a printable
character, or another character with a defined code (like tab or
backspace). It's basically like event.charCode except that it is the
character, not the character code and can be any unicode character not
just an ASCII code. Event.key is the same as event.char for printable
keys. For other keys, even ones like tab or backspace that have
character encodings, it is a string like 'Tab', 'Left' or 'F9'. These
values are supposed to be the same on keypress events as they are on
keyup and keydown events, though keypress would not be fired for those
cases where event.char is null.
Note that neither of these pretends to be a keycode identifying a
particular physical key on the keyboard. If you press the /? key on a
US keyboard while shift is off, but press the shift key before
releasing the /? key, then then on keydown you'll get event.key=='/'
and on keyup you'll get event.key=='?'. The only way your Javascript
program will know that those two events go together is if it happens
to know that those two characters are on the same key. There is an
event.locale value that is supposed to give you some clue on what type
of keyboard is being used, but figuring out what keys go with what on
a particular keyboard is up to you.
Clearly this abandonment of the idea of keycodes is going to cause
problems, but is still probably justified. In many (most?) operating
systems, I don't think the browser can actually tell which key was
pressed. In the browser source code I've seen, the keycodes are
generated from the the character codes, not vice versa, by simply
assuming that the character came from a US keyboard. So the keycode
values never really worked for non-US keyboards.
So while the keycode concept was a handly one, it isn't really
practically extensible in the real world. If you want a keycode in the
DOM 3 universe, you'll have to go on using the legacy event.keyCode
value, which, standards or no standards, isn't going away. The DOM 3
standard seems to recognize this, and reluctantly provides an appendix
with some standards for event.keyCode and the like. It casts a rather
weak vote for what I called "IE keycodes" above.

Capture key press without placing an input element on the page?

How to capture key press, e.g., Ctrl+Z, without placing an input element on the page in JavaScript? Seems that in IE, keypress and keyup events can only be bound to input elements (input boxes, textareas, etc)
For non-printable keys such as arrow keys and shortcut keys such as Ctrl-z, Ctrl-x, Ctrl-c that may trigger some action in the browser (for instance, inside editable documents or elements), you may not get a keypress event in all browsers. For this reason you have to use keydown instead, if you're interested in suppressing the browser's default action. If not, keyup will do just as well.
Attaching a keydown event to document works in all the major browsers:
document.onkeydown = function(evt) {
evt = evt || window.event;
if (evt.ctrlKey && evt.keyCode == 90) {
alert("Ctrl-Z");
}
};
For a complete reference, I strongly recommend Jan Wolter's article on JavaScript key handling.
jQuery also has an excellent implementation that's incredibly easy to use. Here's how you could implement this functionality across browsers:
$(document).keypress(function(e){
var checkWebkitandIE=(e.which==26 ? 1 : 0);
var checkMoz=(e.which==122 && e.ctrlKey ? 1 : 0);
if (checkWebkitandIE || checkMoz) $("body").append("<p>ctrl+z detected!</p>");
});
Tested in IE7,Firefox 3.6.3 & Chrome 4.1.249.1064
Another way of doing this is to use the keydown event and track the event.keyCode. However, since jQuery normalizes keyCode and charCode using event.which, their spec recommends using event.which in a variety of situations:
$(document).keydown(function(e){
if (e.keyCode==90 && e.ctrlKey)
$("body").append("<p>ctrl+z detected!</p>");
});
For modern JS, use event.key!
document.addEventListener("keypress", function onPress(event) {
if (event.key === "z" && event.ctrlKey) {
// Do something awesome
}
});
NOTE: The old properties (.keyCode and .which) are Deprecated.
Mozilla Docs
Supported Browsers
Detect key press, including key combinations:
window.addEventListener('keydown', function (e) {
if (e.ctrlKey && e.keyCode == 90) {
// Ctrl + z pressed
}
});
Benefit here is that you are not overwriting any global properties, but instead merely introducing a side effect. Not good, but definitely a whole lot less nefarious than other suggestions on here.
Code & detects ctrl+z
document.onkeyup = function(e) {
if(e.ctrlKey && e.keyCode == 90) {
// ctrl+z pressed
}
}
Attach a listener to the keydown event instead of keypress, since the latter is now deprecated.
window.addEventListener('keydown', keyDownHandler);
The keydown event triggers continuously while the key is pressed. If you wanna have it fire only once, inside the handler use the event.repeat property as so:
keyDownHandler(event) {
if (!event.repeat) {
<code here will only be executed once while the key is pressed>
}
}
Remember to remove the listener when not needed anymore.
window.removeEventListener('keydown', keyDownHandler);

Which keycode for escape key with jQuery

I have two functions. When enter is pressed the functions runs correctly but when escape is pressed it doesn't. What's the correct number for the escape key?
$(document).keypress(function(e) {
if (e.which == 13) $('.save').click(); // enter (works as expected)
if (e.which == 27) $('.cancel').click(); // esc (does not work)
});
Try with the keyup event:
$(document).on('keyup', function(e) {
if (e.key == "Enter") $('.save').click();
if (e.key == "Escape") $('.cancel').click();
});
Rather than hardcode the keycode values in your function, consider using named constants to better convey your meaning:
var KEYCODE_ENTER = 13;
var KEYCODE_ESC = 27;
$(document).keyup(function(e) {
if (e.keyCode == KEYCODE_ENTER) $('.save').click();
if (e.keyCode == KEYCODE_ESC) $('.cancel').click();
});
Some browsers (like FireFox, unsure of others) define a global KeyEvent object that exposes these types of constants for you. This SO question shows a nice way of defining that object in other browsers as well.
(Answer extracted from my previous comment)
You need to use keyup rather than keypress. e.g.:
$(document).keyup(function(e) {
if (e.which == 13) $('.save').click(); // enter
if (e.which == 27) $('.cancel').click(); // esc
});
keypress doesn't seem to be handled consistently between browsers (try out the demo at http://api.jquery.com/keypress in IE vs Chrome vs Firefox. Sometimes keypress doesn't register, and the values for both 'which' and 'keyCode' vary) whereas keyup is consistent.
Since there was some discussion of e.which vs e.keyCode: Note that e.which is the jquery-normalized value and is the one recommended for use:
The event.which property normalizes event.keyCode and event.charCode. It is recommended to watch event.which for keyboard key input.
(from http://api.jquery.com/event.which/)
To find the keycode for any key, use this simple function:
document.onkeydown = function(evt) {
console.log(evt.keyCode);
}
27 is the code for the escape key. :)
Your best bet is
$(document).keyup(function(e) {
if (e.which === 13) $('.save').click(); // enter
if (e.which === 27) $('.cancel').click(); // esc
/* OPTIONAL: Only if you want other elements to ignore event */
e.preventDefault();
e.stopPropagation();
});
Summary
which is more preferable than keyCode because it is normalized
keyup is more preferable than keydown because keydown may occur multiple times if user keeps it pressed.
Do not use keypress unless you want to capture actual characters.
Interestingly Bootstrap uses keydown and keyCode in its dropdown component (as of 3.0.2)! I think it's probably poor choice there.
Related snippet from JQuery doc
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. For catching actual text entry, .keypress() may
be a better choice.
Other item of interest: JavaScript Keypress Library
Try the jEscape plugin (download from google drive)
$(document).escape(function() {
alert('ESC button pressed');
});
or get keycode for cross browser
var code = (e.keyCode ? e.keyCode : e.which);
if (code === 27) alert('ESC');
if (code === 13) alert('ENTER');
maybe you can use switch
var code = (e.keyCode ? e.keyCode : e.which);
switch (code) {
case 27:
alert('ESC');
break;
case 13:
alert('ENTER');
break;
}
Just posting an updated answer than e.keyCode is considered DEPRECATED on MDN.
Rather you should opt for e.key instead which supports clean names for everything. Here is the relevant copy pasta
window.addEventListener("keydown", function (event) {
if (event.defaultPrevented) {
return; // Do nothing if the event was already processed
}
switch (event.key) {
case "ArrowDown":
// Do something for "down arrow" key press.
break;
case "ArrowUp":
// Do something for "up arrow" key press.
break;
case "ArrowLeft":
// Do something for "left arrow" key press.
break;
case "ArrowRight":
// Do something for "right arrow" key press.
break;
case "Enter":
// Do something for "enter" or "return" key press.
break;
case "Escape":
// Do something for "esc" key press.
break;
default:
return; // Quit when this doesn't handle the key event.
}
// Cancel the default action to avoid it being handled twice
event.preventDefault();
}, true);
Your code works just fine. It's most likely the window thats not focused. I use a similar function to close iframe boxes etc.
$(document).ready(function(){
// Set focus
setTimeout('window.focus()',1000);
});
$(document).keypress(function(e) {
// Enable esc
if (e.keyCode == 27) {
parent.document.getElementById('iframediv').style.display='none';
parent.document.getElementById('iframe').src='/views/view.empty.black.html';
}
});
I'm was trying to do the same thing and it was bugging the crap out of me. In firefox, it appears that if you try to do some things when the escape key is pressed, it continues processing the escape key which then cancels whatever you were trying to do. Alert works fine. But in my case, I wanted to go back in the history which did not work. Finally figured out that I had to force the propagation of the event to stop as shown below...
if (keyCode == 27)
{
history.back();
if (window.event)
{
// IE works fine anyways so this isn't really needed
e.cancelBubble = true;
e.returnValue = false;
}
else if (e.stopPropagation)
{
// In firefox, this is what keeps the escape key from canceling the history.back()
e.stopPropagation();
e.preventDefault();
}
return (false);
}
To explain where other answers haven't; the problem is your use of keypress.
Perhaps the event is just mis-named but keypress is defined to fire when when an actualcharacteris being inserted. I.e. text.
Whereas what you want is keydown/keyup, which fires whenever (before or after, respectively) the user depresses akey. I.e. those things on the keyboard.
The difference appears here because esc is a control character (literally 'non-printing character') and so doesn't write any text, thus not even firing keypress.
enter is weird, because even though you are using it as a control character (i.e. to control the UI), it is still inserting a new-line character, which will fire keypress.
Source: quirksmode
To get the hex code for all the characters: http://asciitable.com/
A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies.
http://jaywcjlove.github.io/hotkeys/
hotkeys('enter,esc', function(event,handler){
switch(handler.key){
case "enter":$('.save').click();break;
case "esc":$('.cancel').click();break;
}
});
hotkeys understands the following modifiers: ⇧,shiftoption⌥altctrlcontrolcommand, and ⌘.
The following special keys can be used for shortcuts:backspacetab,clear,enter,return,esc,escape,space,up,down,left,right,home,end,pageup,pagedown,del,delete andf1 throughf19.
I have always used keyup and e.which to catch escape key.
I know this question is asking about jquery, but for those people using jqueryui, there are constants for many of the keycodes:
$.ui.keyCode.ESCAPE
http://api.jqueryui.com/jQuery.ui.keyCode/
$(document).on('keydown', function(event) {
if (event.key == "Escape") {
alert('Esc key pressed.');
}
});

Categories

Resources