crossbrowser keypress for special keys (arrows,...) in javascript - javascript

I am building a browser interface to a terminal. I need to catch both character (alphanumeric, dot, slash,...) and non-character key presses (arrows, F1-F12,...). Also, if the user holds some key down, it would be nice to get repeated keypresses (the function should be called repeatedly until key is released). The same goes for space key, characters,...
I want this to be as cross-browser as possible (jQuery keypress fails on that account). I have also tried using fork of jquery.hotkeys.js, but if I understand correctly, I can't catch both special and character keys in a single function (one should use keydown for former and keydown for the latter).
Is there a JS library that would allow me to catch both character and special keys?
I hope I'm not missing something obvious. :)
UPDATE To clarify: I am looking for the library that would hide the browser implementation details from me.

The onkeydown it exactly what you need. It captures all keys, even if you are holding a button it is fired repeatedly.
<input type='text' onkeydown='return myFunc(this,event)'>
<script>
function myFunc(Sender,e){
var key = e.which ? e.which : e.keyCode;
if(key == someKey){ // cancel event and do something
ev.returnValue = false;
if(e.preventDefault) e.preventDefault();
return false;
}
}
</script>
UPDATE try and test this with jQuery
$(document).ready(function(){
$('#in').keydown(fn);
});
var cnt = 0;
function fn(e){
var key = e.keyCode ? e.keyCode : e.which;
cnt++;
if(cnt == 10) {
alert('event was fired 10 times. Last time with key: '+key);
cnt = 0;
}
}

The DOM 3 Events spec includes key events, but it's still a working draft so likely not that widely supported yet but should be pretty helpful.
For turning key codes into characters, you might find Quriskmode helpful. Knowing which key was pressed and which modifiers should get you where you want to be. Note that you may have issues mapping all keyboards to the same character sets because some have keys that others don't (e.g. Microsoft "windows" key and Apple command key). A bit of trial and error might be required.
Oh, and you might find the article JavaScript Madness: Keyboard Events interesting.

I ended up using keycode.js, but am building a whole event-managing system around keydown, keypress and keyup events, because just one of the events (keydown) is not enough to determine which character was entered and which key was pressed if there is no corresponding character. Browser incompatibilities are an added bonus to this challenge. :)
Thank you both for your answers, it has helped me understand the problem fully.

Related

How to detect actual characters only with JS key-events (for text-editor)

