Advertisement
Theme Development

Guide to Creating Your Own WordPress Editor Buttons

by

Most likely you know that WordPress is bundled with the HTML WYSIWYG editor, TinyMCE. The variety of features, and the ability to be extended though plugins, make it the most used WYSIWYG editor in the world. WordPress doesn't make use of all its features, however. WordPress customizes it and only keeps parts which are really helpful to users, avoiding messing up the user interface. That also means some features, buttons for example, have been hidden from users. You can totally enable the hidden MCE buttons. Typically they are stylesheet, sub, sup buttons. If even the hidden ones still don't satisfy your needs, then you have to create a TinyMCE plugin to do add your own. In this tutorial, I will walk you through the basics of adding your WordPress Editor buttons by creating a TinyMCE plugin.


Before We Start

As mentioned earlier, we will create a new TinyMCE plugin whose task is to add the new buttons we want. So which buttons are we going to add? We will try to add two simple buttons: Dropcap and Recent Posts, in which the former gives you the ability to convert a selected letter to a drop cap letter, and the latter will display recent posts. The code generates these buttons shown below.

Let's create a new folder named wptuts-editor-buttons (of course, you can change it to something else if you want) in your theme directory (I'm using TwentyTwelve). Continue to create two new files, wptuts.php that invokes customized PHP, and the other named wptuts-plugin.js where the JavaScript code snippets will be located. Finally, open your theme's functions.php file and include the newly created wptuts.php file in it. Note, remember to define its path exactly:

require( 'wptuts-editor-buttons/wptuts.php' );

Then we need to prepare some code for those two buttons:

  • Dropcap - The ideal way of making a letter into drop caps is to simply wrap the user's selected letter within a pre-defined HTML span class which styles that letter to look like drop caps. The CSS code of the class shown below, just appends it to your theme's style.css file:
    		/* Add this code in style.css */
    		.dropcap {
    			float: left;
    			font-size: 80px;
    			padding-right: 7px;
    			line-height: 72px;
    		}
  • Recent Posts - We will make a shortcode that will add a list of recent posts into the page, open the wptuts.php file and add the following code:
    		add_shortcode( 'recent-posts', 'wptuts_recent_posts' );
    		function wptuts_recent_posts( $atts ) {
    			extract( shortcode_atts( array(
    				'numbers' => '5',
    			), $atts ) );
    			$rposts = new WP_Query( array( 'posts_per_page' => $numbers, 'orderby' => 'date' ) );
    			if ( $rposts->have_posts() ) {
    				$html = '<h3>Recent Posts</h3><ul class="recent-posts">';
    				while( $rposts->have_posts() ) {
    					$rposts->the_post();
    					$html .= sprintf(
    						'<li><a href="%s" title="%s">%s</a></li>',
    						get_permalink($rposts->post->ID),
    						get_the_title(),
    						get_the_title()
    					);
    				}
    				$html .= '</ul>';
    			}
    			wp_reset_query();
    			return $html;
    		}

    We assume that when users click the Recent Posts button, the browser will popup a dialog asking them for the number of posts they want to show. After having that number, the editor will fill it as an argument into the above shortcode. For example, if we want to show seven recent posts, the shortcode is generated as follows:

    		[recent-posts numbers="7"/]

Registering a New TinyMCE Plugin

Assuming we already had the new plugin, then we need to register it with WordPress to integrate it into the TinyMCE editor. The code is shown below:

add_action( 'init', 'wptuts_buttons' );
function wptuts_buttons() {
	add_filter( "mce_external_plugins", "wptuts_add_buttons" );
	add_filter( 'mce_buttons', 'wptuts_register_buttons' );
}
function wptuts_add_buttons( $plugin_array ) {
	$plugin_array['wptuts'] = get_template_directory_uri() . '/wptuts-editor-buttons/wptuts-plugin.js';
	return $plugin_array;
}
function wptuts_register_buttons( $buttons ) {
	array_push( $buttons, 'dropcap', 'showrecent' ); // dropcap', 'recentposts
	return $buttons;
}

