1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
/** * http://www.openjs.com/scripts/events/keyboard_shortcuts/ * Version : 2.01.B * By Binny V A * License : BSD */ 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 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<keys.length; i++) { //Modifiers if(k == 'ctrl' || k == 'control') { kp++; modifiers.ctrl.wanted = true; } else if(k == 'shift') { kp++; modifiers.shift.wanted = true; } else if(k == 'alt') { kp++; modifiers.alt.wanted = true; } else if(k == 'meta') { kp++; modifiers.meta.wanted = true; } else if(k.length > 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(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) { 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; } }
Refactorings
No refactoring yet !
Tien Dung
August 6, 2008, August 06, 2008 07:22, permalink
My final attempt :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
/** * http://www.openjs.com/scripts/events/keyboard_shortcuts/ * Version : 2.01.B * By Binny V A * License : BSD * * Refactored by Nguyen Tien Dung ( http://free-and-happy.blogspot.com ) */ window.shortcut = (function () { var defaultOptions = { type : 'keydown', propagate : false, disable : 'input textarea', target : document, keycode : false }; // Work around for Shift key bug created by using lowercase // as a result the shift+num combinationnation was broken var shiftNums = { '`':'~', '1':'!', '2':'@', '3':'#', '4':'$', '5':'%', '6':'^', '7':'&', '8':'*', '9':'(', '0':')', '-':'_', '=':'+', ';':':', "'":'"', ',':'<', '.':'>', '/':'?', '\\':'|' }; // Special Keys and their codes var specialKeys = { 'escape' :27, 'space' :32, 'return' :13, 'enter' :13, 'pause' :19, 'break' :19, 'insert' :45, 'home' :36, 'delete' :46, 'end' :35, 'backspace' :8, 'esc' :27, 'tab' :9, 'scrolllock' :145, 'scroll_lock' :145, 'scroll' :145, 'capslock' :20, 'caps_lock' :20, 'caps' :20, 'numlock' :144, 'num_lock' :144, 'num' :144, '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 modifierMapping = { ctrl :'ctrl', control :'ctrl', shift :'shift', alt :'alt', option :'alt', meta :'meta' }; var bindings = {}; function triggeredInDisableTags(event, disableTags) { if (typeof disableTags !== 'string') return false; var element = event.target || event.srcElement; if (element.nodeType === 3) element = element.parentNode; return (disableTags.toLowerCase().indexOf(element.tagName.toLowerCase()) >= 0) ? true : false; } function matching(combination, options, e) { var i, key, modifier; var want = {}; var keys = combination.split('+'); //Find Which key is pressed var code = e.keyCode || e.which; var char = { 188: ',', 190: '.' }[code] || String.fromCharCode(code).toLowerCase(); var count = 0; for (i=0; i < keys.length; i++) { key = keys[i]; modifier = modifierMapping[key]; if (modifier) { want[modifier] = true; count++; } else if ( (key.length > 1 && specialKeys[key] === code) || (options.keycode === code) || (char === key) || (e.shiftKey && shiftNums[char] === key) ) count++; } // End for (..) return ( keys.length === count && !!want.shift === !!e.shiftKey && !!want.ctrl === !!e.ctrlKey && !!want.alt === !!e.altKey && !!want.meta === !!e.metaKey ); } // Return the function to be called at keypress function makeKeypressedFun( combination, callback, options ) { return function( e ) { e = e || window.event; if ( triggeredInDisableTags(e, options.disable) || !matching(combination, options, e) ) return; callback(e); if( !options.propagate ) { e.stopPropagation && e.stopPropagation(); e.preventDefault && e.preventDefault(); e.cancelBubble = true; e.returnValue = false; } }; } return /*shotcut*/ { add: function(combination, callback, options) { options = options || {}; for (var name in defaultOptions) if (!options.hasOwnProperty(name)) options[name] = defaultOptions[name]; var ele = options.target; if(typeof ele === 'string') ele = document.getElementById(ele); var func = makeKeypressedFun( combination, callback, options ); bindings[combination.toLowerCase()] = { 'callback' : func, 'target' : ele, 'event' : options.type }; //Attach the function with the event if (ele.addEventListener) ele.addEventListener(options.type, func, false); else if (ele.attachEvent) ele.attachEvent('on' + options.type, func); else ele['on' + options.type] = func; }, //Remove the shortcut - just specify the shortcut and I will remove the binding remove: function(combination) { combination = combination.toLowerCase(); var binding = bindings[combination]; delete bindings[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; } }; })();
I found below code very useful:
http://www.openjs.com/scripts/events/keyboard_shortcuts/
Especially when I need to handle keyboard combination (disable default events for "crtl+p" and "ctrl+s" for example)
The code work nicely but the source code is not in a good form. I puts it here so it has chances to become more beautiful shortly.
Here is a copy of original code: