administration mode
Pssst...Ferdy is the creator of JungleDragon, an awesome wildlife community. Visit JungleDragon

 

Article: Advanced Domino TinyMCE integration »

FERDY CHRISTANT - DEC 22, 2006 (07:29:20 AM)

Introduction

This article will explain how to integrate TinyMCE, a web-based rich text editor, into Domino. Ultimate goal is to have it working reliably in all modern browsers, and well integrated into your Domino backend. This exercise has been performed by Jake before, but needs a little updating:

  • The demo database of Jake's article contains a 2 year old version of TinyMCE thats has some bugs that make it hard to get it to play nicely with the modern browsers.
  • This article adds instructions on how to integrate images stored in Domino into the image selection panel of TinyMCE.
  • This article will focus on an optimized integration path where you we will configure TinyMCE to include exactly the functionality we want, and where we only use the files of the TinyMCE package that we truly need.

Before I start, let me state that this article would not be possible without the help of Ben Poole. You can consider this article as our combined service to the community.

For the sake of inspiration, here is a little teaser of what an integrated TinyMCE editor looks like:


Getting started

There are two ways to integrate TinyMCE into your Domino application. One way is to store the TinyMCE source files on your server, in the domino\html directory. From then on, you can refer to these files from multiple applications. The other way is to integrate the TinyMCE source files into your database design. This article will focus on integrating the source files into the database design. The main advantage of this method is that your application will be modular and deployable to any server. The major drawback of course is that if any TinyMCE upgrades are released, you may have to apply them to multiple applications manually.

Throughout the rest of this article I will refer to my Blogo application. Blogo 1.50 has TinyMCE integrated exactly the way described in the rest of this article. So, go ahead, download Blogo 1.50, and open it in Designer.

The source files

TinyMCE consists of a lot of html, js and css files. In the Blogo design, these are stored as File design elements. Not every file of TinyMCE is included, only the ones we need to use TinyMCE's advanced theme. Two extra remarks apply:

Firefox does not recognize the css File design elements as true css files. Therefore, these File design elements have their mime type explicitly set to "text/css". This is done on the second tab of the File Resource properties box.

To enable the integration of images stored in Notes documents in the TinyMCE editor, the file "editor/themes/advanced/editor_template.js" has to be modified. The line containing "image.htm?src=" has to be replaced with "image.htm?open&src=".

This is already done in the Blogo File design elements, so if you are integrating TinyMCE in your own design, you can simply copy all these File design elements to your own design. It will save you a lot of work.

Text areas

TinyMCE basically transforms your html textarea elements into a TinyMCE editor. There are different modes to select which textarea should be turned into a TinyMCE editor. The one demonstrated appears to me as the most flexible and modular way. It tags text area elements with a HTML attribute, to indicate that it needs to be a rich text editor.

If you open up the subform "Page Edit Form" in the Blogo design, somewhere around the bottom the following line demonstrates the attribute:

<textarea rows="20" cols="70" wrap="virtual" name="pgContent" id="pgContent" class="mceEditor" style="width:100%;"></textarea>

Three elements are crucial in this line of code. First, the rows, cols, and width attributes indicate the size of the TinyMCE editor. The name attribute will link it to a rich text field with the same name. This creates the connection between the editor and the field to store the rich text content in. The class="mceEditor" part indicates that this is a TinyMCE textarea. By simply setting an attribute on a textarea we can loosely couple the TinyMCE init script, for maximum flexibility.

Note that in Blogo, the html coming from the TinyMCE editor is stored in a text field (in the Page Fields subform), not a rich text field. The reason is that Blogo does not do Notes client-based rich text editing, only web-based rich text editing. Your own implementation may vary, but integration is still straightforward if you consider the html required for the textarea, as explained above. Jake's original artice contains an agent that tranforms the TinyMCE html content into a rich text field.

The init script

