An input actions such as a keystroke can change the DOM tree in two ways: either native (i.e. the browser decides how to modify the DOM tree) or emulated (i.e. our Javascript code listens for the action, cancels it, then modifies the DOM tree itself).
Our current paradigm is that native input actions should only change DOM inline content (i.e. content inside a ContentBranchNode such as a paragraph or heading). In detail:
- We depend on it being impossible for native actions to change DOM structure (e.g. splitting paragraphs).
- For events that would normally cause structural changes, like Enter keydown or certain Delete/Backspace keydowns, we cancel the native event with preventDefault and then implement the desired behaviour in Javascript.
- Therefore, when polling the DOM tree for changes, we only have to check for inline content changed in the current ContentBranchNode.
However there are popular mobile IMEs that break that paradigm. IME events can be uncancellable (so preventDefault doesn't work), and this can happen when the selection crosses a ContentBranchNode boundary. Therefore we have to revisit that paradigm and work out how to adapt cope with the widened range of behaviours.
As always with IMEs, the solution will involve the following aspects:
- Surveying popular IME+language+browser+platform combinations to learn what kinds of behaviour can happen
- Doing a mixture of observing mutations (i.e. synchronizing DOM -> data model) and fixing them up (i.e. synchronizing data model -> DOM)
- Timing DOM changes to minimize disruption due to premature IME commits
- Working very carefully with event sequencing (see ve.EventSequencer for instance)
- Using knowledge of typical editing behaviour to judge what constitutes a disregardable edge case
These are in no particular order, and in fact feed back on one another.