I enjoy simplicity, in everything. Unnecessary complexity is evil. Have a look at my WordPress plugins.

Using the TinyMCE WYSIWYG editor in your WordPress plugin

Not so long ago I’ve released my latest WordPress plugin which adds a WYSIWYG editor to your text widget’s textarea. I did this by using WordPress’ core TinyMCe functionality. In my search on how to properly include the JavaScript files which are necessary for the TinyMCe editor to work i’ve encountered quite some confusion on how to properly load TinyMCE into your plugin or theme options page. This is how i’ve done it and what works quite well for over 1250 users so far.

Update: This article is outdated. Have a look at the wp_editor function, available since WordPress 3.3

Loading the necessary editor scripts and styles

Let’s say you want use all the functionality that is in WordPress’ post editor including media uploading. We’ll need to  load some JavaScript files to make this work and of course we’ll do this using the only proper way to load a JavaScript file, by using wp_enqueue_script().

wp_enqueue_script(array('jquery', 'editor', 'thickbox', 'media-upload'));

To make the upload functionality pop-up in a nice thickbox screen, for which we’ve already enqueued the necessary JS files, we’ll need to load the thickbox css file too.

wp_enqueue_style('thickbox');

Loading TinyMCE files

WordPress has a nice function that takes care of loading the necessary TinyMCE scripts and stylesheets: wp_tiny_mce(). It isn’t documented in the WP Codex yet but that doesn’t mean it doesn’t work great. In my search to find more information about this function i’ve heard from other developers who’ve tried to load TinyMCE using wp_tiny_mce() that calling the function returned a nasty undefined function error for them. This is because you have to hook this function to admin_head. WordPress loads your plugin files before it loads /wp-admin/includes/post.php that holds the wp_tiny_mce() function so we’ll need to call it later on, so that the function is available when we call it.

add_action("admin_head","myplugin_load_tiny_mce");

function myplugin_load_tiny_mce() {
wp_tiny_mce( false ); // true gives you a stripped down version of the editor
}

Showing a WYSIWYG editor

To show a WYSIWYG editor we can use another WordPress function called the_editor(). You’ll need to provide at least one parameter which sets the content of the textarea upon loading. For now, i’ll just leave this up to an empty string and leave the rest of the parameters to it’s default value.

// ...Your HTML page...
<div id="poststuff">
<?php the_editor(''); ?>
</div>
// ... More HTML, a save button etc..

This outputs a textarea with ‘#content’ as the ID and loads the TinyMCE editor on it. Note the wrapping div with poststuff as an ID, this is only necessary so that the CSS selectors for styling the switch buttons ( visual / html ) work.

Now, when you’ve followed the above steps you’ll notice that everything is working pretty nice except for one thing, the WP-link dialog is not working. This is because we’ll need to call one more function that preloads some TinyMCE dialogs. We’ll hook this function to the footer so it outputs the dialogs wrapped in a hidden div.

add_action( 'admin_print_footer_scripts', 'wp_tiny_mce_preload_dialogs');

UPDATE 06-07-2011 – WordPress 3.2:
Apparently, wp_tiny_mce_preload_dialogs() no longer exists from WP 3.2 on. It got replaced by wp_preload_dialogs() which is now being called from wp_quicktags(). wp_quicktags, on his turn, is being called from the_editor() function. So, if you’re using the_editor() you no longer need to manually call this function to preload the dialogs. :-)

If you’re not using the_editor(), make sure to call wp_preload_dialogs() somewhere from your footer, like this.

wp_preload_dialogs( array( 'plugins' => 'wpdialogs,wplink,wpfullscreen' ) );

The result: a neat WYSIWYG editor with all the functionality the default WP post editor has.

That’s it. If you’ve correctly implemented all the above steps you should have a WYSIWYG editor up and running. Let me know if you experience any problems or know a way to improve a thing or two in the process of loading TinyMCE.

Share this post: on Twitter on Facebook

