Handling Images on a Responsive Sitecore Implementation - Part 1

Tuesday, April 22, 2014 @ 05:26

by Eric Stafford, Staff Developer

Something odd happens when an image is added in the rich text editor. Initially, when the image is inserted the RTE places the width and height properties correctly. However, when we change the properties such as adding a class, the dimensions are now inline styled. Inline styling dimensions isn’t responsive friendly.

Clients should not be expected to edit the HTML. So how do we resolve this issue?

When the client is making changes in the RTE we can fire off code to alter the HTML when the RTE is closed. We can accomplish this by utilizing the saveRichTextContent pipeline.

For content items that haven’t been modified after the new pipeline has been added, we can create a new renderField pipeline.

First we create the code to cycle through the images in the HTML and modify the inline styles.

using System;
using System.Linq;
using HtmlAgilityPack;
 
namespace Company.Library.Pipelines.RichTextContent
{
    public static class RichText
    {
        public static string Content(string content)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(content);
 
            if (!doc.DocumentNode.InnerHtml.Contains("img"))
                return content;
 
            foreach (var img in doc.DocumentNode.Descendants("img"))
            {
                var imgAttr = img.Attributes["style"];
 
                if (imgAttr == null)
                    continue;
 
                var alteredStyles = string.Empty;
                var inlineStyleList = imgAttr.Value.Split(';');
 
                foreach (var style in inlineStyleList)
                {
                    var attrList = style.Split(':');
 
                    if (!attrList.Count().Equals(2))
                        continue;
 
                    var property = attrList[0].Trim();
                    var val = attrList[1].Trim();
 
                    if (property.Equals("width", StringComparison.InvariantCultureIgnoreCase) ||
                        property.Equals("height", StringComparison.InvariantCultureIgnoreCase))
                        img.Attributes.Add(property, val);
                    else
                        alteredStyles += string.Format("{0}:{1}; ", property, val);
                }
 
                imgAttr.Remove();
 
                if (!string.IsNullOrWhiteSpace(alteredStyles))
                    img.Attributes.Add("style", alteredStyles);
            }
 
            return doc.DocumentNode.OuterHtml;
        }
    }
}
// Before
<img style="width: 200px; height: 200px; border: solid 3px #000;" alt="" src="/someimage.png">
 
// After
<img style="border: solid 3px #000;" alt="" src="/someimage.png" width="200px" height="200px">


renderField Pipeline



using System;
using System.Web.UI;
using Sitecore;
using Sitecore.Configuration;
using Sitecore.Pipelines.RenderField;
using Sitecore.Web;
 
namespace Company.Library.Pipelines.RichTextContent
{
    public class Render
    {
        public void Process(RenderFieldArgs args)
        {
            if (!args.FieldTypeKey.Equals("rich text", StringComparison.InvariantCultureIgnoreCase) ||
                string.IsNullOrWhiteSpace(args.FieldValue) || Context.PageMode.IsPageEditorEditing ||
                !Settings.HtmlEditor.SupportWebControls)
                return;
 
            Transform(args);
        }
 
        protected void Transform(RenderFieldArgs args)
        {
            var page = new Page();
            page.AppRelativeVirtualPath = "/";
 
            args.Result.FirstPart = RichText.Content(args.Result.FirstPart);
            var cntr = page.ParseControl(args.Result.FirstPart);
 
            if (cntr == null)
                return;
 
            HtmlUtil.RenderControl(cntr);
        }
    }
}


saveRichTextContent Pipeline

using Sitecore.Shell.Controls.RichTextEditor.Pipelines.SaveRichTextContent;
 
namespace Fleetmatics.Library.Pipelines.RichTextContent
{
    public class Save
    {
        public void Process(SaveRichTextContentArgs args)
        {
            args.Content = RichText.Content(args.Content);
        }
    }
}


Config Settings

Create a custom config file in the App_Config/Include folder if you haven’t done so and add the following:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <renderfield>
        <processor type="Company.Library.Pipelines.RichTextContent.Render, Company.Library" patch:after="processor[@type='Sitecore.Pipelines.RenderField.GetDocxFieldValue, Sitecore.Kernel']">
      </processor></renderfield>
      <saverichtextcontent>
        <processor type="Company.Library.Pipelines.RichTextContent.Save, Company.Library">
      </processor></saverichtextcontent>
    </pipelines>
  </sitecore>
</configuration>