Scott Klarr Jr
How to create Ctrl+Key shortcuts in Javascript
Everybody loves shortcuts, so why should you deny your users of this guilty pleasure when it comes to your javascript-driven web application? Giving your users the ability to execute commands with simple shortcuts can make all the difference in the usability of your application.
Javacript Code
Here is the simple code that allows you to capture when a desired set of keys are pressed. In this example, we are focusing on CTRL+S, but it can be expanded easily with just a few lines of code per shortcut you wish to add.
var isCtrl = false;
document.onkeyup=function(e){
if(e.which == 17) isCtrl=false;
}
document.onkeydown=function(e){
if(e.which == 17) isCtrl=true;
if(e.which == 83 && isCtrl == true) {
//run code for CTRL+S -- ie, save!
return false;
}
}
jQuery Code
Here is an example of how to create a Ctrl+Key based shortcut within javascript using the jQuery Library.
var isCtrl = false;
$(document).keyup(function (e) {
if(e.which == 17) isCtrl=false;
}).keydown(function (e) {
if(e.which == 17) isCtrl=true;
if(e.which == 83 && isCtrl == true) {
//run code for CTRL+S -- ie, save!
return false;
}
});
Explanation
This code is quite simple but let me explain it a little bit. Whenever a key is pressed down, we first check to see if its CTRL being pressed (key code 17). If it is CTRL, then we set isCtrl to true in order to keep track when CTRL is activated, and of course we return isCtrl back to false once CTRL is released via the keyup event. We must keep track of the CTRL activity with a variable because the event will fire on a per-key basis. When you press ctrl+S for example, the event fires twice with two different key codes - making it impossible to simply check for both keys in one swift action.
Now going back to the keydown event; after the CTRL key check, we can look to see if other keys are being pressed. In this example, key code 83 is for the S key, which in one example could be useful for allowing quick saving of a form. And lastly, the return false; plays a very important role in keeping the browser from picking up that particular key combination and acting on it. In the example above of using CTRL+S, normally when you press that the browser will prompt you to save the page - but with the return false, the browser backs down and stays quiet.
Additional Shortcut Examples
var isCtrl = false;
document.onkeyup=function(e){
if(e.which == 17) isCtrl=false;
}
document.onkeydown=function(e){
if(e.which == 17) isCtrl=true;
if(e.which == 83 && isCtrl == true) {
//run code for CTRL+S -- ie, save!
return false;
}
if(e.which == 79 && isCtrl == true) {
//run code for CTRL+O -- ie, open!
return false;
}
if(e.which == 84 && isCtrl == true) {
//run code for CTRL+T -- ie, new tab!
return false;
}
}
Library
As posted in the comments, there is a nice library to get this done over at openjs.com. If your looking for a simple solution that covers all angles, check out Handling Keyboard Shortcuts in JavaScript
Javascript Key Codes
| Key Pressed | Key Code |
|---|---|
| backspace | 8 |
| tab | 9 |
| enter | 13 |
| shift | 16 |
| ctrl | 17 |
| alt | 18 |
| pause/break | 19 |
| caps lock | 20 |
| escape | 27 |
| page up | 33 |
| page down | 34 |
| end | 35 |
| home | 36 |
| left arrow | 37 |
| up arrow | 38 |
| right arrow | 39 |
| down arrow | 40 |
| insert | 45 |
| delete | 46 |
| 0 | 48 |
| 1 | 49 |
| 2 | 50 |
| 3 | 51 |
| 4 | 52 |
| 5 | 53 |
| 6 | 54 |
| 7 | 55 |
| 8 | 56 |
| 9 | 57 |
| a | 65 |
| b | 66 |
| c | 67 |
| d | 68 |
| e | 69 |
| f | 70 |
| g | 71 |
| h | 72 |
| i | 73 |
| j | 74 |
| k | 75 |
| l | 76 |
| m | 77 |
| n | 78 |
| o | 79 |
| p | 80 |
| q | 81 |
| r | 82 |
| s | 83 |
| t | 84 |
| u | 85 |
| v | 86 |
| w | 87 |
| x | 88 |
| y | 89 |
| z | 90 |
| left window key | 91 |
| right window key | 92 |
| select key | 93 |
| numpad 0 | 96 |
| numpad 1 | 97 |
| numpad 2 | 98 |
| numpad 3 | 99 |
| numpad 4 | 100 |
| numpad 5 | 101 |
| numpad 6 | 102 |
| numpad 7 | 103 |
| numpad 8 | 104 |
| numpad 9 | 105 |
| multiply | 106 |
| add | 107 |
| subtract | 109 |
| decimal point | 110 |
| divide | 111 |
| f1 | 112 |
| f2 | 113 |
| f3 | 114 |
| f4 | 115 |
| f5 | 116 |
| f6 | 117 |
| f7 | 118 |
| f8 | 119 |
| f9 | 120 |
| f10 | 121 |
| f11 | 122 |
| f12 | 123 |
| num lock | 144 |
| scroll lock | 145 |
| semi-colon | 186 |
| equal sign | 187 |
| comma | 188 |
| dash | 189 |
| period | 190 |
| forward slash | 191 |
| grave accent | 192 |
| open bracket | 219 |
| back slash | 220 |
| close braket | 221 |
| single quote | 222 |
This topic has the following tags:
Last 5 Linkbacks
- Sep 06, 2009www.icaropablo.com.br
- Aug 26, 2009www.bitsandpix.com



