Tuesday, August 03, 2010

Using Custom ContentFilters with RadEditor and Telerik Reporting

A scenario popped-up last week that lead to a helpful tip I wanted to share with you. Here’s the scenario:

You are using Telerik Reporting for adding simple Business Intelligence to your ASP.NET applications. You are using RadEditor for ASP.NET AJAX to enable your content creators to input HTML in to your system. The Reporting HtmlTextBox only understands limited HTML tags for “paper oriented” page output, so you need to prevent content creators from adding unsupported HTML to tags that will be displayed in reports.

The first thing to understand is that the HtmlTextBox for Telerik Reporting is primarily concerned with enabling basic text formatting using familiar tags from HTML. It is not designed to render HTML like a browser. If you seek functionality like that, check out RadEditor’s built-in PDF export support.

The easiest way to solve this problem and “force” RadEditor to only accept Telerik Reporting-compatible HTML tags is to use Custom ContentFilters.

A ContentFilter is a simple JavaScript class that extends RadEditor’s functionality and adds processing to RadEditor whenever content is accessed (client-side and server-side). At it’s core, a ContentFilter has two methods: getHtmlContent and getDesignContent. Each receives the current content in the editor and is expected to perform some processing (usually done with RegEx) and return the result.

To target Telerik Reporting, we need a ContentFilter that will remove all HTML tags except those understood by the Reporting export engine (currently: FONT, STRONG, B, EM, I, U, A, OL, UL, LI, DIV, SPAN, P, BR, CENTER). We can do that with some RegEx that looks like this:

<(?!\/?(font|strong|b|em|(i(?!mg))|u|a|ol|ul|li|div|span|p|br|center)(?=>|\s?.*>))\/?.*?>

What’s this RegEx doing? In simple English:

  1. Matching the “<” character literally (start of an HTML tag)
  2. Matching any character except those in our list (list of Reporting-friendly tags) – if we find one of our “allowed” character strings, the tag won’t match our expression (and thus won’t be removed)
  3. Matching any remaining characters within the HTML tag (like attributes)
  4. Matching the closing HTML “>” (with possible “/>” self closing tag)

Using this RegEx, we can create a simple JavaScript file to define our custom ReportingFilter for RadEditor:

ReportingFilter = function()
{
ReportingFilter.initializeBase(this);
this.set_isDom(false);
this.set_enabled(true);
this.set_name("ReportingFilter");
this.set_description("Telerik Reporting HTML filter for RadEditor");
}
ReportingFilter.prototype =
{
getHtmlContent: function (content) {
return this._removeHtmlTags(content);
},

getDesignContent: function (content) {
return this._removeHtmlTags(content);
},

_removeHtmlTags: function (initContent) {
var cleanContent;

//Perform necessary REGEX replacement to remove unsupported HTML tags
//Supported Reporting HTML tags: FONT, STRONG, B, EM, I, U, A, OL, UL, LI, DIV, SPAN, P, BR, CENTER
//HTML must be XHTML valid, too, but Editor already provides that filter

//Following REGEX will remove all HTML tags EXCEPT those expliclitly listed
cleanContent = initContent.replace(new RegExp("<(?!\/?(font|strong|b|em|(i(?!mg))|u|a|ol|ul|li|div|span|p|br|center)(?=>|\s?.*>))\/?.*?>", "ig"), "");

return cleanContent;
}
}
ReportingFilter.registerClass('ReportingFilter', Telerik.Web.UI.Editor.Filter);

With our filter defined, we simply add the JavaScript file to our page and initialize the configuration in the client-side OnClientLoaded event of RadEditor:

<script src="reportingfilter.js" type="text/javascript"></script>
<script type="text/javascript">
function editorLoaded(editor, args)
{
editor.get_filtersManager().add(new ReportingFilter());
}
</script>

And for good measure, we can configure our RadEditor toolbars to “encourage” usage of the allowed, limited HTML tags by removing all other options:

<telerik:RadEditor runat="server" ID="editor1" OnClientLoad="editorLoaded" 
StripFormattingOnPaste="AllExceptNewLines" ContentFilters="DefaultFilters">
<Tools>
<telerik:EditorToolGroup>
<telerik:EditorTool Name="Bold" />
<telerik:EditorTool Name="Italic" />
<telerik:EditorTool Name="Underline" />
<telerik:EditorTool Name="FontSize" />
<telerik:EditorTool Name="ForeColor" />
<telerik:EditorSeparator />
<telerik:EditorTool Name="JustifyLeft" />
<telerik:EditorTool Name="JustifyCenter" />
<telerik:EditorTool Name="JustifyRight" />
<telerik:EditorSeparator />
<telerik:EditorTool Name="InsertOrderedList" />
<telerik:EditorTool Name="InsertUnorderedList" />
<telerik:EditorSeparator />
<telerik:EditorTool Name="InsertLink" />
</telerik:EditorToolGroup>
</Tools>
</telerik:RadEditor>

Result: A RadEditor that will automatically remove any HTML tags that Telerik Reporting’s HtmlTextBox doesn’t like. You can extend this example by adding additional processing to the custom filter to strip away unwanted HTML attributes from allowed tags, but that’s just a matter of finding the necessary RegEx.

Download the code for this example [Requires your own copy of Telerik.Web.UI]

0 comments: