WordPress: Adding a Proper Visual Editor to Your Plugin

When developing a new plugin for WordPress, sometimes you want to add a visual/WYSIWYG editor to one of your plugin’s settings fields. Unfortunately, most of the tutorials you’ll find online only explain part of what needs to be done in order to get that working. The main problem I have encountered when looking at these tutorials and example plugins is the fact that they only invoke the visual editor; they don’t offer any way for the user to use the editor in HTML mode.

What’s worse, some of these samples even go so far as to include and use their own version of TinyMCE; which obviously incurs a great deal of overhead and makes the plugin package unnecessarily bloated.

There is a fairly simple solution, though. The first thing you need to know about is the the_editor() function built into WordPress. This function will output the necessary textarea, etc. to build the visual editor.

The next thing you need to do is to enqueue and invoke all of the necessary JavaScripts to make the editor work as expected. To do that, you’ll need to write a function similar to the code below. I recommend placing this function inside of a class definition to avoid any potential namespace conflicts.

function enqueue_editor() {
	wp_enqueue_script('common');
	wp_enqueue_script('jquery-color');
	wp_admin_css('thickbox');
	wp_print_scripts('post');
	wp_print_scripts('media-upload');
	wp_print_scripts('jquery');
	wp_print_scripts('jquery-ui-core');
	wp_print_scripts('jquery-ui-tabs');
	wp_print_scripts('tiny_mce');
	wp_print_scripts('editor');
	wp_print_scripts('editor-functions');

	/* Include the link dialog functions */
	require_once ABSPATH . 'wp-admin/includes/internal-linking.php';
	wp_print_scripts('wplink');
	wp_print_styles('wplink');
	add_action('tiny_mce_preload_dialogs', 'wp_link_dialog');

	add_thickbox();
	wp_tiny_mce();
	wp_admin_css();
	wp_enqueue_script('utils');
	do_action("admin_print_styles-post-php");
	do_action('admin_print_styles');
	remove_all_filters('mce_external_plugins');
}

As far as I can tell, all of these scripts and actions are necessary in order for the editor to work correctly. I assume, if you are not using the media upload feature, you could avoid calling wp_print_scripts('media-upload');, but that’s probably the only one.

Finally, you’ll need to use some specific HTML code to wrap your editor (in order to ensure the JavaScript works correctly). You should use something similar to the following when outputting the editor:

<div id="poststuff">
	<div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
		<?php the_editor('<p>Some sample content.</p>'); ?>
	</div>
</div>
/* Insert the dialog box that's used by the "link" button */
add_action( 'admin_footer', 'wp_tiny_mce_preload_dialogs' );

Notes (and Caveats) on Use

  • If you choose to give your editor a unique name/ID (other than “content”), you will need to add some CSS to your plugin to size the HTML editor appropriately. There is already a CSS definition for #content to make it stretch to the width of the editor properly, but if you assign a unique ID, that CSS obviously won’t apply (and your HTML editor will most likely only stretch about halfway across the editor area).
  • There is a minor bug that keeps the media buttons from working properly if you give your editor a name/ID other than “content”.
  • Unfortunately (at this time, at least), this only works to create a single visual editor on a page. If you attempt to include a second editor, there are various JavaScript issues/bugs that will cause the second editor not to work as you might expect. If you have the need to use multiple visual editors on a single page, you will need to look for another solution, sadly. There have been multiple requests to enhance the functionality of the the_editor() function to support multiple instances on a single page, but most I’ve found have been shot down as “wontfix” issues in the source trac.