From 0451de18d57d3401bd4cc021facbe5fd63b5aae6 Mon Sep 17 00:00:00 2001 From: John Resig Date: Tue, 23 Feb 2010 02:07:02 -0500 Subject: [PATCH] jQuery Hotkeys rewritten to work with jQuery 1.4.2. A bunch of old code stripped and bugs fixed. --- README.md | 80 +++-------- jquery.hotkeys.js | 335 ++++++++++++-------------------------------- test-static-02.html | 26 ++-- test-static-04.html | 2 +- 4 files changed, 120 insertions(+), 323 deletions(-) diff --git a/README.md b/README.md index 4abcd7a..22873d6 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,32 @@ #About -**jQuery.hotkeys** is a plug-in that lets you easily add and remove handlers for keyboard events anywhere in your code supporting almost any key combination. +**jQuery Hotkeys** is a plug-in that lets you easily add and remove handlers for keyboard events anywhere in your code supporting almost any key combination. -It is based on a library [Shortcut.js](http://www.openjs.com/scripts/events/keyboard_shortcuts/shortcut.js) written by [Binny V A](http://www.openjs.com/). +This plugin is based off of the plugin by Tzury Bar Yochay: [jQuery.hotkeys](http://github.com/tzuryby/hotkeys) The syntax is as follows: -
-$(expression).bind(,, );
-$(expression).unbind(,, );
 