The TinyMCE init script is the most important aspect of the integration process. It loads the TinyMCE editor for the selected text areas, and configues the features available in the editor. In Blogo, the initiation script is decoupled from any form you apply it to. In essence, this means that to enable the TinyMCE editor on your form, two simple steps apply:

  1. Mark the text areas on your form that need to be a TinyMCE editor using the class attribute
  2. Insert the "Rich Text Editor" subform at the top of your form.

Easy, right? Let's have a deep look at the initation script in the "Rich Text Editor" subform:

01. <script type="text/javascript" src="editor/tiny_mce.js"></script>
02. <script language="javascript" type="text/javascript">
03. tinyMCE.init({
04.    mode : "specific_textareas",
05.    editor_selector : "mceEditor",
06.    theme : "advanced",
07.    plugins : "table",
08.    apply_source_formatting : "true",
09.    theme_advanced_container_toolbar1_align : "left",
10.    theme_advanced_container_toolbar2_align : "left",
11.    theme_advanced_layout_manager : "RowLayout",
12.    theme_advanced_containers : "toolbar1,toolbar2,mceEditor",
13.    theme_advanced_container_toolbar1 :
14.             "bold,italic,underline,strikethrough,charmap,separator,"+
15.             "justifyleft,justifycenter,justifyright,justifyfull,"+
16.             "separator,bullist,numlist,indent,outdent,separator,"+
17.             "link,unlink,anchor,hr",
18.    theme_advanced_container_toolbar2 :
19.            "tablecontrols,separator,image,removeformat,code",
20.    theme_advanced_path : "false",
21.    remove_script_host : "true",
22.    document_base_url : "<Computed Value>",
23.    relative_urls : "true",
24.    external_image_list_url : "/<Computed Value>/pagRTEImages.js"
25.  })
26.  </script>

Since this script is so crucial for a proper integration, let's go over it line by line:

L01: Include the main TinyMCE javascript library. In Blogo, I make use of the base href tag to make use of relative paths throughout the entire design. The value of the base href tag is set to "http://server/dbpath/". If you do not use a base href tag, you should make sure that the path to the tiny_mce.js File design element is correct, whether it is absolute or relative.

L02: Start a javascript that must be executed as soon as it is loaded.

L03: Initiate the TinyMCE init call. This will only work if the path defined in line 1 is correct.

L04: This line is to indicate which text areas should be transformed to rich text editors. We do not want this for all text areas on our form, only the ones we marked as such.

L05: Indicate that all textarea elements with the attribute class="mceEditor" should be transformed to rich text editors.

L06: TinyMCE has a number of modes. The advanced mode is the one where we have maximum control over the features, so we will use that one.

L07: TinyMCE has a set of plugins to extend the functionality of the basic editor. The table features is not part of the basic functionality, therefore we load it as a plugin.

L08: TinyMCE allows you to switch to html editing mode. This setting will make sure that the HTML code is nicely formatted, making it more readable and easier to edit.

L09-L10: We will defined two rows of buttons in the editor, these two lines make sure that buttons are aligned to the left. By default, they are centered.

L11: This line puts TinyMCE in a mode where we have maximum control over the rows, buttons, order of buttons, etc.

L12: Here we specify that we have three rows: a button row, a second button row, and the TinyMCE editor pane. By naming the rows, we have control over them in the subsequent lines.

L13-L19: These lines define exactly what buttons to insert into which row of the editor. The order of buttons specified here will be respected in the end result. As you can see, you can also insert seperators to group related buttons. You may want different buttons in your own implementation. If so, please refer to the TinyMCE button/controls list.

L20: By default, TinyMCE insert a path element below the editor. The path element displays the hierarchy of html elements based on your cursor position in the editor. I wish not to bother non-technical users with this, so I disabled it.

L21: This parameter makes sure that TinyMCE does not automatically insert the server name into your relative URLs.

L22: The document base URL parameter is crucial to make your paths work. In Blogo it is set to a computed value with the following formula:

tmpProtocol:= "http" + @If(HTTPS="ON"; "s"; "");
tmpProtocol + "://" + Server_Name + "/" + @WebDBName  + "/"

