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

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

To page 1current page
[previous]

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

The reverse of getHTML() is the setHTML() function that takes HTML as text and assigns it to the RichEdit control's document. In this case, <span> elements are split into individual characters. In this function, any special HTML character codes like &amp; and &nbsp; must be first translated to normal characters as the insertText() function will convert any ‘&' characters it sees which will confuse the browser.

 

RichEdit.prototype.setHTML = function(sHTML)

{

  this.oDiv.innerHTML = '';

  this.oLastCursorPos = null;

  this.bInFocus = false;

 

  // get a hidden scratchpad to work on

  var oPad = this.getScratchPad();

  oPad.innerHTML = sHTML;

 

  // iterate through each element of oPad and extract text, <br>, <img>, etc

  var oElt = oPad.firstChild;

  if ( oElt.nodeType == 3 ) // text

  {

    this.insertText(sHTML);

  }

  else

  {

    while ( oElt )

     {

       var oNext = oElt.nextSibling;

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

       {

         // must convert special HTML codes back to text so they

         // can be translated properly by insertText()

         var sText = oElt.innerHTML.replace('&amp;','&');

         sText = sText.replace('&quot;','"');

         sText = sText.replace('&nbsp;',' ');

         sText = sText.replace('&lt;','<');

         sText = sText.replace('&gt;','>');

         sText = sText.replace('&#39;',"'");

       &nbsp ; ; 

         // insert the text from the element with the element's style

         this.insertText(sText, oElt.style);

       }

       else

       {

         // don't know what it is, so insert it verbatim

         this.insertNode(oElt);

       }

       oElt = oNext;

     }

  }

}

How to use the RichEdit control

The RichEdit control is instantiated much like other HTML elements during the document parse phase. To place a RichEdit control into the page, add a <script> tag with code to create a new RichEdit object.

 

<script type="text/javascript">

  oRE = new RichEdit(

    'theEdit',

     {

       width:"100%",

       height:"250px",

       border:"inset gray 2px;",

       backgroundColor:"teal",

       textAlign:"left"

     },

     {

       fontFamily:"serif",

       fontStyle:"normal",

       fontWeight:"normal",

       fontSize:"12pt",

       color:"magenta"

     },

    '<SPAN style="FONT-SIZE: 8pt; COLOR: red; FONT-FAMILY: courier">ello</SPAN><BR>' +

    '<SPAN style="FONT-SIZE: 16pt; FONT-FAMILY: arial; FONT-STYLE: italic">ello</SPAN><BR>' +

    '<SPAN style="FONT-SIZE: 24pt; COLOR: blue; FONT-WEIGHT: bold">ello</SPAN>'

  );

</script>


This code will call the RichEdit constructor, which will create the necessary HTML elements to display the control. At this point, it's useful to link the external style controls to the RichEdit control to allow styles to be modified.

 

<script type="text/javascript">

  oRE.chkBold = document.getElementById('chkBold');

  oRE.chkItalic = document.getElementById('chkItalic');

  oRE.selColor = document.getElementById('selColor');

  oRE.selFont = document.getElementById('selFont');

  oRE.selSize = document.getElementById('selSize');

  function onstylechange(style)

  {

    this.chkBold.checked = (style.fontWeight == 'bold');

    this.chkItalic.checked = (style.fontStyle == 'italic');

    this.selColor.value = style.color;

    this.selFont.value = style.fontFamily;

    this.selSize.value = style.fontSize;

  }

  // add callback handler to get notification of style changes.

  oRE.onstylechange = onstylechange;

</script>


In this example, I've added five external controls for bold, italic, color, font and size that would be defined elsewhere in the HTML page. The onstylechange function is linked in to the RichEdit control to modify these controls when the current style in the RichEdit control changes.

Where would a web forum be these days without emoticons? The ability to add images into the document has become a defacto requirement for any web based system. The insertNode() function will accept any valid HTML node, including <img> elements, and inserts it at the current cursor point.

 

<script type="text/javascript">

  RichEdit.prototype.insertImage = function(src)

  {

     // insert a new <img> element at the current position

     var oImg = document.createElement('img');

    oImg.src = src;

    

    this.insertNode(oImg);

  }

</script>

<button onclick="oRE.insertImage('smile.gif');oRE.focus();">

  <img src="smile.gif">

</button>

<button onclick="oRE.insertImage('frown.gif');oRE.focus();">

  <img src="frown.gif">

</button>


Of course, all of the above code would be next to useless if the user's text could not be transmitted back to some server to be processed (posted to some forum thread, etc. The RichEdit control's getHTML() function provides most of the functionality here; the HTML code can be retrieved from the RichEdit control and placed inside a hidden <input> element.

 

<form action="someForum.asp" method=post name="fred">

  <input type=hidden name=userMsg>

  <button onclick="document.myForm.userMsg.value = oRE.getHTML(); document.myForm.submit();">

    Submit

  </button>

</form>

Conclusion

In this article, I've demonstrated how a formatted text editor can be written using JavaScript. The textual display was handled using a <div> element and user input was taken using onkeypress and onkeydown events attached either to the <div> itself or a hidden <input> element.

The internal document of the editor was modeled with a list of HTML elements using a single <span> element for each character. Other non-divisible elements like images may be inserted into the document as if they were characters.

The cursor was implemented using a vertical bar character that was made to show and hide itself repeatedly to give it a blinking effect.

Some of the astute readers might ask: "Why not use the isEditable feature available in Internet Explorer?" Simply because it's only supported in Internet Explorer. As widespread as Internet Explorer is, it's not universal so it's not ideal for the web at large.

Many readers may notice some omissions to the functionality of the RichEdit control discussed in this article. For example, there is no handling of cut and paste, there is no way to select text and change its format and there are probably other omissions. Unfortunately, many of these features are either beyond the scope of JavaScript programs. If you wish to pursue this matter further, consider it a reader excercise.

Disclaimer

While I have endeavored to make this code as browser compatible as possible, I have only tested it with Internet Explorer (6.0) and Netscape (7.1) as this represents of a large proportion of users.

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 www.silver-daggers.co.uk for more details. He can be reached via e-mail at guyonroche@silver-daggers .co.uk.

 

 

To page 1current page
[previous]

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

URL: http://webreference.com/programming/javascript/gr/column12/1