Lookup table for multiple Key Press - javascript

I am trying to create a look up table ( as i have large number of keys to handle) for handling my keys functionality. So far i have been able to handle single key presses as shown below:
(function(){
document.body.addEventListener('keydown',keysHandler,false);
var keyLookUp = {37:leftKey,39:rightKey,40:DownKey...etc}
function keysHandler(e){
event = e || window.event;
var keycode = event.which || event.keyCode;
keyLookUp[keycode](e);
}
function leftKey(e){
}
function rightKey(e){
}
function DownKey(e){
}
})();
How can i modify the above code to handle the multiple key press functionality also?? like pressing Shift + left key

How can i modify the above code to handle the multiple key press [such as] pressing Shift + ←
The keys Shift, Ctrl, Alt and Alt Gr are modifier keys, this means that they're sent as part of the event you call e and are stored as e.shiftKey, e.ctrlKey, e.altKey and e.altGraphKey, respectively.
So what does this mean for you? If you want to keep your current structure, I see you as having three choices; you can
write completely different functions for the modified versions, e.g.
keyLookUp['37sc'] = leftKeyShiftCtrl;
keyLookUp[
keycode
+ (e.shiftKey ? 's' : '')
+ (e.ctrlKey? 'c' : '')
+ (e.altKey ? 'a' : '')
](e);
look at these values in you current handlers
// inside fn
if (e.shiftKey) {/* different code path */}
pass these as parameters into your handlers (which take extra args)
function leftKey(e, shift, ctrl, alt) { /* ... */ }
keyLookUp[keycode](e, e.shiftKey, e.ctrlKey, e.altKey);
For any combination of keys, you need to track keydown and keyup, see this question

Related

How to obtain full value inside jQuery's keypress event?

I'm writing some jQuery which intercepts the value entered in an input field and determines whether to allow or to prevent the typed value.
I need to get the next value, i.e., what the value will be were I to permit the key-press, and I need to know this value at a point before it is displayed, so I'm using the keypress event.
My question is: inside the keypress event, how can I tell what the resultant value would be were I to permit the key-press? What is the 'potential value'?
If I write out the key-press event object to the console and inspect the properties, I can see that currentTarget.value shows this 'potential value'. However, if I use this property inside the keypress event then it returns only the value prior to the context key-press.
For example, if the user types "a" into an empty text box bound to the following jQuery
$(":input").on("keypress", function(e) {
console.log(e);
console.log(e.currentTarget.value);
});
Digging down through the first console output (e) shows that currentTarget.value = "a".
But the second console output (e.currentTarget.value) will show "".
If the user was then to type "b" into that same text box then:
Manually inspectng e and locating currentTarget.value displays "ab"; Dumping e.currentTarget.value from inside the event displays "a".
Can anyone explain how I can get this 'potential value' while inside the keypress event?
Not the prettiest of solutions (you can see the would be result just before it's reverted), but to save the trouble of discerning between arrow/control and input keys etc, you could store the original value in keypress and revert to that in keyup if needed (also storing the selection positions for complete reversion)
$(":input").keypress(function(e) {
$(this).data('orgValue', {value: this.value, pos: this.selectionStart, selend:this.selectionEnd});
}).keyup(function(e){
var val = this.value;
if(!somevalidation(val)){
var org =$(this).data('orgValue');
this.value = org.value;
this.selectionStart = org.pos;
this.selectionEnd = org.selend;
}
});
Example fiddle
Edit
Did some testing, but jquery makes predicting the outcome relatively easy. Not only does it fill the key property, it also fills other properties on its event on which the type of key can be checked. While testing charCode seems to be 0 for 'non input' keys.
The straight forward would be:
$(":input").keypress(function(e) {
if(!e.charCode)return; //is 0 for non input
var cur = this.value; //current value
var val = cur.substring(0,this.selectionStart)
+ e.key
+ cur.substring(this.selectionEnd);
return cur=== val //unchanged
|| somevalidation(val);
});
But that would not include deletes/backspaces, to handle those as well:
$(":input").keypress(function(e) {
var key,start = this.selectionStart ,end = this.selectionEnd;
if(e.charCode)
key = e.key;
else{
if(e.keyCode===8 || e.keyCode===46){
key = '';
if(end===start){
if(e.keyCode===8)
start--;
else
end++;
}
}
else
return true; //charCode is 0 for non input 46 = delete 8 = backspace
}
var cur = this.value; //current value
var val = cur.substring(0, start) + key + cur.substring(end);
return cur=== val //unchanged
|| somevalidation(val);
});
Fiddle
While testing this seemed to behave as expected. An other way might be have a hidden input field, send the keys there and examine its results, but the above should do the trick.

Detecting ctrl+z (and other control combos) in paper.js

I'm trying to enable editing commands in my paper.js application (such as CTRL+z for 'undo').
Detecting individual letter keys works great, and I can detect modifier keys that are held during mouse events, but I'm having trouble writing an event handler that detects combinations of CTRL and letter keys.
Based on the examples given by fabric.js, what I would expect is a key handler that looks something like this:
function onKeyDown(event) {
if (event.key == 'z' && event.modifiers.control){
//do a thing!
}
}
However, this doesn't work! Weirdly enough, the conditional block never fires. To investigate this, I wrote the following diagnostic handler...
function onKeyDown(event) {
console.log(event.key);
console.log(event.modifiers.control);
}
... and tried it out with various keyboard inputs with some interesting results:
CTRL key only
Key: control
Control: true
z key only
Key: z
Control: false
z key pressed while holding CTRL
Key:
Control: true
These results suggest that the string returned by event.key is different depending on whether the control modifier is held down when another key is typed. Something weird is happening here!
Based on this, how can I detect both of these keys being pressed at the same time?
Here are a couple of vanilla Javascript solutions that should help you:
Solution 1
Check which keycode was pressed down and if the shiftkey is down using native the event object.
function handleKeyDown(evt) {
if (evt.which === 90 && evt.shiftKey) {
// do a thing!
}
};
Solution 2
Keep a global variable for the detecting if the shift key is down and use that in your keydown handler. You'll also need to reset it with a keyup event handler.
var shiftKeyDown = false;
function handleKeyDown(evt) {
if (evt.which === 17) {
shiftKeyDown = true;
} else if (evt.which === 90 && shiftKeyDown) {
// do a thing!
}
};
function handleKeyUp(evt) {
if (evt.which === 17) {
shiftKeyDown = false;
}
};
TL;DR: You can use event.key.charCodeAt(0) to detect the strange character codes returned by CTRL+Z and other CTRL+key combinations.
As it turns out, the CTRL+z combination is special.
The key being returned in this case...
z key while holding control
Key:
Control: true
... looks like an empty string, because the keycode being passed to the event handler corresponds to the special CTRL+z combination, which results in an unprintable character.
To detect this special character, I modfiied the diagnostic handler...
function onKeyDown(event){
console.log("Key: " + event.key);
console.log("Control: " + event.modifiers.control);
console.log("KeyCode: " + event.key.charCodeAt(0));
}
... and tested the same keyboard combinations as before:
CTRL key only
Key: control
Control: true
KeyCode: 99
z key only
Key: z
Control: false
KeyCode: 122
z key pressed while holding CTRL
Key:
Control: true
KeyCode: 26
This means that the special CTRL key combinations can be detected using an event handler like this:
function onKeyDown(event) {
if (event.key.charCodeAt(0) == 26){ // detect the special CTRL-Z code
// do a thing!
}
}
It should be noted that this approach will not work for detecting the control key on its own, since 99 is NOT the character for CTRL, but rather for "c", the first character in the string "control" returned by event.key. For that, you'll still want to use event.modifiers.control.
function onKeyDown(event) {
if (event.event.ctrlKey && event.key == "z") {
//do something
}
}
This should work.

how to extend a object

I'm working on a framework for making games and i have a function for taking key input.
But since its a framework specific options need to be optional an example would be if you want movement by arrow keys, 'aswd' or maybe even mouse but if you want to use mouse you don't want to have arrow keys activated
so what i need to do is add if statements to the function after its declared.
The function:
Note: there is nothing wrong with the function it works fine
var key = [];
onkeydown = onkeyup = function(e){
e = e || even;
key[e.keyCode] = e.type == 'keydown';
//insert here
};
Is there i can add this:
to the place where it says //insert here
if(map[17] && map[16] && map[65]){ // CTRL+SHIFT+A
alert('Control Shift A');
}
Help would be much appreciated.

How can I know a 2 last pressed key on a keyboard

Is it possible to know, what 2 last keys was pressed on keyboard?
How can I do it?
I need to compare this keys, and if they are the same - make some function.
As example, if someone press Enter - this is a first function, if after Enter he press a SPACE- this is a second function. If after the ENTER he press a Ctrl - this is a third function.
So, I hink that only onw way to do it - is make a 2 var with current and previous key value, and make a IF ELSE IF function
:-)
This is a way, how I get a current key value
$('#text').keydown(function(event) {
$('#show').text(event.keyCode);
});
Or, the BETTER question! (I saw it right now)
Directly in this editor, after I press doublespace - it jump to anothe line in live-preview.
How it works? I'm not sure, but I thinks that I need is almost the same.
Thank you very much!
I think storing the last key pressed and checking both the old and new keyCode in the event handler is a good way to do this.
$('#text').keydown((function() {
var lastKey = undefined;
return function(event) {
// here you have both the old and new keyCode
lastKey = event.keyCode;
};
})());
Also, the two spaces thing is Markdown interpretation.
You could start with a very simple jQuery plugin:
(function($) {
$.fn.keyWatcher = function() {
return this.keydown(function(evt){
var $this = $(this);
var prevEvt = $this.data('prevEvt');
$this.trigger('multikeydown',[prevEvt,evt]);
$this.data('prevEvt',evt);
});
};
})(jQuery);
This will raise a new event (multikeydown) whenever a keydown event is usually raised. This will either provide just the keydown event from the current key press, or if there is a previous one it will provide that too.
Usage could be something like:
$(document).keyWatcher().bind('multikeydown',function(evt,prevKey,currKey){
alert('prevKey = ' + ((prevKey) ? String.fromCharCode(prevKey.keyCode) : '(none)'));
alert('currKey = ' + String.fromCharCode(currKey.keyCode));
});
Live example (press keys on the lower right hand pane in jsfiddle): http://jsfiddle.net/9VMUy/1/
The event provided in prevKey and currKey parameters to the event handler contain the original keydown events, so you have full access to the keyCode, the ctrlKey and shiftKey properties etc.
This is probably not the best solution but see if you can use it or parts of it
jsFiddle
var clicks = 0
$("#text").one("keypress", function () {
clicks = 1;
var KeyCode1 = event.keyCode;
$('#result').text(KeyCode1);
$("#text").one("keypress", function () {
clicks = 2;
var KeyCode2 = event.keyCode;
$('#result').text(KeyCode1 + "\n" + KeyCode2);
});
});

Doing key combos with jQuery / JavaScript

I'm curious how i, with the following jQuery plugin code im writing at the bottom of this question, could implement key combos. How it's working so far is it allows a user to create key commands simply by doing a normal jQuery like syntax and provide an event for the key command, like so:
$(window).jkey('a',function(){
alert('you pressed the a key!');
});
or
$(window).jkey('b c d',function(){
alert('you pressed either the b, c, or d key!');
});
and lastly what i want is the ability to do, but can't figure out:
$(window).jkey('alt+n',function(){
alert('you pressed alt+n!');
});
I know how to do this outside of the plugin (on keyup set a var false and on keydown set the var true and check if the var is true when you press the other key), but i don't know how to do this when you dont know what keys are going to be pressed and how many. How do I add this support? I want to be able to allow them to do things like alt+shift+a or a+s+d+f if they wanted. I just can't get my head around how to implement this. Any ideas?
I'm going to release this as an open source plugin and i'd love to give whoever gives me the right, working, answer some credit on the blog post and in the code it's self. Thanks in advance!
(function($) {
$.fn.jkey = function(keyCombo,callback) {
if(keyCombo.indexOf(' ') > -1){ //If multiple keys are selected
var keySplit = keyCombo.split(' ');
}
else{ //Else just store this single key
var keySplit = [keyCombo];
}
for(x in keySplit){ //For each key in the array...
if(keySplit[x].indexOf('+') > -1){
//Key selection by user is a key combo... what now?
}
else{
//Otherwise, it's just a normal, single key command
}
switch(keySplit[x]){
case 'a':
keySplit[x] = 65;
break;
case 'b':
keySplit[x] = 66;
break;
case 'c':
keySplit[x] = 67;
break;
//And so on for all the rest of the keys
}
}
return this.each(function() {
$this = $(this);
$this.keydown(function(e){
if($.inArray(e.keyCode, keySplit) > -1){ //If the key the user pressed is matched with any key the developer set a key code with...
if(typeof callback == 'function'){ //and they provided a callback function
callback(); //trigger call back and...
e.preventDefault(); //cancel the normal
}
}
});
});
}
})(jQuery);
Use keypress instead of keyup/keydown because the latter two do not accurately protray the keycode (reference, see last paragraph). You can reference the altKey ctrlKey and shiftKey boolean properties of the event object in this case...
$(document).keypress(function(e) {
var key = String.fromCharCode(e.which);
var alt = e.altKey;
var ctrl = e.ctrlKey
var shift = e.shiftKey;
alert("Key:" + key + "\nAlt:" + alt + "\nCtrl:" + ctrl + "\nShift:" + shift);
});
Also, you can use String.fromCharCode to translate the key code to an actual letter.
You can't trap multiple keys aside from combinations with Ctrl, Alt, and Shift. You simply can't do it in a single event. So throw the a+s+d+f idea out the window.
Note: Obviously there are certain key combinations that are used by the browser. For instance, Alt + F usually brings up the File menu in Windows. Ctrl + N usually launches a new window/tab. Do not attempt to override any of these combinations.
Here's a live demo for your testing pleasure.
Here's what I came up with. Essentially what I did was created a JSON object that stores all the key codes. I then replace all the provided keys with the codes. If the keys are using the '+' to make a key combo, I then create an array of the codes out of it.
We then create another array that stores all the keys that are being pressed (keyDown add the item, keyUp removes it). On keyDown, we check if it's a single key command or combo. If it's a combo, we check it against all the currently active key presses. If they all match, we execute the callback.
This will work with any number of key combos. Only time I saw that it wasn't working is when you use the 'alert()' to display a message on the key combo because it will no longer remove the items from the active key press array.
(function($) {
$.fn.jkey = function(keyCombo,callback) {
// Save the key codes to JSON object
var keyCodes = {
'a' : 65,
'b' : 66,
'c' : 67,
'alt' : 18
};
var x = '';
var y = '';
if(keyCombo.indexOf(' ') > -1){ //If multiple keys are selected
var keySplit = keyCombo.split(' ');
}
else{ //Else just store this single key
var keySplit = [keyCombo];
}
for(x in keySplit){ //For each key in the array...
if(keySplit[x].indexOf('+') > -1){
//Key selection by user is a key combo
// Create a combo array and split the key combo
var combo = Array();
var comboSplit = keySplit[x].split('+');
// Save the key codes for each element in the key combo
for(y in comboSplit){
combo[y] = keyCodes[ comboSplit[y] ];
}
keySplit[x] = combo;
} else {
//Otherwise, it's just a normal, single key command
keySplit[x] = keyCodes[ keySplit[x] ];
}
}
return this.each(function() {
$this = $(this);
// Create active keys array
// This array will store all the keys that are currently being pressed
var activeKeys = Array();
$this.keydown(function(e){
// Save the current key press
activeKeys[ e.keyCode ] = e.keyCode;
if($.inArray(e.keyCode, keySplit) > -1){ // If the key the user pressed is matched with any key the developer set a key code with...
if(typeof callback == 'function'){ //and they provided a callback function
callback(); //trigger call back and...
e.preventDefault(); //cancel the normal
}
} else { // Else, the key did not match which means it's either a key combo or just dosn't exist
// Check if the individual items in the key combo match what was pressed
for(x in keySplit){
if($.inArray(e.keyCode, keySplit[x]) > -1){
// Initiate the active variable
var active = 'unchecked';
// All the individual keys in the combo with the keys that are currently being pressed
for(y in keySplit[x]) {
if(active != false) {
if($.inArray(keySplit[x][y], activeKeys) > -1){
active = true;
} else {
active = false;
}
}
}
// If all the keys in the combo are being pressed, active will equal true
if(active === true){
if(typeof callback == 'function'){ //and they provided a callback function
callback(); //trigger call back and...
e.preventDefault(); //cancel the normal
}
}
}
}
} // end of if in array
}).keyup(function(e) {
// Remove the current key press
activeKeys[ e.keyCode ] = '';
});
});
}
})(jQuery);
This is just a shot in the dark but maybe it'll help you down the right path.
If it's possible to have that function recognize a hexadecimal value for the key that you entered instead of the literal key (such as 0x6E for the letter 'n'), you could derive what "alt+n" translates to in hex and have the function look out for that value.
If you're looking for something that will let a user easily enter and define key combos using a plain input box, I wrote a plugin that does it for you: http://suan.github.com/jquery-keycombinator/

Categories