About a year ago I made a Rich Text Editor (RTE) prototype to show that it was possible to build one on top of YUI. Of all my YUI examples, it quickly became one of the most requested, and the project indirectly resulted in me joining the YUI team in a formal capacity.
Once I started on the YUI team, building a full-featured YUI Rich Text Editor became my top priority. Even though there are many DHTML-based RTEs available in the open-source world, including Moxiecode’s excellent TinyMCE, there were four key reasons I took on the challenge of building a new one for YUI.
Before I get into the fundamentals of the YUI RTE, let me give you an update on the state of the project. First, this editor is currently a Beta control, and as such there is still much work to be done. Second, it’s neither a site editor nor a development environment. It’s designed for simple things like web mail systems, blog posts and comments, online reviews, and so forth. However, I did try to expose as many hooks and events as possible so that others could build upon the basic A-grade browser foundation that the RTE provides.
My development approach was to bend Safari first. I built it to work in Safari 2 before retrofitting it back to Opera, then Firefox and lastly Internet Explorer. I figured that if I could make Safari do what I wanted, the other three would fall into place nicely. And they did. By choosing to make Safari work first I was able to make the others do things in a standard way as well. I hope that Safari will eventually catch up to its A-grade peers and add support for the things that I have “emulated”, so I took that into consideration too.
Safari 2 is a really good browser, but it was also the most challenging browser to support with the RTE project. It lacks some serious and critical features when it comes to editing HTML content from JavaScript. I will try to explain the main hurdles that Safari presents:
Iframe Focus – One of the biggest issues was actually quite simple to solve. Safari (and Internet Explorer) has an issue with selecting text inside of an embedded iframe. If you select text within the editor’s iframe then click/focus the parent document, the selection within the iframe is lost. Clearly, this makes it rather difficult for a button click to take action on the selection (because the selection is lost when you click the button!). It also makes it difficult to use, say, a YUI Menu Control for a drop down. As I investigated this problem, I determined that if you stop the mousedown event on the button/href the selection doesn’t get lost. However, if something else (say a href in a dropdown menu) gets focus, the selection will still get lost. This leads me to the next Safari trick.
Selection Object – The selection object in Safari is very limited (to say the least). To work around its limitations, the YUI RTE caches a copy of the current selection in the _getSelection method. Then, the next time _getSelection is called I check to see if a cache existed. If the cache is there, I “rebuild” the selection and destroy the cached copy. This little trick is what lets Safari use a YUI Overlay as a menu instead of the more classic approach of a select element. It’s roundabout, but it works.
execCommand limitations – This is the mother of all hacks for Safari (and the others). My biggest problem with the native execCommand method (in all browsers) is that the browser doesn’t tell you what it applied the command to. So there is no real way to get an element reference back after running a command on a selection. The world of JavaScript editors would be so much more civilized if this would happen (hint, hint, nudge, nudge). So what I had to do was implement this feature myself. My current approach may not be the best way to do it (I have some other ideas that I am working through), but it does the job for now. The method is named _createCurrentElement and basically it runs execCommand('fontname', false, 'yui-tmp'); on the given selection (since fontname is supported on all A-Grade browsers). It will then search the document for an element with the font-family/name set to yui-tmp and replace that with a span that has other information in it (attributes about the element that we wanted to create), then it will add the new span to the this.currentElement array, so we now have element references to the elements that were just modified. At this point we can use standard DOM manipulation to change them as we see fit. In short, I’m using the iframe’s DOM to store metadata during editing as a way to enrich the communication that’s possible between the editor and the iframe.
Over the past few years I’ve implemented many of the available RTEs. Because of this I brought a “taste of your own medicine” mentality to the table. I wanted to build an editor that was easy to extend and change. The YUI RTE has Custom Events for everything that I could think of! I made all of the event handlers standalone functions that can be overloaded on the instance or on the prototype. I also tried to make as many things configurable as possible.
Just to give you an idea, let me show you a quick way to change one of the editor’s default behaviors.

