Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions keymaster.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
return;
}

// see if we need to ignore the keypress (filter() can can be overridden)
// see if we need to ignore the keypress (filter() can be overridden)
// by default ignore key presses if a select, textarea, or input is focused
if(!assignKey.filter.call(this, event)) return;

Expand All @@ -77,7 +77,7 @@
if((!_mods[k] && index(handler.mods, +k) > -1) ||
(_mods[k] && index(handler.mods, +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.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
if(handler.method(event, handler)===false){
if(event.preventDefault) event.preventDefault();
else event.returnValue = false;
Expand All @@ -87,7 +87,7 @@
}
}
}
};
}

// unset modifier keys on keyup
function clearModifier(event){
Expand All @@ -104,11 +104,11 @@
_mods[key] = false;
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
}
};
}

function resetModifiers() {
for(k in _mods) _mods[k] = false;
for(k in _MODIFIERS) assignKey[k] = false;
for(var k in _mods) _mods[k] = false;
for(var j in _MODIFIERS) assignKey[k] = false;
}

// parse and assign shortcut
Expand All @@ -121,7 +121,7 @@
key = key.replace(/\s/g,'');
keys = key.split(',');

if((keys[keys.length-1])=='')
if((keys[keys.length-1])==='')
keys[keys.length-2] += ',';
// for each shortcut
for (i = 0; i < keys.length; i++) {
Expand All @@ -135,13 +135,13 @@
key = [key[key.length-1]];
}
// convert to keycode and...
key = key[0]
key = key[0];
key = _MAP[key] || key.toUpperCase().charCodeAt(0);
// ...store handler
if (!(key in _handlers)) _handlers[key] = [];
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
}
};
}

// Returns true if the key with code 'keyCode' is currently down
// Converts strings into key codes.
Expand Down Expand Up @@ -170,8 +170,26 @@
for(k in _MODIFIERS) assignKey[k] = false;

// set current scope (default 'all')
function setScope(scope){ _scope = scope || 'all' };
function getScope(){ return _scope || 'all' };
function setScope(scope){ _scope = scope || 'all'; }
function getScope(){ return _scope || 'all'; }

// unbind all handlers for given key in current scope
function unbindKey(key, scope) {
key = _MAP[key] || key.toUpperCase().charCodeAt(0);
if (scope === undefined) {
scope = getScope();
}
if (!_handlers[key]) {
return;
}
var i;
for (i in _handlers[key]) {
obj = _handlers[key][i];
if (obj.scope === scope) {
_handlers[key][i] = {};
}
}
}

// delete all handlers for a given scope
function deleteScope(scope){
Expand All @@ -184,18 +202,18 @@
else i++;
}
}
};
}

// cross-browser events
function addEvent(object, event, method) {
if (object.addEventListener)
object.addEventListener(event, method, false);
else if(object.attachEvent)
object.attachEvent('on'+event, function(){ method(window.event) });
};
object.attachEvent('on'+event, function(){ method(window.event); });
}

// set the handlers globally on document
addEvent(document, 'keydown', function(event) { dispatch(event, _scope) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
addEvent(document, 'keydown', function(event) { dispatch(event, _scope); }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
addEvent(document, 'keyup', clearModifier);

// reset modifiers to false whenever the window is (re)focused.
Expand All @@ -217,6 +235,7 @@
global.key.getScope = getScope;
global.key.deleteScope = deleteScope;
global.key.filter = filter;
global.key.unbind = unbindKey;
global.key.isPressed = isPressed;
global.key.getPressedKeyCodes = getPressedKeyCodes;
global.key.noConflict = noConflict;
Expand Down
46 changes: 46 additions & 0 deletions test/keymaster.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,52 @@ <h1>Keymaster unit tests</h1>
t.assertEqual('ab', sequence);
},

testUnbindKeyUnscoped: function(t){
key.setScope('all');
var cnt = 0;
key('a', function() { cnt++; });
keydown(65); keyup(65);

// verify key is bound
t.assertEqual(cnt, 1);
key.unbind('a');

// fire event again, verify count did not increment (key was unbound)
keydown(65); keyup(65);
t.assertEqual(cnt, 1);
},

testUnbindKeyScoped: function(t){
var cntForScope1 = 0,
cntForScope2 = 0;
key('a', 'scope1', function() { cntForScope1++; });
key('a', 'scope2', function() { cntForScope2++; });

// verify counter increments in scope 1
key.setScope('scope1');
keydown(65); keyup(65);
t.assertEqual(cntForScope1, 1);
t.assertEqual(cntForScope2, 0);

// verify counter increments in scope 2
key.setScope('scope2');
keydown(65); keyup(65);
t.assertEqual(cntForScope1, 1);
t.assertEqual(cntForScope2, 1);

// verify counter does not increment in scope2 after being unbound
key.unbind('a', 'scope2');
keydown(65); keyup(65);
t.assertEqual(cntForScope1, 1);
t.assertEqual(cntForScope2, 1);

// verify counter does not increment in scope1 after being unbound
key.unbind('a', 'scope1');
key.setScope('scope1');
t.assertEqual(cntForScope1, 1);
t.assertEqual(cntForScope2, 1);
},

testDeleteScope: function(t){
var sequence = '';

Expand Down