Adding a new field to dialog windows in General Link field for Sitecore 6.6

The customer of my current project asked to use some Webtrends™ JS function on the general links on his Sitecore 6.6. Also, he want handle the data inside the "on-click" parameter to each <A> html tag generated by those general link fields. We don't have SPEAK here, but it's not impossible. In fact this is pretty easy. So, let's add an "Click" field there!

Step 1 - Adding some extra files to our VS project

The general link field has several different dialog windows. We are going to change all them on this exercise.
Include on your Visual Studio project the following folders:
  • sitecore\shell\Applications\Dialogs\AnchorLink
  • sitecore\shell\Applications\Dialogs\ExternalLink
  • sitecore\shell\Applications\Dialogs\GeneralLink
  • sitecore\shell\Applications\Dialogs\InternalLink
  • sitecore\shell\Applications\Dialogs\JavascriptLink
  • sitecore\shell\Applications\Dialogs\MailLink
  • sitecore\shell\Applications\Dialogs\MediaLink

Step 2 - Editing the Anchor dialog

Edit the file AnchorLink/AnchorLink.xml. After that, use Reflection on the VS to get the content of the class Sitecore.Shell.Applications.Dialogs.AnchorLink.AnchorLinkForm. With that content let's create a new local class. You can store this new class on any place in your project. After that, replace the reference on the line #9 with the reference of your new class.

In this new class, let's add a couple of new lines. Add the reference to the new field "Click" at the beginning. You can do that with a line similar to this one:
protected Edit Click;
Then, add this line of code at the end of the method OnLoad:
this.Click.Value = this.LinkAttributes["click"];
Finally, add this line on the method OnOK:
LinkForm.SetAttribute(packet, "click", (Control)this.Click);
At this moment the code is going to compile, but the it will not work on Sitecore. It's because we have to overwrite the LinkForm class and we have to add there the new field too. To do that you have to use Reflection again and clone the class locally.
On your version of LinkForm make the following changes.
Add the following code line at the end of the method ParseLink:
this.linkAttributes["click"] = XmlUtil.GetAttribute("click", node);
On the class LinkAttributeNames, add the following property:
public const string Click = "click";

Step 3 - Test our first change!

Let's test our change! Add a new General Link field to some data template. Create an item based on this data template and add some content to our General Link field. You will see that the new field is there. Try to add content to our new field, save it and try to change the value before.

The raw value of the field will look like this:
<link text="Description" linktype="anchor" url="example1" anchor="example1" click="JS code here" />
NOTE: I'm figuring out if there is a bug here on Sitecore. If you add some content with these characters "(" and ")", all is going to fail. Doesn't matter which field you used to add these characters.

Step 4 - Repeat the same changes on all the other dialogs

Repeat the same process on the following dialogs:
  • sitecore\shell\Applications\Dialogs\ExternalLink
  • sitecore\shell\Applications\Dialogs\InternalLink
  • sitecore\shell\Applications\Dialogs\JavascriptLink
  • sitecore\shell\Applications\Dialogs\MailLink
  • sitecore\shell\Applications\Dialogs\MediaLink
In all them, add a new field with the same name (Click). You don't need to change the class LinkForm again.

Clues: while we do all this conversion, we're going to see several code errors related to the namespaces of some classes. To resolve them, you have to remove the namespace of those classes. In this way you are going to take the local ones. Don't use the replace feature of VS. Do this manually.
Example of namespaces that you should remove:
  • Sitecore.Shell.Applications.Dialogs
  • Sitecore.Shell.Applications.Dialogs.GeneralLink

Step 5 - Modify the GeneralLink dialog

This dialog is very special, because it's a dialog that represents all the other dialogs together and it's used on the Page Editor mode.
The XML file is quite large, but you have to add the new field just at the end of the right column area. This new field will look similar to this:
<Literal Text="Click:" GridPanel.NoWrap="true"/>
<Edit Width="100%" Class="scQuirksBoxModel" GridPanel.Row.ID="ClickRow" ID="Click"/>
After this, you have to clone locally the class GeneralLinkForm. Use the same process of the previous ones with Reflection. Remember change the reference on the XML file.
At the beginning of the GeneralLinkForm class, add the property with the new field:
protected Edit Click;
Another more step, add at the end of the method SetCommonAttributes the following line of code:
LinkForm.SetAttribute(packet, "click", (Sitecore.Web.UI.HtmlControls.Control)this.Click);
Finally, you have to add this line of code on the method InitControls:
this.Click.Value = this.LinkAttributes["click"];
Clues: while you are cloning this file, you will see an weird error. A reference to this method looks not work. To resolve this, just replace the this "Sitecore.StringExtensions.FormatWith" by this "Sitecore.StringExtensions.StringExtensions.FormatWith"

Final Step - Modify the GetLinkFieldValue pipeline

This is the last step. We have to add a new pipeline to take the attribute click from the raw field value and put that value on the onclick attribute on the final <A> html tag.
This is the pipeline to create the onclick attribute
This the configuration file for the pipeline
Note: I know... the last part of the pipeline is not too fancy. There are several way to handle the XML data the do the separation. Anyway, I don't want to code many lines to do that very simple operation. I'm open to suggestions.

Hope this post save time on your work. Please, don't leave this blog without a comment :)