Saturday, June 12, 2010

TinyMCE as a JSF 2 composite component

I was looking for a rich text editor that I could use on a jsf page, but quite surprisingly, there seems to be nothing useful.

So I tried creating one of my own by using TinyMCE.

It wasn't actually very tough to do.. here's what kind-of worked:

First, I downloaded TinyMCE, and then copied in the tinymce_3_3_7\tinymce\jscripts\tiny_mce folder into my WebContent/resources.

Then I created my composite component facelet file, tinymce.xhtml under the resources/editors folder.

The component itself is quite simple. It just includes the TinyMCE javascript in the head of the document, and outputs a simple text area. Configuration for TinyMCE is done in the tinymce_init.js.




In tinymce_init.js, I have:

tinyMCE.init({
mode : "specific_textareas",
theme : "simple",
debug : true,
editor_selector : "tinymce"
});

Then in my view page, I use it like this:

<h:head />
<h:body>
<h:form id="form">
<h2>Summary:</h2>
<test:tinymce value="#{bean.summary}"/>

<h:panelGrid id="details" layout="block">
<h:commandButton value="Add details..." action="#{bean.showDetails}"
rendered="#{not bean.detailsAdded}">
<f:ajax render="details" />
</h:commandButton>
<h:commandButton value="Remove details" action="#{bean.hideDetails}"
rendered="#{bean.detailsAdded}">
<f:ajax onevent="ajaxAdjust" render="details"/>
</h:commandButton>
<h:panelGrid id="details2" layout="block" rendered="#{bean.detailsAdded}">
<h2>Details:</h2>
<test:tinymce value="#{bean.details}"/>
</h:panelGrid>
<br />
</h:panelGrid>
<h:commandButton value="Save"/>
</h:form>
</h:body>



So that stuff gets saved upon AJAX postbacks, I added this to tinymce_init.js:

ajaxAdjust=function(evt){
if(evt.status=='begin'){
tinyMCE.triggerSave();
}
};


And here's what I have finally, with everything I need:
- As many rich text editors as I want on a page,
- These editors work nicely with JSF 2, VDL and f:ajax
- These are simple editors - they don't have tens of buttons and options that confuse users