Layer One Media, Senior Sitecore Architect — May 30, 2016
We had what I thought was an interesting issue recently on a client project. I thought it was a great story and a solution worth sharing. A mobile-friendly responsive design was the main goal of this particular project. In this case, the customer was using a collection of General Link fields to control the various navigational features on their Sitecore site. However, during testing on iOS, it was discovered the telephone links that had been created were causing the markup to break.
Upon investigation, the issue was quick and easy to identify. Sitecore was treating the General Link fields that were being used for the Telephone Link Protocol as it does any other link — adding the http:// protocol to the front automatically. One developer even got creative and removed the http:// manually from the field and hit Save. Yes, that did temporarily allow just tel:########### to be stored as desired in the Content Editor. However, Sitecore’s renderField pipeline method GetLinkFieldValue would simply inject it again.
Next, this creative & solution-oriented developer started to utilize JavaScript to clean it up. Thankfully, I was able to get involved first and prevented this from causing extra technical debt. Among my many mantras, such as “Get It Right The First Time”, I also firmly believe in “Fix the issue at the Source” or at least as close to the source as feasible. This developer had already searched Google and found numerous excellent articles, notably the one Akshay wrote. If you want to dive deeper into creating custom Field Types, Renderers, etc., check that out. However, this developer was relatively new to Sitecore and was justifiably overwhelmed at how complex it appeared.
While creating a custom field type is the ideal long-term approach, I also believe in making the least amount of changes to achieve a “Minimum Viable Product.” So I proceeded to show how to resolve this with just one real line of code injected into the appropriate Sitecore pipeline — the “quick fix” approach, which is the simplest and most efficient.
In order to ensure that the tel: protocol remains intact when using a Sitecore General Link or Link field, we create our own custom class following the Sitecore Pipeline pattern of implementing a public virtual void Process(RenderFieldArgs args). Here is the full code:
namespace Sitecore.SharedSource.TelLinkPipeline
{
public class GetTelephoneLinkFieldValue
{
public virtual void Process(RenderFieldArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (Context.Site.DisplayMode == Sites.DisplayMode.Edit) return;
if (args == null || args.FieldTypeKey != "general link") return;
if (string.IsNullOrEmpty(args.Result.FirstPart) &&
string.IsNullOrEmpty(args.Result.LastPart)) return;
args.Result.FirstPart = args.Result.FirstPart.Replace("http://tel:", "tel:");
}
}
}The one line that actually does the work is:
args.Result.FirstPart = args.Result.FirstPart.Replace("http://tel:", "tel:");This class gets inserted into the pipelines using a config patch file:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<renderField>
<processor
type="Sitecore.SharedSource.TelLinkPipeline.GetTelephoneLinkFieldValue, Sitecore.SharedSource.TelLinkPipeline"
patch:after="processor[@type='Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel']" />
</renderField>
</pipelines>
</sitecore>
</configuration>The key thing to notice is that our new pipeline processor gets patched after the out-of-the-box GetLinkFieldValue that injects the http:// prefix.
Finally, I would like to draw attention to the microformat open standards for hCard and h-Card (v2). The business benefit of using these microformats is that they provide a much wider array of compatibility across browsers and devices. The newer h-Card standard dives into deeper requirements for various cultures, time zones, phone number formats, etc. Additionally, microformats are universally understood by search engines.
To implement them, use the Style Class field and populate it with tel for hCard and p-tel for h-Card, and wrap the entire contact block with the appropriate container class:
hCard:
<div class="vcard">
<p class="tel">+1.818.555.1212</p>
</div>h-Card:
<div class="h-card">
<p class="p-name">Joe Bloggs</p>
<p class="p-tel">+1.818.555.1212</p>
</div>Whenever you are ready, you can implement the more advanced features of the microformat — cultures, time zones, phone number formats — using the newer h-Card microformat and the value class pattern.
