How to add a button with a pop-up in WordPress’s TinyMCE editor

The main new feature in version 0.2.0 of WP-Gistpen was the integration of the Gistpen button into WordPress’s TinyMCE editor. Since TinyMCE was upgraded to version 4 in WordPress 3.9, many of the current tutorials are no longer entirely accurate. Additionally, TinyMCE’s documentation is shit, so I just want to share how I integrated a button that triggers a pop-up into TinyMCE 4.

First all, you can find the Gistpen-specific code on Github. All the PHP stuff is here, and the JavaScript is here, if you want to see the specific implementation.

First, register the plugins and the buttons in WordPress on the proper filters:

add_filter( 'mce_external_plugins', 'plugin_slug_add_button' );
function plugin_slug_add_button( $plugins ) {
$plugins['plugin_slug'] = 'path/to/editor/plugin.js';
return $plugins;
}
add_filter( 'mce_buttons', 'plugin_slug_register_button' );
function plugin_slug_register_button( $buttons ) {
array_push( $buttons, 'plugin_slug' );
return $buttons;
}
register-tiny-mce-plugin.php

The mce_external_plugin filter registers the plugin, and the mce_buttons filter registers the button. Just swap out your plugin slugs and the path to the JavaScript file where you’re writing your TinyMCE plugin.

Here’s the TinyMCE plugin code itself. Take a quick look over the whole thing, as it’s a bit complicated, but we’ll go through all of the parts step-by-step:

( function() {
// Register plugin
tinymce.create( 'tinymce.plugins.plugin_slug', {
init: function( editor, url ) {
// Add the Insert Gistpen button
editor.addButton( 'plugin_slug', {
//text: 'Insert Shortcode',
icon: 'icons dashicons-icon',
tooltip: 'Insert Shortcode',
cmd: 'plugin_command'
});
// Called when we click the Insert Gistpen button
editor.addCommand( 'plugin_command', function() {
// Calls the pop-up modal
editor.windowManager.open({
// Modal settings
title: 'Insert Shortcode',
width: jQuery( window ).width() * 0.7,
// minus head and foot of dialog box
height: (jQuery( window ).height() - 36 - 50) * 0.7,
inline: 1,
id: 'plugin-slug-insert-dialog',
buttons: [{
text: 'Insert',
id: 'plugin-slug-button-insert',
class: 'insert',
onclick: function( e ) {
insertShortcode();
},
},
{
text: 'Cancel',
id: 'plugin-slug-button-cancel',
onclick: 'close'
}],
});
appendInsertDialog();
});
}
});
tinymce.PluginManager.add( 'plugin_slug', tinymce.plugins.plugin_slug );
function appendInsertDialog () {
var dialogBody = jQuery( '#plugin-slug-insert-dialog-body' ).append( '[Loading element like span.spinner]' );
// Get the form template from WordPress
jQuery.post( ajaxurl, {
action: 'plugin_slug_insert_dialog'
}, function( response ) {
template = response;
dialogBody.children( '.loading' ).remove();
dialogBody.append( template );
jQuery( '.spinner' ).hide();
});
}
})();
tinyce-plugin.php

First, we create the plugin on line 4. Don’t forget to swap out your plugin slug.

On lines 9-14, we add the button to TinyMCE. You can edit the button text, but it doesn’t look great, or you can define its icon class and display an icon there. cmd defines what command is run when you click the button.

Next, we register the command and open the pop-up using TinyMCE’s windowManager API.

We can define some aspects of the pop-up using their API. Some of these, like the buttons property and the id property, aren’t well documented, but you can see some of the properties here1.

TinyMCE has its own window API, and a number of tutorials will show you how to use it to build your own forms, which you can find and use, but I wanted more flexibility for my form. In a future version of the app, I plan to draw the form with jQuery, as it’ll be faster than requesting it via Ajax, but this was certainly easier. Here’s how this works.

After the pop-up is opened and ready to go, we call a function. That function makes an Ajax call that the form and appends the response to the body of the dialog box.

On the WordPress side of the Ajax call, we just have to register a function to that returns the form.

add_action( 'wp_ajax_plugin_slug_insert_dialog', 'plugin_slug_insert_gistpen_dialog' );
function plugin_slug_insert_gistpen_dialog() {
die(include 'path/to/dialog/form.php');
}
register-ajax.php

You can then create and return a form in standard PHP!

Using some of these techniques, I actually added a search box into my form, and made it possible to create a new Gistpen from the pop-up. If you want to see how that was accomplished, check out the WP-Gistpen project on GitHub.


  1. I’m actually writing this tutorial because of how frustratingly bad the documentation is. For a brief period, I was actually swapping out the button text and giving it a class in jQuery because I didn’t realize you could edit it yourself. Read the source next time, I guess.