Using init callbacks with TinyMCE and wp_editor() in WordPress

WordPress 3.3 introduced wp_editor(). It’s a big improvement over the earlier hacks needed to get a TinyMCE instance on the WP front end. But it broke the feature in my BuddyPress Docs that detected idle time. The problem, in short, was two-fold: my idle-detection JavaScript was loading before the editor was initialized, and it wasn’t detecting key presses inside of the TinyMCE iframe. The solution to both parts of the problem required passing callbacks to the TinyMCE initialization array, in the setup array. It took me a long time to figure out how to do this, so for posterity’s sake, here are some takeaways.

First, the code:

function bp_docs_add_idle_function_to_tinymce( $initArray ) {
	if ( bp_docs_is_bp_docs_page() ) {

$initArray['setup'] = 'function(ed) {
			ed.onInit.add(
				function(ed) {
					_initJQuery();

// Set up listeners
					jQuery(\'#\' + ed.id + \'_parent\').bind(\'mousemove\',function (evt){
						_active(evt);
					});

bp_docs_load_idle();

}
			);

ed.onKeyDown.add(
				function(ed) {
					_active();
				}
			);
		}';
	}

return $initArray;
}
add_filter( 'tiny_mce_before_init', 'bp_docs_add_idle_function_to_tinymce' );

Some notes:

  • I’m passing a ‘setup’ parameter to the TinyMCE init array by filtering tiny_mce_before_init
  • Only do this when you’re editing a BuddyPress Doc – that’s the bp_docs_is_bp_docs_page() check. I don’t want to mess with every instance of TinyMCE on the installation.
  • The setup parameter has to be a string. This gets tricky when the string is supposed to define an unnamed JS callback, because you have to be very careful about escaping quotes. As a string, your callback has to be wrapped in quotes. Also, when WP prints the TinyMCE parameters (and when it sees that your paramater begins with the string ‘function’) it’s going to wrap it in double-quotes. After lots of messing around, I was able to get this to work by using escaped single-quotes. (If you need to double-embed quotes – like a chain of callbacks – use escaped double-quotes.)
  • Where possible, use TinyMCE’s native events. ed.onKeyDown is one of them. It allows me to call my _active() function whenever a key is pressed inside the editor.
  • There are some kinds of actions that aren’t really detectable using TinyMCE’s events. For instance, I wanted to be able to detect when someone was moving their mouse around the iframe and especially TinyMCE’s toolbar. You can see this where I’m binding my callback to mousemove in the TinyMCE _parent element.
  • _initJQuery() and bp_docs_load_idle() are my own functions that need to run after the editor has finished setting up. That’s why they, along with the bind, are called in a callback of ed.onInit – that’s the generic place to put things that need to happen once the editor is up and running.

Using init callbacks with TinyMCE and wp_editor() in WordPress by Boone Gorges, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.

One thought on “Using init callbacks with TinyMCE and wp_editor() in WordPress

Leave a Reply