mobiledoc-kit icon indicating copy to clipboard operation
mobiledoc-kit copied to clipboard

clicking buttons can cause document activeElement and selection to go out of sync

Open bantic opened this issue 9 years ago • 3 comments

In userland code, using the onclick of a button to make programmatic changes to an editor can lead to the window's selection and the document's activeElement to go out of sync: the selection is inside the editor (and is visible as a blinking cursor), but the activeElement is still the button. When this is the case, on the next keystroke the browser will typically insert text into the editor's element (since it has a selection), but because the editor's element is not the activeElement, the key* handlers that the editor has installed on its element will not fire. This usually results in dom mutations that the editor has to attempt to handle using its Mutation Observer code, and sometimes can lead to errors.

There are other ways for the selection and activeElement to go out of sync, but via a button click seems like a common case.

The editor already has some code to handle this case when triggering markup changes. Two things need to happen:

  • The selection manager needs to be updated to be aware of when the document's activeElement changes (and especially when it goes out of sync w/ the window's selection)
  • The editor's _ensureFocus method needs to get called when the editor has selection but not focus

To workaround this problem, the editor's element can be explicitly refocused (editor.element.focus()) in button onclick handlers if the editor is blank. If the editor is not blank, explicitly setting the editor's range (e.g. editor.selectRange(editor.post.tailPosition())) will suffice.

cc @rlivsey

bantic avatar Sep 15 '16 16:09 bantic

This might be some strange combination of mobiledoc, ember-basic-dropdown and, bizzarely, ember-composable-helpers.

When I changed the button from:

<button {{action (pipe (action on-insert type.type) dd.actions.close)}}>

to

<button {{action "selectType" type.type dd}}>

and call dd.actions.close inside the standard action in the component, the issue goes away and I can remove the runloop hack we played with.

It's very strange and I'm digging in some more to try and get a reproduction of exactly what's going on that gets it into the state where mobiledoc has to deal with split focus.

rlivsey avatar Sep 15 '16 16:09 rlivsey

@rlivsey I'm going to add some more guard code to keep the editor's element focused and in sync w/ the selection. But did you were you able to create a reproduction when looking into ember-basic-dropdown and ember-composable-helpers?

bantic avatar Oct 11 '16 16:10 bantic

I wasn't unfortunately, no.

Might be able to spend some more time figuring it out, but if you add the guard clause I can go back to that version of our app and see if that fixes it.

Agree it'd be nice to have a repro though!

rlivsey avatar Oct 11 '16 16:10 rlivsey