Integrate tinyMCE into a WordPress widget

So, the native WordPress text widget is great, right? It allows users to insert virtually any form of content into a widget, provided they either want plain text or know a bit of HTML. The fact that this widget can be used in multiple instances is also awesome. Recently, I’ve needed to provide a bit more control though. Hence, my integration of tinyMCE.

Before I start, this tutorial assumes that you have a widget up and running (multi-instance or a conventional single instance widget) that has a text area which will be replaced with a tinyMCE editor. This tutorial is only about the integration. In my research on this topic, I came across a support query where a user was experiencing the same issue I was having: the content of the tinyMCE replaced text area was not saving. After a bit of testing, I found the solution.

1. Make sure you have a folder of tinyMCE in your theme or wherever your widget code is located. The location isn’t important, it just helps to keep everything pertaining to the widget in the same place.

2. Write a PHP function to initialise tinyMCE. This function will include the tinyMCE Javascript file, as well as run the tinyMCE.init() function to setup our editor blocks.

3. Add an action to the admin_print_scripts on the widgets.php page. This action will run the function declared in step 2.

4. Customise the editor instance (which theme, which buttons, etc) to suit your widget’s requirements. Support on this comes bundled with tinyMCE in the form of example files, and is also available via the support documents on the tinyMCE website.

And that’s it, folks. 🙂 I can post up snippets of the code for each step in a bit, if it would help. 🙂 The above process also replaces all textareas on the widgets page, with a tinyMCE editor.

Updated

This is what the code structure looks like:

function NAME_OF_INIT_FUNCTION()
{
echo 'INSERT YOUR tinyMCE JAVASCRIPT HERE... CALL THE FILE AND RUN THE init FUNCTION';
}

add_action(‘admin_print_scripts-widgets.php’, ‘NAME_OF_INIT_FUNCTION’);

Other resources on the topic

Use TinyMCE in your WordPress 2.8 Plugin > Brolly

Update- This code was posted in the comments by Michael. It has been moved to the post for consistency.

File Paths
define('TMWD_FILE_PATH', dirname(__FILE__), true);
define('TMWD_DIR_NAME', basename(TMWD_FILE_PATH), true);
define('SITE_URL', get_option('siteurl'), true);
#> Plugin Folder and URL to folder
define('TMWD_FOLDER', dirname(plugin_basename(__FILE__)), true);
define('TMWD_URL', SITE_URL.'/wp-content/plugins/' . TMWD_FOLDER, true);
#> hooks
add_action( 'widgets_init', 'tmwd_init' );
add_action('admin_head-widgets.php', 'tinymce');

#> add tinyMCE javas cript to header
func tion tinymce() {
echo ‘<script type=“text/javascript” src=”/jscripts/tiny_mce/tiny_mce.js”>’;
}

#> register wid get
func tion tmwd_​init() {
register_​widget( ‘HTMLContent_​Widget’ );
}