Polar Feb 24, 2008
Most of that is not true. This code is mostly wrong, please check this in IE 6 & FF.
Scott Klarr Feb 25, 2008
Polar, I have tested it in firefox 2, IE 6, and opera. The only bug i have seen is that opera does not seem to respond to return false;
Binny V A Feb 25, 2008
I have created a Keyboard shortcut library for javascirpt - it makes the job much easier.
http://www.openjs.com/scripts/events/keyboard_shortcuts/
Neil M Feb 26, 2008
You can also use the native event.ctrlKey and event.shiftKey properties.
Scott Klarr Mar 07, 2008
LOL, thanks Neil. I had no idea the event had those properties.
Jonathan M Jun 18, 2008
Has this code been tested under IE7? I tried it a couple of different ways and got no response to key combos.
Jeboy Aug 31, 2008
It's very helpful but when alert() or confirm() action is used in conjunction with the keycode combination, ff does not seem to respond to return false.
asp.net Sep 26, 2008
thx, great article
pradnya nigade Oct 17, 2008
plz explain about e.which.
Canon5D Oct 24, 2008
very good javascript review
Vinay Feb 07, 2009
Use This For Ctrl S OR c OR t Like wise....
shortcut = {
'all_shortcuts':{},//All the shortcuts are stored in this array
'add': function(shortcut_combination,callback,opt) {
//Provide a set of default options
var default_options = {
'type':'keydown',
'propagate':false,
'disable_in_input':false,
'target':document,
'keycode':false
}
if(!opt) opt = default_options;
else {
for(var dfo in default_options) {
if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
}
}
var ele = opt.target;
if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
var ths = this;
shortcut_combination = shortcut_combination.toLowerCase();
//The function to be called at keypress
var func = function(e) {
e = e || window.event;
if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
var element;
if(e.target) element=e.target;
else if(e.srcElement) element=e.srcElement;
if(element.nodeType==3) element=element.parentNode;
if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
}
//Find Which key is pressed
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code);
if(code == 188) character=","; //If the user presses , when the type is onkeydown
if(code == 190) character="."; //If the user presses , when the type is onkeydown
var keys = shortcut_combination.split(" ");
//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
var kp = 0;
//Work around for stupid Shift key bug created by using lowercase - as a result the shift num combination was broken
var shift_nums = {
"`":"~",
"1":"!",
"2":"@",
"3":"#",
"4":"$",
"5":"%",
"6":"^",
"7":"&",
"8":"*",
"9":"(",
"0":")",
"-":"_",
"=":" ",
";":":",
"'":"\"",
",":"",
"/":"?",
"\\":"|"
}
//Special Keys - and their codes
var special_keys = {
'esc':27,
'escape':27,
'tab':9,
'space':32,
'return':13,
'enter':13,
'backspace':8,
'scrolllock':145,
'scroll_lock':145,
'scroll':145,
'capslock':20,
'caps_lock':20,
'caps':20,
'numlock':144,
'num_lock':144,
'num':144,
'pause':19,
'break':19,
'insert':45,
'home':36,
'delete':46,
'end':35,
'pageup':33,
'page_up':33,
'pu':33,
'pagedown':34,
'page_down':34,
'pd':34,
'left':37,
'up':38,
'right':39,
'down':40,
'f1':112,
'f2':113,
'f3':114,
'f4':115,
'f5':116,
'f6':117,
'f7':118,
'f8':119,
'f9':120,
'f10':121,
'f11':122,
'f12':123
}
var alpha = {
's':83,
't':84,
'c':67,
'a':65
}
var modifiers = {
shift: { wanted:false, pressed:false},
ctrl : { wanted:false, pressed:false},
alt : { wanted:false, pressed:false},
meta : { wanted:false, pressed:false} //Meta is Mac specific
};
if(e.ctrlKey) modifiers.ctrl.pressed = true;
if(e.shiftKey) modifiers.shift.pressed = true;
if(e.altKey) modifiers.alt.pressed = true;
if(e.metaKey) modifiers.meta.pressed = true;
for(var i=0; k=keys[i],i 1) { //If it is a special key
if(special_keys[k] == code) kp ;
} else if(opt['keycode']) {
if(opt['keycode'] == code) kp ;
} else { //The special keys did not match
if(character == k) {kp ;
}
else {
if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if(character == k) kp ;
}
if(alpha[keys[i]] == code) kp ;
}
}
}
if(kp == keys.length &&
modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
modifiers.shift.pressed == modifiers.shift.wanted &&
modifiers.alt.pressed == modifiers.alt.wanted &&
modifiers.meta.pressed == modifiers.meta.wanted) {
callback(e);
if(!opt['propagate']) { //Stop the event
//e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = false;
//e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
}
}
this.all_shortcuts[shortcut_combination] = {
'callback':func,
'target':ele,
'event': opt['type']
};
//Attach the function with the event
if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
else if(ele.attachEvent) ele.attachEvent('on' opt['type'], func);
else ele['on' opt['type']] = func;
},
//Remove the shortcut - just specify the shortcut and I will remove the binding
'remove':function(shortcut_combination) {
alert(shortcut_combination);
shortcut_combination = shortcut_combination.toLowerCase();
var binding = this.all_shortcuts[shortcut_combination];
delete(this.all_shortcuts[shortcut_combination])
if(!binding) return;
var type = binding['event'];
var ele = binding['target'];
var callback = binding['callback'];
if(ele.detachEvent) ele.detachEvent('on' type, callback);
else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
else ele['on' type] = false;
}
}
/**
shortcut.add("ctrl c",function() {
// alert("Hi there!");
popUpAdd('LookupConsginee.htm');
});
*/
Vinay Feb 07, 2009
Surely it will works well...
Just copy this use like,
shortcut.add("ctrl c",function() {
alert("Hi Ctrl S!");
});
Vinay Feb 07, 2009
In the Shortcut.js,
I added this,
var alpha = {
's':83,
't':84,
'c':67,
'a':65
}
And add this to use that code,
for(var i=0; k=keys[i],i 1) { //If it is a special key
if(special_keys[k] == code) kp ;
} else if(opt['keycode']) {
if(opt['keycode'] == code) kp ;
} else { //The special keys did not match
if(character == k) {kp ;
}
else {
if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if(character == k) kp ;
}
if(alpha[keys[i]] == code) kp ;
}
}
}
Bijoy Mar 20, 2009
About the above shared shortcut code, just try this
//Find Which key is pressed
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code);
character=character.toLowerCase();
I have converted the key charcter to lowercase, and it seems to work fine on all browser. You do not need to define alpha characters.
Hope this is useful...
awers Mar 29, 2009
Hello from Russia =) I`m use this code:
var kCode = {Ctrl37:'CtrlBack', Ctrl39:'CtrlForward',Shift37:'ShiftBack', Shift38:'ShiftUp', Shift39:'ShiftForward'};
var kFuncs = {CtrlBack:null,CtrlForward:null,ShiftBack:null,ShiftForward:null,ShiftUp:null};
function kListener(event){
event = event || window.event;
ccode = event.keyCode ? event.keyCode : event.which ? event.which : null;
if (event.ctrlKey && event.keyCode && ccode !== 17){
if (typeof kFuncs[kCode['Ctrl' ccode]] == 'function') kFuncs[kCode['Ctrl' ccode]]();
}
if(event.shiftKey && event.keyCode && ccode !== 16){
if (typeof kFuncs[kCode['Shift' ccode]] == 'function') kFuncs[kCode['Shift' ccode]]();
}
}
function kBind(act,func){
kFuncs[act] = func;
}
Usage example:
document.onkeydown = kListener;
kBind('ShiftUp',function(){ ... });
Caggie Aug 14, 2009
@awers
Your code works great. Thanks.
Claudio Sep 01, 2009
Hi
I would like to know if you know a way to increase the whole website size in the browser as if you'd use "Ctrl +" on your keyboard but with a script..
Anyone's got an idea?
Ravindra Oct 23, 2009
Hi
I want to capture the event for ctrl and space..
i added this below code for ctrl and space, its working good in firefox. but its not working in IE.
var isCtrl = false;
document.onkeyup=function(e){
if(e.which == 17) isCtrl=false; }
document.onkeydown=function(e){
if(e.which == 17) isCtrl=true;
if(e.which == 32 && isCtrl == true)
{ alert("hi");
return false; } }
Plesae let me know what has to be done..
Thanks in Advance
Ravindra
Khairil Anuar Dec 30, 2009
i add
e.preventDefault()
to jQuery sample to prevent browser action e.g; ctrl-s to prevent browser save dialog
Jordan Boesch Jan 06, 2010
Nice write up Scott. I wrote a jQuery event plugin that simplifies keystrokes and key combos, check it out at http://boedesign.com/blog/2009/12/30/keystrokes-for-jquery/