You would assume that the base href tag accomplishes the same effect. The reason to still do this is that we want our TinyMCE editor to work when we create a new document and when we edit an existing document. As you can imagine the URL hierarchy in both scenarios is different:

server/dbpath/myform?openform

versus:

server/dbpath/view/docid?editdocument

Notice the extra level in the second URL. This is why we need to set the document base URL of TinyMCE.

L23: Set TinyMCE to use relative URLs. together with the two previous lines, this gives us the control over our paths that we want.

L24: By default, TinyMCE will assume that when you try to insert an image in your editor, it must pick them from the web server's file system. Since we want the list to be populated by Notes image attachments, we will set the image picklist to a Page design element, which is explained in the next section. Note that the computed value in this line is set to @WebDbName.

L25-26: End of init call and script.

Domino image integration.

As stated before, we would like TinyMCE to be able to insert images that are stored as attachments inside documents. How you implement this can be specific to your situation, but it should be easy after I explain how this is done in Blogo. 

First, as stated in line 24 of the init script, we direct the source of our images to a Page called "pagRTEImages.js". The purpose of this page is to produce a javascript array of images that TinyMCE will use in the insert image dialog box. The content type of the page is set to html. When you open it, you can see that a javascript array is setup with two elements: an embedded view and a default value (---). The format that TinyMCE expects for the image array is demonstrated in the following example:

var tinyMCEImageList = new Array(
// Name, URL
["Logo 1", "logo.jpg"],
["Logo 2 Over", "logo_over.jpg"]
);

As you can see, it is an associative array where the index is the image description and the value is the image path. The embedded view takes care of outputting this format for the image list. The view design is highly specific for your situation as your view selection and field names will differ from the ones used in Blogo. Still, the "vwResourcesRETPickList" view should give you a good start.
The first column of the view is sorted and hidden. This ensures that the array that we will output is sorted as well. The second column produces the array in the format mentioned above. In this column Blogo filters the attachments, it only allows image attachments to make it into the array. Another feature is that Blogo simulates a file system by using nested image descriptions. Three extra tips:

  • The embedded view has its content type set to html, and the lines to display to 1000
  • Make sure that the column formula that outputs the javascript array ends with a colon, to seperate the array elements
  • Debug the format of your javascript by directly opening the Page in your browser

If all went well, you should now be able to insert Domino images into your rich text content:

Saving the rich text content

Now that we have the rich text capabilities working in the front-end, we need to make sure that upon a document save (submit), the content of the editor is saved into the Notes field. In essence, your editor is still just a textarea element,  and by setting the name attribute to the name of your Notes field, the save should work. Still, TinyMCE offers a way to enforce the content of the editor to be pushed to the underlying text area, after which Domino will do the rest. In the bottom of the "Page Edit" subform, the TinyMCE triggersave method is called:

if ( QuerySave(this.form) ){ tinyMCE.triggerSave(false,false);this.form.submit()}

Your implementation may vary, perhaps you make the call in the onsubmit event of your form. 

Conclusion

Integrating TinyMCE into your Domino application is a big usability improvement. I wrote this article in TinyMCE, and it took me about half the time it would cost if I would type it in HTML. Using this article, hopefully you will find it easy to integrate TinyMCE into your application.

Note that this article did not try to demonstrate the full feature set of TinyMCE. TinyMCE has a wealth of extra functions and ways to customize them. Consider the excellent documentation and forum for more information.

I've been skeptic about web rich text editors for years, considering their cross-browser problems and inconsistent and unreliable behavior. I have delayed implementing them in my own applications. I can now happily confirm that to me, those days are over. I fully trust this editor and I've had zero problems using it, across browsers. I hope this article convinces you to take the same step, if you have not already done so.

Share |

Comments: 34
Reviews: 9
Average rating: rating
Highest rating: 5
Lowest rating: 4

COMMENT: VITOR PEREIRA email

DEC 22, 11:46:42

comment » Thank you so much for this great contribution! «

COMMENT: KATHIR PERI

DEC 22, 03:11:47 PM

comment » Great article!, and a nice line by line code explanation. «

