Almost a year ago I wrote a couple of posts about customizing CKEditor when implementing it with the WYSIWYG module. In the second post I showed how to integrate a custom button and dialog window into the editor.
The method I used to insert the button, however, was a bit of a hack. At the end of the post I alluded to integrating our dialog as a CKEditor plugin. Today we're going to do just that. We'll start by writing a plugin for CKEditor using it's own API. Then, we'll integrate it into the CKEditor toolbar using module hooks from the WYSIWYG module as well as the CKEditor module. By the time you're done this tutorial you'll be controlling CKEditor with the power of a level 99 Final Fantasy Summoner.
This tutorial should work for either Drupal 6 or Drupal 7. If you want to skip the tutorial and just browse the module code (there's lots of comments), I've attached a zipped copy of the finished module at the bottom of the post.
1. Creating the CKEditor plugin
The first step is to create the CKEditor plugin. This is going to be a native CKEditor plugin that will work with both the WYSIWYG module as well as the CKEditor module. CKEditor plugins are actually pretty simple to implement. There's a nice tutorial on the CKEditor site that has everything you need to get started. That combined with what we learned in part two of this tutorial series is all we need to get this plugin working.
Alright so we'll start by creating a new folder "plugins" in our ckeditor_custom module. Then, we'll create a folder for our plugin. We'll be using the same dialog from before which inserts a youtube video iframe into the content area, so we'll call our plugin "youtube". Create a file called "plugin.js" in the youtube folder as well as a folder called "images" for any images the plugin might need (in our case it's just a toolbar icon that we pulled from google images and resized to 16x16 pixels). When you're done your folder heirarchy should look like this:
This is the stock folder heirarchy for CKEditor plugins. The next step is to write the plugin code in plugin.js.:
You might notice a lot of this code is very similar to what we did in the last tutorial. The code to register the dialog as well as the dialog definition itself is exaclty the same. The big difference is that we're registering our dialog command as an actual CKEditor plugin (using CKEDITOR.plugins.add), rather than just cramming it into the editor after it's already been initialized. Speaking of which, we need to clean up the old dialog code from ckeditor_custom_config.js. Just delete everything from line 65 onward.
2. Integrating with the WYSIWYG Module
So now that we've written our plugin, how do we let CKEditor know about it? Well, the WYSIWYG module has a hook for integrating native plugins into it's supported editors: hook_wysiwyg_plugin(). You just provide some information about where your plugin code lives and the WYSIWYG module does the rest:
With this hook, the WYSIWYG module will know to load our plugin when it initializes CKEditor. It will also list our plugin on the WYSIWYG profile administration page. There's just a little bit of cleanup we need to do before we can test it out. Firstly, we need to remove bit of code from ckeditor_custom_wysiwyg_editor_settings_alter() in ckeditor_custom.module where we manually added our youtube plugin. We can also remove the css we added to style the button. Just remove this block (line 88-93):
// This is our new youtube command / dialog that we created in // ckeditor_custom_config.js. If we don't add this here, it won't // show up in the toolbar! $new_grouped_toolbar = array('YouTube'); // Add a css file to the page that will style our youtube button drupal_add_css(drupal_get_path('module', 'ckeditor_custom') . '/ckeditor_custom.css');
Secondly, and this is optional, you can add our new plugin to our re-ordered preferred groupings in ckeditor_custom_wysiwyg_editor_settings_alter(). I added mine just after the "Image" button.
... $preferred_groupings = array('Image', 'YouTube', 'Link', 'Unlink', 'Anchor', '-'); ...
And that's it. Load up one of your WYSIWYG profile settings at admin/config/content/wysiwyg and enable the plugin in the "Buttons and Plugins" section. Then, load up a page with the editor on it and check out your button in all it's glory.
FUN FACT: The WYSIWYG module also includes a nifty API for writing cross-editor Drupal plugins using the hook: hook_INCLUDE_plugin(). This is how a module like media can implement a cross-editor media button. For more info about the WYSIWYG editor API check out wysiwyg.api.php.
3. Integrating with the CKEditor module
Okay, okay, I know that this is supposed to be a series of posts specifically about CKEditor and the WYSIWYG module, but I figure it wouldn't hurt to show you how to integrate our plugin into the CKEditor module. It's actually quite similar to the WYSIWYG module:
And that's it. Just enable the plugin in the plugins management section of the profile settings, then put your button where you want it to go using the drag 'n drop interface of the CKEditor module and you're good to go!
Congratulations! You've just created your very own CKEditor plugin and integrated it properly, or as some might say, the "Drupal Way". You've also just completed the final chapter of the CKEditor & the WYSIWYG Module tutorial series! In addition to this new custom plugin, you should also be able to customize existing CKEditor plugins as well as reorganize and group buttons in the toolbar. Although, on that last one, it looks like an effort to add some sort of button management to WYSIWYG has been made by the project maintainer recently which is exciting.
So, that's it for this one. I hope you've learned something useful along the way. Here are the links to download the finished modules in case you just want to get going without reading through my long-winded tutorial.