Make a Rich Text Editor of any part part of the page
Anatoly Mironov
A while ago I had a case where I needed to implement a rich text editor in my custom webpart. I searched for answers. If you use some built-in field from SharePoint it is not editable in other browsers than Internet Explorer. I wanted the same experience as a wiki page where you can use the Ribbon. In this blog post I’ll show you how to implement this entirely in javascript, with no additional server side fields..
Rich Text Editor
The goal is to make a part of a page behave like a rich text editor. This project which I have worked on, contains a lot of integrations with other systems and we have used Angular as a primary engine for rendering and editing the data. One of the requirements was a rich text editor for editing notes. Due to the custom webparts and Angular, we could not use SharePoint forms. The standalone SharePoint:InputFormTextBox didn’t render a rich text editor in other browsers than Internet Explorer.
<SharePoint:InputFormTextBox
ID="rftDefaultValue"
RichText="true"
RichTextMode="FullHtml"
runat="server"
TextMode="MultiLine"
Rows="5">
</SharePoint:InputFormTextBox>tinyMCE
What we did then, was a tinyMCE implementation through Angular UI. It worked, but we discovered some issues that made it less joyful. More about it in some future blog post:
- tinyMCE needed to recreated in Modal Dialogs
- More code for handling the model states in Angular
- Additional controls for RTE (mini ribbon), that don’t follow the SharePoint and Office style and makes it necessary to learn new ways of text input for users
There are more librarires for WYSIWYG, but tinyMCE is the most tested lib for that.
jQuery SPEditable
Then for a week ago or so, I got an answer on SharePoint StackExchange. Denis Molodtsov linked to his jQuery Plugin: jQuery SPEditable. It is a tiny jQuery extension that turns any (!!!) element on the page into a Rich Text Editor, a WYSIWYG editor that works with the SharePoint Ribbon like any other control on the page. The tiny jQuery extension is as follows (taken from Denis’ blog):
(function ($) {
$.fn.SPEditable = function () {
return this.each(function () {
$(this)
.addClass("ms-rte-layoutszone-inner-editable ms-rtestate-write")
.attr("role",
"textbox")
.attr("aria-haspopup", "true")
.attr("contentEditable",
"true")
.attr("aria-autocomplete", "both")
.attr("aria-autocomplete",
"both")
.attr("aria-multiline", "true");
});
};
$.fn.SPNonEditable = function () {
return this.each(function () {
$(this)
.removeClass("ms-rte-layoutszone-inner-editable ms-rtestate-write")
.removeAttr("role aria-haspopup contentEditable aria-autocomplete aria-multiline");
});
};
})(jQuery);**Genious! ** Why haven’t I thought about it. It is just like that. In order to make an element to be an Rich Text Editor, you have to add some classes and attributes as it is on the built-in controls: 
SharePointifying…
Allright, this is great. But when I see this, two questions arise in my head:
- Why jQuery? jQuery is great, no doubt. But do we use jQuery in this solution? Not at all. Appending classes and attributes is very easy in plain javascript. I would prefer to remove this dependency for this genious solution.
- Isn’t there code in SharePoint that already does this thing? If we can predict the classes and attributes as easy, it should be some utility code in SharePoint javascript libraries?
I think it is much better to use SharePoint javascript utilities whenever it is possible. It has been tested and adjusted for running within SharePoint. So I used grepWin again to dig into the hive folder. I search for contenteditable" and found sp.ui.rte.js:
This file contains among others two functions:
RTE.Canvas.makeRegionEditableRTE.Canvas.makeRegionUneditable
This is the implementation:
RTE.Canvas.makeRegionEditable = function (a) {
ULSNVe: ;
a.setAttribute("contentEditable", true);
a.setAttribute("role", "textbox");
a.setAttribute("aria-autocomplete", "both");
a.setAttribute("aria-haspopup", true);
a.setAttribute("aria-multiline", true);
Sys.UI.DomElement.addCssClass(a, "ms-rtestate-write");
Sys.UI.DomElement.removeCssClass(a, "ms-rtestate-read");
Array.add(RTE.Canvas.$33, a)
};
RTE.Canvas.makeRegionUnEditable = function (a) {
ULSNVe: ;
a.setAttribute("contentEditable", false);
a.removeAttribute("role");
a.removeAttribute("aria-autocomplete");
a.removeAttribute("aria-haspopup");
a.removeAttribute("aria-multiline");
Sys.UI.DomElement.removeCssClass(a, "ms-rtestate-write");
Sys.UI.DomElement.addCssClass(a, "ms-rtestate-read");
Array.remove(RTE.Canvas.$33, a)
};Wow, the implementation is almost the same. Then we can use it, without any jQuery dependency. So actually, we only need to load the SP.UI.Rte.js, find the needed element, and make it editable:
SP.SOD.executeFunc("sp.js", "SP.Utilities.Utility",
function () {
var element = document.getElementById("myId");
var scriptKey = NormalizeSodKey("sp.ui.rte.js");
var link = SP.Utilities.Utility.getLayoutsPageUrl("sp.ui.rte.js");
SP.SOD.registerSod(scriptKey, link);
SP.SOD.executeFunc(scriptKey, "RTE.Canvas",
function () {
RTE.Canvas.makeRegionEditable(element);
});
});I suppose the built-in functions from SharePoint will work even in IE 8. There is another function that can be useful: RTE.Canvas.getEditableRegionHtml(element)
Unsolved issues
SPEditable works only on pages where ribbon editing tools exist: a wiki page, a publishing page, but not in an application page or a simple page provisioned within a module.