COMMENT: DIETMAR

DEC 24, 12:09:43

comment » Did you consider putting the TinyMCE components in a shared resource database? This way you would keep the possibility to update the component for different apps at once, as well as the possibility to easily replicate it to other domino servers as well. Moreover, such a resource database could contain other often needed components too (Name picker, Date picker, time picker. etc). «

COMMENT: DGO emailhomepage

DEC 26, 01:31:53 PM

comment » Hi,

i use tinyMce in our domino development since i've read the Jake's article 2 years ago.

All the pages of our site were created with tinymce without problems (excep with cut and paste from Ms Word )

The latest version provide a new parameter called file_browser_callback.

When you activate this one, tinymce add a button next the "image url" field. This button call a user's function in javascript who open a popup with for example a notes view with all the image of our intranet.

an abstract of our code :

the function to call the popup :

function fileBrowserCallBack(field_name, url, type, win) {

var fileBrowserWindow = new Array();

var cmsURL = _hbase+'(v.actimgtit)?open&count=-1'; // script URL

fileBrowserWindow["file"] = cmsURL + searchString;

fileBrowserWindow["title"] = "Rpertoire Image";

fileBrowserWindow["width"] = "700";

fileBrowserWindow["height"] = "450";

fileBrowserWindow["close_previous"] = "no";

tinyMCE.openWindow(fileBrowserWindow, {

window : win,

input : field_name,

resizable : "yes",

inline : "yes"

});

}

the function who send back the choice :

function returnF4tiny(thisObj)

{

var win = tinyMCE.getWindowArg("window");

var fld = tinyMCE.getWindowArg("input")

// insert information now

win.document.getElementById(fld).value = thisObj;

// close popup window

win.tinyMCE.setWindowArg('editor_id','mce_editor_0');

if (win.getImageData) win.updateImageData();

if (win.showPreviewImage) win.showPreviewImage(thisObj);

tinyMCEPopup.close();

};

Sorry about my english, feel free to mail if you want more explanation.

Hope it will be usefull.. «

COMMENT: DGO homepage

DEC 26, 01:33:56 PM

comment » Sorry i forgot the link to the documentation of the new parameter :

http://tinymce.moxiecode.com/tinymce/docs/option_file_browser_callback.html «

COMMENT: BENOIT

DEC 27, 08:27:32

comment » Very good article, thanks 01 «

COMMENT: LANCE SPELLMAN emailhomepage

DEC 28, 10:30:08 PM

comment » Without having completely gone through this in detail, can you explain what happens when a user includes an outside image in their content? How does domino save this content, as inline base64 encoded mime? «

COMMENT: JUAN F. RUIZ emailhomepage

DEC 29, 01:44:45

comment » Good, Ferdy!

And it will be translated too! I will navigate through JS files, form's, to translate all that messages ... 17 mmm ... well, JS files may be not because i guess TinyMCE has been translated yet. 30 «

COMMENT: FERDY

DEC 29, 08:11:10 AM

comment » Lance,

You cannot include an outside image. You first have to upload the image to the web server (in Blogo this is done using a Resource forum with upload controls), and then you can insert it into your content.

Juan,

Thanks in advance, I look forward to the translated version «

COMMENT: BEN POOLE emailhomepage

JAN 2, 14:06:17

comment » Lance, if you use the "Insert image" button to er, insert an image in your content, then the underlying saved data is simply the usual img tag pointing to the image you reference (the insert image code prompts for a URL).

As Ferdy points out, this code can be augmented to that you can provide users with a "picklist" of images stored in a Domino database (or indeed elsewhere -- you only need provide a Javascript array to detail these images), but the end result is the same: an img link.

In other words, inserting an image in a TinyMCE instance does NOT result in either an in-line Base64-encoded entity or an attachment.

Does that help? 18 «

COMMENT: GUSTAF

JAN 8, 07:35:20

comment » Ferdy,

one problem that I've had... though I still like this and use it since a year or so...:

