Building a simple custom plugin to TinyMce in Episerver.Cms.TinyMce package 2

Having to upgrade TinyMCE in Episerver to latest packages and you have elder plugins? Or want to build some custom plugin in wysiwyg? Here is a very simple example of how.

icon of user profile

Published 1st September 2018
Episerver 11
Episerver.Cms.TinyMce > 2.0
TinyMce > 4.0

In this blog post I’ll give you an example how to implement a custom button plugin in tinyMCE.

Check out my other tinyMCE plugin tips here

  • Example: “A background plate”, a custom button that wraps content into a div with class.

So… 2 steps

  1. Code a tinymce.PluginManager js class
  2. Register the script and plugin

tinymce.PluginManager.add

The main parts in a plugin is explained with this image:

  • Use tinymce.PluginManager.add to register
  • addCommand is used for you custom logic
  • addButton to add your button to toolbar
  • monitorNodeChange is non mandatory, where you can put logic for enabling/disabling your button

Adding your plugin to in a non Episerver site

Add scripts to site:

<script src=”/tinymce/js/tinymce.min.js”></script><script src=”/ClientResources/Scripts/tinymce/plugins/customplateplugin/editor_plugin_v4.js “></script>

Then init tiny:

tinymce.init({  selector: ‘textarea’,
plugins: ‘customplateplugin’,
toolbar: ‘customplateplugin’
});

How to add your external plugin to Episerver XhtmlString property

using EPiServer.Cms.TinyMce.Core;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;

namespace Gosso.Mvc.Business.Initialization
{
    [ModuleDependency(typeof(TinyMceInitialization))]
    public class CustomizedTinyMceInitialization : IConfigurableModule
    {
        public void Initialize(InitializationEngine context)
        {
        }

        public void Uninitialize(InitializationEngine context)
        {
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure<TinyMceConfiguration>(config =>
            {
                config.Default()
                    .AddPlugin("code")// i do want see code
                    .Toolbar(DefaultValues.Toolbar +
                             " | code customplateplugin")
                    .AddExternalPlugin("customplateplugin", "/ClientResources/Scripts/tinymce/plugins/customplateplugin/editor_plugin_v4.js")
            });

        }
    }
}

CSS

You need this CSS to add on site and tinyMCE for this plugin to work:

.plate {
padding: 25px;
background-color: lightgray;
}

The complete js code:

https://gist.github.com/LucGosso/b5c723b832435b8ae396487ef5befdc3#file-editor_plugin_plate-js

"use strict";
var tinymce = tinymce || {};
//Register the plugin
tinymce.PluginManager.add('customplateplugin', function (ed, url) {// ed as editor

    var cssClass = "plate";// your classname
    //your custom logic when button clicked
    ed.addCommand('customplatecmd', function () {
        if (ed.selection.getNode().parentElement.className === cssClass) {
                    var bm = ed.selection.getBookmark();
                    ed.selection.getNode().parentElement.outerHTML = ed.selection.getNode().parentElement.innerHTML;
                    ed.selection.moveToBookmark(bm);
                }
        else if (ed.selection.getNode().parentElement.parentElement != undefined &&
                ed.selection.getNode().parentElement.parentElement.className === cssClass) {
                    var bm = ed.selection.getBookmark();
                    ed.selection.getNode().parentElement.parentElement.outerHTML = ed.selection.getNode().parentElement.parentElement.innerHTML;
                    ed.selection.moveToBookmark(bm);
        }
        else {

            if (ed.selection.getSelectedBlocks().length > 1) {
                ed.selection.setContent('<div class="' + cssClass+'">' +
                    ed.selection.getContent() +
                    '</div>');
                ed.focus();
            }
            else {
                if (ed.selection.getNode().nodeName === "P") {
                    // Stores a bookmark of the current selection
                    var bm = ed.selection.getBookmark();
                    ed.selection.select(ed.selection.getNode(), true);
                    ed.selection.setContent('<div class="' + cssClass+'">' +
                        ed.selection.getNode().outerHTML +
                        '</div>');
                    // Restore the selection bookmark
                    ed.selection.moveToBookmark(bm);
                }
                else if (ed.selection.getNode().parentNode.nodeName === "P") {
                    ed.selection.select(ed.selection.getNode().parentNode, true);
                    ed.selection.setContent('<div class="' + cssClass+'">' +
                        ed.selection.getNode().outerHTML +
                        '</div>');
                }
                ed.focus();
            }
        }
     });

    // Register custom button
    ed.addButton('customplateplugin', {
        title: 'Plate',
        cmd: 'customplatecmd',
        image: url + '/img/plate.png',
        onclick: function () {
            ed.focus();
            //ed.selection.setContent('Hello world!');
            window.tinyMCE.activeEditor.execCommand('customplatecmd');
        }
       , onpostrender: monitorNodeChange //remove this if you would be able to mark several blocks
    });

    // Add a node change handler, selects the button in the UI when a P tag is selected
    function monitorNodeChange() {
        var btn = this;
        ed.on('NodeChange',
            function (e) {
                btn.disabled(!e.element || !e.element.nodeName ||
                    (e.element.nodeName.toLowerCase() !== "p" && e.element.parentNode.nodeName.toLowerCase() !== "p"));//
            });
    }

    return {
        getMetadata: function () {
            return {
                name: 'Gray plate plugin',
                url: 'https://devblog.gosso.se/?p=796'
            };
        }
    };
 });

SEO Terms

  • Add Plugins to TinyMCE
  • TinyMceInitialization example

Resources

About the author

Image of Luc GossoLuc Gosso
– Independent Senior Web Developer
working with Azure and Episerver

Twitter: @LucGosso
LinkedIn: linkedin.com/in/luc-gosso/
Github: github.com/lucgosso