AjaxPatterns
This is the original book draft version for the Rich Text Editor Ajax pattern, offered for historical purposes and as an anti-spam measure.
You're probably better off visiting the Live Wiki Version for Rich Text Editor instead, where you can make changes and see what others have written.

Rich Text Editor

Editor, Formatting, Fonts, Rich, Text, Textarea, Toolbar, Write, WordProcessor, WYSIWYG

Goal Story

Pam's working on a presentation for the steering committee; style will count here. From the toolbar, she sets the font to Arial, the size to 24pt, and switches italics on. She then types out the heading, selects it, and moves to the toolbar again to set the colour scheme.

Problem

How can users create and maintain rich content?

Forces

  • Many Ajax Apps let users create and edit substantial chunks of content.

  • Rich content for the web needs to make the most of HTML, and go well beyond a string of plain-text.

  • Most users don't know HTML; even "easy" markup substitutes for HTML are complicated and inconsistent.

Solution

Incorporate a Rich Text Editor widget with easy formatting and WYSIWYG [14] display. Typically, the widget looks like a mini word processor: a toolbar on top with a rich editing area underneath. The editing area is usually a div, rather than a textarea, meaning that any HTML content is possible.

Typical features include:

  • Flexible font styles, sizes, boldfacing, etc.

  • Flexible colour schemes.

  • Embedded images.

  • Embedded tables.

  • Bullet-point and numeric lists.

  • Indenting and flexible text alignment.

All these features are usually accessible by the toolbar, and also via keyboard shortcuts. It would also be possible to make them available from drop-down menus, though the main examples to date have avoided doing so. In addition, the toolbar sometimes offers other operations too:

Rich Text Editors are a great tool for non-technical users, but as with GUI word processors, they can slow down power users. If power users are important to you, a few guidelines apply:

  • Offer an alternative "WYSIWYN" - What You See Is What You Need - interface, where the user can enter raw HTML and/or some other text-based markup such as Markdown.

  • Offer keyboard shortcuts and advertise them well, e.g. as tooltip “Popup”s on the corresponding toolbar icons.

  • Offer personalised toolbars and keyboard bindings.

The major browsers do have some support for rich text editing. Firefox has Midas, an embedded text editor, and IE has a similar editor available on items flagged as contentEditable. However, neither mechanism is portable, and with both versions, you're stuck with whatever version the user's browser has. For that reason, the best solution right now is probably the “Cross-Browser Component” libraries mentioned in the Real-World Examples below.

Real-World Examples

FCKEditor Library

Frederico Caldeira Knabben's FCKEditor is a feature-rich, open-source, “Cross-Browser Component” you can pull in to your own projects (Figure 1.55, “FCKeditor”). It also has some server-side integration and web remoting support.

Figure 1.55. FCKeditor

FCKeditor

Jotspot, Dojo Rich Text Editor

Jotspot is a wiki host that allows editing in three formats: WYSIWYG, markup, or XML (i.e. the underlying XHTML). The WYSIWYG supports all the Rich Text Editor capabilities mentioned in the Solution, and is based on the open-source Dojo Rich Text Editor component (Figure 1.56, “Jotspot Dojo Editor”). In the simplest case, using the component is as simple as declaring a div with the right class.

 <div class="dojo-Editor"> Initial
              content </div> 

Figure 1.56. Jotspot Dojo Editor

Jotspot Dojo Editor

Writely

Writely promotes itself as "The Web Word Processor". Content is edited using a similar mechanism to Jotspot (above). One nice feature is a spell-check.

Wikipedia

Wikipedia's editing interface is characteristic of slightly older editors which offer a rich editing toolbar, but only a markup-based textarea mechanism for the content (Figure 1.57, “Wikipedia Editor”). This is also true of the open-source MediaWiki framework on which wikipedia is based.

Figure 1.57. Wikipedia Editor

Wikipedia Editor

Rich Text Editor

Kevin Roth's Rich Text Editor is a good demo of the native browser support mentioned in the Solution, because it provides an editor built on top of whichever browser it's running in.

Code Example [FCKEditor]

