Optimizing jQuery Hotkeys - javascript

So I have a web app which uses all the hot keys from A to Z.
Each hot key is used for a tab. So for example:
I have 20 tabs:
#tab1, #tab2, #tab3, #tab4 etc. All tabs get a class of .tabs.
So for the hotkeys to work I made this:
if (e.keyCode == 65) {$('.tabs:not(#tab1)').hide();$("#tab1").fadeIn();}
if (e.keyCode == 66) {$('.tabs:not(#tab2)').hide();$("#tab2").fadeIn();}
if (e.keyCode == 67) {$('.tabs:not(#tab3)').hide();$("#tab3").fadeIn();}
if (e.keyCode == 68) {$('.tabs:not(#tab4)').hide();$("#tab4").fadeIn();}
if (e.keyCode == 69) {$('.tabs:not(#tab5)').hide();$("#tab5").fadeIn();}
if (e.keyCode == 70) {$('.tabs:not(#tab6)').hide();$("#tab6").fadeIn();}
if (e.keyCode == 71) {$('.tabs:not(#tab7)').hide();$("#tab7").fadeIn();}
//etc till keycode 81 and tab20.
So, is there a better optimizing way to make this so it will be written in less characters? Since on each line I'm using twice the the same ID.
Edit/Note: Sorry, the actual tab ID's are random names.
Thanks

Something like this perhaps:
if(e.keyCode >= 65 && e.keyCode <= 81) {
var tab = e.keyCode - 65 + 1;
$('.tabs:not(#tab' + tab + ')').hide();
$('#tab' + tab).fadeIn();
}
I don't see how keycode 81 is supposed to be tab20 though, wouldn't that be tab17?
Update: If your tab ids can be anything at all then just throw them in an array:
var tab_ids = [ 'where', 'is', 'pancakes', 'house', ... ];
if(e.keyCode >= 65 && e.keyCode <= 81) {
var tab = tab_ids[e.keyCode - 65];
$('.tabs:not(#' + tab + ')').hide();
$('#' + tab).fadeIn();
}
If you also have gaps in they keycodes then use an object instead of an array:
var tab_ids = { 65: 'where', 70: 'is', 72: 'pancakes', 73: 'house', ... };
var tab = tab_ids[e.keyCode];
if(tab) {
$('.tabs:not(#' + tab + ')').hide();
$('#' + tab).fadeIn();
}

$('.tabs:not(#tab' + (e.keyCode - 64) + ')').hide();
$("#tab" + (e.keyCode - 64)).fadeIn();

Just replace all these if statements with this code
$('.tabs:not(#tab'+(e.keyCode-64)+')').hide();
$("#tab"+(e.keyCode-64)).fadeIn();

Related

Hotkey combinations don't work if done fast

