How to Create a WYSIWYG Rich Text Editor in JavaScript. Pt. 1 | 3 | WebReference

How to Create a WYSIWYG Rich Text Editor in JavaScript. Pt. 1 | 3

To page 1To page 2current page

How to Create a WYSIWYG Rich Text Editor in JavaScript. Pt. 1

Sometimes it's useful to modify the current style to the surroundings when the cursor is moved. If this is the case the style of the current element is assimilated into the current settings. Also, since the developer will most probably have other controls on the page to display and control the styles, a callback function is called to allow these controls to change too.


RichEdit.prototype.assimilateStyle = function(oElt)


  if ( !oElt ) oElt = this.oDiv.lastChild;


  // when the cursor moves, it is natural that it should take on

  // the style of its surroundings

  while ( oElt && oElt.previousSibling && (!oElt.bHasStyle || (oElt == this.oCursor)) )


     oElt = oElt.previousSibling;


  if ( oElt && oElt.tagName.toLowerCase() == 'span' )



     if ( this.onstylechange != undefined ) this.onstylechange(;



The RichEdit control can gain and lose focus many times for various reasons. When it happens, the cursor should be shown and hidden to suit.


RichEdit.prototype.onBlur = function()


  // when focus goes somewhere else, record the last position

  // and hide the cursor

  this.oLastCursorPos = this.getCursorPos();

  this.bInFocus = false;



RichEdit.prototype.onFocus = function()


  // focus has returned, so re-insert the cursor

  var oPos = this.getCursorPos();

  this.bInFocus = true; 

  this.setCursorPos(oPos.current, false);



The RichEdit's document, its contained text, is contained as a linear list of HTML nodes. Each node represents an indivisible character element within the document. Using this model allows for simple code to handle things like insertions, deletions and cursor movement. Nodes can be inserted into the RichEdit's document using the insertNode() function. This function accepts any valid HTML node and inserts it just before the cursor.


RichEdit.prototype.insertNode = function(oNode)


  // insert a node at the current insertion point.

  var oPos = this.getCursorPos();

  if ( oPos.insert ) this.oDiv.insertBefore(oNode, oPos.insert);

  else this.oDiv.appendChild(oNode);


  // attach an onclick handler to the node so that the

  // cursor can be positioned properly when the user clicks.

  oNode.onclick = RichEdit.prototype.onSpanClick;

  oNode.oRichEdit = this;



The insertText() method inserts a string of text into the document using a specified style, or if none is supplied, the default style. Each character is taken from the string and translated into HTML. The translation is necessary as characters like space, ‘<', ‘&' and a few others can be interpreted by the browser and may not be displayed as intended.


RichEdit.prototype.insertText = function(sText, oStyle)


  // insert a text string

  if ( !oStyle ) oStyle =;


  var n = sText.length;

  for ( var i = 0; i < n; i++ )


     // for each character, insert a new <span> element with current style

     var oSpan = document.createElement('span');

    this.copyStyle(oSpan, oStyle,;

     var c = sText.charAt(i);


     // characters to be translated

    switch ( c )


     case '\n':  oSpan = document.createElement('br'); break;

     case ' ':   oSpan.innerHTML = '&nbsp;';  break;

     case '<':   oSpan.innerHTML = '&lt;';  break;

     case '>':   oSpan.innerHTML = '&gt;';  break;

     case '&':   oSpan.innerHTML = '&amp;';  break;

     case '"':   oSpan.innerHTML = '&quot;';  break;

     case "'":   oSpan.innerHTML = '&#39;';  break;

    default:   oSpan.innerHTML = c;  break;





Next week, we have a look at keyboard input, keeping the cursor visible, the Rich Edit Control, font controls, emoticons, etc.

About the Author

Guyon Roche is a freelance web developer in London, Great Britain. He specializes in Windows platforms with an interest in bridging the gaps between different technologies, visit for more details. He can be reached via e-mail at

To page 1To page 2current page

Created: March 27, 2003
Revised: February 2, 2005