This post is the part II of Enhance SharePoint rich text field. I want to share some of the pitfalls we encounter when working with a RichTextField in compatible mode.
When saving your content, SharePoint clean (a bit?) your html and may erase some parts of it because it allows only a restrictive list of HTML tags.
We choose the compatible mode for that reason: cleaning the garbage such as IMG, TABLE, DIV, SCRIPT, OBJECT … and some attributes.
But TinyMCE manages the Html differently. For example, we will set the word over in underline:
|
TinyMCE generates:
|
The quick brown fox jumps <span style="text-decoration:underline;">over</span> the lazy dog
|
|
HTML accepted by SharePoint:
|
The quick brown fox jumps <u>over</u> the lazy dog
|
The same problem occurs with colored text, background color, relative URL, and URL that do not start with http(s):// (www.google.be is refused but not http://www.google.be).
Look like we should need to perform some cleanup before the postback.
When to clean?
There is no way to change the field's value by C#. The cleaning code process is a black box and you don't have access to override that behavior. So let's look at client side.
In the generated HTML source of a <SharePoint:SaveButton>, we have:
|
<input type="button" name="…$diidIOSaveItem" value="OK" onclick="if (!PreSaveItem()) return false;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(…)" id="… " accesskey="O" class="ms-ButtonHeightWidth" target="_self" />
<input type="button" name="…$diidIOSaveItem" value="OK" onclick="if (!PreSaveItem()) return false;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(…)" id="… " accesskey="O" class="ms-ButtonHeightWidth" target="_self" />
|
And PreSaveItem definition is (in FORM.JS):
|
function PreSaveItem() { if("function"==typeof(PreSaveAction)) { return PreSaveAction(); } return true; }
|
Nice! We can declare a function named PreSaveAction and it will be called before the PostBack. We can do some client-side validation too and cancels the postback if we want. But that's out of scope, we only want to alter the textarea's value.
Warning: pay attention you don't already declare PreSaveAction in your code!
Using TinyMCE's API, we fetch the registered editors and test a flag I declared in the MOSSBASIC config array.
|
var MOSSBASIC = { … sp_compatible: true }
function PreSaveAction() { var c, ed, eds = tinyMCE.editors; for(var ctrl in eds){ ed = tinyMCE.get(ctrl); if(ed.settings.sp_compatible === undefined) continue; c = cleanRTF(ed.getContent()); byid(ctrl + "_spSave").value = c; <- this is the hidden field containing the saved stream used by SP } }
|
How to clean
The clean process consists in some regex stuff. Nothing really interesting here…
|
function cleanRTF(html) { if (html.length > 0) { // reformat some tag html = html.replace(new RegExp("<span\\sstyle=\"text-decoration:\\sunderline;\">(.+)</span>", "i"), '<u>$1</u>'); html = html.replace(new RegExp("<span\\sstyle=\"color:\\s(.+);\">(.+)</span>", "i"), '<font color=\"$1\">$2</font>'); html = html.replace(new RegExp("<span\\sstyle=\"background-color:\\s(.+)\">(.+)</span>", "i"), '<font style=\"background-color:$1\">$2</font>'); // clean dirty tag added by tinymce and refused by SP html = html.replace(/dirty_moz="(?:.+?)(?:")/g, ''); html = html.replace(/(?:mce_href|mce_src)="(?:.+?)(?:")/g, ''); // SP accepts only absolute url. We add http:// prefix to all relative urls html = html.replace(/href="([^"]+)"/g, 'href="http://$1"'); html = html.replace(/http:\/\/http:\/\//g, "http://"); } return html; }
|
Relative Links
This feature is provided by TinyMCE. When inserting a new link, if you insert "Agro/Document Library/readme.doc", TinyMCE will try to convert it to a relative path that can result in "../Document Library/readme.doc". That links will be replaced by a blank link by SharePoint.
You can disable that TinyMCE's option with relative_urls: false.
Office Garbage
As a side note, I want to talk about the Word 2007 font style garbage that occurs when pasting text from MS Word… a plugin exists but is still under construction by the Moxie team. Check it at: http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste
Download updated version of sptinymce.js: sptinymce.js (3.47 kb)