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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8" ?> | |
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense"> | |
<AnchorLink> | |
<FormDialog Icon="People/32x32/target.png" | |
Header="Insert a link to an anchor" | |
Text="Please specify the name of the anchor, e.g. #header1, and any additional properties. When done, click the OK button." | |
OKButton="OK"> | |
<CodeBeside Type="Sitecore.Shell.Applications.Dialogs.AnchorLink.AnchorLinkForm,Sitecore.Client"/> | |
<GridPanel CellPadding="2" Columns="2" Width="100%"> | |
<Label For="Text" GridPanel.NoWrap="true"><Literal Text="Link description:"/></Label> | |
<Edit ID="Text" Width="100%" GridPanel.Width="100%"/> | |
<Label For="Url" GridPanel.NoWrap="true"><Literal Text="Anchor:"/></Label> | |
<Edit ID="Url" Width="100%" /> | |
<Label For="Class" GridPanel.NoWrap="true"><Literal Text="Style class:" /></Label> | |
<Edit ID="Class" Width="100%" /> | |
<Label for="Title" GridPanel.NoWrap="true"><Literal Text="Alternate text:"/></Label> | |
<Edit ID="Title" Width="100%" /> | |
<Label for="Click" GridPanel.NoWrap="true"><Literal Text="Click:"/></Label> | |
<Edit ID="Click" Width="100%" /> | |
</GridPanel> | |
</FormDialog> | |
</AnchorLink> | |
</control> |
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
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Xml; | |
using Sitecore; | |
using Sitecore.Diagnostics; | |
using Sitecore.Web; | |
using Sitecore.Pipelines.RenderField; | |
namespace Website.sitecore | |
{ | |
public class RenderOnClickAttrProcessor | |
{ | |
public void Process([NotNull] RenderFieldArgs args) | |
{ | |
Assert.ArgumentNotNull((object)args, "args"); | |
if (args.FieldTypeKey != "general link") return; | |
var attr = HtmlUtil.ParseTagAttributes(args.FieldValue); | |
if (attr["click"] == null) return; | |
var html = new XmlDocument(); | |
html.LoadXml(args.Result.FirstPart + args.Result.LastPart); | |
var atag = html.SelectSingleNode("/a"); | |
Sitecore.Xml.XmlUtil.AddAttribute("onclick", attr["click"], atag); | |
args.Result.FirstPart = atag.OuterXml.Replace(string.Format("</{0}>", atag.Name), ""); | |
args.Result.LastPart = string.Format("</{0}>", atag.Name); | |
} | |
} | |
} |
This the configuration file for the pipeline
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> | |
<sitecore> | |
<pipelines> | |
<renderField> | |
<processor type="Website.sitecore.RenderOnClickAttrProcessor,Website" patch:before="processor[@type='Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel']" /> | |
</renderField> | |
</pipelines> | |
</sitecore> | |
</configuration> |
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 :)
No comments:
Post a Comment