Preserve active element's focus and selection by morphing around it, when possible #85
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Note: Builds on top of #84 , so please review just the diff of the last commit: 9aed82c . If #84 gets merged, I'll rebase for a easier diff.
Overview
The new two-pass algorithm is a big improvement maintaining hidden state and element identity, but since more nodes are getting moved around vs v0.3.0, its more likely that the currently focused element (or its ancestor) will get moved, and focus and/or selection will be lost. Aside from being a regression in fidelity, this has frustrating real-world consequences, at least in the context of a real-time collaborative app.
This PR aims to preserve focus and selection across morphs by morphing around the active element and its ancestors, thus ensuring they never get moved.
Implementation
This strategy has two steps:
Idiomorph.morph(old, new)
. If both traced paths are have the same sequence oftagName#id
, preserving the focused element is possible, and we save a map of this information in the context.insertionPoint
position. Once this is done, we can just continue morphing as normal. In this way, the active element and its ancestors are never moved, and focus is preserved.Notes / Caveats / Limitations:
When we have
moveBefore
, none of this is necessary, so we check for its existence while building the morph context, and if so none of this gets run. However, when we don't havemoveBefore
, there are three situations where this PR doesn't preserve focus. All of them might become the subject of future improvements, but they're out of scope for this PR.