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.
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
- Code a tinymce.PluginManager js class
- 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
- https://world.episerver.com/documentation/developer-guides/CMS/add-ons/customizing-the-tinymce-editor-v2/
- https://world.episerver.com/blogs/Ben-McKernan/Dates/2018/3/an-updated-tinymce-package-has-been-released/
- https://www.tinymce.com/docs/advanced/creating-custom-dialogs/
- https://www.tiny.cloud/docs/api/tinymce/tinymce.windowmanager/#open
- https://www.tiny.cloud/docs/advanced/creating-a-plugin/
About the author
Luc Gosso
– Independent Senior Web Developer
working with Azure and Episerver
Twitter: @LucGosso
LinkedIn: linkedin.com/in/luc-gosso/
Github: github.com/lucgosso