Using NicEditor in XPages
In my recent Bootstrap/jQuery project, I was looking for a rich text editor that I could use. I ended up settling on NicEdit, but it took a little bit to get it working properly. Here's the steps I used.First, I downloaded the files from the web site. There were two files that I placed into a folder I created called "nicedit" inside "WebContent". (You have to go into Package Explorer to import those files). The files are nicEdit.js and nicEditorIcons.gif
I also created my own JavaScript file that I imported into that "nicedit" folder. More on that later.
I updated my theme to automatically bring in those files on every XPage. Here's the theme code:
<!-- rich text editor JS -->
<resource>
<content-type>application/x-javascript</content-type>
<href>nicedit/nicEdit.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>nicedit/moveNicEditorContentOnSave.js</href>
</resource>
The icons in the GIF file are brought in by the nicEdit JavaScript code, so that isn't needed inside the theme.
On the XPage, I have a input text area used in Edit mode and a computed text value used in Read mode. This is done because the content is stored as HTML and the text area would show the raw HTML instead of the formatted HTML. With a computed text control, I can set the output to display HTML. Here's an example:
<xp:text escape="false" rendered="#{javascript:!document1.isEditable()}" value="#{document1.Comments}">
</xp:text>
<xp:inputTextarea id="Comments" value="#{document1.Comments}" style="width:700px; height:200px;"
styleClass="niceditor" rendered="#{javascript:document1.isEditable()}">
</xp:inputTextarea>
Next, at the bottom of the XPage, there is some jQuery code to initialize everything with a class of "niceditor" to use the editor. Since that class is only on the text area shown in edit mode, it only applies in edit mode.
<xp:scriptBlock type="text/javascript">
<xp:this.value><![CDATA[
$(document).ready(function(){
var editors = document.getElementsByClassName("niceditor");
for (var i=0; i<editors.length; i++) {
new nicEditor().panelInstance(editors[i].id);
}
})
]]></xp:this.value>
</xp:scriptBlock>
Finally, on my "Save & Close" on "Save" buttons, I call the moveNicEditorContentOnSave() JavaScript function to move the content from the editor back into the underlying field. All that code is stored in an external JavaScript file called "moveNicEditorContentOnSave.js". Here is the content of that file, which I imported into the "nicedit" folder inside "WebContent" just to have everything together:
function moveNicEditorContentOnSave() {
var editors = document.getElementsByClassName("niceditor");
for (var i=0; i<editors.length; i++) {
var textArea = document.getElementById(editors[i].id);
var textEditor = nicEditors.findEditor(editors[i].id);
textArea.value = textEditor.getContent();
}
}
Note that the code relies on the "niceditor" class name, so I can't vary that among my different XPages. I could have put the code of that function inside the Save & Close and Save action buttons, but I wanted to keep it isolated since it was something that was never going to change.