#> Widget Class
class HTMLContent_​Widget extends WP_​Widget {

#> con struct
func tion HTMLContent_​Widget() {
#> set tings
$widget_​ops = array( ‘class name’ => ‘htm l con tent’, ‘descrip tion’ => __(‘Widget to add HTML con tent to Widget Area.’, ‘htm l con tent’) );
$control_​ops = array( ‘width’ => 600, ‘height’ => 350, ‘id_​base’ => ‘htmlcontent-​​widget’ );

#> cre ate wid get
$this->WP_Widget( ‘htmlcontent-​​widget’, __(‘HTML Content Widget’, ‘htm l con tent’), $widget_​ops, $control_​ops );
}

#> tem plate dis play
func tion wid get( $args, $instance ) {
extract( $args );
#> html con tent
$con tent = $instance[’content’];
echo $before_​widget;
if ( $con tent ) { printf( ‘%1$s’, $con tent ); }
echo $after_​widget;
}

#> save wid get con tents
func tion update( $new_​instance, $old_​instance ) {
$instance = $old_​instance;
$instance[’content’] = $new_instance[’content’];
return $instance;
}

#> dis play wid get in wid gets screen
func tion form( $instance ) {

#> Defaults
$defaults = array( ‘con tent’ => __(‘TODO :: ADD Your HTML here.’, ‘htm l con tent’));
$instance = wp_​parse_​args( (array) $instance, $defaults );
#> TinyMCE Setup Instances
?>

tinyMCE.init({
mode : “tex tareas”,
theme : “advanced”,
editor_selector:“get_field_id( ‘con tent’ ); ?>”,
plu gins : “safari, pagebreak, style, layer, table, save, advhr, advimage, advlink, emotions, iespell, inlinepopups, insertdatetime, preview, media, searchreplace, print, contextmenu, paste, directionality, fullscreen, noneditable, visualchars, nonbreaking, xhtmlxtras, template”,
/​/​ Theme options
theme_​advanced_​buttons1 : “save,newdocument, | ,bold, italic, underline, strikethrough, |, justifyleft, justifycenter, justifyright, justifyfull, styleselect, formatselect, fontselect, fontsizeselect”,
theme_​advanced_​buttons2 : “cut, copy, paste, pastetext, pasteword, |, search, replace, |, bullist, numlist, |, outdent, indent, blockquote, |, undo, redo, |, link, unlink, anchor, image, cleanup, help, code, |, insertdate, inserttime, preview, |, forecolor, backcolor”,
theme_​advanced_​buttons3 : “tablecontrols, |, hr, removeformat, visualaid, |, sub, sup, |, charmap, emotions, iespell, media, advhr, |, print, |, ltr, rtl, |, fullscreen”,
theme_​advanced_​buttons4 : “insertlayer, moveforward, movebackward, absolute, |, styleprops, |, cite, abbr, acronym, del, ins, attribs, |, visualchars, nonbreaking, template, pagebreak”,
theme_​advanced_​toolbar_​location : “top”,
theme_​advanced_​toolbar_​align : “left”,
theme_​advanced_​statusbar_​location : “bot tom”,
theme_​advanced_​resizing : true,
setup : function(ed) {
ed.onChange.add(function(ed) {
tinyMCE.triggerSave();
});
}
});

<tex tarea name=“get_field_name( ‘con tent’ ); ?>” class=“get_field_id( ‘con tent’ ); ?>” id=“get_field_id( ‘con­tent’ ); ?>”>
end class
?>

Thanks for this code, Michael.

31 Comments

    1. Hey Jennifer. 🙂

      Thanks for your comment.

      No problem. I’m going to set up syntax highlighting as well, which will certainly help visually. 🙂

      Cheers,
      Matt.

  1. Actually, I think I figured out how to implement what you have there. Unfortunately, it’s still not working 🙁 If I view source, I can see the tinymce code in the header of the widgets page (so it’s calling my tinymce init function in my widgets/plugin), but it still isn’t applying the tinymce to my textarea in my widget. I can’t figure out what else I’m missing to make it work…

    1. Are you using the WordPress integrated tinyMCE? I’m using a dedicated copy in my theme folder (where the widget code is).

      Do you have Firebug installed? If so, does it return any error messages?

      Oh, and is the path to the tinyMCE files an absolute path? I create this path using the get_bloginfo() function.

  2. Ok – so this is how far I’ve gotten: I was linking to the wordpress bundled tinymce. The original problem was that I had wanted a simple editor – but for some reason only the advanced editor would display. So it shows up in the widget, but when I go to save my widget, it doesn’t save the text changes, and then reverts the textarea back to the non-tinymce view. I’m beginning to wonder if this is an issue with the new widget class in 2.8 because that just seems particularly odd.

    1. I ran into the same issues.

      To have control over the editor displayed in the widgets, I decided to go with a fresh non-Wordpress instance of the tinyMCE code. This afforded me the control and simplification of the editor that I sought.

      Due to the integration of the above method I chose, this also resolved the issues of preserving the text editor and applying the changes made when using the editor.

      I hope this helps, Jen. Let me know if you require further assistance. 🙂

  3. Ok – I put the tinymyce folder in folder with my plugin, linked to that instead, the editor shows up on the widget, but when I go to save the changes/widget – it doesn’t save the textarea content (saves the other fields I happen to have in the widget – just not the textarea field with the tinymce) and again, after that save, the textarea reverts back to the non-tinymce view… 🙁

  4. Sorry to spam your thread 🙂 The other weird thing… after it changes to the non-tinymce view, any changes I make after that point in that textarea ARE saved… it just doesn’t want to save the textarea content with the tinymce view “on”…

    1. It’s cool. 🙂

      I’m not sure about the first issue you’ve mentioned… about the content not saving when edited with the editor. The only thing I can think of off the top of my head is the tinyMCE “mode” option. I have this set to “textareas”. Do you have this as well?

      I have also experienced the issue of the editor not coming back after the first save. I’ll be looking into this and will post if I find a solution. 🙂

  5. There’s got to be a better solution than this – but because I have a way-to-tight deadline for this, this workaround will have to do… I’m going to use the “add/remove editor” toggle in tinmyce and just make my changes with the editor – toggle the editor OFF and then save the changes. It works – but it’s kinda stupid it has to be that way…

    1. My first thought is that the issues are unrelated to the WordPress 2.8 Widgets API, as the tinyMCE integration isn’t directly modifying the code of the widgets, per-say. It’s targeting all textareas on the page where the init function is called.

      If I come across a solution to the disappearing editor bug, I’ll post it as soon as I do. 🙂

  6. Oh – FYI – another solution that’s working better (and also has solved some serious lag on the widgets page – I’ve now turned on “accessibility mode” – not as slick as before with being able to drag drop widgets, etc. – but that wasn’t really working too well for me anyway…

    1. Hi Candice.
      Thanks for your comment.

      I have not yet attempted integration of a tinyMCE editor with a text widget in WordPress 2.8.

      As soon as I have results, I’ll post my findings here. 🙂

      Cheers,
      Matt.

    1. Thanks Candice. Switching to “exact” mode would be my next step, after including and setting up the editor. 🙂

      How is your widget/plugin to integrate tinyMCE into the text widget going?

  7. I’ve got it working now.. but only when the Accessibility Mode is turned on. When that’s on, everything works perfectly.

    If AM is off (e.g. the default drag & drop mode) ::
    — then it loads up the tinyMCE thing and lets you edit the text and do all your fancy doodads to it and then when you hit “Save” it switches back to the regular text editor (sans tinyMCE) and has lost all the changes you made while the tinyMCE stuff was working.

    1. Great. 🙂

      So the next step is to get it working without AM. 🙂

      I should have a bit of time today to do some research and testing into this. 🙂

  8. It seems the issue to this problem is with how wordpress is handling the ajax requests. TinyMCE.init is called on load when the widgets page is loaded. In order to keep the editor intact it will require recalling the init function after the ajax request completes. Maybe using jquery’s live feature to bind to the textarea’s class? I will keep ya’ll updated on my progress if i get this feature to work without the AM.

    1. Thanks, Michael. 🙂

      The use of jQuery’s live() sounds like a pretty solid solution to me. This may prevent users using a pre-1.3 version of jQuery from using this feature as, if I understand correctly, live() has been included only since jQuery 1.3. This can, however, easily be resolved by including the jQuery library from Google Code instead of relying on the native WordPress jQuery library. 🙂

      Thanks for posting, Michael. I look forward to reading your progress updates. 🙂

      Cheers,
      Matty.

  9. Here’s a correction to my previous post: the live function wouldn’t work in this situation since it handles events such as click, mouseover etc.

    I did however get tinyMCE to load into a widget in wordpress 2.8.3. For those of you having trouble getting the editor to save in the widget form, you must include this code into the tinyMCE.init function :

    setup : function(ed) {
    ed.onChange.add(function(ed) {
    tinyMCE.triggerSave();
    });
    }

    Now the main problem with this situation was that wordpress loads the form again after you save. Disabling the editor. What I did was in the update function of the widget I pass a variable to define that the content has been updated. Then in the form display code I check for this variable and recall the init function to get the editor back into the widget.

    After I tidy up my code a bit I will post it and hopefully it will help a lot of you guys out. =)

  10. Here it is cleaned up and fully functional … Please note you will need to place the TinyMCE libraries into the directory of the plug-in. Hope you enjoy =)

    (Code snippet moved to main post content, for consistency.)

  11. Hi all, I had lots of problems trying to get WordPress’ TinyMCE code to work with my plugin nicely. I kept running into problems trying to load the language translations. This resulted in having all these ugly titles in the link and image insert menus. I was including the javascript manually because using wp_enqueue_script(‘tinymce’) didn’t seem to work.

    The solution was to simply call the following function in the template_redirect action (wp_head might work as well):

    wp_tiny_mce();

    Then I simply inserted my initialization code, and everything works, language translation and all!

    /* */

    Here’s my blog post on the subject: [ Link moved to main blog post. Thanks Dan. 🙂 ]

Leave a Comment

Your email address will not be published. Required fields are marked *