Allow Javascript and iFrames in TinyMCE editor for EPiServer CMS 11 & 10

As I explained in this blog post, it is easy to add and remove features to a TinyMCE editor in Episerver. However, when you want to add things that are outside of the usual features the editor allows, you must dig dipper in the documentation of TinyMce. For instance, when you want to add an iframe or some JS plugins to a page using the TinyMCE editor. This post, will guide you through the configuration required to allow both.

The first thing we are going to do is to create a page model with a XhtmlString property.

uusing EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using EpiExamples.Attributes;

namespace EpiExamples.Models.Pages
{
    /// <summary>
    /// Used for the pages mainly consisting of manually created content such as text, images, and blocks
    /// </summary>
    [SiteContentType(GUID = "9CCC8A41-5C8C-4BE0-8E73-520FF3DE8267")]
    public class StandardPage : PageData
    {
        [Display(
            GroupName = SystemTabNames.Content,
            Order = 310)]
        [CultureSpecific]
        public virtual XhtmlString MainBody { get; set; }

        [Display(
            GroupName = SystemTabNames.Content,
            Order = 320)]
        public virtual ContentArea MainContentArea { get; set; }
    }
}

After that we are going to create an initialization module for the TinyMCE configurations or use the one you already have in your project. I am using as base the default implementation of the class ExtendedTinyMceInitialization.cs from the Alloy template. Please pay special attention to the comments in the code.

using EpiExamples.Models.Pages;
using EPiServer.Cms.TinyMce.Core;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;

namespace EpiExamples.Business.Initialization
{
    [ModuleDependency(typeof(TinyMceInitialization))]
    public class ExtendedTinyMceInitialization : IConfigurableModule
    {
        public void Initialize(InitializationEngine context)
        {
            // Do nothing
        }

        public void Uninitialize(InitializationEngine context)
        {
            // Do nothing
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure<TinyMceConfiguration>(config =>
            {
                // Add epi support to the default settings.
                config.Default().AddEpiserverSupport();
                
                // Add js and iframe capabilities to default settings.
                var jsConfigurationSettings = config.Default().Clone()
                    .AddSetting("valid_children", "+body[style],+div[span],+a[div|i]") // Allow body with style property, div with span inner elements and anchor with div or i inner elements
                    .AddSetting("allow_html_in_named_anchor", "true") // If allows or not html in a named anchor
                    .AddSetting("allow_script_urls", "true") // If it allows scripts urls, this is needed to enable js content
                    .AddSetting("extended_valid_elements", // List of valid elements in the editor, this includes scritps (for js), iframe, and several others. What you send inside the [] are the allowed inner elements for that tag 
                        "script[language|type|src],iframe[src|alt|title|width|height|align|name|style],picture,source[srcset|media],a[id|href|target|onclick|class],span[*],div[*]")
                    .AddPlugin(
                        "epi-link epi-image-editor epi-dnd-processor epi-personalized-content print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor " +
                        " imagetools colorpicker textpattern help code") // A lot of epi features, it is not related to enable js or iframes
                    .Toolbar(
                        "formatselect styleselect | bold italic underline strikethrough subscript superscript | epi-personalized-content | removeformat | fullscreen preview | code"
                        , "") // Three parameter for first second and third row
                    .Menubar("edit insert view tools") // Menu bar elements
                    .BlockFormats("Paragraph=p;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6"); // Formats
                
                // Set new configuration to standard page main body property
                config.For<StandardPage>(m => m.MainBody, jsConfigurationSettings);
            });
        }
    }
}

To achieve the same when you are using Episerver CMS 10, you can instead create a class decorated with an attribute called TinyMCEPluginNonVisual

using EPiServer.Editor.TinyMCE;

namespace EpiExamples.Business.Editors
{
    [TinyMCEPluginNonVisual(PlugInName = "ExtendedConfiguration", ServerSideOnly = true, AlwaysEnabled = true,
        EditorInitConfigurationOptions = "{ extended_valid_elements: 'script[language|type|src],iframe[src|alt|title|width|height|align|name],picture,source[srcset|media],a[id|href|target|onclick|class],span[*],div[*]'," +
                                         " valid_children: '+body[style],+div[span],+a[div|i]'," +
                                         " allow_html_in_named_anchor: 'true'," +
                                         " allow_script_urls: 'true' }")]
    public class TinyMCECustomConfiguration
    {
    }
}

And then in your page or block model you will decorate the field with a Property Settings attribute and the type of the new class

        [CultureSpecific]
        [PropertySettings(typeof(TinyMCECustomConfiguration))]
        [Display(GroupName = Global.GroupNames.Footer, Order = 900)]
        public virtual XhtmlString MainBody { get; set; }

It is time to test the results in the editor interface. First, we will write down an iFrame in the TinyMce editor pointing to the home page of the site.

The result is a page with the iFrame in it showing the home page

Now, we are going to write down a JavaScript function and an anchor to call that function

The result is a page with an anchor saying click here and when is clicked the message “Hello world” appears

And that is all. It is important to remember that giving too much power to editors can be dangerous. You should always try to restrict the amount of features you allow in the RTF editor. Having said that, it is good to know is still possible to add JavaScript code and iFrames through a RTF editor. I hope it will help someone and as always keep learning !!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: