As a quick overview, we had a need for streamlining our content creation process. We use standard HTML blocks to perform custom XSLT transformation before posting the content to our customer facing website, and needed a structured method for storing and transforming the data. Initially, we used Reusable Content Blocks to store the base HTML, and then used some CSS to highlight the editable regions. Unfortunately, the process became very difficult to manage, and required us to train our content editors in html best practices, which was extremely inefficient.
To streamline the process, we created a custom HTML editor and gave the users simple menus to click which would allow them to enter just the content which we would then wrap with our predefined content blocks. The menu's allow a user to click a specific block type, key in the content, and click the save button to view the preview article before saving. Here are a few screen captures to illustrate:
Content Editor Menus |
Content Editor Dialog |
As you can see in the above images, we created a menu to allow for editing and adding of content blocks. When an option is clicked, a Dialog Window opens containing 1 or 2 rich html editors depending on the block type. We chose to go with the standard Publishing HtmlEditor control because our users liked the ribbon options for easily formatting text and inserting links. I have seen other similar implementations that use the Telerik RadEditor or another third-party editor for adding HTML content.
The Nuts and Bolts
The HtmlEditor can be found in the Microsoft.SharePoint.Publishing.WebControls namespace, and is intended to work specifically with publishing pages. The class is sealed, so creating a new editor from the base class is impossible. After a little bit of tweaking though, it really wasn't difficult to get the editor working on our custom application page.
I first created a new SharePoint Empty Project in VS 2010, and added a new Application Page to the /_layouts folder. I like to keep my custom pages organized, so I created a folder under Layouts called "Editor". To use the HtmlEditor, you will need to add references to the following DLL's in your project:
Microsoft.SharePoint.Publishing.dll - located in \14\ISAPI\
Microsoft.Web.CommanUI.dll - located in \14\ISAPI\
I then modified opened my ApplicationPage.aspx file and made the following modifications:
I removed the reference to the aspx.cs page, which is added by default, and changed the MasterPageFile to use v4.master instead of ~/masterurl/default.master. The reason for the different master page is that we have some heavy customization for our default branding, and I didn't want this to carry over to our application page.
I then added the following references:
These references ensure that you can add the HtmlEditor to the page, and that the Ribbon controls will load.
Next, in the PlaceHolderMain section I added a reference to the editor:
<Publishing:HtmlEditor ID="htmlEditor" runat="server" />
By default, the reference to the editor was not added to the designer.cs file, so you will need to manually add it if you want to interact with it in your aspx.cs file.
In the aspx.cs file, you will need to add these two using statements:
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.WebControls;
To fully configure the editor for use, you will need to override the OnInit() function. Here is the code I used:
protected override void OnInit(EventArgs e)
{
SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);
if (ribbon != null)
{
ribbon.TrimById("Ribbon.EditingTools.CPEditTab.Layout");
ribbon.TrimById("Ribbon.EditingTools.CPEditTab.EditAndCheckout");
}
htmlEditor.Field = new RichHtmlField();
htmlEditor.Field.ControlMode = SPControlMode.Edit;
htmlEditor.Field.EnableViewState = true;
htmlEditor.Field.AllowReusableContent = false;
htmlEditor.Field.MinimumEditHeight = "200px";
this.Form.Controls.Add(htmlEditor.Field);
btnSave.Click += new EventHandler(btnSave_Click);
base.OnInit(e);
}
As you can see, I also trim the Wiki controls from the Ribbon. I don't have a need for the Layout and Check out functions. I then create a new RichHtmlField() which stores the contents of the HtmlEditor. Notice that I set the field ControlMode to edit, and modify a few additional parameters to hide options from the ribbon. The final step is to add the RichHtmlField control to the page. Adding the field to the page causes the page to render the associated Ribbon Contextual Tabs. Without it, you would only see a text area for entering content, but the Ribbon would never display.
To get the rest of the editor wired up required some javascript to handle the population of the editor control, and a few hidden fields for storing parameters from the parent page such as editor type and control id. We have up to 8 editable sections for a standard article, so the id of the parent content area was necessary to maintain the position of our content blocks. I also perform an initial post back of the page via javascript in order to validate the variables and throw an error message is one of the required values is missing.
To post the content back to the parent page, I use a button click event, and the following code to write the information back to the parent:
string close = "<script src="\"/_layouts/jquery/jquery-1.4.2.min.js\"" type="\"text/javascript\"">
</script>
<div id="\"content\""></script>
" + Html + "</div>
<script type="\"text/javascript\"">
var obj = new Object(); obj.content = $('#content').html(); obj.id = " + hdControlId.Value + "; window.frameElement.commonModalDialogClose(obj, 1);
</script>";
Context.Response.Write(close);
Context.Response.Flush();
Context.Response.End();
This essentially clears the context of the page and returns a modalDialogClose() command with my returned values.
Conclusion
Hopefully this post will save you some time in trying to get the SharePoint HTML Editor to display on an application page. If you have any questions, feel free to drop me a line.