Integrating a Rich-text Widget with Struts


The problem was straightforward, all I needed was a rich-text editor that would allow me to create XHTML that I could then send back to the client. I already had a textarea, and I just wanted a rich-text replacement. I thought this was going to be simple, but the problem cost me hours. In this entry, I show the process I used to identify a suitable AJAX/Javascript library, read on…

I thought that the process would be as easy as:

  1. Choose one of two widely used AJAX frameworks
  2. Drop the right js file in the right directory
  3. Include it in my master template
  4. Write some js to render a rich-text editor component
  5. (maybe) write some onclick code that took care of populating the proper form field

In the end, it was a piece of cake, but getting to the solution took me hours.

The Contenders

I had anticipated that the scriptaculous or openrico people would’ve come up with some sort of rich text component by now, but I couldn’t find a rich-text editor in either project. The app already had a dependency on the prototype library, so I googled rich-text prototype library, but I couldn’t find anything worth looking at. After some research the two candidates I identified were:

Dojo’s site seemed slicker, the documentation appeared to be more professional, and the fact that Dojo is the foundation of jot, made me favor it over FCKeditor. I’ve used FCKeditor before, I knew it worked, but I had never integrated it with a server-side framework. From what I could see, Dojo would provide much more than just a rich-text editor, Dojo is a whole collection of components, code, and widgets. That’s something I’m interested in, so….

Dojo Madness

I proceeded to select Dojo, downloaded the Kitchen Sink distribution, and quickly hit a brick wall. I tried to integrate the dojo.widget.Editor into my system only to have the Firefox Javascript console tell me that the package couldn’t be loaded by Dojo. dojo.require() was failing. I then tailed the access.log, only to see that dojo was trying to load the modules from the wrong path. Here’s the central issue, in this particular application, the request path never maps to a real folder, and it appeared that the dojo library was attempting to find each package from a relative directory. So, while I included the dojo.js by referencing /resources/js/dojo/dojo.js, the library was trying to reference the dojo src tree relative to the request path. So, if my page was /member/edit.do?id=29922, Dojo was trying to load dojo.widget.Editor from /member/edit/src/widget/Editor.js when it should be trying to lod from /resources/js/dojo/src/widget/Editor.js.

After some time screwing around with the dojo.js file, I stumbled on this piece of documentation. I can alter the path prefix that dojo uses to load a particular package with this syntax: setModulePrefix(modulePath, prefix). Great, so I played around with that for an hour, until I looked at the definition of this function in dojo.js. It is defined as setModulePrefix: function(module, prefix), and from what I could gather, the dojo documentation confused the order of the parameters. The documentation says “dojo.setModulePrefix("src/", "dojo");” when it should be “dojo.setModulePrefix("dojo", "src/");“. Note: I’m ready for someone from DOJO to correct me if I’m mistaken, but it appears that the documentation is wrong.

I ended up setting the Module Prefix appropriately for “dojo”, but after another few hours, I couldn’t get the system to work properly because it couldn’t locate other components. I then proceeded to dive into the dojo.js (uncompressed) so I could start the laborious process of printing debug statements with alert(). This is the tedious downside of the new AJAX reality. I tried to load this sucker up in Venkman, but it just wasn’t cooperating. That’s when I started to realize that dojo was trying to load an iframe and a Flash movie called storage.swf for every request. I also couldn’t figure out how to change the path from which it expected to load this flash movie. IMO, this was just too much magic for my taste, all I wanted was a rich-text editor and now I’ve got Flash movies…

I’m positive that other people have spent the time to get dojo working with Java, and I’d encourage them to post solutions to the comment area, but after losing five hours to Dojo, I decided that it was time to punt and go to FCKeditor.

FCKeditor

After my trial by Dojo, FCKeditor was a breath of fresh air. The 3 step installation process is a bit misleading, but getting the widget to render was a piece of cake. I could answer my own questions from the demo code, and I was up and running with working FCKeditor + Struts form in no time. I ued the code from html sample2 to replace the text area, and then I ussed the code from html sample8 to call GetXHTML() on an instance of the Editor. so, to sumarize, form loads, FCKeditor replaces a textarea, then onclick of the submit button populates that textarea with the XHTML from the FCKeditor.

Step-by-step Integration

  1. Download FCKeditor distribution, unpack it somewhere in your webapp. I unpacked mine in “resources/FCKeditor”.
  2. Include the fckeditor.js as a script in your page
  3. Find a struts form that already uses an html:textarea
  4. To replace a textarea with an FCKeditor, here’s the script:
    
     var oFCKeditor = new FCKeditor( 'notes' ) ;
     oFCKeditor.BasePath = "${fckEditorBase}" ;
       oFCKeditor.ToolbarSet = 'Basic' ;
     oFCKeditor.ReplaceTextarea() ;
    
       
  5. Put the following code in the onclick of your submit button:
    var oEditor = FCKeditorAPI.GetInstance('notes');
    document.getElementsByName('notes')[0].value
                  = oEditor.GetXHTML(true);
       

Conclusion

Please if I’m missing something about the Dojo configurtion, leave a comment. I’d prefer to use Dojo as a platform, and if someone has a soution to my absolute/relative path blues, please post it. But, in the meantime, I’m very happy with the simplicity of the FCKeditor-based solution. I can drop the FCKeditor straight into my application without having to modify anything on the server-side.