The Create Link Dialog – Say you want to use a different input utility for link creation (a pre-defined links list maybe?) instead of the default link editor. Well, here’s some sample code to turn it into a JavaScript prompt:
var oEditor = new YAHOO.widget.Editor('demo');
oEditor._handleCreateLinkClick = function() {
oEditor.on('afterExecCommand', function() {
var str = prompt('URL: ', 'link');
var el = this.currentElement[0].setAttribute('href', str);
}, oEditor, this);
};
Using this technique, you could easily write your own property editor. By the way, the “insert image” dialog can be overridden in exactly the same way (for example to make it a photo picker), just override the _handleInsertImageClick method. You could either override it as above, or you could override all editor instances (so every editor on the page would behave the same) like this:
YAHOO.widget.Editor.prototype._handleCreateLinkClick = function() {
};
If you don’t like the visual design of the RTE, simply change the CSS. As with YUI’s entire family of controls, the visual presentation of the control is written in CSS and can be reskinned to suit your implementation. See the RTE’s skinning example for more information on how CSS controls the presentation of the RTE specifically. We’ve even provided the Photoshop source file for the icons to make it easier for you to create a design that’s customized for your site. Maybe you like the colors, but you don’t want to see the labels above the “groups”? Well, add these few lines of CSS:
.yui-skin-sam .yui-toolbar-container .yui-toolbar-group h3 {
display: none;
}
.yui-skin-sam .yui-toolbar-container .yui-toolbar-group {
margin-top: .75em;
}
Once you dig in, I think you will find that the YUI RTE is pretty flexible and easy to extend.
Safari was tough, but I’m stubborn. When Safari properly supports execCommand, things will be even better. YUI’s RTE is exceptionally extensible and customizable; from very low-level functionality all the way up through the visual layer. It’s also semi-lightweight, and will be even lighter before I’m done with it.
I hope you enjoy my first YUI control. Please keep the feedback coming.
March 23, 2010 at 3:52 pm
Hrzio –
If you are using SSL you can not serve the Editor from the CDN, you must use a local copy. Since the editor is including code from a non-ssl server it will break.
For support you should visit: http://yuilibrary.com/forum
April 19, 2010 at 2:25 am
Hi,
We have an unusual requirement of a Rich Text Editor with out a toolbar for a webpage!
Though it sounds strange, the requirement is, we should be able to paste some formated text copied from somewhere else in to this text area which should be an RTE.
Though we tried disabling or removing buttons in the YUI simple editor, we ended up with a simple text area!
Kindly let me know is there any way to remove all the buttons and still keep the editor as it is?
Thank you,
Asha.
April 19, 2010 at 9:11 am
@Asha –
You should post support requests to our forum: http://yuilibrary.com/forum
Editor will not work without a toolbar, but you can render the Editor and then use CSS to hide it like this:
.yui-skin-sam .yui-toolbar-container {
display: none;
}
April 20, 2010 at 2:56 am
Hi Dav,
It works. Sure, would post in the forums.
Thanks.
August 4, 2010 at 5:31 am
Hi!
Editor doesn’t work in Opera properly.
Open your example in Opera and try to change font color or font size : http://developer.yahoo.com/yui/examples/editor/icon_editor.html
August 4, 2010 at 9:29 am
@Alexandre –
Opera changed some things under the hood in their latest release that made it incompatible with the current release of the Editor.
October 15, 2010 at 9:23 am
Hi Dav,
I’m having issue with the setEditorHTML method on Chrome and Safari. I pass in an html string and the editor displays the html string that I passed in. Any ideas?
Thanks,
Matthew
October 15, 2010 at 9:59 am
Matthew — All support questions for YUI components should be directed to the forums: http://yuilibrary.com/forum/ -Eric
February 13, 2011 at 11:59 am
how do i remove the image description, padding and border settings from the image options dialog.
Thanks for the editor and the CDN facility.
February 14, 2011 at 11:23 am
@milan –
Just use simple CSS:
.yui-editor-panel .yui-toolbar-group-padding,
.yui-editor-panel .yui-toolbar-group-border,
.yui-editor-panel #editor_insertimage_title {
display: none;
}
You might want to ask further support questions on the forum: http://yuilibrary.com/forum/