WordPress TinyMCE button for shortcode

For those of you who didn’t know, TinyMCE has a straight-forward way to include a form in a modal window which you can use to generate shortcodes.

This is great news because it will make WordPress editors much less prone to error not having to write shortcodes by hand.

How do you do it?

So the approach in the WordPress way to do this is:

  1. Add the button to the WordPress TinyMCE toolbar using the “mce_buttons” ( or others ) filter.
  2. Ask TinyMCE to load a new JavaScript plugin for the editor which will handle the button.
  3. In the TinyMCE JavaScript plugin add the button and handle its events.
  4. Optionally if you have a custom shortcode, define it with its arguments.

In my example I have created a small plugin, which can be found on Github.

The plugin will add a button on the first row of the editor which when clicked will open a modal. The modal is handled by the WindowManager class included in TinyMCE. Another great part of using this approach is that you already have what is needed to generate a form.

After that, getting the parameters from the form and generating a shortcode to be inserted in the content is pretty easy.

You can get the whole plugin here.

I think the code is self-explanatory for the most part.

Things to watch out for

The code can be easily included in another plugin and extended to generate multiple buttons.

One issue I found not very intuitive at first is that if you add another button you will need to define another plugin for it to be taken into consideration, even if it’s in the same file.

So in the function where you add the js plugins you’ll end up with:

function add_embed_button_js( $plugin_array ) {
   $plugin_array['msb_button'] = plugin_dir_url( MSB_PLUGIN_FILE ) . 'assets/js/embed_button.js';
   $plugin_array['msb_button_2'] = plugin_dir_url( MSB_PLUGIN_FILE ) . 'assets/js/embed_button.js';
   return $plugin_array;
}

I trust that TinyMCE won’t attempt to load the same file 2 times. Also I am aware it might not be the right approach but it works!

Also, as mentioned in the plugin README – by default the plugin will add a button with no icon so you might miss it.