garann means > totes profesh

a defunct web development blog

a wishlist for contenteditable

Thu, 06 Jan 2011 01:31:01 +0000

For the past month, off and on, I've been working on this text editor. It's basically functional now, and I stand by my assertion that building bespoke text editors with contenteditable is a worthwhile consideration for sites that need minimal editing options. I even managed to add spell-check. That feature's only available in IE (I'll get to why), but that's fine since built-in spell checking is now the norm and most other browsers include it. However, working this closely with contenteditable has given me a real clear picture of its shortcomings as implemented now, what things I really wish were standard, and what standards I wish browsers were currently equipped to support.

wrap a selection with arbitrary HTML

Initially, formatBlock sounds very promising. Mozilla's excellent designMode command documentation says developers can use this command to wrap a selection in almost any block-level element. Sadly, those block-level elements, in practice, wrap the entire line that contains the selection instead of separating it out and moving the selection and its parent to a new line. This is in keeping with the behavior of insertUnorderedList, for example, but is annoying because this command doesn't work any other way. The MDC docs offer em and button as examples of tags you could potentially insert, but in my tests those failed and execCommand returns false. Read a little further in Mozilla's documentation and you'll find that IE supports an even smaller subset of HTML tags, which barely even matters because wrapping HTML around a selection is already only useful in such a small number of cases. This pretty much rules out advanced editing or truly being able to use contenteditable to edit a webpage.

wrap a selection with a CSS class

With the exception of IE, browsers carry out commands like bold or italic by wrapping the selection being acted upon in a span with inline CSS specifying the formatting. Wrapping selections in spans (or fonts *cough-IE-cough*) with a class assigned instead of that inline CSS should be pretty easy, but the option just doesn't seem to be there. I've looked. Again, even if you're of the school that believes contenteditable is just for editing webpages and not for rich text editors or other vulgar uses, this seems like a necessity. It's not reasonable to expect to offer enough diverse HTML tags that editors will be able to produce whatever functionality and styling they need without having that class for JavaScript and CSS to use as a hook, especially when the tags contenteditable produces differ between browsers.

a designMode command to create a selection

So we don't beat up on IE too much, I'll mention right away that IE does have this, and it works pretty well. This, as a matter of fact, is the secondary reason that my text editor ended up only supporting spell check for IE. IE has a command, findText, that takes a string and looks for it in the contenteditable area. This came up prior to the spell check when I was trying to help our automation engineer figure out how to programmatically mimic selecting some text and clicking text editor buttons to format it, so I had to find a solution for Firefox as well. It's super elegant. You ready? We wrapped the text to be selected in an <i> and used range.selectNode to highlight it. Had this not been automated, that wouldn't have worked, cause you can't just type HTML into a contenteditable area, we would've had to calculate the offset and length of the selection within it's containing node or textnode. FYI, once you talk about selections spanning one or more nodes, that ceases to be any fun. It would be great if other browsers would support findText.

my cursor? please?

There's some strange intialization most browsers seem to require in a contenteditable area. Firefox, for example, will allow you to click into the area and type normally, but you don't get a cursor until it's added the <br> that I guess lets it know the area has changes. I've been experimenting with various kinds of placeholder text - because putting so much as a space inside the editor allows any browser to click into it normally - but everything I've tried is a little screwy. It would be much nicer if offering to let the user create a new text node were a browser's default behavior in an empty contenteditable area.

for mobile webkit to support it

Or, at least, if mobile webkit is not going to support contenteditable, for it to quit pretending that it does (feature sniffing for execCommand doesn't work - webkit claims everything is peachy). Clicking into a contenteditable area doesn't bring up the user's keyboard. Links within the area continue to function as links, no matter what kind of JavaScript I've applied (this may be because I suck). It appears that in mobile webkit all child nodes of the contenteditable area inherit the same bizarre implementation of contenteditable the parent has and become useless buttons. Which is to say, you can attempt to move your cursor into the middle of a text node and instead the text node will be highlighted and you will not get a cursor of any sort. From what I've read online, this is a very vexing problem for the developers of these browsers, but I really hope they're able to figure it out.

for more consistent results

Guess what fontName, fontColor, and fontSize produce in IE? A span with its style attribute filled with font-family:'Comic Sans MS';font-size:70px;font-color:#f0f;? Nope! Give up? It's font tags! Just like 19-fucking-96. I have not yet installed IE9 because for a long time I didn't have Windows7, and then I did but I'd stopped caring. Maybe IE9 fixes this. But we all know it's going to be another decade before IE9's older siblings go back to the primordial tar pit they crawled out of and until then, using built-in designMode formatting commands means that your user generated content has motherfucking font tags in it. There's not a lot that can be done about the other browsers and their inline CSS, but my personal wish is that browsers will implement some reserved classes (e.g., .agent-format-italic or something) and attach those instead. Probably best to just be happy that most browsers are using spans, though. But, IE? That font bullshit? Not cool, buddy.

You may feel like this is awfully complainy for someone who started this blog post declaring her modest triumph over this same technology. Like I said, I still think this is loads better than having to download and customize someone else's editor. But to get my very simple one working, I've had to employ some dirty tricks, and that's the only thing that frustrates me. To wit:

So I guess let that serve as a warning to you if you decide to go down this path. Although I wish contenteditable were more mature and more standardized, I've also had fun working with it. Since we all got JavaScript frameworks and HTML5 and CSS3 support, it's getting rarer and rarer that it's necessary to hack something. Dirty and shameful though it's been, it's also been interesting.