Applying it to already existing documents with a RTF containing a long text with linebreaks and such. I didn't manange to convert the text to HTML without losing layout on the linebreaks - the best and easiest way was to leave them, andthen they did convert to , but the layout was then different than it was before editing... 04

They should have been shift-entered to get a more correct result. «

COMMENT: PATRICK KWINTEN emailrating

FEB 2, 07:58:51

comment » Thanks for the explanation, this is really usefull in daily development life «

COMMENT: BJORN LARSEN

MAR 12, 12:43:44

comment » Thanks a million, absolutely excellent information 18 «

COMMENT: OYUN emailhomepagerating

APR 7, 18:32:56

comment » perfect, thank you 01 «

COMMENT: DANIEL SCHADE homepagerating

JUN 27, 09:32:46 AM

comment » Ferdy, thanks for this.

Did you plan to enable special characters in the title of pages like

germans ? All of them will be replaced by a ? sign and the rest

of the word will be lost during the saving progress.

Greetings Daniel «

COMMENT: MATT email

AUG 20, 17:51:57

comment » Many Thanks Ferdy, very useful article.

I do have a small problem which I can replicate in your sample Blogo template. In Opera, when adding images it uses the absolute URL instead of the relative one. It is fine in IE and Mozilla e.g. I added a smiley to the Blogo sample and it came out as:

SRC="http://localhost/Blogo/s3_blog_160.nsf/resources/MyResource/$FILE/emoticon.gif"

Any ideas what might be causing this or how to get around it?

cheers Matt «

COMMENT: PATEL NASRULLAH emailrating

SEP 7, 12:20:02 PM

comment » Hi,

Thank you..... Very excellent.

Please can you help me how to set path for image upload....... 01 «

COMMENT: SANDY email

SEP 18, 04:10:11 PM

comment » hi,

I my tinymce is working in firefox but not in any version of ie,

please help me fix it.

Sandy «

COMMENT: FREDRIC BERLING rating

NOV 15, 14:02:30

comment » Last comment was some time ago , but i hope you can shed some light over my "problem".

I integrated tinymce in an application where i have documents containing a richtext item.. These documents show up nicely when i am in read mode, but when swithing to EditMode and TinyMce gets hold of my field i loose all images and linebreaks and formatting.

I have played around with Content as Mime Html" etc without luck.

Can domino feed TimyMce with the HTML rendered from the RTF field? «

COMMENT: FERDY

NOV 20, 10:28:41 AM

comment » Frederick,

I believe it is somewhat possible, but it definitely is not trivial and probably hard to get stable. This is why I have chosen not to go that way and only offer a web-based rich text editor. «

COMMENT: ALAN WHITE emailhomepagerating

MAY 2, 2008 - 11:06:52

comment » I need to build a domino web site where users can post formatted text

and like you I decided to only allow editing via a brwoser cleint

so this article was a great help

before integrating TinyMCE into my real application I decide to build a prototype.

I've tried to pare down your example to the minimum code and I'm having problems

In my prototype I have

1. loaded all tresources

2. created a subform equivalent to your Rich TextEditor subform

(marked with with passthru HTML throughout)

3. Created a form iths

a. the subform

b. HTML to create the text area

c. HTML to create a simple save button

d. Javascript in theJSHeader to handle the click

function saver() {

tinyMCE.triggerSave(false,false);

document.forms[0].submit()

}

when I try this the editor comes up nicely

you can put in formatted text

the document saves

BUT ...

there is no item on the document that is created containing the HTML equivalent of the

WHERE AM I GOING WRONG? «

COMMENT: RENATE email

AUG 1, 2008 - 12:01:35

comment » Hi! Just a short question - I cannot make the anchor links work..

I create an anchor link. Give it a name, ie XyZ. Then I mark the text I want to link to this anchor - and click the create link button, and types inn #xyz, and saves. However, in your blog, it cannot open the link, because it misses the document id in the url...

I tried this in the old demo, and it worked, but maybe I am doing it wrong?? It would be very nice if anyone can point me in the right direction, as this is cruical for selecting a Rich Text Editor...

Thanks, Renate «

