From 978190d6f58e3f170347b1e600cc843c2435004c Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Thu, 21 Feb 2013 13:33:42 -0800 Subject: [PATCH] Extend keymaster to support dispatching key events to elements. Overload key() to include key(descriptor, view, element) where descriptor is the same as the shortcut definition version, view is the dispatch view (defaults to 'window'), element is the dispatch target. Add selftest.html, modified from test.html to issue console.warn for passing tests and console.error for failures --- keymaster.js | 50 ++++++++++++++---- selftest.html | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 selftest.html diff --git a/keymaster.js b/keymaster.js index ee85d32..625f9c5 100644 --- a/keymaster.js +++ b/keymaster.js @@ -125,9 +125,40 @@ for(k in _MODIFIERS) assignKey[k] = false; } - // parse and assign shortcut - function assignKey(key, scope, method){ - var keys, mods, i, mi; + function storeKey(keyCode, key, mods, scope, method) { + if (!(keyCode in _handlers)) _handlers[keyCode] = []; + _handlers[keyCode].push({ shortcut: key, scope: scope, method: method, key: key, mods: mods }); + } + + function createKeyEvent(keyCode, mods, view, type) { + var i; + var keyboardEvent = document.createEventObject ? document.createEventObject() : document.createEvent("Events"); + keyboardEvent.initEvent(type, true, true); + keyboardEvent.view = view; + keyboardEvent.keyCode = keyCode; + keyboardEvent.which = keyCode; + + for(i = 0; i < mods.length; i++) { + keyboardEvent[modifierMap[mods[i]]] = true; + } + + return keyboardEvent; + } + + function dispatchKey(keyCode, key, mods, view, element) { + var keyboardEvent; + view = view === 'all' ? window : view; + keyboardEvent = createKeyEvent(keyCode, mods, view, 'keydown'); + element.dispatchEvent(keyboardEvent); + keyboardEvent = createKeyEvent(keyCode, mods, view, 'keypress'); + element.dispatchEvent(keyboardEvent); + keyboardEvent = createKeyEvent(keyCode, mods, view, 'keyup'); + element.dispatchEvent(keyboardEvent); + } + + // parse and assign shortcut or dispatch keyEvent + function assignKey(key, scope, method) { + var keys, mods, i, mi, keyCode; if (method === undefined) { method = scope; scope = 'all'; @@ -148,13 +179,12 @@ mods[mi] = _MODIFIERS[mods[mi]]; key = [key[key.length-1]]; } - // convert to keycode and... - key = key[0] - key = code(key); - // ...store handler - if (!(key in _handlers)) _handlers[key] = []; - _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods }); - } + keyCode = code(key[0]); + if (typeof method === 'function') // ...store handler + storeKey(keyCode, keys[i], mods, scope, method); + else // ... dispatch event + dispatchKey(keyCode, keys[i], mods, scope, method); + } }; // Returns true if the key with code 'keyCode' is currently down diff --git a/selftest.html b/selftest.html new file mode 100644 index 0000000..ea2b8a6 --- /dev/null +++ b/selftest.html @@ -0,0 +1,137 @@ + + + The Keymaster + + + + + +

+ The Keymaster Self Test. +

+ + + + + +

The Self Test simulated the first five items on this manual test list:

+
    +
  1. Press 'c'. Nothing should be logged on console.
  2. +
  3. Press 'o' or Enter or Cursor ←. Console should log function call.
  4. +
  5. Press 'i'. Switches scope to 'issues'.
  6. +
  7. Press 'c'. Console should log function call.
  8. +
  9. Press 'o' or Enter or Cursor ←. Console should log function call.
  10. +
  11. Press and hold 'm'. Console should log a message every second.
  12. +
  13. Every second console should log a message listing all the currently pressed keycodes.
  14. +
+ +

+ At any time, try pressing ⌘+right, shift+left or ctrl+shift+alt+d. +

+ +

+ When a input, a select or a textarea element is focused, key inputs should be ignored. +

+ + + +