Controlling Content Editable

I’m burned out. I busted my rear end last week writing a piece of code that has been a major problem for us. Equals uses a web technology called content editable. In short it allows a developer to segment a section of a web page and say that the user can type there. It is similar to a text area but content editable allows for rich text editing (bold, lists, headlines, etc).

The concept of content editable is amazing but there are a couple of major problems with it:

  1. The standards are different across browsers. How returns are treated, for example, is completely different on WebKit (Safari and Chrome) than IE than Firefox. I haven’t even tried it on Opera and other browsers.
  2. The cursor is a foreign thing to most browsers. Except for text areas and text fields, we were never really meant to be able to see a cursor on an HTML page.

We had to make a number of very difficult decisions here and have to admit that one of the reasons Equals is taking longer than we anticipated is simply because we ended up re-writing most of the way the note is handled. Equals relies heavily on every line having an appropriate container, whether that is a div, a p, or a header tag.

When we started out we thought we would write our code to control the cursor and then would modify the content editable area as we went along. But what we found is that controlling the cursor is very difficult. Since controlling the cursor isn’t well supported [1], making sure it always does the thing we want it to do is dangerous. We had all kinds of weird behavior.

Furthermore, the original code we wrote for this is the first Javascript code we had written. What a horrible way to get our feet wet! Upon further study, it became clear that there was a better way to write this portion of Equals, one that would be much more stable, much more portable, and allow us to do things in the future we couldn’t fathom doing today with the original code.

So a few weeks ago we decided to re-write it. The goal was to generally let content editable do what it wants and then adjust after the fact. We also moved more HTML out of the content editable area, which will stabilize the content and make it easier for us to handle stuff like copy and other across-document functions.

We also found that how we start the HTML within the content editable area makes a big difference on how the browser forms its HTML. It will repeat that first line for every return key if set up correctly. Firefox, though, prefers <p><br></p>, Safari and Chrome prefer <div><br></div>, and IE prefers <div></div> without the break. It also matters when this is set. Firefox and IE don’t seem to care, but Safari and Chrome require page load.

Once I figured this out, other pieces fell into place and typing notes became routine. It all just worked. I took 750 lines of code and reduced it to 150 lines of code. I even was able to handle cut and copy correctly.

Until a user pasted something into the content editable area. Then all hell broke loose. And that’s why I’m burned out.

Last week I wrote 150 lines of code, all of it dealing with the process of pasting [2]. The problem with paste is that it pastes whatever it has in its paste memory buffer, whether that is well-formed HTML or not. Again, I didn’t want to control the contents of the paste. So I let the content editable do what it wants and then, after the fact, go through the entire document and clean it up [3].

The edge cases are ridiculous on this one and I have only tested it in Safari so far, but the code feels fairly solid. It handled a plethora of variations and bizarre behaviors. And if it does end up working out, I have a nice function we can call if an Equals note does get out of whack for any reason. Here’s hoping the code stands and I don’t have to patch it further. This 150 lines could be spaghetti code really really easily.

[1] If you need to deal with cursor stuff, I highly recommend Rangy. We still use it some but not as much as we did in the first revision.

[2] And undo and redo, technically, although I consider both of those a side-benefit of fixing paste.

[3] I thought of alternatives like pasting into a hidden text area, cleaning up the code, then moving it into the content editable area. That may still be an option if my way fails completely in the end. But that required me to control the paste process, and that is something I wasn’t comfortable with having control over in all browsers.

2 thoughts on “Controlling Content Editable

  1. Yeah, ContentEditable is one of those features of the Web that has so much promise, yet is a nightmare to deal with the undocumented differences between browsers. It’s one of the reasons the Web tends toward being read-only, counter to the intent of the original hypertext people.

    My sympathies.

Comments are closed.