COMMENT: RENATE email

AUG 1, 2008 - 12:05:30

comment » By the way, I forgot to say that I just downloaded your BLOGO db yesterday, and played with it for a couple of hours! It is great!

Hope you can help me out with the anchor stuff...

Ren «

COMMENT: JAVIER

AUG 22, 2008 - 10:09:29

comment » Hi Ferdy,

Im trying build an application which allows editing RTF both notes and browser but when i save changes in browser with TinyMCE I only can read plain text in notes client like: "Hello World!".

Now I am creating a Java agent to read this text and create a new Rich text field using NotesRichTextStyle but is quite heavy and difficult.

Any suggestions?

Thank you and congratulations on the article! «

COMMENT: FERDY

AUG 22, 2008 - 07:09:36 PM

comment » Javier,

What you want is not easy and hard to make bullet-proof. The reason is that TinyMCE stores the rich text in plain text HTML, whilst the Notes client uses a proprietary format to store rich text.

I believe Jak Howlett of CodeStore has a solution to this on his site (codestore.net), where he uses an agent to mess with mime types. Give it a try 18 «

COMMENT: FREDRIK rating

SEP 1, 2008 - 12:33:42

comment » Have anybody had problems with attachments

I have a for that I have implemented Tiny MCE in and it works great but below this field I have an upload control that you counld upload files to the document. And the problem seams to be that Domino is attaching the files to the Richtext field that I have the text in now.

Any Ideas how to get the attachments just to be uploaded into the document and not too my richtext field ? «

COMMENT: FERDY

SEP 2, 2008 - 07:45:21 AM

comment » Hi Frederik,

It's been a while since I've last done this, but I think you can do this by placing a $$V2AttachmentOptions field on the form. «

COMMENT: FREDRIK

SEP 2, 2008 - 09:46:35

comment » Sorry but the $$V2AttachmentOptions doesn't work if the form has a richtext field «

COMMENT: BENOIT emailhomepagerating

OCT 7, 2008 - 13:22:34

comment » Hi,

i've done this by placing a richtext field at the top of the form, before the textarea for tinymce.

now, when i save a document where a file was uploaded, the file is stored in the first richtext field.

do not forget to put a $$V2AttachmentOptions field and to hide the richtext field too.

As always, go to codestore.net to see how Jake is doing upload control integration.

bye. «

COMMENT: EDWIN homepage

MAR 17, 2009 - 11:26:20 AM

comment » Thanks for your results. «

COMMENT: CARLOS email

AUG 3, 2009 - 06:12:19 P.M.

comment » Dear Ferdy:

Your site is greart and your articule too, but nowadays I'm developing other web app and my user need that in its lotus web form he can add embedded code media...I used the web app tynimcev0.9 from web site Jake(http://codestore.net/store.nsf/unid/BLOG-20050209?OpenDocument), please, can you tell, How can I that functionality to add embedded code media?,

1000 thanks,

Carlos. «

COMMENT: STEVE C email

FEB 4, 2011 - 04:20:31

comment » Hi Ferdy, I've been banging my head trying to get rich text editors to work. I've tried the yahoo one and now this one

http://www.scriptiny.com/2010/02/javascript-wysiwyg-editor/

I'm stuck at trying to save the rich text. If I understand it right, I have got my editor working fine and attach all the properties to this:

But I can't get it to save to my notes field. My notes field is called 'input' with an id of 'input'. Please put me out of my misery!

Thanks

Steve

Now, I've tried «

COMMENT: IRFAN emailrating

APR 21, 2011 - 10:18:13 AM

comment » What is the license of BLOGO?

Thanks for the knowledge :) «

COMMENT: FERDY

APR 21, 2011 - 02:45:43 PM

comment » @Irfan. It's open source, although I no longer actively support it. «

RATE THIS CONTENT (OPTIONAL)
Was this document useful to you?
 
rating Awesome
rating Good
rating Average
rating Poor
rating Useless
CREATE A NEW COMMENT
required field
required field HTML is not allowed. Hyperlinks will automatically be converted.