-$(document).bind('keydown', 'Ctrl+a', fn);
-
-// e.g. replace '$' sign with 'EUR'
-$('input.foo').bind('keyup', '$', function(){
-    this.value = this.value.replace('$', 'EUR');
-});
-
-$('div.foo').unbind('keydown', 'Ctrl+a', fn);
-
-## [Live Demo](http://jshotkeys.googlepages.com/test-static-01.html) + $(expression).bind(types, keys, handler); + $(expression).unbind(types, handler); + + $(document).bind('keydown', 'ctrl+a', fn); + + // e.g. replace '$' sign with 'EUR' + $('input.foo').bind('keyup', '$', function(){ + this.value = this.value.replace('$', 'EUR'); + }); ## Types Supported types are `'keydown'`, `'keyup'` and `'keypress'` -## Options -The options are `'combi'` i.e. the key combination, and `'disableInInput'` which allow your code not to be executed when the cursor is located inside an input ( `$(elem).is('input') || $(elem).is('textarea')` ). - -As you can see, the key combination can be passed as string or as an object. You may pass an object in case you wish to override the default option for `disableInInput` which is set to `false`: -
-$(document).bind('keydown', {combi:'a', disableinInput: true}, fn);
-
-I.e. when cursor is within an input field, `'a'` will be inserted into the input field without interfering. +## Notes If you want to use more than one modifiers (e.g. alt+ctrl+z) you should define them by an alphabetical order e.g. alt+ctrl+shift -Modifiers are case insensitive, i.e. 'Ctrl+a' 'ctrl+a'. - -## Handler -In previous versions there was an option propagate which is removed now and implemented at the user code level. - -When using jQuery, if an event handler returns false, jQuery will call `stopPropagation()` and `preventDefault()` +Hotkeys aren't tracked if you're inside of an input element (unless you explicitly bind the hotkey directly to the input). This helps to avoid conflict with normal user typing. ## jQuery Compatibility -Tested with *jQuery 1.2.6* + +Works with jQuery 1.4.2 and newer. It known to be working with all the major browsers on all available platforms (Win/Mac/Linux) @@ -51,43 +36,10 @@ It known to be working with all the major browsers on all available platforms (W * Safari-3 * Chrome-0.2 -## Features added in this version (0.7.x) - * Implemented as $.fn - let you use `this`. - * jQuery selectors are supported. - * Extending `$.fn.bind` and `$.fn.unbind` so you get a single interface for binding events to handlers - -## Overriding jQuery -The plugin wraps the following jQuery methods: - * $.fn.bind - * $.fn.unbind - * $.find - -Even though the plugin overrides these methods, the original methods will *always* be called. - -The plugin will add functionality only for the `keydown`, `keyup` and `keypress` event types. Any other types are passed untouched to the original `'bind()'` and `'unbind()'` methods. - -Moreover, if you call `bind()` without passing the shortcut key combination e.g. `$(document).bind('keydown', fn)` only the original `'bind()'` method will be executed. - -I also modified the `$.fn.find` method by adding a single line at the top of the function body. here is the code: - -
-    jQuery.fn.find = function( selector ) {
-        // the line I added
-        this.query=selector;
-        // call jQuery original find
-        return jQuery.fn.__find__.apply(this, arguments);
-    };
-
- -You can read about this at [jQuery's User Group](http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d) - -###Notes +### Addendum Firefox is the most liberal one in the manner of letting you capture all short-cuts even those that are built-in in the browser such as `Ctrl-t` for new tab, or `Ctrl-a` for selecting all text. You can always bubble them up to the browser by returning `true` in your handler. Others, (IE) either let you handle built-in short-cuts, but will add their functionality after your code has executed. Or (Opera/Safari) will *not* pass those events to the DOM at all. *So, if you bind `Ctrl-Q` or `Alt-F4` and your Safari/Opera window is closed don't be surprised.* - - -###Current Version is: beta 0.7 \ No newline at end of file diff --git a/jquery.hotkeys.js b/jquery.hotkeys.js index 9456690..fbd71c7 100644 --- a/jquery.hotkeys.js +++ b/jquery.hotkeys.js @@ -1,250 +1,99 @@ /* -(c) Copyrights 2007 - 2008 + * jQuery Hotkeys Plugin + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Based upon the plugin by Tzury Bar Yochay: + * http://github.com/tzuryby/hotkeys + * + * Original idea by: + * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ +*/ -Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ - -jQuery Plugin by Tzury Bar Yochay -tzury.by@gmail.com -http://evalinux.wordpress.com -http://facebook.com/profile.php?id=513676303 +(function(jQuery){ + + jQuery.hotkeys = { + version: "0.8", -Project's sites: -http://code.google.com/p/js-hotkeys/ -http://github.com/tzuryby/hotkeys/tree/master + specialKeys: { + 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", + 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", + 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", + 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", + 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", + 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", + 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" + }, + + shiftNums: { + "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", + "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", + ".": ">", "/": "?", "\\": "|" + } + }; -License: same as jQuery license. + function keyHandler( handleObj ) { + // Only care when a possible input has been specified + if ( typeof handleObj.data !== "string" ) { + return; + } + + var origHandler = handleObj.handler, + keys = handleObj.data.toLowerCase().split(" "); + + handleObj.handler = function( event ) { + // Don't fire in text-accepting inputs that we didn't directly bind to + if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) || + event.target.type === "text") ) { + return; + } + + // Keypress represents characters, not special keys + var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ], + character = String.fromCharCode( event.which ).toLowerCase(), + key, modif = "", possible = {}; -USAGE: - // simple usage - $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');}); - - // special options such as disableInIput - $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {}); - -Note: - This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind -*/ + // check combinations (alt|ctrl|shift+anything) + if ( event.altKey && special !== "alt" ) { + modif += "alt+"; + } -(function (jQuery){ - // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find - if (jQuery.fn.__bind__ === undefined){ - jQuery.fn.__bind__ = jQuery.fn.bind; - } - if (jQuery.fn.__unbind__ === undefined){ - jQuery.fn.__unbind__ = jQuery.fn.unbind; - } - if (jQuery.fn.__find__ === undefined){ - jQuery.fn.__find__ = jQuery.fn.find; - } - - var hotkeys = { - version: '0.7.9', - override: /keypress|keydown|keyup/g, - triggersMap: {}, - - specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', - 20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del', - 35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', - 109: '-', - 112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', - 120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'}, - - shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", - "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", - ".":">", "/":"?", "\\":"|" }, - - newTrigger: function (type, combi, callback) { - // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}} - var result = {}; - result[type] = {}; - result[type][combi] = {cb: callback, disableInInput: false, shortcut:combi}; - return result; - } - }; - // add firefox num pad char codes - //if (jQuery.browser.mozilla){ - // add num pad char codes - hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99: - '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*', - 107: '+', 109: '-', 110: '.', 111 : '/' - }); - //} - - // a wrapper around of $.fn.find - // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d - jQuery.fn.find = function( selector ) { - this.query = selector; - return jQuery.fn.__find__.apply(this, arguments); - }; - - jQuery.fn.unbind = function (type, combi, fn){ - if (jQuery.isFunction(combi)){ - fn = combi; - combi = null; - } - if (combi && typeof combi === 'string'){ - var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString(); - var hkTypes = type.split(' '); - for (var x=0; xTest #02 $(document).ready(function(){ $(document).bind('keydown', 'ctrl+l', function(){$('#input_01')[0].focus();}) .bind('keydown', 'shift+#', function(){$('#input_01')[0].value = "Shift#";}) - .bind('keyup', 'a', function(event){ - var v = $('#input_01')[0].value; - v = v.replace("a", "b"); - v = $('#input_01')[0].value = v; - - }) //.bind('keyup', function () { alert (arguments); }) .bind('click', function (event){ if (event.target == $('html')[0]){ alert("save the planet, don't waste energy over meaningless clicking"); } }); - $('input.foo').bind( - 'keydown', {combi:'ctrl+k', disableInInput: false}, function(event){ - log('binding keydown/ctrl+k to input applied on #' + event.target.id + ''); - event.stopPropagation(); - event.preventDefault(); - } - ); + + $('#input_01').bind('keyup', 'a', function(event){ + this.value = this.value.replace(/a/g, "b"); + }); + + $('input.foo').bind('keydown', 'ctrl+k', function(event){ + log('binding keydown/ctrl+k to input applied on #' + event.target.id + ''); + return false; + }); + $('table').bind('keydown click keyup', 'ctrl+l', clickHandler); }); function clickHandler(event){ log('binding ' + event.type + ' with(ctrl+l) to table applied on #' + event.target.id + ''); - event.stopPropagation(); - event.preventDefault(); + return false; } function unbindClick(){ diff --git a/test-static-04.html b/test-static-04.html index c2cc996..470edd0 100644 --- a/test-static-04.html +++ b/test-static-04.html @@ -16,7 +16,7 @@ alert("Hello Slash"); return false; }); - jQuery(document).bind('keydown', 'ctrl+p', function (evt){ + jQuery(document).bind('keydown', 'ctrl+p meta+p', function (evt){ alert("think green-don't print"); return false; });