48 Responses to “Using the TinyMCE WYSIWYG editor in your WordPress plugin”

  1. Hey Danny,

    Great post, very useful! How would I go about having multiple WYSIWYG editors on one theme options page? They seem to be interfering with one another.

    Thanks again,

    Thijs.

    • Hi Thijs,

      You can’t just call the_editor() twice because of interfering ID’s. You can however set a ‘editor_selector’ variable when calling wp_tiny_mce().

      wp_tiny_mce( false, array( 'editor_selector' => 'wysiwyig_editor' ) );

      Then you can just add 'wysiwyg_editor' as a class to the textarea's that you want to apply TinyMCE on. You'll have to copy the media-upload options and the visual / html switch buttons. Also, you'll have to copy the quicktags for the HTML view. Take a look at the HTML that is normally generated by the_editor() and copy the parts you need.

      You might need to change some id's here and there and apply some styling of your own. Unfortunately the_editor() doesn't allow us for easy multiple editors, yet.

      Hope that helps!

  2. Danny, great tutorial! One thing – how do I use the_editor() with get_option and update_option so I can save and retrieve what my user typed in there?

    • Hi Jones,

      The first parameter of the_editor sets the initial content of the textarea upon loading, that’s where you pass your retrieved content. The seconds parameter sets the id and the name attribute of the textarea, which is ‘content’ by default. So upon submitting the contents of the textarea will be in $_POST['content'] by default.

      Check out the_editor() in wp-includes/general-template.php for more info on it’s parameters.

      Hope that helps!

      • DAnny,
        That definitely helps, I should have looked there before! My problem now is that the editor is permanently stuck in “HTML” mode and clicking on “Visual” does nothing. Likewise, I can’t add links, or anything. JS debugging gives me this error whenever I click “Visual”:

        Error: switchEditors is not defined

        Do you know what I missed here? I followed your instructions above closely. Thanks much.

  3. Hi!

    First of all, thanks for writing this post, there are a lot snippets around but no complete guide..at least i didn’t found one.

    May be it’s because I’m using the german version of wordpress but using wp_tiny_mce AND the_editor leads to some (localization) errors which are adressed by this trac ticket:
    http://core.trac.wordpress.org/ticket/15102

    On the other hand, using the_editor with different id’s is working fine for me. Only tried this with WP3.2RC1
    Thanks

  4. Have you noticed any issues with this code in IE8 and 3.2?

    I had two plugins using custom TinyMCE stuff and they both suffer the following issue:
    Under 3.2, Ie8, the Link button generates this blank box instead of helping make a link:
    http://i.imgur.com/lJJeO.png

  5. Hi Danny,

    As my first plugin, I’m trying to do a variation on yours, but I’m starting knowing very little and trying to figure things out as I go. Good start, huh? Anyway, I was going through your code and came to a part that has to do with the wp_tiny_mce_preload_dialogs() function you discuss above. There is the following if-statement in the add_hooks function of backend.php that appears to be a check of the version of WordPress that is being used:

    if((int) get_bloginfo(‘version’) >= 3.2)

    But should it be “(float)” instead of “(int)”? For example, if the version being used is 3.2, won’t (int)3.2 return the integer 3 and, therefore, not be >= 3.2?

    Please remember, I said I’m starting knowing very little.

    Thanks,
    Tim

    • Hi Tim,

      You are absolutely right here, a stupid mistake from my side. I’m surprised none of the users running WP <3.2 noticed it yet. Thanks!

      O and good luck on your plugin! Be prepared, TinyMCE and WordPress equals *@!#!. There are some updates coming for WP 3.3 which should make things easier though. :)

  6. Not stupid, just a good challenge for me. Glad it helped.

    It looks like you’ve added the ability to use the widget multiple times on a page. When I tried to do that with 1.0.6, the second widget, upon creation, would have values in the title and text from the first widget and wouldn’t save the new text I tried to put in. Now, with 1.0.7 I can do that. Awesome!

    Thanks and great work!
    Tim

  7. I’m newer than new here so please don’t get annoyed. I downloaded WYSIWYG Widget the other day.. of course I can’t get it to work. I read the above but I don’t know where to go to input the scripting… I’m very confused, but I don’t want plain text- please help!

  8. Hi Danny,

    Really good.
    But not working for me.
    I’m making a plugin wich is adding TinyMce on the fly with javascript and tinyMCE.execCommand(‘mceAddControl’, false, … )

    My problem is the WP-link dialog is not working.

    What could i do please ?

    • Hi Yann,

      Some things have changed in the latest WP update (WP 3.2+), so first of all, what version are you running? Check if the dialog is visible in your admin_footer. If not, you should add the appropriate hook that prints the dialog in your admin_footer. Let me know how things are working for you, as this is a delayed response you’ve most likely already fixed the issue!

  9. I’ve implemented your solution but I get this javascript error when trying to insert an image into the editor :

    Uncaught TypeError: Object [object DOMWindow] has no method ‘send_to_editor’

    I’m using WP 3.2.1

  10. Hi, great article, but i am having still one bug.
    I am using WordPress 3.2.1

    And i am trying to add wysiwyg editor in my plugin, everything renders fine. But the problem i have is that the upload/insert links not working and nothing pops-up :/ What might be the reason?

    • Hi Paulus,

      Sorry for the delayed response. At the moment the TinyMCE that comes with WP 3.2.x isn’t that stable and things are going to be updated in feature WP versions. I am waiting for those versions to update my plugin according to those changes. Please be patient in the meantime. :)

      Cheers, Danny.

  11. Hi Danny,

    Thanks for the great tutorial. However, the Upload/Insert media buttons aren’t displaying in my custom menu page. I’m using WordPress 3.2.1. What could I be missing?

  12. I’ve used this method of adding multiple editors before, however the link popup window doesn’t work because of interfering ID’s.

    When the main editor is in VISUAL mode, when the other mce_editors loads the link pop does appear, but the ‘add link’ button doesn’t do anything and reloads the entire page.

    However, when I switch the main editor to HTML, and reload the page (so VISUAL doesn’t load), the link button works on all the additional editors?

    So it seems the main editor JS is interfering with the generated editors.

    I haven’t found a solution yet.

  13. Awesome! I thought implementing tinyMCE editor would definitely take some time. But your guide made it very easy (implementing it on WordPress 3.2 is simpler, I should say). It works like a charm, thanks a lot!

  14. Hi,
    the script is working great, but it clears (line breaks) when switching between WYSIWYG editor and HTML editor.

    How can I set it not to clear line breaks?

  15. Thanks! This works on 3.3.1 on custom post types, but doesn’t work when trying to multiple editors to the media uploads window.

    Adding meta boxes to the media upload box requires manipulating the fields as a string, as wp_editor() is a function I cannot see how to output this as a string to the fields, and call javascript to enable the boxes?

    I’ve seen people using ob:

    ob_start();
    wp_editor(“”,$editor_id,$editor_settings);
    $ic = ob_get_clean( );

    But I cannot get it to work.

  16. Hi Tom, i didn’t understand what you try to archieve but
    it should be:

    ob_start();
    wp_editor(“”,$editor_id,$editor_settings);
    $ic = ob_get_contents( );
    ob_end_clean();

    then simply echo $ic.

    if you try to dynamically add an editor instance (via ajax)there a some more things to do in order to get the editor working.

  17. Hi Kai

    THanks for the reply, yes I noticed that. I have the editor dynamically added, but I don’t know what else is needed via javascript in order to enable the editor?

  18. Before I try to answer this question. Are you adding this editor where the native editor is already present (any post/page/cpt edit screen) or somewhere else.

  19. Well ok, never done or tried this before.

    Just to make sure we have the same base situation:

    I’ve made a quick test by using this example to add the Editor as an extra field:
    http://www.billerickson.net/wordpress-add-custom-fields-media-gallery/

    This works so far, and the editor markup shows up.

    I guess you know how to add custom js script to the window.

    This is far from complete/perfect but should give you an idea where to start:
    http://pastebin.com/HB7tNbCE

    This has to be called on the media uploader. I didn’t try this with new uploads but on the media library tab this works.

    Switching between visual mode and html, Quicktags..those things won’t work yet.

    But maybe this is helpful for you though.

  20. Hey Tom,

    i’ve got this working on my local server.
    Maybe it’s better if we stop spamming Dannys blog. Feel free to contact me via mail and i’ll send you the two files i have. kai {AT.ungestaltbar.de}

  21. Hi
    Thanks for the tutorial. I am trying to load wp_editor through wordpress admin ajax but I am not able to display it properly. No icons but visual/html and media upload are displayed. Also it is not working as normal. But without ajax everything is fine.

    I saw the source and see that the wp adds some js in the footer for tinymce. But how to do the same when loaded via ajax.

    Thanks.

  22. Hey All,

    First off, thanks for the great resource!
    However, im having some issues getting it to work, for me, the
    wp_tiny_mce( false, array( “editor_selector” => “wysiwyig_editor” ) );
    does not work :( and since theres already a editor on the page, i cannot use the “the_editor()” call.

    Im on wordpress 3.3.1, trying to tweak an existing plugin (i know, baaaad) to have the pretty editor. (the plugin is ‘enhanced header / footer injections’)

    I’ve added an action (next to the existing actions) for it like so;
    add_action( ‘admin_print_footer_scripts’, ‘nlws_efhi_admin_footer’);
    And defined the function ‘below that’ like so;
    function nlws_efhi_admin_footer() {
    wp_preload_dialogs( array( ‘plugins’ => ‘wpdialogs,wplink,wpfullscreen’ ) );
    }

    But it totally seems to skip over the wp_tiny_mce calls i made, i made those inside an action wich i tried to add to ‘admin_head’ and later ‘wp_head’, but with no succes (in backend)

    So, does anybody know if the above still works in 3.3.1? and if so, can you spot from the (semi good) description above what im doing wrong??
    To me, the problem appears to be that the wp_tiny_mce calls dont work, but im unsure how to verify/debug this.

    Any help highly appreciated.
    Best regards,
    Olivier

  23. I just noticed the order in which i explain my issue is a bit vague (prolly not helped by my lumberjack english skills) so to follow up, a little elaboration;

    I added the wp_tiny_mce calls to an action;
    add_action( ‘wp_head’, ‘nlws_ehfi_load_tiny_mce’);

    Wich points to the function;
    function nlws_ehfi_load_tiny_mce() {
    wp_tiny_mce( false, array(“editor_selector” => “wysiwyig_editor1″) ); // true gives you a stripped down version of the editor
    wp_tiny_mce( false, array(“editor_selector” => “wysiwyig_editor2″) );
    }

    Wich in turn should enable it for 2 textareas in the page, with class wysiwyig_editor1 & wysiwyig_editor2

    That, however, doesnt happen, searching for a reason ive been looking at the wp_preload_dialogs call, but i just tested with a quicky echo and that part actually does work, so its just the wp_tiny_mce calls that dont work :(

    Any ideas?
    Thanks in advance, sorry for the vague message before this
    Best regards,
    Olivier

  24. Thanks Bro it’s working great for me. but i have one question.
    When i insert an image in editor and press the submit button then how can i get the image contents?
    Please Reply

    Thanks

  25. Thanks, but useless. Given that there is no mention of WHERE to put these various commands. And don’t say ‘functions.php’. My WP installation has about 30 of them.

    • 30 functions.php files? The theme you are running should have only 1. Anyway, I figured if you are into developing WordPress plugins you know where to put these functions. This article is outdated nowadays anyway. Hope you figured it out by now though.

Leave a Reply