This example introduces the FCKEditor API and looks at some of the internals. To use FCKEditor in your own project, first create a regular textarea:

    <textarea id="comments"></textarea>

FCKEditor can then replace the texteditor with a rich editor:

    var commentsEditor = new FCKeditor("comments");
    commentsEditor.ReplaceTextarea();

To track usage, register an initialisation handler for the global FCKEditor module, which applies to all editor instances. Here you probably want to set up an event handler which will fire when a user changes an individual editor. See the API documentation for more details and options.

      function FCKeditor_OnComplete(editor) {
        editor.Events.AttachEvent('OnSelectionChange', onEditorChange);
      }
      function onEditorChange(editor) {
        // Respond to change.
        // You can get the editor contents with editor.GetXHTML();
      }

Now the internals. ReplaceTextarea will locate the textarea object, hide it, then insert the Rich Text Editor content just above it.

    FCKeditor.prototype.ReplaceTextarea = function()
      ...
      var oTextarea = document.getElementById( this.InstanceName ) ;
      oTextarea.style.display = 'none' ;
      ...
      this._InsertHtmlBefore( this._GetIFrameHtml(), oTextarea ) ;

_GetIFrameHtml() outputs the HTML for the editor IFrame, and its source is fckeditor.html. The editor is structured as a three-row table. The top row is the toolbar (and some other controls for expanding and collapsing it, omitted); the second row is the WYWIWYG editing area, backed by an IFrame; the third row shows the HTML source, usually invisible.

    <table height="100%" width="100%" cellpadding="0" cellspacing="0"
           border="0" style="TABLE-LAYOUT: fixed">
      <tr>
        ...
        <td id="eToolbar" class="TB_ToolbarSet" unselectable="on"></td>
        ...
      </tr>
      <tr id="eWysiwyg">
        <td id="eWysiwygCell" height="100%" valign="top">
          <iframe id="eEditorArea" name="eEditorArea" height="100%" width=
"100%"
                  frameborder="no" src="fckblank.html"></iframe>
        </td>
      </tr>
      <tr id="eSource" style="DISPLAY: none">
        <td class="Source" height="100%" valign="top">
          <textarea id="eSourceField" dir="ltr" style="WIDTH: 100%; HEIGHT: 100%"></textarea>

        </td>
      </tr>
    </table>

The toolbar consists of toolbar buttons linked to commands. The commands follow the Command pattern (Gamma et al., 1995) - they are objects encapsulating a command, and can be launched with from either the toolbar or a keyboard shortcut. The command is identified in each toolbar button declaration, along with several display properties.

 var FCKToolbarButton = function (commandName,
    label, tooltip, style, sourceView, contextSensitive) 

For example, here's the toolbar button to paste plain text:

 oItem = new FCKToolbarButton('PasteText',
    FCKLang.PasteText, null, null, false, true); 

The PasteText command above is ultimately tied to Command object which will launch a Paste Text dialog.

 FCK.PasteAsPlainText=function() {
      FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteAsText,
      'dialog/fck_paste.html',400,330,'PlainText'); } 

Manipulations on the WYSIWYG editor content involve getting hold of the content element and just altering its HTML. In the case of the Paste operation, it appends the new HTML, sHtml at the right place.

    var oEditor = window.parent.InnerDialogLoaded() ;
    ...
    oEditor.FCK.InsertHtml(sHtml) ;

Related Patterns

For editing large chunks of text, you might experiment with a “Virtual Workspace”

Provide a “Progress Indicator” while saving text. Indeed, many text editors take a while to start up as well, partly due to scripting overhead and partly due to toolbar images. Thus, a “Progress Indicator” might help during loading as well.

Create a “Status Area” to help the user monitor details such as word count and cursor position, if these aren't already provided by the Rich Text Editor widget. You'll need to hook into the widget's event model to keep the status up-to-date.

Metaphor

A Rich Text Editor is like an embedded GUI word processor.



[14] "What You See Is What You Get" (WYSIWYG) interfaces are a staple of windows-based apps, where the editing interface is essentially the same as the output output (i.e. a printout or a presentation).

Live Wiki Version for Rich Text Editor