The important filter hook mce_external_plugins is used to hook the new plugin to TinyMCE. We need to pass a plugin ID (wptuts) and the absolute URL pointing to our wptuts-plugin.js file. The mce_buttons hook is used to tell the TinyMCE editor which buttons in our plugin we want to show. The dropcap and showrecent are the ID values of these buttons that we plan to create. Keep in mind these values, they will be used later.


Setting Up TinyMCE Plugin

In general, I think the best way to extend or develop something on a platform is to consult the documentation for that platform. TinyMCE has its own wiki that you might find useful. By following an example of how to create a TinyMCE plugin, we have the following initialisation code:

(function() {
	tinymce.create('tinymce.plugins.Wptuts', {
		/**
		 * Initializes the plugin, this will be executed after the plugin has been created.
		 * This call is done before the editor instance has finished it's initialization so use the onInit event
		 * of the editor instance to intercept that event.
		 *
		 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
		 * @param {string} url Absolute URL to where the plugin is located.
		 */
		init : function(ed, url) {

		},

		/**
		 * Creates control instances based in the incomming name. This method is normally not
		 * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons
		 * but you sometimes need to create more complex controls like listboxes, split buttons etc then this
		 * method can be used to create those.
		 *
		 * @param {String} n Name of the control to create.
		 * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.
		 * @return {tinymce.ui.Control} New control instance or null if no control was created.
		 */
		createControl : function(n, cm) {
			return null;
		},

		/**
		 * Returns information about the plugin as a name/value array.
		 * The current keys are longname, author, authorurl, infourl and version.
		 *
		 * @return {Object} Name/value array containing information about the plugin.
		 */
		getInfo : function() {
			return {
				longname : 'Wptuts Buttons',
				author : 'Lee',
				authorurl : 'http://wp.tutsplus.com/author/leepham',
				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example',
				version : "0.1"
			};
		}
	});

	// Register plugin
	tinymce.PluginManager.add( 'wptuts', tinymce.plugins.Wptuts );
})();

Remember to add this code into the wptuts-plugin.js file. We've left the code comments for you to easily understand what's going on. The above code just does two main tasks:

  1. First, defining a new TinyMCE plugin in a safe way by calling TinyMCE's create method. Our plugin's behavior will be defined in the init and createControl functions. You can see that the plugin's information is declared in the getInfo function too. Our plugin will have the name Wptuts and the ID wptuts as you can see.
  2. Last, simply add our new plugin into the TinyMCE Plugin Manager.

Creating Buttons

In the init function, we start to create our buttons. The code seen as follows:

(function() {
	tinymce.create('tinymce.plugins.Wptuts', {
		init : function(ed, url) {
			ed.addButton('dropcap', {
				title : 'DropCap',
				cmd : 'dropcap',
				image : url + '/dropcap.jpg'
			});

			ed.addButton('showrecent', {
				title : 'Add recent posts shortcode',
				cmd : 'showrecent',
				image : url + '/recent.jpg'
			});
		},
		// ... Hidden code
	});
	// Register plugin
	tinymce.PluginManager.add( 'wptuts', tinymce.plugins.Wptuts );
})();

By using the addButton method of the ed object, we tell the current editor that we want to create all these buttons. This method accepts two arguments:

  • The first one is the button's ID. In the previous section, we mentioned it. It must be the same as the one we defined before. Otherwise, it will not work properly.
  • The second one is the object containing the button's information, such as:
    • The button's title
    • The most important: the task that the button will do. Take a look at the cmd property, it has the value of showrecent. That is the command's ID which is executed every time it is called, we will go into detail shortly
    • The image of the button. Note that the URL parameter holds the absolute directory's URL in which our plugin is located, this makes it easier to reference the image that you want. So you need to place your image into the plugin's folder and ensure its name to is set precisely to the image's value.

Now, check the WordPress editor and we will see our buttons showing up. However, they do nothing right now.

Guide-To-Creating-Your-Own-WPs-Editor-Buttons-1
Our buttons showed up.

