HTML5 Part 3: The ContentEditable Attribute

If you have been using blogs and message boards for some time then, you should be familiar with Rich Text Editing. RTE was created to make simple web page editing easy for people who were not familiar with HTML and, any one person could submit content.

For developers, the biggest hindrance to RTE is downloading an entire application (it’s not small which means more .js file downloading for your users) and then going through the instructions on how to install it and add the code that generates the Rich Text Editor. My favorite RTE has been TinyMCE. You can also download various plugins for TinyMCE to help make life easier (or harder depending on who is going to use it). You simply add the correct javascript code, edit some settings and away you go. Unfortunately, you also have to do some reading to figure out how to validate it in JavaScript and submit it through AJAX.

Enter the ContentEditable attribute… It’s [not] new, easy to install and supported well enough in all current version, major browsers.

It’s not new?

No. Surprisingly enough, ContentEditable has been supported by Internet Explorer since version 5.5. A couple of years ago, I tried using ContentEditable for a project. But, because of the shoddy support in most browsers (except IE 8), I dropped the idea and just used TinyMCE instead.

Fortunately, HTML5 has come along way and so has ContentEditable. As always, you can go to my HTML5/CSS 3 test page to see an example in action. Let’s dive in.

The ContentEditable attribute

To use the ContentEditable attribute on an element all it takes is this:

<div id="divName" contenteditable="true"></div>

As you can see, it’s pretty easy. And an example in the DOM:

document.getElementById("divName").contentEditable = "true";//or false

Now you can write text within a DIV element. This can be done with multiple elements like P and IFRAME. So, now you are asking yourself, “Is that it?” The answer is no, because while writing into an element is cool and all, the whole other point of ContentEditable is to emulate a Rich Text Editor (using bold, italic, underline, URL etc.).

The designMode attribute

The whole ContentEditable process is too good to be simple. In order to create a true Rich Text Editor environment, you need to enable the designMode attribute in an element like this:

<div id="divName" contenteditable="true" designmode="on"></div>

An example in the DOM:

document.getElementById("divName").designMode = "On";//or Off

Now you are one step closer to creating an interface for your Rich Text Editor. To this this you will need the JavaScript method, execCommand. You can see a list of the method commands here.

Creating bold, italic, underline and URLs with execCommand

To use execCommand do this:

document.execCommand("command", false, "string value");

For this example I will cite my HTML5 example. The HTML:

<div id="contentEditableDiv" contenteditable="true" designmode="on" style="width:300px; height:150px; border:1px solid #000;"></div>
<input type="button" name="contentEditableBtn" id="bold" value="B" style="font-weight:bold;" />
<input type="button" name="contentEditableBtn" id="italic" value="I" style="font-style:italic" />
<input type="button" name="contentEditableBtn" id="underline" value="U" style="text-decoration:underline;" />
<input type="button" name="contentEditableBtn" id="createlink" value="URL"  />
<input type="button" name="showhtml" id="showhtml" value="Show HTML" onclick="alert(document.getElementById('contentEditableDiv').innerHTML)"  />
<script type="text/javascript">window.onload = function() {useCe();}</script>

And the Javascript:

function useCe() {
var bts = document.getElementsByName("contentEditableBtn");
for(a = 0; a < bts.length; a++) {
bts[a].onclick = useBtn;
}
}
function useBtn() {
var urlPrompt = this.value == "URL" ? prompt("Enter URL:", "http://") : null;//You can use null or ""
document.execCommand(this.id, false, urlPrompt);}//In place of the variable urlPrompt, you can use null or ""

window.opera || document.all ? document.getElementById("contentEditableDiv").focus() : "";

It’s really not that hard and as you can see, we got ourselves a simple Rich Text Editor. First, when the page loads, the useCe() function will execute. This will add the onclick event to each button in the document.getElementsByName(“contentEditableBtn”) array. Every UI button shares the same name but, they all have different ids which are used to help call the method command. For example, <input type=”button” name=”btnName” id=”bold” /> then document.execCommand(this.id, false, “string value”).

Once one of the buttons are clicked, they will call the useBtn() function which will run the execCommand method and then it will bold, italicize, underline or create a link out of your text. Did you happen to notice the window.opera || document.all conditional within the useBtn() function?

In Firefox, Chrome and Safari, if you press one of the UI buttons for the editor, the focus remains on the DIV. This is not the case with Opera and Internet Explorer. When the UI buttons are pressed, the focus is put onto the button you pressed. So, why the conditional at all? Why not just use document.getElementById(“contentEditableDiv”).focus() all by itself? Because, if this conditional is not there, the entire body of text within your Editor will highlight in Firefox, Chrome and Safari. This is not good if you just want to bold one word you are currently writing.

Remember ContentEditable is not perfect

If you press on the Show HTML button you can see the HTML that is produced when you use the Editor. Test it out in different browsers. You will notice that each browser will use different HTML markup. So, while in Firefox text is bolded with <span style=”font-weight:bold;”>text</span>, in Chrome text is bolded with <b>text</b> and in IE text is bolded with <STRONG>text</STRONG> (I used CAPS because this is how IE puts out the HTML). Keep this in mind if you are going to use this to submit text using for example, PHP, and you want to strip all except for certain tags. You will have to do some testing.

In Internet Explorer (remember that I am testing IE 9 Beta), you have to highlight the text and then press the UI button you want to use. You cannot press a UI button and then write text because, nothing will happen to your text.

The example I built seems to be having problems in Maemo Web Browser and Mobile Firefox for Maemo 5. In Maemo Web Browser, once you use a UI button it always stays on even when moving onto another line until you turn it off in the midst of typing. The HTML markup placement is a little screwy. As for Mobile FF, it takes quite a few tries (taps in the element) before you are able to being typing anything. I am using ContentEditable on a DIV with a personal project and it works just OK. In both browsers typing is lagged. In Maemo, there’s some kind of bug with the hardware keyboard and ContentEditable. The On-Screen keyboard does not work at all.

Advertisements

About gopha

Gopha is a web programmer, techie and heir to several Nigerian fortunes. In his spare time he likes to game, spend time with his wife, daughters and dogs. He eats [far too much], watches TV and lift weights. He also like to take moonlit walks on the beach and sing songs next to a roaring campfire, in a white sweater with his acoustic guitar. View all posts by gopha

2 responses to “HTML5 Part 3: The ContentEditable Attribute

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: