Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: tj/keymaster
base: master
...
head fork: tj/keymaster
compare: gh-pages
Checking mergeability… Don't worry, you can still create the pull request.
  • 6 commits
  • 5 files changed
  • 0 commit comments
  • 2 contributors
Commits on Aug 28, 2011
@chetan51 chetan51 Initial deployment efad85f
@chetan51 chetan51 Changed test to index 856e155
Commits on Aug 29, 2011
@madrobby madrobby Merge pull request #7 from chetan51/keymaster
---

Hey,

Ive added the `gh-pages` branch to my fork, so that you can immediately try out a live demo at http://chetan51.github.com/keymaster/. If you want to add this to your repository, you can pull my `gh-pages` branch into a `gh-pages` branch of your own. Then youd get a link like http://madrobby.github.com/keymaster/ which you can add as the "homepage" to your repository and add to your README.

Thanks,
Chetan
fb22cd1
@madrobby madrobby gh pages demo branch 9ac70be
@madrobby madrobby updated demo bd7b41e
Commits on Aug 30, 2011
@madrobby madrobby update demo to latest keymaster version (fixes FF error) a1477f1
View
20 MIT-LICENSE
@@ -1,20 +0,0 @@
-Copyright (c) 2011 Thomas Fuchs
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
93 README.markdown
@@ -1,93 +0,0 @@
-# keymaster.js
-
-Keymaster is a simple (~60 LoC) micro-library for defining and
-dispatching keyboard shortcuts. It has no dependencies.
-
-*It’s a work in progress (e.g. beta), so spare me your nerdrage and instead
-contribute! Patches are welcome, but they are not guaranteed to make
-it in.*
-
-One global method is exposed, `key` which defines shortcuts when
-called directly. Use `key.setScope` for switching scope.
-
-At any point in time (even in code other than key shortcut handlers),
-you can query the `key` object for the state of modifier keys. This
-allows easy implementation of things like shift+click handlers. For example,
-`key.shift` is `true` if the shift key is currently pressed.
-
-Keymaster understands the following modifiers:
-`shift`, `option`, `⌥`, `alt`, `ctrl`, `control`, `command`, and `⌘`.
-
-When an `INPUT`, `SELECT` or `TEXTAREA` element is focussed, Keymaster
-doens't process shortcuts.
-
-```javascript
-// define short of 'a'
-key('a', function(){ alert('you pressed a!') });
-
-// returning false stops the event and prevents default browser events
-key('ctrl+r', function(){ alert('stopped reload!'); return false });
-
-// multiple shortcuts
-key('command+r, ctrl+r', function(){ });
-
-// shortcut with a scope
-key('o, enter', 'issues', function(){ /* do something */ });
-key('o, enter', 'files', function(){ /* do something else */ });
-key.setScope('issues'); // default scope is 'all'
-
-// query modifier keys
-if(key.shift) alert('shift is pressed, OMGZ!');
-```
-
-Keymaster should work with any browser that fires `keyup` and `keydown` events,
-and is tested with IE (6+), Safari, Firefox and Chrome.
-
-See `test.html` for a live demo.
-
-```javascript
-key('c', 'issues', function(){
- console.log('c/issues');
-});
-
-key('command+r, ctrl+r', 'issues', function(){
- console.log('Hijacked Command+R or Ctrl+R, damn!');
- return false;
-});
-
-key('i', function(){
- key.setScope('issues');
- console.log('Switched to "issues" scope. Command+R or Ctrl+R is now no longer reloading...');
-});
-
-key('i', function(){
- console.log('(example of multiple assignment)');
-});
-
-key('o, enter, left', function(){
- console.log('o, enter or left pressed!');
-});
-
-key('ctrl+c', function(){
- console.log('this is not the command line');
-});
-
-key('⌘+right,shift+left,ctrl+shift+alt+d', function(event){
- console.log('command+right, or shift+left, or ctrl+shift+alt+d');
- console.log('here is the event: ', event);
- console.log('key.control', key.control);
- console.log('key.ctrl', key.ctrl);
- console.log('key.shift', key.shift);
- console.log('key.alt', key.alt);
- console.log('key["⌘"]', key[""]);
- return false; // prevent default & stop propagation
-});
-```
-
-## TODO
-
-* Make behavior with `INPUT` / `SELECT` / `TEXTAREA` configurable
-* Comprehensive test suite
-
-Keymaster is (c) 2011 Thomas Fuchs and may be freely distributed under the MIT license.
-See the `MIT-LICENSE` file.
View
5 test.html → index.html
@@ -21,6 +21,10 @@
<li>Press 'c'. Console should log function call.</li>
<li>Press 'o' or Enter or Cursor &larr;. Console should log function call.</li>
</ol>
+
+ <p>
+ At any time, try pressing ⌘+right, shift+left or ctrl+shift+alt+d.
+ </p>
<p>
When a input, a select or a textarea element is focused, key inputs should be ignored.
@@ -66,3 +70,4 @@
</script>
</body>
</html>
+
View
75 keymaster.js
@@ -7,86 +7,117 @@
_handlers = {},
_mods = { 16: false, 18: false, 17: false, 91: false },
_scope = 'all',
+ // modifier keys
_MODIFIERS = {
- shift: 16,
+ '': 16, shift: 16,
option: 18, '': 18, alt: 18,
- ctrl: 17, control: 17,
- command: 91, '': 91 },
+ ctrl: 17, control: 17,
+ command: 91, '': 91
+ },
+ // special keys
_MAP = {
- backspace: 8, tab: 9,
+ backspace: 8, tab: 9, clear: 12,
enter: 13, 'return': 13,
- escape: 27, space: 32,
+ esc: 27, escape: 27, space: 32,
left: 37, up: 38,
- right: 39, down: 40 };
-
+ right: 39, down: 40,
+ del: 46, 'delete': 46,
+ home: 36, end: 35,
+ pageup: 33, pagedown: 34 };
+
+ for(k=1;k<20;k++) _MODIFIERS['f'+k] = 111+k;
+
+ // handle keydown event
function dispatch(event){
- var key, tagName, handler, k,i, hl, hmi, hmil, modifiersMatch;
+ var key, tagName, handler, k, i, modifiersMatch;
tagName = (event.target || event.srcElement).tagName;
key = event.keyCode;
+
+ // if a modifier key, set the key.<modifierkeyname> property to true and return
+ if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
if(key in _mods) {
_mods[key] = true;
+ // 'assignKey' from inside this closure is exported to window.key
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
return;
}
+
+ // ignore keypressed in any elements that support keyboard data input
if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') return;
+
+ // abort if no potentially matching shortcuts found
if (!(key in _handlers)) return;
- for (i = 0, hl = _handlers[key].length; i < hl; i++) {
+
+ // for each potential shortcut
+ for (i = 0; i < _handlers[key].length; i++) {
handler = _handlers[key][i];
+
+ // see if it's in the current scope
if(handler.scope == _scope || handler.scope == 'all'){
- modifiersMatch = (handler.mods.length > 0 && (function(){
- for(hmi = 0, hmil = handler.mods.length; hmi < hmil; hmi++)
- if(!_mods[handler.mods[hmi]])
- return false;
- return true;
- })());
+ // check if modifiers match if any
+ modifiersMatch = handler.mods.length > 0;
+ for(k in _mods)
+ if((!_mods[k] && handler.mods.indexOf(+k) > -1) ||
+ (_mods[k] && handler.mods.indexOf(+k) == -1)) modifiersMatch = false;
+ // call the handler and stop the event if neccessary
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
if(handler.method(event, handler.key, handler.scope)===false){
- if(event.stopPropagation) event.stopPropagation();
- if(event.cancelBubble) event.cancelBubble();
if(event.preventDefault) event.preventDefault();
else event.returnValue = false;
+ if(event.stopPropagation) event.stopPropagation();
+ if(event.cancelBubble) event.cancelBubble = true;
}
}
}
}
};
+ // unset modifier keys on keyup
function clearModifier(event){
var key = event.keyCode, k;
+ if(key == 93 || key == 224) key = 91;
if(key in _mods) {
_mods[key] = false;
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
}
};
+ // parse and assign shortcut
function assignKey(key, scope, method){
- var keys, mods, i, mi, kl, ml;
+ var keys, mods, i, mi;
if (method === undefined) {
method = scope;
scope = 'all';
}
key = key.replace(/\s/g,'');
keys = key.split(',');
- for (i = 0, kl = keys.length; i < kl; i++) {
+ // for each shortcut
+ for (i = 0; i < keys.length; i++) {
+ // set modifier keys if any
mods = [];
key = keys[i].split('+');
if(key.length > 1){
mods = key.slice(0,key.length-1);
- for (mi = 0, ml = mods.length; mi < ml; mi++)
+ for (mi = 0; mi < mods.length; mi++)
mods[mi] = _MODIFIERS[mods[mi]];
key = [key[key.length-1]];
}
+ // convert to keycode and...
key = key[0]
key = key.length > 1 ? _MAP[key] : key.toUpperCase().charCodeAt(0);
+ // ...store handler
if (!(key in _handlers)) _handlers[key] = [];
_handlers[key].push({ scope: scope, method: method, key: keys[i], mods: mods });
}
};
+ // initialize key.<modifier> to false
for(k in _MODIFIERS) assignKey[k] = false;
+ // set current scope (default 'all')
function setScope(scope){ _scope = scope || 'all' };
-
+
+ // cross-browser events
function addEvent(object, event, method) {
if (object.addEventListener)
object.addEventListener(event, method, false);
@@ -94,9 +125,11 @@
object.attachEvent('on'+event, function(){ method(window.event) });
};
+ // set the handlers globally on document
addEvent(document, 'keydown', dispatch);
addEvent(document, 'keyup', clearModifier);
+ // set window.key and window.key.setScope
global.key = assignKey;
global.key.setScope = setScope;
})(this);
View
4 keymaster.min.js
@@ -1,4 +0,0 @@
-// keymaster.js
-// (c) 2011 Thomas Fuchs
-// keymaster.js may be freely distributed under the MIT license.
-(function(a){function l(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,function(){c(window.event)})}function k(a){e=a||"all"}function j(a,b,d){var e,h,i,j,k,l;d===undefined&&(d=b,b="all"),a=a.replace(/\s/g,""),e=a.split(",");for(i=0,k=e.length;i<k;i++){h=[],a=e[i].split("+");if(a.length>1){h=a.slice(0,a.length-1);for(j=0,l=h.length;j<l;j++)h[j]=f[h[j]];a=[a[a.length-1]]}a=a[0],a=a.length>1?g[a]:a.toUpperCase().charCodeAt(0),a in c||(c[a]=[]),c[a].push({scope:b,method:d,key:e[i],mods:h})}}function i(a){var b=a.keyCode,c;if(b in d){d[b]=!1;for(c in f)f[c]==b&&(j[c]=!1)}}function h(a){var b,g,h,i,k,l,m,n,o;g=(a.target||a.srcElement).tagName,b=a.keyCode;if(b in d){d[b]=!0;for(i in f)f[i]==b&&(j[i]=!0)}else{if(g=="INPUT"||g=="SELECT"||g=="TEXTAREA")return;if(!(b in c))return;for(k=0,l=c[b].length;k<l;k++){h=c[b][k];if(h.scope==e||h.scope=="all")o=h.mods.length>0&&function(){for(m=0,n=h.mods.length;m<n;m++)if(!d[h.mods[m]])return!1;return!0}(),(h.mods.length==0&&!d[16]&&!d[18]&&!d[17]&&!d[91]||o)&&h.method(a,h.key,h.scope)===!1&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble&&a.cancelBubble(),a.preventDefault?a.preventDefault():a.returnValue=!1)}}}var b,c={},d={16:!1,18:!1,17:!1,91:!1},e="all",f={shift:16,option:18,"⌥":18,alt:18,ctrl:17,control:17,command:91,"⌘":91},g={backspace:8,tab:9,enter:13,"return":13,escape:27,space:32,left:37,up:38,right:39,down:40};for(b in f)j[b]=!1;l(document,"keydown",h),l(document,"keyup",i),a.key=j,a.key.setScope=k})(this)

No commit comments for this range

Something went wrong with that request. Please try again.