Building a WYSIWYG plugin in Drupal
This blog post is more than 10 years old, so the content may be out of date.
As developers, we usually praise and curse WYSIWYG editors equally. They all suffer from issues, but they're usually better than the alternative - trying to convince clients and content editors to use raw HTML? Not likely!
These usually work with input filters: say for example, you have a YouTube plugin which lets you enter a video ID and embeds the video in the post.
The input filter would probably take something like [youtube:mELysb2vcrc], and translate the code in square brackets into the HTML code required to embed the YouTube player.
Wouldn't it be great if - instead of having to remember silly square-bracket syntax - you could simply click the YouTube icon in the WYSIWYG toolbar, type the video ID into a popup box, and click OK? This is where wysiwyg integration comes in.
The module code
The module code's simple: you just implement a hook:
/** * Implementation of hook_wysiwyg_include_directory(). * * This tells the Wysiwyg module to search within the 'plugins' directory for * Wysiwyg plugins. * * @param String $type * The type of plugin being checked. One of: * - editor: for WYSIWYG editors such as TinyMCE, CKEditor, Nice Edit, etc. * - plugin: for toolbar buttons such as bold, add-image, strike-through, etc. * * @return String * The path to the plugin directory (relative to this module). This is usually * simply the plugin-type: e.g. "plugin" or "editor". */ function wysiwyg_plugin_example_wysiwyg_include_directory($type) { return $type; }
You then create a directory/file structure:
- plugins - $pluginName - $pluginName.css - $pluginName.js - images (if needed) - langs - en.js - $pluginName.inc
Within $pluginName.inc, you add a specially named hook implementation:
/** * Specially named implementation of hook_wysiwyg_plugin(). * * Should be named {$module}_{$plugin}_plugin(). */ function wysiwyg_plugin_example_foo_plugin() { $plugins['foo'] = array( 'title' => t('Foo: an eample wysiwyg plugin'), // The 'icon file' is the icon that appears in the Wysiwyg toolbar. 'icon file' => 'foo.toolbar_icon.gif', 'icon title' => t('An example wysiwyg plugin'), 'settings' => array(), ); return $plugins; }
The $pluginName.css file is required to avoid 404s, but can be empty if your plugin doesn't require custom css (there may well be a way to avoid this - comments/feedback welcome!)
The $pluginName.js file looks after what happens when you click the toolbar icon, or enable/disable the WYSIWYG editor. In this example, we simply add a HTML comment (which is represented in the WYSIWYG by an icon).
// $Id$ (function ($) { Drupal.wysiwyg.plugins['foo'] = { /** * Return whether the passed node belongs to this plugin (note that "node" in this context is a JQuery node, not a Drupal node). * * We identify code managed by this FOO plugin by giving it the HTML class * 'wysiwyg_plugin_example-foo'. */ isNode: function(node) { res = $(node).is('img.wysiwyg_plugin_example-foo'); return ($(node).is('img.wysiwyg_plugin_example-foo')); }, /** * Invoke is called when the toolbar button is clicked. */ invoke: function(data, settings, instanceId) { // Typically, an icon might be added to the WYSIWYG, which HTML gets added // to the plain-text version. if (data.format == 'html') { var content = this._getPlaceholder(settings); } else { var content = '<!--wysiwyg_example_plugin-->'; } if (typeof content != 'undefined') { Drupal.wysiwyg.instances[instanceId].insert(content); } }, /** * Replace all <!--wysiwyg_example_plugin--> tags with the icon. */ attach: function(content, settings, instanceId) { content = content.replace(/<!--wysiwyg_example_plugin-->/g, this._getPlaceholder(settings)); return content; }, /** * Replace the icons with <!--wysiwyg_example_plugin--> tags in content upon detaching editor. */ detach: function(content, settings, instanceId) { var $content = $('<div>' + content + '</div>'); $.each($('img.wysiwyg_plugin_example-foo', $content), function (i, elem) { elem.parentNode.insertBefore(document.createComment('wysiwyg_example_plugin'), elem); elem.parentNode.removeChild(elem); }); return $content.html(); }, /** * Helper function to return a HTML placeholder. * * Here we provide an image to visually represent the hidden HTML in the Wysiwyg editor. */ _getPlaceholder: function (settings) { return '<img src="' + settings.path + '/images/foo.content_icon.gif" alt="<--wysiwyg_example_plugin->" title="<--wysiwyg_example_plugin-->" class="wysiwyg_plugin_example-foo drupal-content" />'; } }; })(jQuery);
I'm currently looking for a good place to contribute this knowledge to Drupal.org - possibly to the wysiwyg module or a new wysiwyg-examples module, and a handbook entry.
Comments
Anonymous (not verified)
December 21, 2010 - 7:23pm
Permalink
This is great info, thanks a lot!
Drew (not verified)
August 9, 2011 - 5:21pm
Permalink
thanks Marcus - exactly what I needed - will thank you in beer form some time soon.
skiller (not verified)
November 11, 2011 - 11:27am
Permalink
Nice job! But I have a question: what if I want to create a dialog? How can I implement a dialog and show it?
paul (not verified)
December 18, 2011 - 1:35am
Permalink
Thanks dude,
very short and informative. Your function signature explanation {$module}_{$plugin}_plugin() saved my day ;)
@skiller: look at the wysiwyg_imageupload module to see how a dialog is built.
thanks
Paul
dc-systems (not verified)
August 11, 2012 - 11:26am
Permalink
Lifesaver. This is literally the only place on the net I could find this info - and it still works in Drupal 7.14. (At first I wasn't sure where to create the plugins directory/file structure - but of course it just goes inside my own module directory.) Many, many thanks.
samirm mankar (not verified)
September 17, 2012 - 11:40am
Permalink
nice and very helpful guidelines.
jamiew (not verified)
September 19, 2012 - 11:37am
Permalink
Thanks helped me a lot
Alex (not verified)
October 15, 2012 - 10:05am
Permalink
Great info here. Managed to work this out before finding your post but stuck on the next bit of my plugin. I am trying to use the tinyMCE windowManager to create a popup box to allow the user to make a selection. Please could you let me know how to do this using this method.
Native plugins like emoticons use this method:
Jen (not verified)
October 15, 2012 - 8:21pm
Permalink
This was very helpful! Thank you for posting it!
x7ian (not verified)
July 17, 2014 - 4:43am
Permalink
My friend, where can i find more documentation on this subjext, particularly the javascript api. I need to make the buton show a popup window, recieve some input and then insert something in the wysiwyg, but i cant find mor information on the api, this is almost the only source i can find in the web.
Thank you!
Add new comment