Matt Bailey
Designer & Developer

SilverStripe CMS - Adding a TinyMCE Editor to Widgets

image

I’m working on a Silverstripe site at the moment, and I’m widgetising a lot of the frontend components to make the site more flexible for the client. Most of the widgets have been fairly simple to set up, but I’m working on one with a textarea that would benfit from using TinyMCE (the built in SilverStripe WYSIWYG editor). The problem is that the widgets module doesn’t support HtmlEditorField form fields, so I set out to find a way round this.

Please bear in mind, I’m a designer who does a bit of coding, so delving deep into the core code of SilverStripe and extending classes, models, decorators or whatever wasn’t really an option.

The solution that I came up with is actually quite simple, but it has one disadvantage - it doesn’t integrate with the SilverStripe files library or SiteTree like the editor normally does. In laymans terms this means that if you use the Image or Link buttons you can only manually type/paste in URLs. Personally this serves my purposes; I just wanted a simple editor with very basic style controls, like Bold, Italic, Unordered List and so on. If this suits you too, then read on…

First of all create a file for some javascript in mysite/. I’ve simply called mine admin.js/.

In this file we need to add some code to initialise the editor. I’ve put this into a function so I can reuse it, the reason being is that the editor needs to be not only initialised on page load, but also after any ajax events. Here’s the code:

/**
 * Initialise TinyMCE
 */
function initialiseTinyMCE() {
    tinyMCE.init({
        mode: "specific_textareas",
        editor_selector: "textarea",
        width: "356",
        theme_advanced_buttons1 : "bold,italic,separator,justifyleft,justifycenter,justifyright,justifyfull",
        theme_advanced_buttons2 : "bullist,numlist,separator,link,unlink,image,code",
        theme_advanced_buttons3 : "formatselect",
        extended_valid_elements: "img[class|id|src|alt|title|onmouseover|onmouseout|name|usemap]",
        theme_advanced_blockformats : "p,div,h1,h2,h3,h4,h5,h6,blockquote"
    });
}

/**
 * After document ready calls
 */
jQuery(document).ready(function() {
    initialiseTinyMCE();
});

/**
 * After ajaxStop calls
 */
jQuery(document).ajaxStop(function() {
    initialiseTinyMCE();
});

All that remains is to load the javascript. You can do this by adding the following code to mysite/_config.php:

LeftAndMain::require_javascript('mysite/admin.min.js');

All being well you should see an editor in your widget like this (obviously not on an angle - that’s just me being arty-farty):

image

So, let’s break the above code down a bit.

mode: "specific_textareas",
editor_selector: "textarea",

These two lines tell TinyMCE the elements to turn into editors. In this case Silverstripe only adds the class textarea to textareas. It worries me a bit that this is not very specific (it will effect any element on the page with the class textarea), but it hasn’t caused a problem so far.

width: "356",

This sets the width of the editor, obviously ;)

theme_advanced_buttons1 : "bold,italic,separator,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "bullist,numlist,separator,link,unlink,image,code",
theme_advanced_buttons3 : "formatselect",

theme_advanced_buttons defines the buttons to use (there are three rows).

extended_valid_elements: "img[class|id|src|alt|title|onmouseover|onmouseout|name|usemap]",

extended_valid_elements defines the options to show in the image pop-up. The reason I’m using this is because I wanted to remove the width and height attributes - for anyone familiar with responsive web design you’ll know why this is neccessary, but in simple terms it allows images to scale within their containers, rather than remaining a fixed size.

theme_advanced_blockformats : "p,div,h1,h2,h3,h4,h5,h6,blockquote"

theme_advanced_blockformats defines which html tags to show in the ‘paragraph’ selectlist.

In terms of running the function you’ll see I’m calling it in two places. jQuery(document).ready(function() { ... you’ll probably already be very familiar with. Any code in here will run when the document is ready. jQuery(document).ajaxStop(function() { ... is something I learned only recently (halleujah for jQuery). Any code in here runs after every ajax event has finished - perfect!

TinyMCE has a multitude of configuration options, which you should check out.

I’ve only just set this up, so it’s not been tested much yet. If I come across any issues I’ll update the post. If anyone else notices anything let me know. That aside I hope this post helps someone else out.