Posted 02/21/2015 by Akshay Sura
I wanted to extend the General Link field to add a new Menu Item to create a Telephone link. A Telephone link is primarily used to render a telephone number so that it helps the mobile user to dial out the phone number.
e.g.: <a title=”Call Customer Service at 1-222-333-4455″ class=”phone” href=”tel:12223334455″>Call Customer Service</a>
In order to achieve this functionality we need to do the following:
1. Go to the Core database, and add a menu item under /sitecore/system/Field types/Link Types/General Link/Menu. Name it Telephone.
2. Set the Display Name field of this newly created Menu Item to Insert Telephone Link
3. Set the Message field to contentlink:telephonelink(id=$Target)
4. Create a class called TelephoneLink to handle the link message. The above entry in the Message Field should match the switch case statement.
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Text; using System.Threading.Tasks; using Sitecore; using Sitecore.Data; using Sitecore.Diagnostics; using Sitecore.Shell.Applications.ContentEditor; using Sitecore.Text; namespace YOURNAMESPACE { public class TelephoneLink:Link { // Handles the message. public override void HandleMessage(Sitecore.Web.UI.Sheer.Message message) { Assert.ArgumentNotNull(message, "message"); base.HandleMessage(message); //base handles other message requests string name = message.Name; string str = name; if (name != null) { switch (str) { case "contentlink:telephonelink": { var url = new UrlString(UIUtil.GetUri("control:TelephoneLinkForm")); //find control and open url base.Insert(url.ToString()); return; } default: { return; } } } if (Value.Length > 0) { SetModified(); } Value = String.Empty; } } }
5. Click on General Link and modify the Control property to content:TelephoneLink
6. Create a config patch file to register the control source.
<controlSources> <source mode="on" namespace="YOURNAMESPACE" assembly="YOURASSEMBLY" prefix="content"/> </controlSources>
7. Create a new folder called TelephoneLink under /sitecore/shell/Applications/Dialogs
8. Create an xml file called TelephoneLink.xml
<?xml version="1.0" encoding="utf-8" ?> <control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense"> <TelephoneLinkForm> <FormDialog Icon="Network/32x32/mail.png" Header="Insert a telephone link" Text="Please specify the telephone number address and any additional properties. When done, click OK." OKButton="OK"> <CodeBeside Type="YOURNAMESPACE.TelephoneLinkForm,YOURASSEMBLY"/> <a id="telephone"></a> <GridPanel Class="scFormTable" 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="Telephone Number:"/></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%" /> </GridPanel> </FormDialog> </TelephoneLinkForm> </control>
9. Create a class called TelephoneLinkForm to act as the code behind for TelephoneLink.xml
using System; using System.Collections.Specialized; using System.Text.RegularExpressions; using Sitecore; using Sitecore.Diagnostics; using Sitecore.Shell.Applications.Dialogs; using Sitecore.Web.UI.HtmlControls; using Sitecore.Web.UI.Pages; using Sitecore.Web.UI.Sheer; using Sitecore.Xml; namespace YOURNAMESPACE { public class TelephoneLinkForm : LinkForm { protected Edit Class; protected Edit Text; protected Edit Title; protected Edit Url; public TelephoneLinkForm() { } private string GetTelephone() { string value = this.Url.Value; string str = value; if (str.Length > 0) { if (str.IndexOf(":", StringComparison.InvariantCulture) >= 0) { str = str.Substring(str.IndexOf(":", StringComparison.InvariantCulture) + 1); } if (!(new Regex(@"^(1?(-?d{3})-?)?(d{3})(-?d{4})$", RegexOptions.IgnoreCase)).IsMatch(str)) { return "__Canceled"; } } if (value.Length > 0 && value.IndexOf(":", StringComparison.InvariantCulture) < 0) { value = string.Concat("tel:", value); } return value; } protected override void OnLoad(EventArgs e) { Assert.ArgumentNotNull(e, "e"); base.OnLoad(e); if (Context.ClientPage.IsEvent) { return; } string item = base.LinkAttributes["url"]; if (base.LinkType != "tel") { item = string.Empty; } this.Text.Value = base.LinkAttributes["text"]; this.Url.Value = item.Replace("tel:", ""); this.Class.Value = base.LinkAttributes["class"]; this.Title.Value = base.LinkAttributes["title"]; } protected override void OnOK(object sender, EventArgs args) { Assert.ArgumentNotNull(sender, "sender"); Assert.ArgumentNotNull(args, "args"); string tel = this.GetTelephone(); if (tel == "__Canceled") { SheerResponse.Alert("The telephone number is invalid.", new string[0]); return; } Packet packet = new Packet("link", new string[0]); LinkForm.SetAttribute(packet, "text", this.Text); LinkForm.SetAttribute(packet, "linktype", "tel"); LinkForm.SetAttribute(packet, "url", tel); LinkForm.SetAttribute(packet, "anchor", string.Empty); LinkForm.SetAttribute(packet, "title", this.Title); LinkForm.SetAttribute(packet, "class", this.Class); SheerResponse.SetDialogValue(packet.OuterXml); base.OnOK(sender, args); } } }
10. We need to handle the Rendering of the Telephone Link, so create processor RenderPhoneLink
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.Pipelines.RenderField; using Sitecore.Xml.Xsl; namespace YOURNAMESPACE { public class RenderPhoneLink { public void Process(Sitecore.Pipelines.RenderField.RenderFieldArgs args) { if (args != null && (args.FieldTypeKey == "link" || args.FieldTypeKey == "general link")) { Sitecore.Data.Fields.LinkField linkField = args.Item.Fields[args.FieldName]; if (!string.IsNullOrEmpty(linkField.Url) && linkField.LinkType == "tel") { args.Parameters["href"] = linkField.Url; } } } } }
11. Add to config patch file to run the RenderPhoneLink processor right before the GetLinkFieldValue processor
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/"> <sitecore> <controlSources> <source mode="on" namespace="YOURNAMESPACE" assembly="YOURASSEMBLY" prefix="content"/> </controlSources> <pipelines> <renderField> <processor patch:before="*[@type='Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel']" type="YOURNAMESPACE.RenderPhoneLink, YOURASSEMBLY" /> </renderField> </pipelines> </sitecore> </configuration>
Now all you have to do is to keep using the sc fields such as <sc:Link and the field value will be rendered properly.
If you have any questions or comments please get in touch with me. Thank you.