If you are WordPress developer, then at some point you may come across customizing or extending the WordPress Visual Editor. For example, you may want to add a button to the Visual Editor’s toolbar to allow your client to easily insert a text box or a call to action button without writing any HTML code. In this article, we will show you how to create a TinyMCE plugin in WordPress.
Requirements
This tutorial is intended for advanced users. If you are a beginner level user who just wants to extend visual editor, then please check out TinyMCE Advanced plugin or take a look at these tips on using WordPress visual editor.
For this tutorial, you will need basic coding skills, access to a WordPress install where you can test it out.
It is a bad practice to develop plugins on a live website. A minor mistake in the code can make your site inaccessible. But if you must do it on a live site, then at least backup WordPress first.
Creating Your First TinyMCE Plugin
We will begin by creating a WordPress plugin to register our custom TinyMCE toolbar button. When clicked, this button will allow user to add a link with a custom CSS class.
The source code will be provided in full at the end of this article, but until then, let’s create the plugin step-by-step.
First, you need to create a directory in wp-content/plugins
folder of your WordPress install. Name this folder tinymce-custom-link-class
.
From here, we’ll begin adding our plugin code.
The Plugin Header
Create a new file in the plugin directory we just created and name this file tinymce-custom-link-class.php
. Add this code to the file and save it.
/** * Plugin Name: TinyMCE Custom Link Class * Plugin URI: http://wpbeginner.com * Version: 1.0 * Author: WPBeginner * Author URI: https://www.wpbeginner.com * Description: A simple TinyMCE Plugin to add a custom link class in the Visual Editor * License: GPL2 */
This is just a PHP comment, which tells WordPress the name of the plugin, as well as the author and a description.
In the WordPress admin area, activate your new plugin by going to Plugins > Installed Plugins, and then clicking Activate beside the TinyMCE Custom Link Class plugin:
Setting Up Our Plugin Class
If two WordPress plugins have functions with the same name, then this would cause an error. We will avoid this problem by having our functions wrapped in a class.
class TinyMCE_Custom_Link_Class { /** * Constructor. Called when the plugin is initialised. */ function __construct() { } } $tinymce_custom_link_class = new TinyMCE_Custom_Link_Class;
This creates our PHP class, along with a construct, which is called when we reach the line $tinymce_custom_link_class = new TinyMCE_Custom_Link_Class;
.
Any functions we add inside this class shouldn’t conflict with other WordPress plugins.
Start Setting Up Our TinyMCE Plugin
Next, we need to tell TinyMCE that we might want to add our custom button to the Visual Editor‘s toolbar. To do this, we can use WordPress’ actions – specifically, the init
action.
Add the following code inside your plugin’s __construct()
function:
if ( is_admin() ) { add_action( 'init', array( $this, 'setup_tinymce_plugin' ) ); }
This checks if we are in the WordPress Administration interface. If we are, then it asks WordPress to run the setup_tinymce_plugin
function inside our class when WordPress has finished its initial loading routine.
Next, add the setup_tinymce_plugin
function:
/** * Check if the current user can edit Posts or Pages, and is using the Visual Editor * If so, add some filters so we can register our plugin */ function setup_tinymce_plugin() { // Check if the logged in WordPress User can edit Posts or Pages // If not, don't register our TinyMCE plugin if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) { return; } // Check if the logged in WordPress User has the Visual Editor enabled // If not, don't register our TinyMCE plugin if ( get_user_option( 'rich_editing' ) !== 'true' ) { return; } // Setup some filters add_filter( 'mce_external_plugins', array( &$this, 'add_tinymce_plugin' ) ); add_filter( 'mce_buttons', array( &$this, 'add_tinymce_toolbar_button' ) ); }
This checks if the current logged in WordPress user can edit Posts or Pages. If they can’t, there’s no point in registering our TinyMCE Plugin for that User, as they’ll never see the Visual Editor.
We then check if the user is using the Visual Editor, as some WordPress users turn this off via Users > Your Profile. Again, if the user is not using the Visual Editor, we return (exit) the function, as we don’t need to do anything else.
Finally, we add two WordPress Filters – mce_external_plugins
and mce_buttons
, to call our functions which will load the required Javascript file for TinyMCE, and add a button to the TinyMCE toolbar.
Registering the Javascript File and Button to the Visual Editor
Let’s go ahead and add the add_tinymce_plugin
function:
/** * Adds a TinyMCE plugin compatible JS file to the TinyMCE / Visual Editor instance * * @param array $plugin_array Array of registered TinyMCE Plugins * @return array Modified array of registered TinyMCE Plugins */ function add_tinymce_plugin( $plugin_array ) { $plugin_array['custom_link_class'] = plugin_dir_url( __FILE__ ) . 'tinymce-custom-link-class.js'; return $plugin_array; }
This function tells TinyMCE that it needs to load the Javascript files stored in the $plugin_array
array. These Javascript files will tell TinyMCE what to do.
We also need to add some code to the add_tinymce_toolbar_button
function, to tell TinyMCE about the button we’d like to add to the toolbar:
/** * Adds a button to the TinyMCE / Visual Editor which the user can click * to insert a link with a custom CSS class. * * @param array $buttons Array of registered TinyMCE Buttons * @return array Modified array of registered TinyMCE Buttons */ function add_tinymce_toolbar_button( $buttons ) { array_push( $buttons, '|', 'custom_link_class' ); return $buttons; }
This pushes two items onto the array of TinyMCE buttons: a separator (|), and our button’s programmatic name (custom_link_class
).
Save your plugin, and then edit a Page or Post to view the Visual Editor. Chances are, the toolbar isn’t displaying right now:
Don’t worry – if we use our web browser’s inspector console, we’ll see that a 404 error and notice have been generated by TinyMCE, telling us that it can’t find our Javascript file.
That’s good – it means we’ve successfully registered our TinyMCE custom plugin, and now need to create the Javascript file to tell TinyMCE what to do.
Creating the Javascript Plugin
Create a new file in your wp-content/plugins/tinymce-custom-link-class
folder, and name it tinymce-custom-link-class.js
. Add this code in your js file:
(function() { tinymce.PluginManager.add( 'custom_link_class', function( editor, url ) { }); })();
This calls the TinyMCE Plugin Manager class, which we can use to perform a number of TinyMCE plugin related actions. Specifically, we’re adding our plugin to TinyMCE using the add
function.
This accepts two items; the name of the plugin (custom_link_class
) and an anonymous function.
If you’re familiar with the concept of functions in coding, an anonymous function is simply a function with no name. For example, function foobar() { ... }
is a function that we could call somewhere else in our code by using foobar()
.
With an anonymous function, we can’t call that function somewhere else in our code – it’s only being called at the point the add()
function is invoked.
Save your Javascript file, and then edit a Page or Post to view the Visual Editor. If everything worked, you’ll see the toolbar:
Right now, our button hasn’t been added to that toolbar. That’s because we’ve only told TinyMCE that we are a custom plugin. We now need to tell TinyMCE what to do – that is, add a button to the toolbar.
Update your Javascript file, replacing your existing code with the following:
(function() { tinymce.PluginManager.add( 'custom_link_class', function( editor, url ) { // Add Button to Visual Editor Toolbar editor.addButton('custom_link_class', { title: 'Insert Button Link', cmd: 'custom_link_class', }); }); })();
Notice our anonymous function has two arguments. The first is the editor
instance – this is the TinyMCE Visual Editor. In the same way we can call various functions on the PluginManager
, we can also call various functions on the editor
. In this case, we’re calling the addButton
function, to add a button to the toolbar.
Save your Javascript file, and go back to your Visual Editor. At a first look, nothing seems to have changed. However, if you hover your mouse cursor over to the right of the top row’s rightmost icon, you should see a tooltip appear:
We’ve successfully added a button to the toolbar, but it needs an image. Add the following parameter to the addButton
function, below the title:
line:
image: url + '/icon.png',
url
is the URL to our plugin. This is handy if we want to reference an image file within our plugin folder, as we can append the image file name to the URL. In this case, we’ll need an image called icon.png
in our plugin’s folder. Use the below icon:
Reload our Visual Editor, and you’ll now see your button with the icon:
Defining a Command to Run
Right now, if you click the button, nothing will happen. Let’s add a command to TinyMCE telling it what to do when our button is clicked.
In our Javascript file, add the following code below the end of the editor.addButton
section:
// Add Command when Button Clicked editor.addCommand('custom_link_class', function() { alert('Button clicked!'); });
Reload our Visual Editor, click the button and an alert will appear confirming we just clicked the button:
Let’s replace the alert with a prompt, asking the user for the link they want to wrap around the selected text in the Visual Editor:
// Add Command when Button Clicked editor.addCommand('custom_link_class', function() { // Check we have selected some text that we want to link var text = editor.selection.getContent({ 'format': 'html' }); if ( text.length === 0 ) { alert( 'Please select some text to link.' ); return; } // Ask the user to enter a URL var result = prompt('Enter the link'); if ( !result ) { // User cancelled - exit return; } if (result.length === 0) { // User didn't enter a URL - exit return; } // Insert selected text back into editor, wrapping it in an anchor tag editor.execCommand('mceReplaceContent', false, '<a class="button" href="' + result + '">' + text + '</a>'); });
This block of code performs a few actions.
First, we check if the user selected some text to be linked in the Visual Editor. If not, they’ll see an alert telling them to select some text to link.
Next, we ask them to enter a link, again checking if they did. If they cancelled, or didn’t enter anything, we don’t do anything else.
Finally, we run the execCommand
function on the TinyMCE editor, specifically running the mceReplaceContent
action. This replaces the selected text with our HTML code, which comprises of an anchor link with class=”button”, using the text the user selected.
If everything worked, you’ll see your selected text is now linked in the Visual Editor and Text views, with the class set to button
:
Summary
We’ve successfully created a WordPress plugin which adds a button to the TinyMCE visual editor in WordPress. This tutorial has also covered some of the basics of the TinyMCE API and WordPress filters available for TinyMCE integrations.
We added code so that when a user clicks our custom button, they’re prompted to select some text in the Visual Editor, which they can then link to a URL of their choice. Finally, our plugin then replaces the selected text with a linked version that contains a custom CSS class called button
.
We hope this tutorial helped you learn how to create a WordPress TinyMCE plugin. You may also want to check out our guide on how to create a site-specific WordPress plugin.
If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.
Hubertus
Wonderful, just that what I needet.
Thank you verry much.
rich
Hi, I am getting the following error:
Deprecated TinyMCE API call: .onNodeChange.add(..)
Joel
Brilliant article – I had to search forever to find something this simple and easy to understand. For someone completely new to this, it was very annoying how every single tutorial would conveniently leave out the directory to create this plugin in. Thanks so much!
Friso
Good article, I used it in my own plugin. Quick tip tough, you don’t have to use an object by refence anymore in PHP, so instead of &$this, you can do just $this. Since objects are passed by reference in default
Michael
Sorry, but i get always a error message
Warning: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in C:\xampp\htdocs\wordpress\wp-includes\class-wp-hook.php on line 298
Can you tell me, whats wrong?
Wita
You guys always awesome, nice tutorial