SaaS CMS has officially launched! Learn more now.

Old tiny mce version, image caption issue

Vote:
 

Hi!

EPiServer is currently using TinyMCE v3. It isn't possible to add caption to images, but this is possible in TinyMCE v4. Does anyone know if TinyMCE will be upgraded soon, or do you have a good workaround?

#175712
Feb 28, 2017 9:05
Vote:
 

Hi,

There was a survey here on World a couple of moths ago about the rich text editor. There is plans of upgrading or replacing the current one. But no information about when yet.

Editors can put the caption text in the alt text field for the image and then you can create your own display template for XhtmlString and find this caption text and render it.

Create Views\Shared\DisplayTemplates\XhtmlString.cshtml, put this code inside the view:

@model XhtmlString

@Html.XhtmlStringFiltered(Model)

Create this extension method:

public static IHtmlString XhtmlStringFiltered(this HtmlHelper htmlHelper, XhtmlString input)
        {
            if (input == null || input.IsEmpty)
            {
                return MvcHtmlString.Empty;
            }

            var contextMode = htmlHelper.ViewContext.RequestContext.GetContextMode();

            if (contextMode == ContextMode.Default || contextMode == ContextMode.Preview)
            {
                var rendered = htmlHelper.XhtmlString(input);
                var html = rendered.ToHtmlString();

                // We could have a complete filter pipeline here in
                // the future.
                var filter = new ImageCaptionFilter();
                var filtered = filter.Filter(html);

                return MvcHtmlString.Create(filtered);
            }
            else
            {
                return htmlHelper.XhtmlString(input);
            }
        }

Create this filter:

public class ImageCaptionFilter
    {
        /// <summary>
        ///     See http://stackoverflow.com/questions/317053/regular-expression-for-extracting-tag-attributes for reference.
        ///     This will not only find attributes, but also the caption inside the alt attribute since " is optional in the expression.
        /// </summary>
        private const string AttributesRegex = "(\\S+)=[\"']?((?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?";

        private const string ImageRegex = "<img.*caption=.*\\/>";

        public ImageCaptionFilter()
        {
            this.TranslatedCssClasses = new Dictionary<string, string>
            {
                { "image--left", "media-container--left" },
                { "image--right", "media-container--right" },
                { "image-fullwidth", "media-container--fullwidth" }
            };
        }

        public Dictionary<string, string> TranslatedCssClasses { get; private set; }

        public string Filter(string input)
        {
            foreach (Match m in Regex.Matches(input, ImageCaptionFilter.ImageRegex, RegexOptions.IgnoreCase))
            {
                var attributes = Regex.Matches(m.Value, ImageCaptionFilter.AttributesRegex, RegexOptions.IgnoreCase);

                var figure = new TagBuilder("figure");
                figure.AddCssClass("media-container");

                var img = new TagBuilder("img");
                img.AddCssClass("media-container__source");

                var figcaption = new TagBuilder("figcaption");
                figcaption.AddCssClass("media-container__caption");

                foreach (Match attribute in attributes)
                {
                    var name = attribute.Groups[1].Value;
                    var value = attribute.Groups[2].Value;

                    if (name.Equals("class", StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (var cssClass in value.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
                        {
                            if (this.TranslatedCssClasses.ContainsKey(cssClass))
                            {
                                figure.AddCssClass(this.TranslatedCssClasses[cssClass]);
                            }
                            else
                            {
                                img.AddCssClass(cssClass);
                            }
                        }
                    }
                    else if (name.Equals("caption", StringComparison.OrdinalIgnoreCase))
                    {
                        figcaption.SetInnerText(value);
                    }
                    else if (name.Equals("alt=\"caption", StringComparison.OrdinalIgnoreCase))
                    {
                        // attribute name can be "alt=\"caption" if there is no alt text, just a caption...
                        figcaption.SetInnerText(value);

                        // ... then we need to add an empty alt attribute
                        img.Attributes.Add("alt", string.Empty);
                    }
                    else
                    {
                        img.MergeAttribute(name, value);
                    }
                }

                figure.InnerHtml += img.ToString(TagRenderMode.SelfClosing);
                figure.InnerHtml += figcaption.ToString(TagRenderMode.Normal);

                input = input.Replace(m.Value, figure.ToString(TagRenderMode.Normal));
            }

            return input;
        }
    }
#175721
Edited, Feb 28, 2017 13:03
Vote:
 

This worked, thank you so much! :)

#175725
Feb 28, 2017 14:48
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.