Start experiment: associate key bindings with CSS selectors

KeyEventHandler holds references to BindingSets. The name "binding set"
is based on the concept of a CSS ruleset. The idea is to choose a key
binding for an event based on what selectors (match / most closely
contain) the event's target DOM node.
This commit is contained in:
Nathan Sobo
2012-01-09 16:53:10 -08:00
committed by Corey Johnson & Nathan Sobo
parent 3a1d167a0f
commit 18e614e88d
4 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
KeyEventHandler = require 'key-event-handler'
$ = require 'jquery'
describe "KeyEventHandler", ->
handler = null
beforeEach ->
handler = new KeyEventHandler
fdescribe "handleKeypress", ->
describe "when there is a mapping in a selector that matches the event's element", ->
fragment = null
deleteCharHandler = null
insertCharHandler = null
beforeEach ->
handler.bindKeys '.command-mode', 'x': 'deleteChar'
handler.bindKeys '.insert-mode', 'x': 'insertChar'
fragment = $('<div class="command-mode">')
deleteCharHandler = jasmine.createSpy 'deleteCharHandler'
insertCharHandler = jasmine.createSpy 'insertCharHandler'
fragment.on 'deleteChar', deleteCharHandler
fragment.on 'insertChar', insertCharHandler
it "only triggers an event based on the key-binding in that selector", ->
handler.handleKeypress(keypressEvent('x', target: fragment[0]))
expect(deleteCharHandler).toHaveBeenCalled()
expect(insertCharHandler).not.toHaveBeenCalled()
deleteCharHandler.reset()
fragment.removeClass('command-mode').addClass('insert-mode')
handler.handleKeypress(keypressEvent('x', target: fragment[0]))
expect(deleteCharHandler).not.toHaveBeenCalled()
expect(insertCharHandler).toHaveBeenCalled()

View File

@@ -15,6 +15,9 @@ window.keydown = (pattern) ->
window.createKeyEvent = (pattern) ->
$.Event "keydown", atom.keyBinder.parseKeyPattern(pattern)
window.keypressEvent = (pattern, properties={}) ->
$.Event "keypress", _.extend(atom.keyBinder.parseKeyPattern(pattern), properties)
window.waitsForPromise = (fn) ->
window.waitsFor (moveOn) ->
fn().done(moveOn)

View File

@@ -0,0 +1,46 @@
$ = require 'jquery'
module.exports =
class BindingSet
namedKeys:
backspace: 8, tab: 9, clear: 12, enter: 13, 'return': 13,
esc: 27, escape: 27, space: 32, left: 37, up: 38, right: 39,
down: 40, del: 46, 'delete': 46, home: 36, end: 35, pageup: 33,
pagedown: 34, ',': 188, '.': 190, '/': 191, '`': 192, '-': 189,
'=': 187, ';': 186, '\'': 222, '[': 219, ']': 221, '\\': 220
selector: null
bindings: null
constructor: (@selector, @bindings) ->
commandForEvent: (event) ->
if $(event.target).is(@selector)
for pattern, command of @bindings
return command if @eventMatchesPattern(event, pattern)
null
eventMatchesPattern: (event, pattern) ->
pattern = @parseKeyPattern pattern
pattern.ctrlKey == event.ctrlKey and
pattern.altKey == event.altKey and
pattern.shiftKey == event.shiftKey and
pattern.metaKey == event.metaKey and
pattern.which == event.which
parseKeyPattern: (pattern) ->
[modifiers..., key] = pattern.split '+'
if @namedKeys[key]
charCode = @namedKeys[key]
key = null
else
charCode = key.toUpperCase().charCodeAt 0
ctrlKey: 'ctrl' in modifiers
altKey: 'alt' in modifiers
shiftKey: 'shift' in modifiers
metaKey: 'meta' in modifiers
which: charCode
key: key

View File

@@ -0,0 +1,19 @@
$ = require 'jquery'
BindingSet = require 'binding-set'
module.exports =
class KeyEventHandler
bindingSetsBySelector: null
constructor: ->
@bindingSets = []
bindKeys: (selector, bindings) ->
@bindingSets.push(new BindingSet(selector, bindings))
handleKeypress: (event) ->
for bindingSet in @bindingSets
if command = bindingSet.commandForEvent(event)
$(event.target).trigger(command)
return