Hey, I just wanted to port this CKEditor code...But I am having trouble with the examples to form off of...It just outputs a piece of text (token) to the body of the editor and I'd like to be able to use it using the WYSIWYG JS API so I can hook into it from another module. Here is the CKEditor code:

CKEDITOR.config.editorial_tokens =  [
   {
      name:'insertcontent',
      icon:'images/content-icon.png',
      html:'[tokenname]',
      title:'A token'
   }
];


CKEDITOR.plugins.add( 'editorial_tokens',
{
   init : function( editor )
   {
      var buttonsConfig = editor.config.editorial_tokens;
      console.log(buttonsConfig);
      if (!buttonsConfig)
         return;

      function createCommand( definition )
      {
         return {
            exec: function( editor ) {
               editor.insertHtml( definition.html );
            }
         };
      }

      // Create the command for each button
      for(var i=0; i<buttonsConfig.length; i++)
      {
         var button = buttonsConfig[ i ];
         console.log('/sites/all/modules/custom/settings/editorial/ckeditor/plugins/editorial_tokens/' + button.icon);
         var commandName = button.name;
         editor.addCommand( commandName, createCommand(button, editor) );

         editor.ui.addButton( commandName,
         {
            label : button.title,
            command : commandName,
            icon : '/sites/all/modules/custom/settings/editorial/ckeditor/plugins/editorial_tokens/' + button.icon
         });
      }
   } //Init

} );

Please help me address.

Comments

rayvan created an issue. See original summary.

TwoD’s picture

Issue summary: View changes
TwoD’s picture

UPDATE: This code is now tested and verified.

You need 3 files.

pga_editorial/pga_editorial.info:

name = PGA Editorial
core = 7.x

pga_editorial/pga_editorial.php:

/**
 * Implements hook_wysiwyg_plugin().
 *
 * Modify the CKEditor image dialog for use with the picture module.
 */
function pga_editorial_wysiwyg_plugin($editor, $version) {
  $plugins = array();
  if ($editor == 'ckeditor') {
    $path = drupal_get_path('module', 'pga_editorial') . '/ckeditor/plugins/editorial_tokens';
    $plugins['editorial_tokens'] = array(
      'path' => $path,
      'buttons' => array(
        'insertcontent' => t('Insert Video Token'),
        'insertcontent2' => t('Insert Gallery Token'),
      ),
      'options' => array(
        'editorial_tokens' => array(
          array(
            'name' => 'insertcontent',
            'icon' => base_path() . $path . '/images/video-icon.png',
            'html' => '[inline-video]',
            'title'  => t('A video'),
          ),
          array(
            'name' => 'insertcontent2',
            'icon' => base_path() . $path . '/images/gallery-icon.png',
            'html' => '[inline-gallery=]',
            'title'  => t('A gallery'),
          )
        ),
      ),
      'load' => TRUE,
      'internal' => FALSE,
      'init' => TRUE,
    );
  }
  return $plugins;
}

pga_editorial/ckeditor/plugins/editorial_tokens/plugin.js:

CKEDITOR.plugins.add('editorial_tokens', {
   init : function( editor ) {
      var buttonsConfig = editor.config.editorial_tokens;
      if (!buttonsConfig) {
         return;
      }

      function createCommand( definition ) {
         return {
            exec: function( editor ) {
               editor.insertHtml( definition.html );
            }
         };
      }
      // Create the command for each button
      for(var i=0; i<buttonsConfig.length; i++) {
         var button = buttonsConfig[i];
         var commandName = button.name;
         editor.addCommand( commandName, createCommand(button, editor) );

         editor.ui.addButton( commandName, {
            label : button.title,
            command : commandName,
            icon : button.icon
         });
      }
   } //Init
} );

Enable the Drupal module and the buttons will show up in the Wysiwyg profile GUI.

rayvan’s picture

That didn't work unfortunately...The JS asset is loading, and I verified the text format profiles checkboxes are enabled for Insert Editorial Token, and I made sure the icon path is a valid path.

Please let me know if you have other suggestions.

TwoD’s picture

Are you getting JavaScript errors in the browser's debug tools?
Is console.log(buttonsConfig); not printing the correct values, if any at all?
Does the button show up in the editor?
I just noticed I missed one property in the hook_wysiwyg_plugin() implementation: 'init' => TRUE.
I'll edit my previous post and add it. It tells the editor to actually include the plugin in its list of plugins to load...

rayvan’s picture

Thanks for the immediate help TwoD, here is the finalized code that worked with your help:

In .module


/**
 * Implements hook_wysiwyg_plugin().
 *
 * Modify the CKEditor image dialog for use with the picture module.
 */
