Extending the SDL Tridion 2011 Rich Text Field Format Toolbar

The Problem

A client recently asked for a product demo. They had specific scenarions to be followed, including the creation/insertion of mathematical equations. The sample content suggested that they wanted the equations to be displayed inline with textual content. In other words, the equations would need to be added to the source of a rich text field.

I figured that if I could find an equation editor that would run in an HTML page then I could somehow extend the RTF format toolbar to launch the functionality, then inserting whatever the editor returned in to the RTF at the location of the cursor. It was actually very easy to find a suitable editor – CodeCogs have a javascript-based editor that can be embeded in an HTML page which creates image representations of the described equations. Having found the right editor I then had to figure out how to extend the toolbar to enable the functionality. A quick email to R&D provide me with the lead I needed – the toolbar can be extended in the same way you would extend a ribbon toolbar elsewhere in the interface.

Knowing where I was going to, and knowing which direction to start off in, but not knowing the exact route I was going to follow to get to my destination, I set off. I achieved a moderate degree of succuess – adding a button to the toolbar which opened a popup containing the editor, and returning a fixed string of HTML to the RTF. Unfortunately some conflict between the Tridion javascript and the 3rd party javascript meant that I couldn’t get the end-to-end process to work completely, but it did give me an understanding of how to approach this type of extension. So that the effort was not all in vain I refactored what I’d created to deliver a reference implementation.  The key elements of the extension are detailed below.


Adding the toolbar button

There are plenty of examples available that show how to add a button to a ribbon toolbar in SDL Tridion 2011, so I won’t go in to the details of this. There is some specific configuration though, so I will cover this. I wanted to create a button in a custom group on the format toolbar that appeared only when editing Components. This is how it’s configured:

        <!-- RIBBON TAB -->

        <!-- GROUPS -->
        <ext:extension assignid="ExtensionGroup" pageid="FormatPage" name="RTF Extensions">
                <ext:view name="ComponentView">
                    <ext:control id="ItemToolbar"/>

        <!-- BUTTONS -->
        <ext:extension pageid="FormatPage" groupid="ExtensionGroup" name="Button&lt;br/&gt;Reference" assignid="ButtonReference">
            <ext:title>Button Reference</ext:title>
                <ext:view name="ComponentView">
                    <ext:control id="ItemToolbar"/>

You can see from this config snippet that I configured an RTF Extensions group with the ID “ExtensionGroup”, associated with the “FormatPage” – this is the ID of the Format ribbon tab, on which my group, and the button will appear. The button is also associated with “FormatPage”, as well as my custom group. The final part of the picture is where the group and the button are applied. I specified the “ComponentView” view as I wanted this to only appear when editing a Component. For the extension to appear for all item types apparently the name attribute can be omitted. For other item types, just specify the appropriate view name, e.g. PublicationView, FolderView, etc.

Controlling the availability of the button

Once I had the button appearing when I wanted it to, the next step was to make sure it was only active when the RTF was active. Having been use to configuring extension availability based on the selection of an item in a list view I was stuck again on how to proceed. Another email to R&D pointed me towards the existing toolbar button implementations to see how it’s done out-of-the-box. This is what I was able to find:

RTFExtensions.Commands.ButtonReference.prototype._isAvailable = function ButtonReference$_isAvailable(target) {
    if (target.editor.getDisposed()) {
        return false;

    return true;

RTFExtensions.Commands.ButtonReference.prototype._isEnabled = function ButtonReference$_isEnabled(target) {
    if (!Tridion.OO.implementsInterface(target.editor, "Tridion.FormatArea") || target.editor.getDisposed()) {
        return false;

    return true;

There was a little more to it than that, but this is what was relevant to my extension. Essentially the “selection”, or target is related to the cursor location, and contains the RTF editor. I didn’t investigate, but I assume that if I’d selected a block of text then the target would reference this.

Opening the popup

This will probably be the shortest part of this post as opening a popup is easy – I just used the $popup object. What looked like it would be tricky would be to get hold of the HTML created in the popup so it could be insterted in to the RTF at the cursor. More emails to R&D had me checking out more of the existing code used by the CME.

Getting the return value from the popup

It turns out that this is relatively straight-forward, but is handled in 2 parts. The first part is to “prime” the popup to provide the return value, which is done before the popup is opened. The second part is to initiate the return of the value, which is handled with in the popup. Both parts are tied to events.

Here’s the code needed before the popup is opened (in fact, the complete execute function):

RTFExtensions.Commands.ButtonReference.prototype._execute = function ButtonReference$_execute(target) {
    if (target.item.isActivePopupOpened()) {

    function ButtonReference$execute$onPopupCanceled(event) {

    var url = $config.expandEditorPath("/Popups/PopupReference.aspx", "ButtonReference");
    var popup = $popup.create(url, "toolbar=no,width=100,height=100,resizable=yes,scrollbars=yes", null);

    $evt.addEventHandler(popup, "submit",
        function ButtonReference$execute$onPopupSubmitted(event) {
            // Update FA
            var value = event.data.value;
            if (value) {

            // Release

    $evt.addEventHandler(popup, "unload", ButtonReference$execute$onPopupCanceled);


You can see that I’m setting a function to handle the submit event. This function gets the return value from the event data and applies it to the selected RTF editor. To compliment this code, the javascript for the popup needs to fire the submit event. Here’s the code that sets the return value and triggers the event:


RTFExtensions.Popups.PopupReference = function (element) {
    Type.enableInterface(this, "RTFExtensions.Popups.PopupReference");

RTFExtensions.Popups.PopupReference.prototype.initialize = function () {
    $log.message("Initializing Button Reference popup...");
    this.callBase("Tridion.Cme.View", "initialize");

    var p = this.properties;
    var c = p.controls;

    p.HtmlValue = { value: null };

    c.InsertButton = $controls.getControl($("#InsertButton"), "Tridion.Controls.Button");
    $evt.addEventHandler(c.InsertButton, "click", this.getDelegate(this._execute));

RTFExtensions.Popups.PopupReference.prototype._execute = function () {
    this.properties.HtmlValue.value = "<p><u>Sample string of HTML</u></p>";
    this.fireEvent("submit", this.properties.HtmlValue);


You can see that a button control on the popup page is referenced, an event handler is added to deal with the button being clicked, and in the click-executed function the submit event is fired with the HTML to be added to the RTF as a parameter.

What’s in the popup?

The source below is from the popup page in my reference implementation. The important parts to note are the Tridion UI controls namespace reference in the html element and the button (that uses the reference). The button ties back to the javascript in the previous section.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PopupReference.aspx.cs" Inherits="Button.Reference.Popups.PopupReference" %>

<%@ Import Namespace="Tridion.Web.UI.Core" %>
<%@ Import Namespace="Tridion.Web.UI" %>
<%@ Import Namespace="System.Web" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://www.sdltridion.com/web/ui/controls">

<head id="Head1" runat="server">
    <title>Reference Button Popup</title>
    <form id="form1" runat="server">
        <h1>Reference Button Popup</h1>
            <c:button id="InsertButton" runat="server" label="Insert" />

The popup implementation javascript and the Tridion core dependencies are added in the code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Tridion.Web.UI.Controls;
using Tridion.Web.UI.Core.Controls;

namespace Button.Reference.Popups
    [ControlResourcesDependency(new Type[] { typeof(Popup), typeof(Tridion.Web.UI.Controls.Button), typeof(Stack), typeof(Dropdown), typeof(List) })]
    public partial class PopupReference : TridionPage
        protected override void OnInit(EventArgs e)

            TridionManager tm = new TridionManager();

            tm.Editor = "RTFButtonReference";
            System.Web.UI.HtmlControls.HtmlGenericControl dep = new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
            dep.InnerText = "Tridion.Web.UI.Editors.CME";

            System.Web.UI.HtmlControls.HtmlGenericControl dep2 = new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
            dep2.InnerText = "Tridion.Web.UI.Editors.CME.commands";

            //Add them to the Head section
            this.Header.Controls.Add(tm); //At(0, tm);

The line “[ControlResources(“RTFExtensions.ButtonReference”)]” links the popup to the javascript and style references in the extension config.  The code in OnInit adds the relevant core dependencies. Without these some of API calls made, e.g. .fireEvent, won’t work.


Hopefully this post has helped to explain how to add a RTF toolbar button. It’s not meant as a step-by-step tutorial, more as a introduction to some of the steps implemented to make an RTF button extension work. The source code has been shared through the Tridion Practice site on Google Code. Feel free to download the source and play with it.


2011 GUI Extensions and SiteEdit 2009 SP3

I’ve recently been working on a GUI extension for 2011. Following the great work being done in the Power Tools project I refactored my server-side functionality in to a Model. This brings my extension in line with the approach used by our R&D guys when they create extensions. It also, apparently, broke SiteEdit in my environment


It didn’t take much figuring out the cause of my problem – the only change to my environment between SiteEdit working and the problem appearing was the refactoring of my extension. A quick tweak of the configuration to disable it had SiteEdit working again. I launched Firebug to see if It would highlight anything untoward, and it was clear to see that SiteEdit was trying load my Model!

I thought this was strange, but a quick email to R&D confirmed that this was the expected behaviour. Apparently SiteEdit loads the CME in the background when it starts.


The solution was a a simple one in the end – when you configure your Model’s virtual directory in CME website in IIS, you need to make sure you also do it in the SiteEdit website. It wasn’t clear to me whether it’s good practice to do the same for your Editors, but I didn’t and it wasn’t an issue for me.

SDL Tridion 2011 AppData

Recently I’ve been working on a GUI extension that involves determining the URL of a published Page and the shortening it using bitly. For the use case I have in mind it doesn’t make sense to get a new short URL every time the extension functionality is called for a specific Page. This means I needed a way to persist the shortened URL, so it could be reused as and when needed.

I knew some of my colleagues had solved the problem in extensions they’d developed so I put the question to them. I received a few answers, and fewer options than answers, but the general recommendation was to use “AppData”.

Here’s what Frank has to say about AppData:

One of the new features in Tridion 2011 that has not gotten much public attention is the so-called application data (AppData for friends). The application data feature gives us a mechanism to store additional, application-specific data with every Tridion item. So if you have a Component in Tridion that corresponds to some file outside in the real world, you could store the path to the file in the Component’s AppData. You can of course also store that information in a metadata field. But doing so exposes the information to every user that has access to the Component. The beauty (and curse) of AppData is that it is only available through the API. It is meant to be produced and consumed by an add-on application.

So, pretty much exactly what I wanted 🙂

Using AppData

Now understanding what I should use I set about understanding how to use it.  The new Tridion .Net API may well have support for AppData, but as the recommended approach for communication with the core application is to use the Core Service, and all the feedback I was getting was telling me to use the Core Service, I was concentrating on, of course, the Core Service. It’s actually a very simple process, as the examples below should show.

When working with AppData you need to provide an application id and, optionally, and item id. The application id is the identifier for the custom application, against which the relevant data is stored. The optional item id allows you to tie the application’s data to a specific Tridion item. Whether or not you specify an item id depends on the type of data you want to store. In my case it was relevant to a selected Page so I would be specifying the item id.

With the code examples it’s important to note that I’m using a proxy class for the Core Service, and a static helper method to get the client object. The focus of the examples is to show how to use the client to interact with AppData, not to show how to create a client connection to the Core Service.

Getting AppData

CoreService2010Client client = ServiceClient.GetCoreServiceClient();
string appDataValue = string.Empty;
ApplicationData appData = client.ReadApplicationData(itemId, applicationId);

if (appData != null)
    Byte[] data = appData.Data;
    appDataValue = Encoding.Unicode.GetString(data);


As you can see, to get the data you call .ReadApplicationData, specifying the appropriate ids. If the AppData object exists, you get the data as a byte array and it to an encoded string. This string can be the value itself, as it was in my case, or it could be JSON or XML representing a more complex set of information. For the latter you would need to process the value further to extra the information you require.

Setting AppData

CoreService2010Client client = ServiceClient.GetCoreServiceClient();
Byte[] byteData = Encoding.Unicode.GetBytes(valueToStore);
ApplicationData appData = new ApplicationData
    ApplicationId = applicationId,
    Data = byteData,
    TypeId = url.GetType().ToString()
client.SaveApplicationData(itemId, new[] { appData });

Setting AppData is almost the exact reversal of the process to get it.  You create an AppData object, convert the string to store to an encoded byte array, set the application id, and then save against the relevant item id. The big difference here is that you can save multiple AppData objects in one go as they’re passed to .SaveApplicationData as an array. I’m not sure how often you’d actually do this, but it’s nice to know that it’s an option.

Deleting AppData

Of course, if you can get or set AppData it’s also handy to be able to delete it. I can imagine that you might tie this in to a delete event in the Event System to make sure that you don’t end up with lots of orphaned application data in your database.

CoreService2010Client client = ServiceClient.GetCoreServiceClient();
client.DeleteApplicationData(itemId, applicationId);

Nice and simple here – call .DeleteApplicationData for the appropriate item id and application id and it’s job done.

Additional Info

If you don’t want to tie your application data storage to a specific item you just need to use null where the samples show itemId. It’s important to remember that, when using AppData, you’re storing information in the Tridion database. Overuse has the potential to bloat the db, so make careful consideration when taking this route. AppData is also not versioned, so if you overwrite a value you will lose the previous value. It may be possible to specify a version number in the item id (if you’re using it) – something like tcm:xx-xx-xx-v1, where v1 represents version 1 of the relevant item (but I’m sure you knew that already).