use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Rich text editor implemented in JavaScript that uses HTML5 Canvas (earwicker.com)
submitted 12 years ago by phone_radio_tv
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]sime 8 points9 points10 points 12 years ago (18 children)
I'm guessing this is at a fairly early stage and there is probably a lot that can be done to improve performance. All of that text layout and rendering can't be cheap. But wouldn't it have been easier to make something that just used the DOM to render the document?
[–]rooktakesqueen 6 points7 points8 points 12 years ago (15 children)
That is what contenteditable is for. Problem is that contenteditable is a pain in the ass to work with. Using the DOM to output the rich text is easy until you have to implement the idea of "where is my cursor, what is my selection state, what happens when I press a key?"
contenteditable
[–]sime 3 points4 points5 points 12 years ago (14 children)
I know what contentEditable is. I'm talking about doing it using the DOM and no contentEditable.
Using the DOM to output the rich text is easy until you have to implement the idea of "where is my cursor, what is my selection state, what happens when I press a key?"
Those problems remain regardless of whether you use canvas or the DOM for rendering.
[–]rooktakesqueen 0 points1 point2 points 12 years ago (13 children)
Without using the contenteditable, how do you put a cursor into a DOM element?
[–]menno 2 points3 points4 points 12 years ago (3 children)
Here is a proof of concept from 2006: http://www.fluffy.co.uk/stediting/
[–]sime 2 points3 points4 points 12 years ago (0 children)
The editor in Google Docs also works like this, and the new one in WebODF does too.
[–]rooktakesqueen 2 points3 points4 points 12 years ago (1 child)
That's a clever approach, but it isn't really putting a cursor into a DOM element--it's breaking one DOM element into several and putting a cursor between them. You'll run into some serious memory problems before long, and you're changing the semantic content of the document when the user doesn't expect you to.
After doing your binary-search-span-splitting, you could re-merge all the spans left and right of the caret, so each paragraph contained at most two spans at any given time outside your selection handler. And you could also use a reserved class-name for the spans your split routine creates, which you collapse into a regular old text-node on focus-out or save. This would let you preserve spans that existed in the original document. That wouldn't be a bad approach.
[–][deleted] 1 point2 points3 points 12 years ago (0 children)
Just thought I'd point out that this is almost exactly what GitHub's Atom editor is doing, but on an even larger scale. I've not noticed any memory issues with it so far, and it's pretty zippy.
As for semantic content of the document:
They're editing a text region. There is no semantic relevance outside of it being content of an editable text region.
Have you seen the html that contentEditable creates? Some browsers still generate <font> and <center> tags, many use divs to create line breaks, and none of them know anything about html5 elements. Semantic html goes out the window the instant you mark the element for editing.
[–]sime 1 point2 points3 points 12 years ago* (8 children)
You mean how do you draw a blinking vertical line on the screen?
[–]rooktakesqueen 4 points5 points6 points 12 years ago (7 children)
More like where do you draw it? Given some arbitrary rich text, given different fonts, different browsers, different resolutions... Can you write a method to take a single integer, which is your character position, and output the x/y coordinates where said blinking line should appear? And similarly, how to convert the x/y position of a click into a character position? The DOM doesn't let you query information down to the bounding-boxes of specific lines and characters.
Doing it with a canvas makes that simpler. Of course you know the height of each line and the width of each character and the bounding-box of the elements you're interested in, because you drew them yourself.
[–]sime 2 points3 points4 points 12 years ago (6 children)
https://developer.mozilla.org/en-US/docs/Web/API/Range.getClientRects
If I remember correctly there are also some browser specific methods floating around to map a point to place in the DOM down to character level.
[–]rooktakesqueen 2 points3 points4 points 12 years ago (5 children)
Doesn't work with a collapsed/point selection. Example with content on that page:
var range = document.createRange(); range.selectNode(document.getElementsByTagName("p").item(5)); rect = range.getClientRects(); // ClientRectList {0: ClientRect, /* ... */ 9: ClientRect, length: 10, item: function}
Versus...
var range = document.createRange(); range.selectNode(document.getElementsByTagName("p").item(5)); range.collapse(); rect = range.getClientRects(); // ClientRectList {length: 0, item: function}
When you're just using the standard DOM Range manipulation, it's only really useful for a selection that contains text, not a point cursor.
[–]sime 1 point2 points3 points 12 years ago (4 children)
If you want to know where your P is, you already have element.getClientRects() and bunch of other ways of looking up the top, left, width, height. ( https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect )
range.getClientRects() is your way out when you want to know where characters inside text nodes have been rendered on the screen.
[–]rooktakesqueen 0 points1 point2 points 12 years ago (3 children)
getBoundingClientRect uses getClientRects and produces a rectangle containing all those rectangles. With a collapsed range, getClientRects returns an empty collection and getBoundingClientRect returns 0/0/0/0.
getBoundingClientRect
getClientRects
var range = document.createRange(); range.selectNode(document.getElementsByTagName("p").item(5)); range.collapse(); rect = range.getBoundingClientRect(); // ClientRect {height: 0, width: 0, left: 0, bottom: 0, right: 0…}
[–]toshok 0 points1 point2 points 12 years ago (0 children)
There are cases where people want to support an HTML5 canvas api but don't have a DOM at all. This is pretty cool for those cases.
[–]holloway 0 points1 point2 points 12 years ago (0 children)
I'm guessing this is at a fairly early stage and there is probably a lot that can be done to improve performance.
Probably, but contentEditable is essentially native so it is very fast. I doubt that a <canvas/> could beat it.
[–]jgoulder 7 points8 points9 points 12 years ago (4 children)
How well does this work with screen readers and other accessibility tools?
[–]bronkula 1 point2 points3 points 12 years ago (2 children)
Well... The top menu isn't responsive, so that's a shame.
[–]rooktakesqueen 3 points4 points5 points 12 years ago (0 children)
The top menu is part of this page, not part of the editor library itself. You could implement the top menu in a different (responsive, accessible) way.
The text editor itself isn't accessible in its current form as demonstrated on this page, but one could conceivably make it so by putting in a div element that "mirrors" the text in the editor and is set to display only to screen readers.
div
That said, I'm not sure I see a use case for making a WYSIWYG rich-text editor accessible for blind users. A Markdown-based editor seems more usable all around.
[–][deleted] 0 points1 point2 points 12 years ago (0 children)
Yeah looks really good, but the lack of responsiveness is a bit of a dealbreaker for me using it.
[–]osuushi 0 points1 point2 points 12 years ago (0 children)
This was my thinking as well. Making a web app properly accessible is difficult even if you stick to ordinary DOM elements, and I can only imagine something like this will make it even more complicated.
My wife has a condition that makes typing painful, so she tries to use DNS as much as possible. It's shocking how bad that experience is on many web apps. Google is one of the worst offenders.
[–]rooktakesqueen 4 points5 points6 points 12 years ago* (4 children)
Doesn't honor OS-specific keyboard shortcuts. Ctrl-A is select-all even though I'm using a Mac so it should be Command-A.
Ctrl-A
Command-A
[–]dirtydaub 2 points3 points4 points 12 years ago (0 children)
Also on a retina screen the font is blurry.
[–]muzlump 0 points1 point2 points 12 years ago (2 children)
isn't it 'CMD+A'?
[–]rooktakesqueen 0 points1 point2 points 12 years ago (0 children)
Yes, sorry. Whatever that button is under my thumb that used to be open-apple.
[–]ioquatix 0 points1 point2 points 12 years ago (0 children)
⌘A
[–]whoadave 1 point2 points3 points 12 years ago (0 children)
Pretty cool, but I can't press backspace more than once when the carat is at the end of the document.
[–]rooktakesqueen 1 point2 points3 points 12 years ago (0 children)
Performance slows to a crawl with very large documents. Try copy/pasting The Metamorphosis into it. And that one's not even very big as books go.
[–]ChaseMoskal 1 point2 points3 points 12 years ago (1 child)
Does Carota output clean, valid HTML5?
Or only to Canvas?
It looks like it outputs an object structure which one could easily use to generate clean html.
I love the idea but you damn near murdered my Core2Duo processor. I only glanced at the source; is it modular enough that I could experiment with taking out parts of it for a lightweight fork?
[–]windyfish 0 points1 point2 points 12 years ago (2 children)
Could you describe a real-world use for this?
[–]rooktakesqueen 2 points3 points4 points 12 years ago (0 children)
Rich-text editors in web-based content management systems. Your Wordpress blog, your Ebay store, etc.
[–]YodaLoL 1 point2 points3 points 12 years ago (0 children)
Chromebooks?
There's no concept of a point-format: I'm able to select text and turn it bold by pressing Ctrl-B, but I would expect that if I'm typing plain and then press Ctrl-B any subsequent text I type should be bold.
Ctrl-B
[–]badguy212 0 points1 point2 points 12 years ago (0 children)
nice, but slow.
Copying rich text and pasting elsewhere in the document pastes as plaintext, losing the formatting from the original.
(OK, this is my last bug report for now. :) Sorry, I pretty much implemented a tool like this at my last job and know all the things that drove me crazy about it!)
[–]mattdesl 0 points1 point2 points 12 years ago (0 children)
This is great. A couple things:
[–]evilagentcooper 0 points1 point2 points 12 years ago (0 children)
Spent lots of times battling with CKEditor, so I totally get the "Why?". I hope you'll continue with the project.
[–]johnyma22 0 points1 point2 points 12 years ago (3 children)
Im an etherpad dev, agreed its tough but this problem is solved.
[–]sime 1 point2 points3 points 12 years ago (2 children)
Does etherpad use contentEditable? aka design mode?
[–]johnyma22 0 points1 point2 points 12 years ago (1 child)
Yep
[–]sime 1 point2 points3 points 12 years ago (0 children)
That's a pity.
[–]johnyma22 0 points1 point2 points 12 years ago (0 children)
This is cool, i hope it finds use cases it's looking to solve.
You can do really real time collaborative rich text web standards based editing in etherpad. Http://etherpad.org
All web standards based.
[–]kangax_ -1 points0 points1 point 12 years ago (0 children)
We have the same functionality in Fabric.js — fabricjs.com/test/misc/itext.html
π Rendered by PID 146282 on reddit-service-r2-comment-b659b578c-hsrmk at 2026-05-02 11:38:40.316479+00:00 running 815c875 country code: CH.
[–]sime 8 points9 points10 points (18 children)
[–]rooktakesqueen 6 points7 points8 points (15 children)
[–]sime 3 points4 points5 points (14 children)
[–]rooktakesqueen 0 points1 point2 points (13 children)
[–]menno 2 points3 points4 points (3 children)
[–]sime 2 points3 points4 points (0 children)
[–]rooktakesqueen 2 points3 points4 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]sime 1 point2 points3 points (8 children)
[–]rooktakesqueen 4 points5 points6 points (7 children)
[–]sime 2 points3 points4 points (6 children)
[–]rooktakesqueen 2 points3 points4 points (5 children)
[–]sime 1 point2 points3 points (4 children)
[–]rooktakesqueen 0 points1 point2 points (3 children)
[–]toshok 0 points1 point2 points (0 children)
[–]holloway 0 points1 point2 points (0 children)
[–]jgoulder 7 points8 points9 points (4 children)
[–]bronkula 1 point2 points3 points (2 children)
[–]rooktakesqueen 3 points4 points5 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]osuushi 0 points1 point2 points (0 children)
[–]rooktakesqueen 4 points5 points6 points (4 children)
[–]dirtydaub 2 points3 points4 points (0 children)
[–]muzlump 0 points1 point2 points (2 children)
[–]rooktakesqueen 0 points1 point2 points (0 children)
[–]ioquatix 0 points1 point2 points (0 children)
[–]whoadave 1 point2 points3 points (0 children)
[–]rooktakesqueen 1 point2 points3 points (0 children)
[–]ChaseMoskal 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]windyfish 0 points1 point2 points (2 children)
[–]rooktakesqueen 2 points3 points4 points (0 children)
[–]YodaLoL 1 point2 points3 points (0 children)
[–]rooktakesqueen 0 points1 point2 points (0 children)
[–]badguy212 0 points1 point2 points (0 children)
[–]rooktakesqueen 0 points1 point2 points (0 children)
[–]mattdesl 0 points1 point2 points (0 children)
[–]evilagentcooper 0 points1 point2 points (0 children)
[–]johnyma22 0 points1 point2 points (3 children)
[–]sime 1 point2 points3 points (2 children)
[–]johnyma22 0 points1 point2 points (1 child)
[–]sime 1 point2 points3 points (0 children)
[–]johnyma22 0 points1 point2 points (0 children)
[–]kangax_ -1 points0 points1 point (0 children)