function pga_editorial_wysiwyg_plugin($editor, $version) {

  $plugins = array();
  if ($editor == 'ckeditor') {
    $path = base_path() . drupal_get_path('module', 'pga_editorial') . '/ckeditor/plugins/editorial_tokens'; // You may need to prefix with base_path(), forgot which...
    $plugins['editorial_tokens'] = array(
      'path' => $path,
      'buttons' => array( // This is for Wysiwyg's GUI and so it knows the internal name of the button to enable.
        'insertcontent' => t('Insert Video Token'),
        'insertcontent2' => t('Insert Gallery Token'),
      ),
      'options' => array( // Everything below this key gets converted to JSON and merged into the config object sent to the editor instance.
        'editorial_tokens' => array(
          array(
            'name' => 'insertcontent',
            'icon' => '/images/video-icon.png',
            'html' => '[inline-video]',
            'title'  => t('A token'),
          ),
          array(
            'name' => 'insertcontent2',
            'icon' => '/images/gallery-icon.png',
            'html' => '[inline-gallery=]',
            'title'  => t('A token'),
          )
        ),
      ),
      'load' => TRUE,
      'internal' => FALSE,
      'init' => TRUE,
    );
    return $plugins;
  }
}

In plugin.js:

CKEDITOR.plugins.add('editorial_tokens',
{
   init : function( editor )
   {
editorial_tokens =  [
   {
      name:'insertcontent',
      icon:'/sites/all/modules/custom/settings/editorial/ckeditor/plugins/editorial_tokens/images/video-icon.png',
      html:'[inline-video]',
      title:'Video'
   },
   {
      name:'insertcontent2',
      icon:'/sites/all/modules/custom/settings/editorial/ckeditor/plugins/editorial_tokens/images/gallery-icon.png',
      html:'[inline-gallery]',
      title:'Gallery'
   }
];

      var buttonsConfig = editorial_tokens;
      if (!buttonsConfig) {
         return;
      }

      function createCommand( definition )
      {
         return {
            exec: function( editor ) {
               editor.insertHtml( definition.html );
            }
         };
      }
      // Create the command for each button
      for(var i=0; i<buttonsConfig.length; i++)
      {
         var button = buttonsConfig[i];
         console.log(buttonsConfig[i]);
         var commandName = button.name;
         editor.addCommand( commandName, createCommand(button, editor) );

         editor.ui.addButton( commandName,
         {
            label : button.title,
            command : commandName,
            icon : button.icon
         });
      }
   } //Init

} );
rayvan’s picture

Status: Active » Closed (works as designed)
Issue tags: +insert token into body wysiwyg plugin

TwoD resolved this issue.

This works as designed but I feel there could be more information inside of wysiwyg.api.js or README to the effect of how TwoD resolved this, in this thread. Perhaps just throw the working code sample in there...

rayvan’s picture

Oh, apparently I also needed this in my hook_init for the module (I initially thought it was just loaded by AJAX, but its not):

	drupal_add_js(drupal_get_path('module', 'pga_editorial') . '/ckeditor/plugins/editorial_tokens/plugin.js', array('scope' => 'footer'));
TwoD’s picture

Issue tags: -insert token into body wysiwyg plugin

The relevant documentation is in wysiwyg.api.php. Since you have a native CKEditor plugin, you only need hook_wysiwyg_plugin() and not the information in wysiwyg.api.js. The other plugin hooks and wysiwyg.api.js are for when you want to write a cross-editor plugin using just Wysiwyg module's API.

The hook_init() implementation should not be needed. It would load the plugin on every page, vs just on the edit forms it's needed.

The 'load' => TRUE, 'internal' => FALSE 'path' => .... and 'init' => TRUE directives in hook_wysiwyg_plugin() should tell the editor to load the plugin file from a non-interrnal (not relative to the editor library folder) from the specified path and initialize the plugin on its own.

Initializing and loading, in the case of CKEditor would equate to WYSIWYG adding the plugin name to the config.plugins list. If it's an internal plugin either bundled with the CKEditor library or afterwards installed into its own plugins folder, CKEditor itself knows where to find the plugin file. If 'internal' is FALSE, WYSIWYG sends along the full path to the plugin file and registers that path with CKEDITOR.plugins.addExternal() before creating any editor instances.

TwoD’s picture

I've updated my code in #3 and tested it.

This version removes the need for duplicating the button definitions on both the PHP and JS side of things as the definitions in PHP are sent down to the CKEditor configuration anyway.
It also keeps the paths correct if the module is installed elsewhere and there's no need to add the plugin script using hook_init().

The path to the plugin should be relative to the Drupal root, so no base_path() there, but the paths to the icons needed to be absolute or CKEditor will interpret them as relative to its own root.