Using jQuery and jQuery UI in TinyMCE Dialog Iframe

WordPress is a wonderful tool.  But some things are very difficult to do.  A WordPress plugin I recently created (called Tweet This) adds a button to the WordPress editor toolbar.  This button, when clicked, opens a sizable dialog window with lots of items and a fair amount of jQuery and jQuery UI code.

 

My Toolbar Button:

tinymce-button

 

My Dialog:

gouda-example-0-1024x778

 

 

Getting  jQuery and jQuery UI to work inside the dialog box was challenging because it is poorly documented and not a commonly executed task.  The dialog box was by far the most time and labor intensive aspect of the plugin.  And was the source of many headaches and frustration.  So, now that I’ve figured it out, I want to write it down so I don’t forget!  And, hopefully, it will help you out as well.

 

The Problem

WordPress makes it easy to include jQuery and jQuery UI in admin pages using the wp_enqueue_script function.  However, TinyMCE dialog boxes are opened dynamically as iframes.  They are not loaded in advance, and the source code for the dialog box is independent of the WordPress admin page.

So jQuery isn’t present, and WordPress doesn’t have the capability to load jQuery in the dialog box.  It needs to be included another way.

 

 

The Easy Solution

The easy solution is to simply include jQuery (and jQuery UI if needed) in your dialog box like you would on any HTML page.  You can download it yourself or use Google’s hosted versions.

 

But this is a very inelegant solution.  It slows down the loading of your dialog box dramatically.  And will cause the WordPress plugin folks to reject your plugin because you are creating a dependency on an external source and/or you are re-including a different version of something that WordPress already has, has tested, and approves of.

In other words, this works, but is bad form and unacceptable.

 

The Better Solution

The better solution isn’t terribly difficult in theory, but was awful to figure out how to do.  The documentation wasn’t helpful, and it seemed I was the only human being on the planet not using the easy solution.  But, with information cobbled together from lots of other sources, I figured it out.  And it’s pretty simple to do.

 

In words, what you need to do, is pass jQuery as an argument to your dialog, and pass the dialog box context to jQuery when using it.

Okay, now let’s see what that actually means.  A simplified version of my TinyMCE plugin code is included below.

 

 

The entire plugin initialization code is wrapped in an immediately-invoked function expression (IIFE) since it is all self-contained.  This IIFE takes the jQuery variable from the global scope and uses it inside as the infamous dollar-sign variable ($).  You will need your WordPress plugin to include jQuery in the admin section using the previously mentioned wp_enqueue_script function.

 

The above code register a button and a command with TinyMCE.  The command is tied to the button and it opens a dialog box which loads content from a file called tinymce-dialog.html.  Any arguments you want passed to this dialog are put into an object and passed as the second arguments to windowManager.open().  You can add as many arguments as needed, but you will need to pass at least the jQuery variable which is the last argument in the example above.

 

Then, the contents of tinymce-dialog.html is simply any HTML, CSS, and/or JavaScript you want in your dialog box.  The JavaScript at the bottom shows how to use jQuery.  An explanation is included underneath the code.

 

By passing jQuery as an argument in the plugin initialization code, it is now included in the dialog box document.  You can fetch passed arguments using the following:

Now, the variable args is the object passed in the initialization code:

 

And jQuery is args[‘jquery’].  To make life simple, I assigned jQuery to the $ variable.

 

Now, using jQuery should work the same as normal, with one crucial exception.

jQuery’s context is the parent window, not the dialog box.  Any selectors you use will search the parent document, not the dialog unless you specify that the dialog is the context you want.  This is done by passing the body tag of the dialog element as the second argument in  jQuery’s $ function.  There are multiple ways of getting and using this body tag, but in my opinion, this is the simplest:

Use plain JavaScript to select the first body tag it encounters in the DOM and store it in a variable.  If you have multiple body tags on your page (multiple iframes?), this won’t work, but when using the WordPress post/page editor, the first and only iframe should be your TinyMCE dialog and it works beautifully.

 

 

And now, as long as you remember the context argument, jQuery will work as expected within the dialog.

 

 

Not too difficult once you’ve figured it out.  But I’ve lost many hours figuring it out.  Hopefully, you won’t have the same problem!

 

3 Comments

John Morris

Well, I hope this has helped you out. I posted another post which goes into more detail about the whole TinyMCE dialog process a while ago: http://johnmorris.me/computers/software/how-to-create-a-tinymce-editor-dialog-window-in-a-wordpress-plugin/. That may help too.

I’m actually battling other related problems with TinyMCE in that Tweet This WordPress plugin right now. I really like most of WordPress, but dealing with the editor is absolutely awful and fraught with problems. The number of man hours it has sucked from my schedule is crazy.

Reply
funkyphenix

Thank you very much for this.
First and only tutorial i read which is addressing this (quite) annoying problem of getting jQuery in a tinymce modal window. Life savior !!!

Reply

Leave a Reply