Think of them as having only a none nestable <span> tag with a style attribute.
That particular bug with slack would be possible to fix with JS. The particular difference about that style is there is a little bit of padding at the start of the style. Bowsers have no understanding of clicking on that padding to select inside the the beginning of the inline style.
How? No matter what I try, the insertion point is always before the bold element, and not inside it.
[sandbox]: https://codesandbox.io/s/gracious-dew-rx3xhz?file=/index.htm...
On my Mac, Firefox 104.0.2 inserts new characters inside the <strong>, so they're bold.
In Chrome, the browser API allows positioning the selection there, but during the input event, the selection ends up normalized to just before the strong tag, so the characters aren't inserted into the <strong> tag.
In Safari, the browser API accepts the arguments to set the selection to the first position inside the strong tag, but normalizes during the API call, and the selection always ends up right before the strong tag.
The variance of contentEditable is a huge impediment to using the API raw. If you want reliable, relatively low-level control of rich text input on the web, use ProseMirror.
(I learned a lot about this stuff while working on Notion's rich-text editor, which is all custom.)
- The default behavior that triple-click to selects a whole paragraph/line will stop at the first contenteditable=false element.
- Android may dismiss the keyboard & selection if the selection ever touches one of your contenteditable=false marker elements.
- Firefox won't let you place the caret in between two contenteditable=false elements, or at the start or end of a contenteditable=true element if the first/last child is contenteditable=false.
Why not use ProseMirror?
Why not use ProseMirror? It doesn't fix this issue, does it? At least in the demos on their website you cannot insert text at the beginning of a styled element. You cannot do it even in a native application (at least on macOS) without a custom handling of the selection.
Do you happen to have any more samples to demonstrate how difficult it is to work with contenteditable APIs?
I think natively if you don’t jump into a tag and you don’t jump out of a tag. So if your cursor is in the tag and you move to the boundary, you stay in it. Similarly if you are outside of it, and move to the boundary you stay outside of it.
So I basically would listen to the the relevant input events, see if I’m at the boundary and the orientation of the cursor (which I save in memory) and if I’m only moving across a boundary (i.e. not to the next character) I call event.preventDefault(), manipulate the range accordingly, and update the orientation state.
I’m not sure how to style the caret it self (other then the color) but I’m sure it can be achieved with some absolute position hacking.
The innovation is the visual indicator, the cursor tail. The rest is how WordPerfect worked 30 years ago.
It is horrifying to think how much the Microsoft Word approach has hobbled rich text editing for all those years, and continues to do so.
Microsoft Word may never have problems inserting any formatting, but I have; when it comes to paragraph structure, indenting and such, I find it very hard to predict. For example, I'll look at sections of a document with basically the same structure, but in one place the spacing between a table and the paragraph that follows is much larger, and I have no idea why or how to make them the same.
The feature there is named "directional caret"...
When I came up with this feature in Bike I was pretty proud of the idea and it seemed original. Then a few weeks later I came across your post on StackExchange UX... everything already been invented I guess :) I'm curious how you came with idea? Also have you come across other editors that implement it?
For me I new that something bothered me about rich text editing... always seemed more painful then required. I was also aware of the idea of split cursor from Humane Interface book. And also aware of affinity idea from text cursor position in wrapped text editor lines. Bike's typing affinity came from combining those ideas.
Anyway would love to hear any related thoughts or ideas.
Internally the inline formatting will be marked as tags in a rage, exactly like html. Essentially there is a possible cursor position both inside and outside a formatting tag, but both appear as the same visual location on the screen. This is such a lovely way to indicate the difference.
So with this code:
There are two cursor positions that are visually the same place: Most editors "jump" over one of those positions to hide the implementation detail from users. This idea exposes it with a little tail on the cursor.