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.

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">

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:
Aparrently, wp_tiny_mce_preload_dialogs() no longer exists from WP3.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 the function to preload any dialogs!

If you’re not using the_editor(), make sure to call wp_preload_dialogs() somewhere from your footer in the following manner:


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.

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

Thijs — June 15, 2011 at 5:39 pm

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.

    Danny van Kooten — June 16, 2011 at 10:03 am

    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!

jones — June 16, 2011 at 10:25 pm

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?

    Danny van Kooten — June 16, 2011 at 10:49 pm

    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!

      jones — July 4, 2011 at 6:56 pm

      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.

Kai — June 20, 2011 at 8:53 pm

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

tanie ulotki uk — June 27, 2011 at 12:32 pm

After I open up your Rss feed it appears to be to be a lot of junk, is the issue on my side?

    Danny van Kooten — June 27, 2011 at 1:23 pm

    The issue appears to be on Feedburner’s side. Heard others complain about it as well. I’m sorry, looks like it’s fixed now! :-)

MadtownLems — July 12, 2011 at 6:56 pm

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

    Danny van Kooten — July 13, 2011 at 5:40 am

    Hi Jason,

    Didn’t notice it yet, but tested right away and I’m having the same problem with 3.2 and IE8. Same problem in my WYSIWYG Widgets plugin so I’m gonna look into it ASAP. Do you have any idea what’s causing it yet? :)

    Thanks for mentioning!

Eggroll — July 17, 2011 at 3:29 am

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

    Danny van Kooten — July 17, 2011 at 9:58 am

    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. :)

Eggroll — July 17, 2011 at 8:44 pm

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

Kreative Touch — July 20, 2011 at 6:38 pm

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!

Yann — August 8, 2011 at 4:26 am

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 ?

    Danny van Kooten — August 17, 2011 at 5:43 pm

    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!

Yann — August 18, 2011 at 11:53 am

Hi Danny,

I am with WP 3.2.1.
It’s ok, i’ve fixed my problem.
If just forgot a hook for jquery.

Tanks,
Yann

nebulousGirl — August 18, 2011 at 5:33 pm

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

nebulousGirl — August 18, 2011 at 5:59 pm

Nevermind my previous post I was adding my actions too late and they weren’t even executed.

My bad…

Paulius — August 19, 2011 at 11:23 am

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?

    Danny van Kooten — August 30, 2011 at 8:31 pm

    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.

Sam — September 5, 2011 at 8:37 am

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?

Thom — October 13, 2011 at 3:22 pm

I have the same issue (http://wordpress.org/support/topic/media-upload-buttons-dont-work-as-expected?replies=1). That’s sad to hear .. :(
Thanks.

Ramon Fincken — October 16, 2011 at 6:57 pm

Very nice, but it appears that the CSS stylesheet is missing for the HTML/tiny view, ( 3.2.1 )

Tom — October 21, 2011 at 11:00 am

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.

galih.firm — November 14, 2011 at 2:24 am

Nice tutorial dude!
but i have some trouble here, I have plug the_editor() to my custom widget, but its won’t to save.

any solution??

galih.firm — November 14, 2011 at 2:58 am

the script doesn’t replace the text area, even I change the id.
So it $_POST[] with empty text area

Tejaswini — December 10, 2011 at 2:16 pm

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!

Dustin — December 28, 2011 at 9:05 pm

Thanks for this article Danny. Very helpful!

Neo85 — January 12, 2012 at 10:49 pm

“wp_tiny_mce( false, array( ‘editor_selector’ => ‘wysiwyig_editor’ ) );”

thx buddy this helped me a lot ;-)

Mariusz — January 15, 2012 at 3:38 pm

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?

Tom — January 18, 2012 at 12:37 pm

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.

Kai — January 18, 2012 at 1:37 pm

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.

Tom — January 18, 2012 at 1:45 pm

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?

Kai — January 18, 2012 at 6:01 pm

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.

Tom — January 18, 2012 at 6:08 pm

I think so yes. I’m trying to add the editor to the media upload window, see screenshot of my example:
http://tinypic.com/view.php?pic=14ipno3&s=5

The editor is being called on the page edit window, but the media upload is called in an i-frame so this is separate I believe.

Kai — January 18, 2012 at 7:18 pm

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.

Kai — January 18, 2012 at 7:19 pm

well, Bill Erickson does not have an actual example but the ‘html’ example is the technic i’ve used.

tom — January 18, 2012 at 7:50 pm

amazing thank you Kai, I shall try and implement this tommorow

Kai — January 19, 2012 at 12:00 am

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}

Kumar — March 21, 2012 at 4:00 pm

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.

Olivier — April 10, 2012 at 1:57 pm

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

Olivier — April 10, 2012 at 2:05 pm

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

Usman — April 25, 2012 at 4:10 pm

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

Jerry — December 14, 2012 at 9:54 pm

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.

    Danny van Kooten — January 2, 2013 at 7:50 pm

    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

Pallet Tafels