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.
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.
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 span
s (or font
s *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.
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
.
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.
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.
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 span
s, 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:
- Browser-sniffing to get around mobile webkit
- Wrapping misspelled words in
font
tags because I can't use classes or arbitrary HTML - That nasty business with selecting text in Firefox I mentioned
- Having to go through the hidden textarea to strip out HTML comments because either
innerHTML
orcontenteditable
won't admit they're there - Having to insert
hr
s before and after pasted text so that I can find it and clean up the markup - Generally bringing shame upon my family
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.