Adding Buttons' Commands

We've defined the name of the commands our buttons will execute, but have not yet defined what they will actually run. In this step, we will set up the things our buttons will do. Inside the init function, continue to add this code as shown:

(function() {
	tinymce.create('tinymce.plugins.Wptuts', {
		init : function(ed, url) {
			ed.addButton('dropcap', {
				title : 'DropCap',
				cmd : 'dropcap',
				image : url + '/dropcap.jpg'
			});

			ed.addButton('showrecent', {
				title : 'Add recent posts shortcode',
				cmd : 'showrecent',
				image : url + '/recent.jpg'
			});

			ed.addCommand('dropcap', function() {
				var selected_text = ed.selection.getContent();
				var return_text = '';
				return_text = '<span class="dropcap">' + selected_text + '</span>';
				ed.execCommand('mceInsertContent', 0, return_text);
			});

			ed.addCommand('showrecent', function() {
				var number = prompt("How many posts you want to show ? "),
					shortcode;
				if (number !== null) {
					number = parseInt(number);
					if (number > 0 && number <= 20) {
						shortcode = '[recent-post number="' + number + '"/]';
						ed.execCommand('mceInsertContent', 0, shortcode);
					}
					else {
						alert("The number value is invalid. It should be from 0 to 20.");
					}
				}
			});
		},
		// ... Hidden code
	});
	// Register plugin
	tinymce.PluginManager.add( 'wptuts', tinymce.plugins.Wptuts );
})();

Now, the ed.addCommand method will help us to add a new command. You need to pass the command's ID and the callback function that will be executed if it was called by the ed.execCommand method. Note that ed represents the tinyMCE.activeEditor object. Let's take a look at the callback functions:

  • In the dropcap command, the desire we want is when a user selects a letter and clicks the DropCap button, the letter will then be transformed to drop cap form. So how do we get that letter? Well, the ed.selection.getContent method will do that for us. Next, once we've gotten that letter we just wrap it within a span element. Remember to set this element's class value to dropcap that we've defined before, right? Finally, we have the complete text that needs to be inserted back into the editor. TinyMCE has a default command with the name mceInsertContent which is used to insert specific content into the editor, how to use it is shown above. The content will be passed as the third argument of the mceInsertContent method.
  • A similar thing happens in the showrecent command as in the dropcap command, excepting we don't need to get the user's selected content. We just simply display a dialog asking the user how many posts they want to show up, then insert that number value in an appropriate shortcode syntax.

Registering Custom CSS for Buttons (Optionally)

Instead of adding pure text when the buttons insert contents into the visual editor, we can make it much more visual by registering custom CSS for our buttons. It depends on which type of content data, and you can choose an appropriate style. For example, our Dropcap's style can have the same as the one showing on the front-end. So you can take its CSS code in the very top of this post, then place it into the editor-style.css file (for default, see add_editor_style for detais).

For shortcodes, they might not have an HTML element themselves. How should we style them? Well, this situation is much more complex to achieve the result, it's not impossible though (you can see some default WordPress button such as 'Add media'). However, it can still be a tricky, by wrapping that shortcode in a HTML element and then styling that element just like above. It's quite simple, not completely perfect though. In this post, we won't focus on that complex processing.


Results

Finally, the results we get are shown as following:

Test-the-Dropcap-button.
Test the Dropcap button.

Then, on the front-end:

Dropcap-letter-in-front-end.
Dropcap letter in front-end.

And the Recent Posts button works well too:

Recent-Posts-button-worked.
Recent Posts button worked.

Conclusion

Okay, we covered a practice which is quite simple and easy to follow. You might notice that the Recent Posts button allows you to adjust a setting (the number of posts that will show). You certainly know that we used the default JavaScript, prompt, to achieve that. What if you want a more complex popup, which has many settings rather than only one? Well, in another post we will discuss this and try another approach.

Any feedback about this post will be appreciated. Thanks for reading, and see you later.


Reference

Related Posts