Cross-Browser Compliant Rich Text Editor: A Start

It seems that DIY rich text is not just far from impossible but it’s cross-browser compliant as well. With the World Cup giving me more down-time between matches, I’ve had some time to tinker with my homework; and with the only match today at 1:30 (that’s 2:30 for those of us on DST), I’ve also got a little time to share it.

Starting from a base example at http://html5demos.com/, I’ve generated something that caters a little bit more to my needs. Not to belittle the work of the original author but after testing the example, I was a little surprised that he claimed it was fully cross-browser compliant. In a sense it was; the text could be manipulated by simply selecting it and typing away, but the way it behaved in Firefox was suspect.

While in Chrome it performed admirably (all the CTRL + B/U/I/… shortcuts worked fantastically), this was not so in Firefox. So there was no way to truly apply formatting to the text. Additionally, designmode was applied to the whole document instead of only the element that was to be editable. This meant that the whole document was editable. It’s true that nothing behaves perfectly across every browser and compromises must be made but, in this case, I believe the editor’s cross-browser behaviour can be fairly consistent across them all.

Before I get into the details, see what I’ve done so far with Rich Text Editor 0.1.

Step 1: Get Rid of the Extra Weight

The first thing I had to do in order to work with the file was to get rid of the non-essentials. Number 1 on that list was the CSS styling. While I’m adding functionality, the page doesn’t need to look fancy. Next, was a quick clean-up of the javaScript. Once all that was left was only what was essential to the rich text functionality, that’s when the real work started.

Step2: What Have I Selected?

In order to add formatting to a portion of text (ie make it bold, italic, etc) we must first know the answer to the question, ‘Which text?’ The answer to this one, of course, is ‘The piece that I selected.’ But only if it were that simple. Currently, my way to discover that answer involves just about 100 lines of javaScript. I’m the first to admit that my method is a bit overlong and convoluted but it works… for now.

It involves first inserting an empty <span> at the beginning of the user selection. This acts as a marker for both deciding which text has been selected by the user and the position for re-insertion of the text once it has been formatted. The full text that that follows the empty <span> is taken and compared with the text that has been copied from the user selection range and pasted into a node that is never inserted in the document. Both of these are then pared down until they are equivalent. This gives the user selection.

Why so complex? Truthfully, this is a bit unecessary. It occurred to me after implementing it this way that inserting a second empty <span> at the end of the user selection and finding the text in between would suffice. And before this is through, I’m sure that will be how this is done. But I suppose, it’s a process.

The original problem I was facing, why I simply couldn’t take the text located in the user selection range, was this; the text within the user selection range does not include the HTML tags, and I need those HTML tags. To get around this, I tried exporting the contents from the range to another node. This proved to be better but still the output proved unusable. The tags within the selection were brought along in their correct positions, but they were automatically terminated at the end of the selection or opened at the beginning. This meant that I couldn’t fully trust what I had.

This is why I used this output and decided to compare it with what was actually in the editable area. It meant that I could get rid of those extraneous opening and closing HTML tags and then play around with the correct user selection.

Step 3: Time to Add Some Formatting

This part was tricky in terms of figuring out what must be done to get it right but really is quite simple. You have to realize that there are two cases that can occur: either the some of the text is not bold already (using bold as a general example for any simple type of formatting) or all of the text selected is bold.

If there is any piece of the text that is not bold it is to be all made bold. This is done using replacement commands governed by regular expressions as follows:

sel = sel.replace(new RegExp('(?!^)(<(' + reg + ')[^>]*>)+', 'gi'), '</' + type + '>$&');

sel = sel.replace(new RegExp('(<(' + reg + ')[^>]*>)+', 'gi'), '$&<' + type + '>');

sel = sel.replace(new RegExp('(?!^)(</(' + reg + ')>)+', 'gi'), '</' + type + '>$&');

sel = sel.replace(new RegExp('(?!^)(</(' + reg + ')>)+(?!(<|$))', 'gi'), '$&<' + type + '>');

if(startbefore == -1 || endbefore > startbefore)

{

sel = sel.replace(new RegExp('^(?!<)', 'gi'), '<' + type + '>$&');

}

if(endafter == -1 || (endafter > startafter && startafter > -1))

{

sel = sel.replace(new RegExp('(?!(</[^>]+>)(\w*)*(</' + type + '>)(\w*)(</[^>]+>))*(\w*)$', 'gi'), '$&</' + type + '>');

}

In the code above, the references are:

  • sel: The user selection
  • reg: The list of HTML tags (u, i, span, ul, etc) that can be (or, at this point, I expect to be) present in the text
  • type: The HTML tag that corresponds to the type of formatting being done
  • startbefore: the position of any opening tag of type before the user selection
  • endbefore: the position of any closing tag of type before the user selection
  • startafter: the position of any opening tag of type after the user selection
  • endafter: the position of any closing tag of type after the user selection

If the text is already bold, then it must be stripped of this formatting. This is done by calling the following commands:

sel = sel.replace(new RegExp('^(?!<)', 'gi'), '</' + type + '>$&');

if(endafter > -1 && (endafter < startafter || startafter == -1))

{

sel = sel.replace(new RegExp('(?!(</[^>]+>)(\w*)*(</' + type + '>)(\w*)(</[^>]+>))*(\w*)$', 'gi'), '$&<' + type + '>');

}

There really is not much more to my little update of the page. And while I realize I am repeating myself, you can see what I’ve done so far with Rich Text Editor 0.1.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>