I'm trying to make a hotkey for a web app, for example Ctrl + z performs the undo function.
It seems that when I press the keys fast (as I'm used to from using desktop apps a lot), it doesn't register. The single key press registers, but it misses the combination for some reason.
From what I understand, you have to keep track of which buttons are held down via keypress events, which is what I've done below.
Try the code below. Hitting Z outputs Z. Hitting CTRL then Z slowly outputs CTRL + Z. Hitting CTRL then Z quickly outputs Z. When I perform the action at the same speed in say Notepad for windows, it works flawlessly almost every time.
https://codepen.io/samkeddy/pen/YQjgdZ?editors=1010#0
var ctrlPressed=false, altPressed=false;
window.addEventListener("keydown", function (e) {
hotkey = e;
if (e.keyCode == 17) ctrlPressed = true;
if (e.keyCode == 18) altPressed = true;
e.preventDefault();
});
window.addEventListener("keyup", function (e) {
hotkey = window.event;
if (e.keyCode == 17) ctrlPressed = false;
if (e.keyCode == 18) altPressed = false;
if (e.keyCode == 90){
if (altPressed && ctrlPressed && e.keyCode == 90)
addText('ALT + CTRL + Z');
else if (ctrlPressed && e.keyCode == 90)
addText('CTRL + Z');
else
addText('Z');
}
});
//meaningless, just adds text to doc so you can see it
function addText(text) {
var theDiv = document.getElementById("output");
theDiv.appendChild(document.createElement("br"));
var content = document.createTextNode(text);
theDiv.appendChild(content);
}
Use e.ctrlKey to check if ctrl is down instead of variables, and just check for the hotkey combination on keydown, don't do anything on key up.
https://codepen.io/samkeddy/pen/gRdBpq
function KeyPress(e) {
var evtobj = window.event? event : e
if (evtobj.keyCode == 90 && evtobj.ctrlKey) addText("CTRL + Z");
else if (evtobj.keyCode == 90) addText("Z");
}
document.onkeydown = KeyPress;

How can I capture altKey + i, u, e, n with jQuery?

I'm trying to set up a keyboard for a foreign language. I'm using jQuery to convert keys pressed into foreign characters. I am using:
A - Z
ALT + A - Z
SHIFT + A - Z
ALT + SHIFT + A - Z
My code works for all of these except these 4:
ALT + I
ALT + U
ALT + E
ALT + N
It works fine in Firefox, but in Chrome and Safari (I'm using a mac) I get these accent marks - ˆ, ¨, ´, ˜ - instead of the foreign character that is supposed to go into the textarea.
Here is some of the code:
function type(e, char, textArea) {
e.preventDefault();
var start = textArea[0].selectionStart;
var end = textArea[0].selectionEnd;
var len = textArea.val().length;
var newPos = start + char.length;
textArea.val(textArea.val().substring(0, start) + char + textArea.val().substring(end, len));
textArea[0].setSelectionRange(newPos, newPos);
}
$('textarea').keydown(function(e) {
var textArea = $(this);
if (e.which == 65 && e.altKey) {type(e, 'अ', textArea);return false;}
if (e.which == 68 && e.altKey) {type(e, 'ड', textArea);return false;}
if (e.which == 73 && e.altKey) {type(e, 'इ', textArea);return false;}
if (e.which == 74 && e.altKey) {type(e, 'ज्ञ', textArea);return false;}
});
This works when e.which is 65, 68, and 74, but not 73.
How can I get this to work right?
You know it's funny, I'm also constantly asking myself why something doesn't work in chrome even though it works just fine everywhere else. In this case, I'm assuming it has to do with the fact that both e.which and e.keyCode have been depreciated for e.key and e.code.
That being noted, I still use e.keyCode in production, so I know it still works with the latest version of chrome. Maybe do some console.log(e) and see what values are actually being returned?
I don't have chrome on my personal computer, so I can't test this, but I simplified your code and made a fiddle that works on my machine. Hopefully it helps point you in the right direction.
function InsertSymbol(symbol, $selector) {
let cursor = $selector[0].selectionStart,
text = $selector.val();
$selector.val(text.substr(0, cursor) + symbol + text.substr(cursor)).focus()[0].setSelectionRange(++cursor, cursor);
}
$('textarea').on('keydown', function(e) {
if (e.altKey) {
e.preventDefault();
switch (e.keyCode) {
case 69: InsertSymbol('इ', $(this)); break;
case 73: InsertSymbol('अ', $(this)); break;
case 78: InsertSymbol('ज्ञ', $(this)); break;
case 85: InsertSymbol('ड', $(this)); break;
}
}
});
https://jsfiddle.net/rvgj35kt/2/
I'm using Chrome on Mac and your jsFiddle example https://jsfiddle.net/s0fmpgaj/ is working. When I press ALT + SHIFT + i
It returns the special char you defined.

How to use spacebar and if statements in JS?

I am making a game based off of a tutorial at http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/ it is going well but I wanted to make the function that reads if the two items are touching only happen when the space bar is pressed.
if (hero.x <= (monster.x + 32)
&& monster.x <= (hero.x + 32)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)) {
++monstersCaught;
reset();
}
if (hero.x <= (tack.x + 32)
&& tack.x <= (hero.x + 32)
&& hero.y <= (tack.y + 32)
&& tack.y <= (hero.y + 32)) {
monstersCaught -= monstersCaught;
reset();
}
if (monstersCaught > 10) {
monstersCaught -= 10;
}
How should I fix the
if (hero.x <= (tack.x + 32)
&& tack.x <= (hero.x + 32)
&& hero.y <= (tack.y + 32)
&& tack.y <= (hero.y + 32)) {
monstersCaught -= monstersCaught;
reset();
}
so that it only goes if the space bar is pressed?
Most easy way is to know at any moment the status of your keyboard : for that you have to listen to keyboard events and update an array containing the status of each key.
This will lead to something like :
window.keyStates = []; // now you can use keyStates anywhere.
// good enough since you seem to be in the first steps.
window.addEventListener('keydown',
function(e) { keyStates[e.keyCode || e.key] = true;} );
window.addEventListener('keyup',
function(e) { keyStates[e.keyCode || e.key] = false;} );
Once you have done that, you can test anywhere, anytime, the status of the space key with :
if (keyStates[32] == true) { ... }
you might prefer, for readability, define a key object that will hold the few keycodes you use :
window.key = {
space : 32,
enter : 13,
left : 37,
up : 38,
right : 39,
down : 40
}
that way, you can write :
if ( keyStates[key.space] == true ) {
...
}
which is more easy to grasp.
(Rq : if you search for keycodes, looking here is one way : https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent )
If you use jQuery you can do something similar to this:
$(window).keypress(function(e) {
if (e.which === 32) {
//do your logic here
}
});
32 is the keycode for spacebar
Or in just javascript (Run this code in Document ready as displayunicode(event)):
function displayunicode(e){
var unicode=e.keyCode? e.keyCode : e.charCode;
if(unicode == 32){
//do your code
}
}

Working with multiple key press events (windows key)

While working with the multiple keypress events i found this code which worke fine
$(document).bind('keypress', function(event) {
if( event.which === 65 && event.shiftKey ) {
alert('you pressed SHIFT+A');
}
});
But to make it to work wth combinig with windows key... like
event.which === 65 && event.windowsKey
it failed...
Is there any option to make it work with windows key?
if it is a mac machine there is no key as windows..so what could be the alternate option for windows key in mac
Use keyup event.
On a Mac left Command is which = 91, right Command is which = 93. I can't tell what are those on Windows, but you can test it yourself. As #ian commented they should be 91 and 92 respectively.
To test
$(document).on('keyup', function(e) {
var modKey = "";
if (e.shiftKey) modKey += "shiftKey,";
if (e.ctrlKey) modKey += "ctrlKey,";
if (e.altKey) modKey += "altKey,";
if (e.metaKey) modKey += "metaKey,";
console.log ("which: " + e.which + " modkey: " + modKey );
});
UPDATE: Try use keydown event and event.metaKey
$(document).on('keydown', function(e) {
if(e.which === 65 && event.metaKey ) {
console.log ("You pressed Windows + A");
}
});
Remember the key you pressed before. Like if you press shift. get a boolean or something to shiftPressed = true on a onKeyRelease make it false again. That way you can check if shiftPressed == true && aPressed == true before doing something
I made something a while ago for a little WASD game. Perhaps it makes more sense if you see the code:
var up = false;
var down = false;
var left = false;
var right = false;
function keyUp(e) {
keyCode = (e.keyCode ? e.keyCode : e.which);
if (keyCode == 37 || keyCode == 65) {
left = false;
}
if (keyCode == 38 || keyCode == 87) {
up = false;
}
if (keyCode == 39 || keyCode == 68) {
right = false;
}
if (keyCode == 40 || keyCode == 83) {
down = false;
}
}
function forceStopMoving() {
left = false;
up = false;
right = false;
down = false;
}
function keyDown(e) {
keyCode = (e.keyCode ? e.keyCode : e.which);
if (keyCode == 37 || keyCode == 65) {
left = true;
}
if (keyCode == 38 || keyCode == 87) {
up = true;
}
if (keyCode == 39 || keyCode == 68) {
right = true;
}
if (keyCode == 40 || keyCode == 83) {
down = true;
}
}

How to Trigger an event with keys(ctrl +)(jQuery)

How can I trigger an event with jQuery if I press the Ctrl key plus the ++ key(zoom in).
key = Ctrl ++
Try this
$(window).keypress(function(e){
if((e.which == 61 && e.ctrlKey) || (e.which == 43 && e.ctrlKey)){
//Ctrl + "+" is pressed, 61 is for =/+ anr 43 is for Numpad + key
}
});
An example of binding to Ctrl+I. Note that you can't override default browser behavior, so many of the Ctrl+(letter) shortcuts are reserved (Ctrl+T = new tab, Ctrl+N = new Window, Ctrl+P = Print etc...)
$(window).keydown(function(e){
if(e.which == 17)
$(window).bind('keydown.ctrlI', function(e){
if(e.which == 73){
e.preventDefault();
alert('CTRL+I');
}
});
});
$(window).keyup(function(e){
if(e.which == 17)
$(window).unbind('keydown.ctrlI');
});
// the element at which you are firing the event
var div = $('#foo');
// the event handler
div.bind('paint', function() {
$(this).addClass('painted');
});
$(window).keydown(function(e) {
// if CTRL + + was pressed
if ( e.ctrlKey && e.which === 187 ) {
// trigger the event
div.trigger('paint');
}
});
Live demo: http://jsfiddle.net/NMYJW/

Categories