Introduction
Here is a How-to for integrating the FCKEditor with SharePoint as a Web Part. Also, this article helps you implement a custom image browser for this Web Part.
Background
I was searching the Internet a lot in order to find how to integrate a WYSIWYG editor such as TinyMCE or FCKEditor with the SharePoint platform, but without luck. So, I did it myself.
Why bother? Both SharePoint Server (MOSS 2007) and the free version WSS 3.0 has integrated WYSIWYG editors. But they lack some features:
- The WSS 3.0 WYSIWYG editor can’t upload images
- Both versions can’t insert Flash files
- They are bad in working with tables
- Any customization (such as custom file browsers, link management) is very hard to implement
So, I tried to implement one of the most used WYSIWYG editors in the world, FCKEditor. You can download it here. For this project, I used the FCKeditor.Net
control for creating a Web Part and the FCKEditor 2.6.3 core scripts.
The idea is simple; to use FCKEditor instead of the Content Editor Web Part.
Using the code
fckeditor.zip is complete FCKeditor with the fileUpload ASPX page and code. FCKMossEditor is a Web Part VS2005 project.
Step 1: Creating a Web Part
So we need a Web Part. I will not describe here what a Web Part is, because I assume that everyone who uses SharePoint knows what a Web Part is. In display mode, our Web Part will render HTML to SharePoint users, and in editor mode, we will use FCKEditor to manage the content.
I created a Web Part in Visual Studio 2005. The easiest way to do it is to download Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions and to install it. Then, just use New>Project>C#> SharepPoint> Web Part project template.
- Pick a nice name and click OK. I chose FCKMossEditor, and here is how it looks like in VS2005:
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
namespace FckMossEditor
{
[Guid("9edcd0c0-c649-48d1-8acd-bd6c9b01a030")]
public class FckMossEditor : System.Web.UI.WebControls.WebParts.WebPart
{
public FckMossEditor()
{
this.ExportMode = WebPartExportMode.All;
}
protected override void Render(HtmlTextWriter writer)
{
}
}
}
- You will need to add a reference to the
FCKEditor.Net
control you downloaded before. So, click References in the Solution Explorer, and then click Add Reference. Navigate to the directory where you unpacked the FCKEditor.Net
control, and add it to your project. - You will need to create the
EditorPart
class. In the EditorPart
class, we tell SharePoint what we want to display in the Editor Zone of our content editor Web Part. All credits for the following code goes to Sahil Malik who wrote this great article: Writing Custom Editors for WebParts. Only, he used the Telerik RAD editor, and here I’m using FCKEditor. If you plan on developing Web Parts for SharePoint, you will need this article. Speaking of Sahil Malik, if you are interested in developing workflows with VS2005, he has some great articles (SharePoint 2007 Workflows - Setting up your environment) about it.
OK, let’s go back to our Web Part. Create a new class called HtmlEditor
. Here’s the code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using FredCK.FCKeditorV2;
namespace FckMossEditor
{
class HtmlEditor : EditorPart
{
private FCKeditor htmlContentTxt;
public HtmlEditor()
{
this.ID = "HtmlEditor";
}
protected override void CreateChildControls()
{
htmlContentTxt = new FCKeditor();
htmlContentTxt.ImageBrowserURL = "/fckeditor/fileUpload.aspx";
htmlContentTxt.ToolbarSet = "MyToolbar";
htmlContentTxt.Width = 525;
htmlContentTxt.Height = 500;
Controls.Add(htmlContentTxt);
}
public override bool ApplyChanges()
{
EnsureChildControls();
FckMossEditor part = WebPartToEdit as FckMossEditor;
if (part != null)
{
part.DisplayText = htmlContentTxt.Value;
}
else
{
return false;
}
return true;
}
public override void SyncChanges()
{
EnsureChildControls();
FckMossEditor part = WebPartToEdit as FckMossEditor;
if (part != null)
{
htmlContentTxt.Value = part.DisplayText;
}
}
}
}
Only three methods here. CreateChildControls
creates a new FCKEditor.Net
control and sets a few properties for it. ImageBrowserURL
is the most important one. Here, we say to FCKEditor where our file browser page is. Yes, we create a custom file browser page with an upload feature in step 3. The images will be kept on the SharePoint server. We are using the Toolbarset
property to control what toolbar buttons will appear. There are more FCKEditor properties that you can set, please explore them.
- Then, go back to the main class (FckMossEditor.cs, in my case) and edit it. Here’s the code:
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Collections.Generic;
namespace FckMossEditor
{
[Guid("7de64613-aa8e-46bb-a7cd-ed36ea03f159")]
public class FckMossEditor :
System.Web.UI.WebControls.WebParts.WebPart, IWebEditable
{
public FckMossEditor()
{
this.ExportMode = WebPartExportMode.All;
}
private string displayText = "Hello World!";
[WebBrowsable(true), Personalizable(true)]
public string DisplayText
{
get { return displayText; }
set { displayText = value; }
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.Write(displayText);
}
#region IWebEditable Members
EditorPartCollection IWebEditable.CreateEditorParts()
{
List<editorpart /> editors = new List<editorpart />();
editors.Add(new HtmlEditor());
return new EditorPartCollection(editors);
}
object IWebEditable.WebBrowsableObject
{
get { return this; }
}
#endregion
}
}
Here, we have our DisplayText
property that will hold a value for the Web Part. We extend our class with the IWebEditable
interface, which provides an interface for the developers to specify custom editing controls that are associated with a Web Part control. We declare the HtmlEditor
class as an editor class for our Web Part, so when the user selects to edit our Web Part, an instance of the HtmlEditor
class will display (which renders FCKEditor). And, at last, in the Render
method, we display the DisplayText
property to the SharePoint visitors.
Step 2: Configure FCKEditor
- First, copy FCKEditor (the one you downloaded at the beginning of this article) to the SharePoint app folder. In my case, it was in C:\Inetpub\wwwroot\wss\VirtualDirectories\80. It looks like this:
- I added my own toolbar (
MyToolbar
) to the config file (fckconfig.js). There are two toolbars by default (Basic and Default), but the default is too much and the basic is basic, so I made my own.
FCKConfig.ToolbarSets["MyToolbar"] = [
['Cut','Copy','Paste','PasteText','PasteWord'],
['Undo','Redo','-','Bold','Italic','Underline','StrikeThrough'],
'/',
['OrderedList','UnorderedList','-','Outdent','Indent'],
['Link','Unlink','Anchor'],
['Style'],
['Table','Image','Flash','Rule','SpecialChar'],
['About']
] ;
- At this moment, you can deploy the Web Part you built in step 1 (click Build>Deploy FCKMossEditor in VS2005) and everything will work. You can add your new Web Part to the SharePoint page:
And, when you modify the shared Web Part, FCKEditor will appear:
You have only one problem. The file browser for the image and Macromedia Flash files will try to upload your media to the /UserFiles/ folder in your web app. If you use SharePoint, it would be natural to store the media in SharePoint. So, wait for Step 3.
Step 3: Custom FileBrowser
We want to store media files to the SharePoint server. This is the quick way.
- Open fckconfig.js.
- Find var _FileBrowserLanguage and change it. It should look like this:
var _FileBrowserLanguage = 'aspx' ;
var _QuickUploadLanguage = 'aspx' ;
- Set
FCKConfig.ImageUpload
to false
(FCKConfig.ImageUpload = false;
). - If you remember, when we created the Web Part, we add this line to the
HtmlEditor
class:
htmlContentTxt.ImageBrowserURL = "/fckeditor/fileUpload.aspx";
So we need this file. I created fileUpload.aspx page with the code-behind page.
I added a TreeView
control, an Image control, a file control, and two buttons, and it looks like this:
I made a simple solution that puts all the images to the Pics folder in SharePoint. When you select an existing image, the image appears and you can select to add it to your FCKEditor control:
Code for the button click event:
sendImage = true;
slika = Image1.ImageUrl;
Or you can upload an image to SharePoint by browsing for an image and clicking the Upload button. Here is the upload button click event:
SPWeb sourceWeb;
SPSite sourceSite = SPControl.GetContextSite(Context);
sourceWeb = sourceSite.AllWebs["/"];
sourceWeb.AllowUnsafeUpdates = true;
SPFolder destFolder = sourceWeb.GetFolder("Pics");
if (!destFolder.Exists) destFolder = sourceWeb.Folders.Add("Pics");
try
{
if (File1.PostedFile == null)return;
string strFileName = File1.PostedFile.FileName.Substring(
File1.PostedFile.FileName.LastIndexOf("\\") + 1);
Stream fStream = File1.PostedFile.InputStream;
byte[] contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
destFolder.Files.Add(strFileName, contents,true);
Response.Write("UploadDocFile :: Success" + strFileName);
sourceWeb.Dispose();
}
catch (Exception ex)
{
Response.Write("UploadDocFile ::" + ex.Message);
}
- You need to code the
Page_load
event too. Here, we populate the treeview control with the images from the SharePoint Pics folder:
public Boolean sendImage;
public string slika="", align="", opis="";
protected void Page_Load(object sender, EventArgs e)
{
Image1.Visible = false;
Label1.Visible = false;
Button2.Visible = false;
SPWeb sourceWeb;
List<spdocumentlibrary> docLibs;
SPSite sourceSite = SPControl.GetContextSite(Context);
sourceWeb = sourceSite.AllWebs["/"];
sourceWeb.AllowUnsafeUpdates = true;
docLibs = new List<spdocumentlibrary>();
SPFolder destFolder = sourceWeb.GetFolder("Pics");
if (!destFolder.Exists) destFolder = sourceWeb.Folders.Add("Pics");
folderTree.Nodes.Clear();
foreach (SPFile file in destFolder.Files)
{
TreeNode t = new TreeNode();
t.Text = file.Title;
t.Value =sourceSite.Url.ToString()+"/"+ file.Url.ToString();
folderTree.Nodes.Add(t);
}
sourceWeb.Dispose();
}
- What about the public boolean
sendImage
? This is a dirty trick to send info back to FCKEditor, and we use it in fileUpload.aspx. We have this:
<% if (sendImage)
{ %>
<script type="text/javascript">
var alt="";hspace="";vspace="";width="";height="";
var lresult = new Array();
lresult['src'] = "<%=slika %gt;";
lresult['align'] ="<%=align %>";
lresult['alt'] = "<%=opis %>";
lresult['border'] = "0";
lresult['hspace'] = "5";
lresult['vspace'] = "5";
window.opener.SetUrl( "<%=slika %>", 110, 120, "<%=opis %>" );
self.close();
</script>
<% } %>
sendImage = true; slika = Image1.ImageUrl;
Don’t be confused with the variable slika
; it means image in Serbian.
- You can download the fileUpload.aspx and fileUpload.aspx.cs files here. You can just put them to FCKEditor folder in the SharePoint app.
- You can do the same thing for the file browser for Flash and link browser pages.
- Additionally, you can extend the treeview to work with several folders.
History
If the sendImage
variable is true
, then send the image file name back to FCKEditor. Of course, sendImage
is true
only if you click the Choose button. Remember, we had it in the onClick
event of the Choose button: