Merge pull request #13412 from atom/dg-mb-fix-editor-focus-issue

Fix issue where editor fails to regain focus
This commit is contained in:
Damien Guard 2016-12-08 17:08:14 -08:00 committed by GitHub
commit cf20aef9db
4 changed files with 31 additions and 20 deletions

View File

@ -78,6 +78,19 @@ describe "TextEditorElement", ->
jasmine.attachToDOM(element) jasmine.attachToDOM(element)
expect(element.querySelectorAll('.decoration').length).toBe initialDecorationCount expect(element.querySelectorAll('.decoration').length).toBe initialDecorationCount
it "can be re-focused using the previous `document.activeElement`", ->
editorElement = document.createElement('atom-text-editor')
jasmine.attachToDOM(editorElement)
editorElement.focus()
activeElement = document.activeElement
editorElement.remove()
jasmine.attachToDOM(editorElement)
activeElement.focus()
expect(editorElement.hasFocus()).toBe(true)
describe "focus and blur handling", -> describe "focus and blur handling", ->
it "proxies focus/blur events to/from the hidden input", -> it "proxies focus/blur events to/from the hidden input", ->
element = new TextEditorElement element = new TextEditorElement

View File

@ -1,15 +1,6 @@
module.exports = module.exports =
class InputComponent class InputComponent
constructor: -> constructor: (@domNode) ->
@domNode = document.createElement('input')
@domNode.classList.add('hidden-input')
@domNode.setAttribute('tabindex', -1)
@domNode.setAttribute('data-react-skip-selection-restoration', true)
@domNode.style['-webkit-transform'] = 'translateZ(0)'
@domNode.addEventListener 'paste', (event) -> event.preventDefault()
getDomNode: ->
@domNode
updateSync: (state) -> updateSync: (state) ->
@oldState ?= {} @oldState ?= {}

View File

@ -42,7 +42,7 @@ class TextEditorComponent
@assert domNode?, "TextEditorComponent::domNode was set to null." @assert domNode?, "TextEditorComponent::domNode was set to null."
@domNodeValue = domNode @domNodeValue = domNode
constructor: ({@editor, @hostElement, tileSize, @views, @themes, @styles, @assert}) -> constructor: ({@editor, @hostElement, tileSize, @views, @themes, @styles, @assert, hiddenInputElement}) ->
@tileSize = tileSize if tileSize? @tileSize = tileSize if tileSize?
@disposables = new CompositeDisposable @disposables = new CompositeDisposable
@ -70,12 +70,12 @@ class TextEditorComponent
@scrollViewNode.classList.add('scroll-view') @scrollViewNode.classList.add('scroll-view')
@domNode.appendChild(@scrollViewNode) @domNode.appendChild(@scrollViewNode)
@hiddenInputComponent = new InputComponent @hiddenInputComponent = new InputComponent(hiddenInputElement)
@scrollViewNode.appendChild(@hiddenInputComponent.getDomNode()) @scrollViewNode.appendChild(hiddenInputElement)
# Add a getModel method to the hidden input component to make it easy to # Add a getModel method to the hidden input component to make it easy to
# access the editor in response to DOM events or when using # access the editor in response to DOM events or when using
# document.activeElement. # document.activeElement.
@hiddenInputComponent.getDomNode().getModel = => @editor hiddenInputElement.getModel = => @editor
@linesComponent = new LinesComponent({@presenter, @domElementPool, @assert, @grammars, @views}) @linesComponent = new LinesComponent({@presenter, @domElementPool, @assert, @grammars, @views})
@scrollViewNode.appendChild(@linesComponent.getDomNode()) @scrollViewNode.appendChild(@linesComponent.getDomNode())
@ -346,7 +346,6 @@ class TextEditorComponent
focused: -> focused: ->
if @mounted if @mounted
@presenter.setFocused(true) @presenter.setFocused(true)
@hiddenInputComponent.getDomNode().focus()
blurred: -> blurred: ->
if @mounted if @mounted

View File

@ -25,8 +25,17 @@ class TextEditorElement extends HTMLElement
@emitter = new Emitter @emitter = new Emitter
@subscriptions = new CompositeDisposable @subscriptions = new CompositeDisposable
@hiddenInputElement = document.createElement('input')
@hiddenInputElement.classList.add('hidden-input')
@hiddenInputElement.setAttribute('tabindex', -1)
@hiddenInputElement.setAttribute('data-react-skip-selection-restoration', true)
@hiddenInputElement.style['-webkit-transform'] = 'translateZ(0)'
@hiddenInputElement.addEventListener 'paste', (event) -> event.preventDefault()
@addEventListener 'focus', @focused.bind(this) @addEventListener 'focus', @focused.bind(this)
@addEventListener 'blur', @blurred.bind(this) @addEventListener 'blur', @blurred.bind(this)
@hiddenInputElement.addEventListener 'focus', @focused.bind(this)
@hiddenInputElement.addEventListener 'blur', @inputNodeBlurred.bind(this)
@classList.add('editor') @classList.add('editor')
@setAttribute('tabindex', -1) @setAttribute('tabindex', -1)
@ -117,12 +126,10 @@ class TextEditorElement extends HTMLElement
themes: @themes themes: @themes
styles: @styles styles: @styles
workspace: @workspace workspace: @workspace
assert: @assert assert: @assert,
hiddenInputElement: @hiddenInputElement
) )
@rootElement.appendChild(@component.getDomNode()) @rootElement.appendChild(@component.getDomNode())
inputNode = @component.hiddenInputComponent.getDomNode()
inputNode.addEventListener 'focus', @focused.bind(this)
inputNode.addEventListener 'blur', @inputNodeBlurred.bind(this)
unmountComponent: -> unmountComponent: ->
if @component? if @component?
@ -132,9 +139,10 @@ class TextEditorElement extends HTMLElement
focused: (event) -> focused: (event) ->
@component?.focused() @component?.focused()
@hiddenInputElement.focus()
blurred: (event) -> blurred: (event) ->
if event.relatedTarget is @component?.hiddenInputComponent.getDomNode() if event.relatedTarget is @hiddenInputElement
event.stopImmediatePropagation() event.stopImmediatePropagation()
return return
@component?.blurred() @component?.blurred()