I am working on a WYSIWYG-like editor for equations (in combination with plain text).
Since implementing the functionalities (for equations) that I'd like to have won't work using the existing frameworks (contentEditable or document.designMode), I am now building an editor from scratch. (so far it has worked out good, I've successfully implemented most functionalities of a normal editor)
I've been using the keydown event to detect user input while in "edit-mode" (that is, when the user has clicked on the editor-area, also displaying the cursor), but the problem with that is, that when clicking "alt" or "strg" or other keys that aren't actual characters, they'll also get displayed in my editor.
Now, what I've tried is to ignore those keys by using if-statements, but there are 2 issues I see with that:
1. It may influence performance, when too many keys have to be ignored
2. I can never be sure, if there doesn't exist some exotic key, perhaps on a Mac or so, which I didn't ignore
I have also tried to use the keypress event instead, which worked mostly fine, but still displayed "Enter" and "Delete", so who knows what others keys it may display too. Also, it is labelled as "deprecated".
Are there any better ways of doing that, or will I just have to make a big list of keys to ignore?
A simple (but limited) approach would be to check if the keydown event's keyCode is between 65 (code for key 'a') and 90 (code for 'z').
If you need more than just letters though, another solution would be to check the event's key and its length. For actual characters, the key simply holds that character (so length 1). For Ctrl, Shift, etc., key will hold the full name of the key, e.g. "Control", "Shift", etc.
So, if a key is an actual character, the key property will have a length of 1.
document.onkeydown = function(e) {
var keycode = e.keyCode;
if(e.key.length == 1) {
document.querySelector("#editor").innerHTML += e.key;
}
}
<p id="editor"></p>
You can check this one too
document.addEventListener("keydown", (event) => {
console.log(event);
if (event.code === "Escape") {
console.log("abc");
}
});

keypress and keyup - why is the keyCode different?

Related: JavaScript KeyCode vs CharCode
Here is some code you can try at home or in a jsfiddle:
el.addEventListener( 'keyup', function( e ) {
console.log( 'Keyup event' );
console.log( e.keyCode );
} );
el.addEventListener( 'keypress', function( e ) {
console.log( 'Keypress event' );
console.log( e.keyCode );
} );
Why is the keyCode different?
I can understand why one should use keypress only, but what I don't understand is how two key events, given the same hit key on the keyboard, give different keyCodes.
PS: I'm not worrying about legacy browsers support, I tried this in Chrome and was surprised, and couldn't find an explanation.
The events are for completely different purposes. Use keyup and keydown for identifying physical keys and keypress for identifying typed characters. The two are fundamentally different tasks with different events; don't try to mix the two. In particular, keyCode on keypress events is usually redundant and shouldn't be used (except in older IE, but see the linked document below for more on that); for printable keypresses it's usually the same as which and charCode, although there is some variation between browsers.
Jan Wolter's article on key events, already linked to in another answer, is the definitive word on this subject for me and has tables describing what each of the different properties returns for each type of key event and each browser.
There is a good article on quirksmode.org answering exactly that question. You might also want to look at Unixpapa's results.
Well, I stumbled upon one difference when i was trying to copy user's entry from one input of the form to some other part of the form , which I had locked for my for users to edit.
What i found was, that whenever a user moved to the next label using key upon completing the input, one last keyboard entry was missed in the copied entry when I used eventListener to keypress and this got resolved on using keyup.
So, in conclusion Keypress listens to the state at the instant when the key was pressed, leaving aside the result of keypress, whereas keyup listens to the system status after the key has been pressed and includes the result of the keypress.

javascript - calculate "true" keyCode

When I press a key on my keyboard, I can get the keyCode of that key using e.keyCode. But the keyCode I get does not consider the pressed alt/ctrl/shift keys, wich modify the key code.
Fortunately, I get the properties shiftKey/altKey/ctrlKey with the event so I am able to calculate the "true" key code.
But I don't know how to calculate this correctly. Where can I read about that?
Is it as easy as substracting 32 if shift ist pressed and so on, or are there much exceptions?
You're mistaken, key codes don't change because they refer to a specific key on the keyboard. Regardless of modifier keys, those codes stay the same (and even the modifier keys themselves have a key code).
Capture the keypress event, which will allow you to access character codes.
el.onkeypress = function (evt) {
alert( (evt || window.event).charCode );
}
I don't understand why you would like to calculate the "true" keyCodes. If you are making shortcuts for your site/app/whatever, you could simply check if the button was pressed was (for example) S and that Ctrl was pressed at the same time.
True keyCodes have no meaning by itself (unless you need it for something specific).
Btw, you should consider using jQuery for your project. It normalizes the keyCodes so you don't have any weird behavior in any browser (Windows and OS). I guess that is more important.

get character typed, cross-browser

Simple question -- Does anyone know of a reliable cross-browser function to get the character typed from a keydown event? I can write one from the quirksmode grid but would rather not re-invent the wheel for something so simple yet so non-standard.
Let me clarify:
There is no way to do this simply using event.keyCode or event.which. The overall logic is something like:
get keycode
detect shift, ctrl
if ctrl, ignore
create map of keycodes with and without shift key
example map {186 : ';', 187 : '=', 188 : ',', ....}
need a seperate map for shift key modifier
map needs to change depending on browser (especially Safari Mac which has keycodes like 60,000)
if keycode is in map, return mapped key
if keycode is not in map, normalize numbers, apply shift modifier key if necessary, return String.fromCharCode(key)
It's not a simple solution, which is why I'm looking for a pre-made one :)
Are you willing to use jQuery?
$("input").bind("keydown",function(e){ var value = this.value + String.fromCharCode(e.keyCode); }
I believe that switching to the keypress event would solve the issue mentioned in your comment. Would the code below meet your requirments?
$("input").bind("keypress",function(e){ var value = this.value + String.fromCharCode(e.keyCode); }
I've been wondering the same thing for years. Recently I got fed up with having to look up keycodes for events that I wrote a module called keysight that translates keypress, keydown, and keyup events into characters and keys respectively.
Example:
element.addEventListener("keydown", function(event) {
var character = keysight(event).char
})
It doesn't ignore anything on ctrl, so you'd have to do that manually if you want. But it does all the rest of the logic you gave.

How can I prevent entry of non-numerals a text field?

I found this question. However, most of the answers intercept the key press, check the key code, and stop the event if it isn't an acceptable key code.
There are a some problems with that.
A common bug among all the answers is that shift key combinations are not prevented so users can enter stuff like "#" or "&".
Users can still paste in bad values from the clipboard.
When you start messing around with the key press event, the webpage starts doing weird, unexpected things. For example if the field has focus and the user tries to reload the page by pressing command-R it won't work. Or they can't tab out of the field.
I would like a solution that allows the keypress, then checks the entered value against a regex and removes unwanted characters.
I'm looking for a solution along these lines:
Doesn't intercept the keypress event.
Ideally uses a regex after the keypress.
OK if it uses jQuery.
Doesn't require installing a plug-in.
I tried this function:
$('input.numerals_only').keypress(function() {
var v = $(this).val();
var no_nonnumerals = v.replace( /[^0-9]/, '' );
$(this).val(no_nonnumerals);
});
But that doesn't work. I'm still able to type in letters.
Any info on why it doesn't work? How could I modify it so it works? Other suggestions?
If you use keyup and also blur you should handle most cases. Someone keys in text and also if they paste in a value into the text box. As the blur function will remove the bad values as well.
$('input.numerals_only').keyup(AllowOnlyNumber).blur(AllowOnlyNumber);
function AllowOnlyNumber()
{
var v = $(this).val();
var no_nonnumerals = v.replace(/[^0-9]/g, '');
$(this).val(no_nonnumerals);
}
Of course if html5 is an option you could always do:
<input type="number"/>
jsfiddle example.
The thing your regexp is missing, which is why it didn’t work for keypresses neither, is the g flag for a global regexp check.
Use var no_nonnumerals = v.replace( /[^0-9]/g, '' );
If you use keyup instead of keypress it will always remove the incorrect characters.
You can also use this to actually block the events:
$('input.numerals_only').keypress(function(event) {
if(event.keyCode < 48 || event.keyCode > 57){
return false;
}
});
Use the keyup event. It is triggered after the key is processed by the browser:
$('#txtInput')
.keyup(function(ev) {
var newValue = this.value.replace(/[^0-9]/, '');
$(this).val(newValue);
});
I wrote a jQuery plugin to do this. Demo and code here http://brianjaeger.com/process.php
It uses a regular expression to validate whatever you want.
There are a few issues:
it's a plugin (however, you could suck out the code and plunk it into your other JavaScript if you want. -its easier just to use as plugin)
Unfortunately there is no way to limit pasted information directly (across all browsers) - My solution to this was to add validation on focus change as well as keypress.

Categories