Skip to content

Commit

Permalink
atom#130 target document.activeElement when replayed
Browse files Browse the repository at this point in the history
To correctly simulate user input in replaying keystroke, key event
should be sent to activeElement instead of original event.target
  • Loading branch information
t9md committed Apr 27, 2016
1 parent 72532d6 commit b693298
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
44 changes: 39 additions & 5 deletions spec/keymap-manager-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -199,22 +199,36 @@ describe "KeymapManager", ->
assert.equal(events[0].target, elementB)

describe "when the keystroke partially matches bindings", ->
[workspace, editor, events] = []
[workspace, editor, editor2, events, inputElement, input2Element] = []

beforeEach ->
workspace = appendContent $$ ->
@div class: 'workspace', ->
@div class: 'editor'
@div class: 'editor', ->
@input class: 'input', type: 'text'
@div class: 'editor2', ->
@input class: 'input2', type: 'text'
editor = workspace.firstChild
editor2 = editor.nextSibling
inputElement = document.querySelector('.input')
input2Element = document.querySelector('.input2')
inputElement.focus()

keymapManager.add 'test',
'.workspace':
'd o g': 'dog'
'd p': 'dp'
'v i v a': 'viva!'
'v i v': 'viv'
'.editor': 'v': 'enter-visual-mode'
'.editor.visual-mode': 'i w': 'select-inside-word'
'.editor':
'v': 'enter-visual-mode'
'm': 'focus-input2'
'm j': 'editor-m-j'
'a': 'editor-a'
'.editor2':
'a': 'editor2-a'
'.editor.visual-mode':
'i w': 'select-inside-word'

events = []
editor.addEventListener 'textInput', (event) -> events.push("input:#{event.data}")
Expand All @@ -224,6 +238,10 @@ describe "KeymapManager", ->
workspace.addEventListener 'viv', -> events.push('viv')
workspace.addEventListener 'select-inside-word', -> events.push('select-inside-word')
workspace.addEventListener 'enter-visual-mode', -> events.push('enter-visual-mode'); editor.classList.add('visual-mode')
workspace.addEventListener 'focus-input2', -> events.push('focus-input2'); input2Element.focus()
workspace.addEventListener 'editor-m-j', (event) -> events.push('editor-m-j')
editor.addEventListener 'editor-a', (event) -> events.push('editor-a')
editor2.addEventListener 'editor2-a', (event) -> events.push('editor2-a')

describe "when subsequent keystrokes yield an exact match", ->
it "dispatches the command associated with the matched multi-keystroke binding", ->
Expand Down Expand Up @@ -326,6 +344,19 @@ describe "KeymapManager", ->
keymapManager.handleKeyboardEvent(buildKeydownEvent('g', target: editor))
assert.deepEqual(events, ['control-dog'])

describe "when focused element changed in the middle of replaying keystroke", ->
it "replay keystroke against newly focused element", ->
keymapManager.handleKeyboardEvent(buildKeydownEvent('m', target: editor))
keymapManager.handleKeyboardEvent(buildKeydownEvent('j', target: editor))
assert.deepEqual(events, ['editor-m-j'])

events = []
assert.deepEqual(document.activeElement, inputElement)
keymapManager.handleKeyboardEvent(buildKeydownEvent('m', target: editor))
keymapManager.handleKeyboardEvent(buildKeydownEvent('a', target: editor))
assert.deepEqual(events, ['focus-input2', 'editor2-a'])
assert.deepEqual(document.activeElement, input2Element)

describe "when the partially matching bindings all map to the 'unset!' directive", ->
it "ignores the 'unset!' bindings and invokes the command associated with the matching binding as normal", ->
keymapManager.add 'test-2',
Expand All @@ -352,7 +383,10 @@ describe "KeymapManager", ->

beforeEach ->
elementA = appendContent $$ ->
@div class: 'a'
@div class: 'a', ->
@input class: 'input', type: 'text'
inputElement = document.querySelector('.input')
inputElement.focus()

events = []
elementA.addEventListener 'y-command', (e) -> events.push('y-keydown')
Expand Down
2 changes: 1 addition & 1 deletion src/keymap-manager.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ class KeymapManager

# If the event's target is document.body, assign it to defaultTarget instead
# to provide a catch-all element when nothing is focused.
target = event.target
target = if replay then document.activeElement else event.target
target = @defaultTarget if event.target is document.body and @defaultTarget?

# First screen for any bindings that match the current keystrokes,
Expand Down

0 comments on commit b693298

Please sign in to comment.