How would this work? Isn't the content editable attribute magic so far as web code is concerned. You can't currently implement contenteditable in userspace, can you?
I guess maybe you could make an attribute which just enables a flashing cursor, and then everything else could be done with DOM apis...
We might have to add some magic hooks into currently-internal parts of the browser, so the fidelity may not be 100% if contenteditable is shipped as part of content. It'd be an interesting experiment and might help to highlight gaps in the Web platform.
I believe Google Docs implements it's own text layout entirely from scratch. Sure, you can do that, but that's a lot of work, and it doesn't perform particularly well.
I've implemented text editing on top of contenteditable, and directly via key events etc. The latter is far less work. contenteditable gets you 60% of the way there but is so buggy and inconsistent that you have to override all its behavior anyway.
As a user I bet I’d prefer the contenteditable approach. I find that absolutely consistently the cleverer a web rich text editing widget tries to be, the worse the experience is, and the more it breaks my model of how such things work on the native platform. Dropbox Paper’s is atrocious (I’ve reported several super-annoying bugs, and never had even a response). Slack’s new widget is abysmal (I haven’t even bothered filing bugs with them, because everyone else has already complained about the same things—most of all, its caret handling is quite insane). Google Docs I haven’t edited with for many years, so I can’t fairly remark on it. I can think vaguely of a couple of tech demos of not using contenteditable at all from a few years back, and at that time they were awful on desktop and entirely unusable on mobile. I don’t know if the situation has improved at all from that, but I’m sceptical.
Do you happen to have either or both implementations on the public internet? If so, I could see just how many seconds it takes me to be infuriated by them, especially by the non-contenteditable text editor. If I fail, I will gladly eat my metaphorical hat, but presently I would assign odds of well under 0.1% of that happening.
Sure, contenteditable has many bugs and inconsistencies, and Chrome’s implementation especially is a toy as regards functionality (e.g. poor table and image handling, difficulty with distinguishing a caret inside the end of one node from one after the end of that node), but much of the 60% that it gets you is stuff you can’t get at all any other way, especially insofar as it varies by platform, mostly deliberately.
pcwalton’s proposal interests me because it would actually concretely examine what can and can’t be done, and definitely identify the shortcomings. It would have a chance of actually being good.
> I find that absolutely consistently the cleverer a web rich text editing widget tries to be, the worse the experience is
I don't know about this. Google Docs isn't great (I haven't used Paper), but CodeMirror (https://codemirror.net/) is excellent. Performance is flawless. All the platform shortcuts + extra niceties like multiple cursors.
I should have clarified that I’m specifically speaking of rich text editors. CodeMirror is a plain text editor, which removes most of the difficult-to-implement-without-contenteditable stuff. It uses a textarea, not any contenteditable or contenteditable-like thing.
CodeMirror is rather good as such things go. Last time I tried it it had serious issues with some keyboards on Android (regardless of browser, I believe), but that looks to be working well now. Well, either that or the new Firefox for Android has worked around the input problems; could be either, I don’t have a URL that I know was broken and hasn’t been updated recently.
But even so, it still has problems, some niggling and some major. Navigation keys don’t behave natively (e.g. on Windows, select a range and then press Up or Down and it should go up or down one line from where the caret is, but instead Up takes you to the start of the selection and Down to the end). I can’t get a caret thumb on Firefox on Windows, and it seems very hit-and-miss on Android, and the Samsung keyboard on Android is going crazy with its suggestions as you move the caret around the document—and that’ll be basically because of my next point.
Perhaps most seriously, it’s completely unusable from the perspective of accessibility tech. And most damningly, guess what the solution to that is? They’re working on CodeMirror 6, and concerning accessibility https://codemirror.net/6/ says:
> This version leaves more to the browser, instead of “faking” the editing process in JavaScript. This makes it more transparent to screen readers and other accessibility tools.
You know what “leaving more to the browser” means?
contenteditable.
Yep.
It still interferes with various native user agent functionality (e.g. navigation keys are still wrong and it’s still interfering with caret thumb and long press on at least Windows), but it’s distinctly better because it reduces the amount of the important type of cleverness.
And that's why having contenteditable split out from the browser engine would be great. Instead of reimplementing parts to work around issues, you could just fix the issues directly.
> contenteditable gets you 60% of the way there but is so buggy and inconsistent that you have to override all its behavior anyway.
Believe me, I know. I did my own once upon a time (back when IE6 was still a thing, and supporting IE-style ranges was required!). How do you deal with things like the caret if you're rolling your own. Just fake it with a div?
I think there was a text input element that you actually typed into, which showed the cursor and handled IME. After composing a character, that character would be rendered into a div and the input element moved to the next position. I've also written versions with a blinking div, or a canvas element, but I think the input element is the better approach to leverage browser IME.
I guess maybe you could make an attribute which just enables a flashing cursor, and then everything else could be done with DOM apis...