Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unbind method + unit tests + method argument #73

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
52 changes: 37 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,29 @@
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, method) {
key = _MAP[key] || key.toUpperCase().charCodeAt(0);
if (typeof scope !== 'string') {
method = scope;
scope = getScope();
}
if (!_handlers[key]) {
return;
}
var i;
for (i in _handlers[key]) {
obj = _handlers[key][i];
if (obj.scope === scope) {
if (!method || obj.method === method) {
_handlers[key][i] = {};
}
}
}
}

// delete all handlers for a given scope
function deleteScope(scope){
Expand All @@ -184,18 +205,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 +238,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
102 changes: 102 additions & 0 deletions test/keymaster.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,108 @@ <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);
},

testUnbindKeyUnscopedWithMethod: function(t) {
key.setScope('all');
var cntForMethod1 = 0;
var cntForMethod2 = 0;
var method1 = function() { cntForMethod1++; }
var method2 = function() { cntForMethod2++; }

key('a', method1);
key('a', method2);

// verify key is bound
keydown(65); keyup(65);

// verify key is bound
t.assertEqual(cntForMethod1, 1);
t.assertEqual(cntForMethod2, 1);

// verify unbind just unbinds the correct method
key.unbind('a', method1);
keydown(65); keyup(65);
t.assertEqual(cntForMethod1, 1);
t.assertEqual(cntForMethod2, 2);
},

testUnbindKeyScopedWithMethod: function(t){
key.setScope('all');
var cntForMethod1 = 0;
var cntForMethod2 = 0;
var method1 = function() { cntForMethod1++; }
var method2 = function() { cntForMethod2++; }

key('a', 'scope1', method1);
key('a', 'scope1', method2);

// verify key is bound
key.setScope('scope1');
keydown(65); keyup(65);

// verify key is bound
t.assertEqual(cntForMethod1, 1);
t.assertEqual(cntForMethod2, 1);

// verify scope is set
key.setScope('scope2');
keydown(65); keyup(65);
t.assertEqual(cntForMethod1, 1);
t.assertEqual(cntForMethod2, 1);

// verify unbind just unbinds the correct method
key.unbind('a', 'scope1', method1);
key.setScope('scope1')
keydown(65); keyup(65);
t.assertEqual(cntForMethod1, 1);
t.assertEqual(cntForMethod2, 2);
},

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

Expand Down