In this weekly series, Martin describes a question that was raised by a Fonto developer, how it was resolved and why Fonto behaved like that in the first place. This week, a partner is confused about reading the selection!
Like usual, a support issue came in
Hey there, we are seeing something strange and we think it is a bug on your side:
1. In any editor, create a paragraph with a few words
2. Select that paragraph using the mouse, observe the selection in the XML view
3. Read the selected range, we usedselectionManager.cloneSelectionRange()
to do so, you might want to add some component that displays that
a. See that the start and the end node are the same
4. Select the paragraph using the keyboard, make sure to reflect the XML view as close as you can
5. Check your selected range
a. Notice the start and the end nodes are differentWhat is going on here? Should the positions not be equal?
A Fonto partner
Let’s see what is actually happening here. I am using the trial editor with a custom component that displays the start and end of the selection in the toolbar.
const startContainer = useManagerState(selectionManager.selectionChangeNotifier, () => selectionManager.getStartContainer()); const startOffset = useManagerState(selectionManager.selectionChangeNotifier, () => selectionManager.getStartOffset()); const endContainer = useManagerState(selectionManager.selectionChangeNotifier, () => selectionManager.getEndContainer()); const endOffset = useManagerState(selectionManager.selectionChangeNotifier, () => selectionManager.getEndOffset()); const summary = `${startContainer?.nodeName};${startOffset} - ${endContainer?.nodeName};${endOffset}`; const log = <pre>{summary}</pre>
With this logging output in the toolbar, we indeed see that the selection in the XML sometimes changes, even though the selection in the HTML looks the same!
The different selections when clicking around in the editor.
This is totally expected!
Let us give a bit more background here. Selections in Fonto are represented by Ranges. These in turn represent two points, given by a node and an offset, either among the node’s child nodes or in its text content. Some endpoints are functionally equivalent, such as a position at the end of a text node and one just after it, but some may have a more semantic difference.
For mouse-driven selections, Fonto Editor depends on browser behavior, and the exact endpoints you get may end up in different places based on where the browser places that selection. This especially happens in the more ambiguous cases (e.g., end of text node, after that text node, after the surrounding element). There are some known issues where the browser simply gives an incorrect position if you click somewhere, and while we’ve managed to work around some of those case (using the zero-width space characters you may see in the editor HTML), we have not been able to solve all of them.
We handle keyboard-driven selection manipulation ourselves, so there we have a bit more control over where exactly the endpoints end up. In most cases, you can press (shift +) the arrow keys one more time to expand or move your selection to the exact position.
In similar cases internally where we need to determine whether an element is “fully selected” we do this by checking if the endpoints of the current selection were equivalent to the element’s boundaries, for some definition of equivalence. Typically, this is done by attempting to traverse the Blueprint from the selection endpoints to those boundaries and checking if no significant content is found in-between. You can do the same using our arePositionsEquivalent helper.
That said, we’re aware that the distinction between some selections is not obvious to users, such as elements with all content selected vs elements that are themselves selected, and selections containing only the start or end of an element but not that element’s content.
We’re currently gathering information and use cases to improve this behavior in the future. If you run in the same issue, or similar cases where the selection is not placed where you’d expect, we are happy to hear from you! In which scenario(s) do users need precise control over the selection? What types of selections do they need to make? Is clicking breadcrumbs an acceptable work-around to select full elements?
I hope this explained how Fonto works and why it works like that. During the years we built quite the product, and we are aware some parts work in unexpected ways for those who have not been with it from the start. If you have any points of Fonto you would like some focus on, we are always ready and willing to share! Reach out on Twitter to Martin Middel or file a support issue!
Developer advocate / Evangelist. Has been with Fonto since it all began in 2013. He’s currently designing the next steps in Fonto Developer APIs with the input of our valuable partners.
In his spare time, Martin is an avid home brewer.
Receive updates on new Fonto Why & How blog posts by email