Third & GroveThird & Grove
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') {
    return;
  }
  $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) {
        // event.data is the element that's being inserted.  We only care about
        // table elements in this example.
        if (event.data.getName() != 'table') {
          return;
        }
        // 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.
        event.data.appendTo(div);
        // Replace the original element with the wrapper.
        event.data = div;
      }, null, null, 1);
    }
  });
})(jQuery);

 

 

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.
db_merge('wysiwyg')
  ->key(array('format' => 'full_html'))
  ->fields(array(
    'settings' => serialize($profile->settings),
  ))
  ->execute();
 
wysiwyg_profile_cache_clear();

 

 

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.