Dec 22, 2016 - Josh Fremer

Creating a CKEditor plugin with Drupal 7 using WYSIWYG


Sometimes the markup provided by CKEditor is insufficient for your CSS needs. In our case, we needed <table> elements to have a wrapper to satisfy our mobile stylesheet requirements.

To offer this functionality, we need to create a CKEditor plugin. This can be done with or without the WYSIWYG module. My project already has WYSIWYG installed, so I chose to implement hook_wysiwyg_plugin() (if you don't use WYSIWYG, you'll implement hook_ckeditor_plugin() to similar effect):

 * Implements hook_wysiwyg_plugin().
function mymodule_wysiwyg_plugin($editor, $version) {
  if ($editor != 'ckeditor') {
  $plugins = array();
  $plugins['wraptables'] = array(
    'path' => drupal_get_path('module', 'mymodule') . '/plugins/wraptables',
    'filename' => 'plugin.js',
    'load' => TRUE,
    'extensions' => array('wraptables' => t('Wrap Tables')),
  return $plugins;



This tells Drupal that there is a CKEditor plugin available and where to find the javascript for it. In my mymodule module directory, there is a subdirectory named plugins with a directory named wraptables. This contains the plugin.js file that defines the plugin behaviors:



(function($) {
  CKEDITOR.plugins.add('wraptables', {
    init: function(editor) {
      // React to the insertElement event.
      editor.on('insertElement', function(event) {
        // is the element that's being inserted.  We only care about
        // table elements in this example.
        if ( != 'table') {
        // Create a new div element to use as a wrapper.
        var div = new CKEDITOR.dom.element('div').addClass('table-scroll');
        // Append the original element to the new wrapper.;
        // Replace the original element with the wrapper. = div;
      }, null, null, 1);



See the CKEditor documentation for all the things you can do with the CKEDITOR variable.



After implementing the above steps, you'll have a new plugin available. It will still need to be enabled for each profile at admin/config/content/wysiwyg/profile (if you're using the WYSIWYG module) or admin/config/content/ckeditor. This can also be done programmatically:

$profile = wysiwyg_profile_load('full_html');
$profile->settings['buttons']['wraptables'] = array('wraptables' => 1);
// I wasn't able to get entity_save() to work here.
  ->key(array('format' => 'full_html'))
    'settings' => serialize($profile->settings),



If you're using the CKEditor module instead of WYSIWYG, the above code will need to be modified. Use ckeditor_profile_load() instead and check the return value for the correct format.



These are all the steps you need to follow to create a basic plugin. If your extension involves adding a button to the CKEditor interface, I recommend taking a long look at ckeditor_linkchange, a fully-functioning Drupal module with extensive documentation.