Building a WYSIWYG plugin in Drupal
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; }
- 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; }
// $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);


Comments
Anonymous (not verified)
Tue, 12/21/2010 - 19:23
Permalink
This is great info, thanks a lot!
Drew (not verified)
Tue, 08/09/2011 - 17:21
Permalink
thanks Marcus - exactly what I needed - will thank you in beer form some time soon.
skiller (not verified)
Fri, 11/11/2011 - 11:27
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)
Sun, 12/18/2011 - 01:35
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
Add new comment