A relatively unknown feature of the Tridion CMS product is the GUI extensibility framework.
This is actually a fantastic feature which allows us to create and supplement the user interface with just about any type of addition we can think of.
It is pretty unknown because of the lack of documentation but with a little bit of investigation work it is possible to find all sorts of treasures we can use to extend the current GUI.
Here’s one example that is already available on the SDLTridionWorld website’s Community eXtensions section: “Republish from publish queue”, this nifty extension gives users the ability to republish items directly from the queue instead of the normal way of locating the item within the folder or structuregroup hierarchy.
The extension framework is quite robust (not without limitations of course) and allows us to add toolbar items, context menu options, tree nodes or simply run scripts that can do just about anything.
In this article I’m focusing on the latter, adding a scripted extension to do different tasks.
If you’ve done any kind of javascript development you know how difficult and complex it can get, that’s where jQuery comes in, jQuery being a javascript library created to ease the development of client side code.
jQuery’s CSS selectors and methods for DOM manipulation are exactly the tools to help us create Tridion GUI extensions quickly and with relative ease.
The way the extension framework is built allows us to create a jQuery extension that can be reused by other extensions.
Creating the jQuery GUI extension
Every extension is made up of (typically) at least 3 files:
- Extension.xml
- 1033.xml
- Script.js
The first being the extension definition, containing the ID of the extension and references to the script files that will be used.
The 1033.xml file is the language resource file, it is needed for installing the extension but there’s no requirement to fill it with any labels.
The Script.js contains our extension’s code, unlike the other two files, it can have any file name.
So, to create our jQuery extension we will need the following:
Extension.XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?>
<Extension ID="Jquery" xmlns="http://www.tridion.com/ContentManager/5.2/WebGUI/Extensions">
<OnOpenItem>
<Script SRC="jquery.js" Language="JavaScript">
<IncludeFor ItemType="1"/>
<IncludeFor ItemType="2"/>
<IncludeFor ItemType="4"/>
<IncludeFor ItemType="8"/>
<IncludeFor ItemType="16"/>
<IncludeFor ItemType="32"/>
<IncludeFor ItemType="64"/>
<IncludeFor ItemType="128"/>
<IncludeFor ItemType="512"/>
</Script>
</OnOpenItem>
<OnDefault>
<Script Language="JavaScript" SRC="jquery.js" />
</OnDefault>
</Extension>
|
This is the structure of the file we need to adhere to, if we don’t, the installation will fail.
The important things to notice are, the ‘ID’ attribute, this can have almost any value but notice that this will define the name of the extension’s folder that will be created.
Then we define when the extension is loaded, there are a couple of options here.
The <OnOpenItem> will load the extension when the item window opens, for the items we specify using the <IncludeFor> and then setting the ‘ItemType’ to the desired type (16 being Component).
Or the <OnDefault> which will make the extension load for the main GUI screen.
It’s important to notice that even if you have the ‘OnDefault’ element in the extension file, you still need to also use the ‘IncludeFor’ instruction for each item type (under ‘OnOpenItem’) you wish to write an extension for.
Next, we need the jquery library file itself and we point the extension definition file to it by using the ‘SRC’ attribute.
Simply download the latest version from jQuery.com and copy it to the extension folder(for simplicity i’ve renamed it to jquery.js).
If you’re using Outbound Email 2.0 (Tridion 2009) it is very important to know that the OE extension defines its own ‘$’ shortcut which is the one jQuery uses. So to avoid the conflict I’ve added the following line to the bottom of the jquery.js file:
window.$j = jQuery.noConflict(true);
What this little line does is it assigns the jQuery shortcut to ‘$j’ to avoid the conflict with Outbound Email.
Once we have these 3 files ready, we need to zip them up and install the extension.
Tridion comes with a utility for installing extensions, called: “TCMExtensionInstaller” and its located under the BIN folder of the Tridion installation(i.e.: c:\tridion\bin).
To install simply run:
<tridion_home>\bin\TCMExtensionInstaller.exe –add “c:\temp\jquery.zip”
This is what you should see:
If you go now and check this folder: <tridion_home>\web\extensions you should see that a new jQuery folder has been created:
From now on we can start writing extensions using jQuery.
Make sure to clear IE’s cache so the extension is actually loaded before you attempt to use it.
Extension Example
There are many things extensions can do that the GUI itself doesn’t. Let’s take a simple example, notifying the user about unwanted characters being entered into the title of a component.
Tridion allows us to configure the allowed characters of a component title by changing a certain XSLT file on the server so when the user tries to save they will be prompted with an error, but what about letting the user know they are entering invalid characters while they type? Well, this will require an extension.
Here’s a way for how this extension could look like:
Before an invalid character is inserted:
Once a character defined as invalid is entered:
And here’s the extension’s code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
var _example_unwantedChars = ["^", "*", "$"]; //unwanted characters to look for
var _example_invalidColor = "#FFA07A"; //background color when invalid
$j(document).ready(function ()
{
try
{
example_cLog("starting example extension code");
var tabContainer = $j("#GUITabContainer");
var compTab = $j("#Component", tabContainer);
if (compTab.length > 0)
{
compTab[0].onContentChanged = function () //need to act when tab is loaded
{
OnTransform(); //mimic the way the GUI handles the load of the first tab
var titleField = $j("#Title", compTab); //get the title field
titleField.keyup(function (e) //check for unwanted chars on every key entered
{
var foundUnwanted = false;
var title = titleField.val();
$j(_example_unwantedChars).each(function (i, elm)
{
if (title.indexOf(elm) > -1) foundUnwanted = true;
});
if (foundUnwanted)
{
titleField.css("background-color", _example_invalidColor); //color the field with warning color
titleField.attr("title", "Title contains invalid characters!"); //explain what the problem is to the user
}
else
{
titleField.css("background-color", "");
titleField.attr("title", "");
}
});
}
}
}
catch (error)
{
example_cLog("error!"); //prevent the extension from throwing unexpected errors, log to console instead
}
});
function example_cLog(s)
{
if (this.console && typeof console.log != "undefined")
{
console.log(s);
}
}
|
First we use the jQuery ready method to run our code once the page has loaded, however because of the way the Tridion item page is built, not all elements are loaded onto the screen at that point, that’s why we need to use the custom ‘onContentChanged’ event of the Component tab.
Once we’re in the content changed event handler we need to call ‘OnTransform()’ which is a method that is called internally by the GUI but since we “hijacked” the event handling we need to call it ourselves.
From there its just standard client side coding, we find the title input field (‘#Title’) and attach a handler to the ‘onkeyup’ event. For each key press we check the title for the presence of the invalid characters defined in the beginning of the script (^, *, $).
If at least one of the characters is found, we color the title field with a warning red to alert the user to their mistake.
This is a very simple example of what we can do with GUI extensions but it emphasizes the liberty we have in modifying(without hacking) and extending the interface to make it fit our implementation’s needs, especially in combination with making our users’ experience with the solution a better one.
A couple of important notes about writing extensions in general, especially for those who intend to write several of those:
- Make sure you wrap your code with try, catch blocks so your extensions don’t interfere with the user if something goes wrong.
- Give unique names to the methods you write, for example, prefix them with the name of the extension, this will prevent conflicts with other extensions or with the native GUI methods.
- Because of the extension integrated nature, it might be difficult do discern between an error coming from the GUI or from the extension. At that point, before you turn to customer support, make sure to remove your extensions (TCMExtensionInstaller.exe -remove <extension id>) and test again.
To download the code for this article, follow these links:
Yoav, nice article. Is this extension framework also supported in SDL Tridion 2011?
Hi Albert,
As far as i know, unfortunately, the extensions written prior to Tridion 2011 will not work on the new GUI. Specifically, extensions that change or manipulate the DOM as the example in this article.
Hopefully, I will have some time soon to play with the new GUI and ill see how and if extensions can be reused.
Thanks,
Yoav.
Nice article and good addition to the Content Manager Explorer.
Yoav, great stuff. The example you gave makes food for thought as to other scenarios that it could become useful. 🙂
Thank you for this helpful article! 🙂
Great stuff Yoav! thanks for the great example. I’m sure lots of people will find this helpful and might start to create their own.
Very nice! Functionally simple and useful, and your article shows in detail how you’ve solved the technical challenges.
why do all these comments look like spam, yet I know they all are from real people that I know 😀
Good point, considering that about half of the comments are yours 😉
Keep up the good stuff yoav,
@julian well i guess only spammers post positive news in general ;p
Lovely plugin !