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.