Changed the toolbar definition format to JSON, added dependency handling. sort_buttons
authorHenrik Danielsson
Tue, 19 Feb 2013 10:47:31 +0000 (11:47 +0100)
committerHenrik Danielsson
Wed, 20 Feb 2013 12:14:34 +0000 (13:14 +0100)
This allows the toolbar to be modified without having JavaScript enabled
and simplifies serialization/deserialization. Changed 'Extensions' to
'Plugins' and made sure plugins required by buttons are automatically
enabled and explicitly stored in the profile when saving the form.

13 files changed:
editors/ckeditor.inc
editors/fckeditor.inc
editors/markitup.inc
editors/nicedit.inc
editors/openwysiwyg.inc
editors/tinymce.inc
editors/whizzywig.inc
editors/wymeditor.inc
editors/yui.inc
wysiwyg.admin.inc
wysiwyg.admin.js
wysiwyg.api.php
wysiwyg.module

index 3fb6253..90b19d8 100644 (file)
@@ -29,7 +29,7 @@ function wysiwyg_ckeditor_editor() {
     ),
     'toolbar groups' => TRUE,
     'toolbar rows' => TRUE,
-    'toolbar separator' => TRUE,
+    'toolbar separator' => '-',
     'install note callback' => 'wysiwyg_ckeditor_install_note',
     'version callback' => 'wysiwyg_ckeditor_version',
     'themes callback' => 'wysiwyg_ckeditor_themes',
@@ -40,7 +40,8 @@ function wysiwyg_ckeditor_editor() {
     'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings',
     'proxy plugin' => array(
       'drupal' => array(
-        'load' => TRUE,
+        'title' => t('Drupal proxy plugin'),
+        'load' => FALSE,
         'proxy' => TRUE,
       ),
     ),
@@ -279,47 +280,33 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) {
   $toolbar = array();
   $extra_plugins = array();
   $plugins = wysiwyg_get_plugins($editor['name']);
-  foreach ($config['extensions'] as $plugin => $buttons) {
-    foreach ($buttons as $button => $enabled) {
-      if (!isset($plugins[$plugin]['extensions'][$button])) {
-        continue;
-      }
-      // Add plain extensions.
-      if (!empty($plugins[$plugin]['load'])) {
-        $extra_plugins[] = $plugin;
-      }
-      // Allow plugins to add or override global configuration settings.
-      if (!empty($plugins[$plugin]['options'])) {
-        $settings = array_merge($settings, $plugins[$plugin]['options']);
-      }
+  foreach ($config['plugins'] as $plugin => $enabled) {
+    if (!$enabled || !isset($plugins[$plugin])) {
+      continue;
+    }
+    // Add plain extensions.
+    if (!empty($plugins[$plugin]['load'])) {
+      $extra_plugins[] = $plugin;
+    }
+    // Allow plugins to add or override global configuration settings.
+    if (!empty($plugins[$plugin]['options'])) {
+      $settings = array_merge($settings, $plugins[$plugin]['options']);
     }
   }
 
-  foreach ($config['toolbar'] as $row) {
-    foreach ($row as $buttons) {
-      $group = array();
-      foreach ($buttons as $button_config) {
-        $plugin = $button_config['plugin'];
-        $button = $button_config['button'];
-        if ($button == 'separator') {
-          $group[] = '-';
-          continue;
-        }
-        if (!isset($plugins[$plugin]['buttons'][$button])) {
-          continue;
-        }
-        $group[] = $button;
-
-        // Add external Drupal plugins to the list of extensions.
-        if (!empty($plugins[$plugin]['proxy']) || empty($plugins[$plugin]['internal']) || !empty($plugins[$plugin]['load'])) {
+  foreach ($config['toolbar'] as $config_row) {
+    foreach ($config_row as $buttons) {
+      $row = array();
+      foreach ($buttons as $button) {
+        // Cross-editor plugin buttons are prefixed by the proxy plugin name.
+        if (strpos($button, '.') !== FALSE) {
+          list($plugin, $button) = explode('.', $button);
+          // @todo Proxy-plugins: remove when allowing multiple buttons.
           $extra_plugins[] = $button;
         }
-        // Allow plugins to add or override global configuration settings.
-        if (!empty($plugins[$plugin]['options'])) {
-          $settings = array_merge($settings, $plugins[$plugin]['options']);
-        }
+        $row[] = $button;
       }
-      $toolbar[] = $group;
+      $toolbar[] = $row;
     }
     $toolbar[] = '/';
   }
@@ -430,6 +417,7 @@ function wysiwyg_ckeditor_proxy_plugin_settings($editor, $profile, $plugins) {
 function wysiwyg_ckeditor_plugins($editor) {
   $plugins = array(
     'default' => array(
+      'title' => t('CKEditor core'),
       'buttons' => array(
         'Bold' => t('Bold'), 'Italic' => t('Italic'), 'Underline' => t('Underline'),
         'Strike' => t('Strike-through'),
index 782fcdb..d5db2d1 100644 (file)
@@ -21,7 +21,7 @@ function wysiwyg_fckeditor_editor() {
     ),
     'toolbar groups' => TRUE,
     'toolbar rows' => TRUE,
-    'toolbar separator' => TRUE,
+    'toolbar separator' => '-',
     'version callback' => 'wysiwyg_fckeditor_version',
     'themes callback' => 'wysiwyg_fckeditor_themes',
     'settings callback' => 'wysiwyg_fckeditor_settings',
@@ -29,7 +29,8 @@ function wysiwyg_fckeditor_editor() {
     'plugin settings callback' => 'wysiwyg_fckeditor_plugin_settings',
     'proxy plugin' => array(
       'drupal' => array(
-        'load' => TRUE,
+        'title' => t('Drupal proxy plugin'),
+        'load' => FALSE,
         'proxy' => TRUE,
       ),
     ),
@@ -143,36 +144,25 @@ function wysiwyg_fckeditor_settings($editor, $config, $theme) {
   $settings['ToolbarSet'] = 'Wysiwyg';
   $toolbar = array();
   $plugins = wysiwyg_get_plugins($editor['name']);
-  foreach ($config['extensions'] as $plugin => $buttons) {
-    foreach ($buttons as $button => $enabled) {
-      if (!isset($plugins[$plugin]['extensions'][$button])) {
-        continue;
-      }
-      // Allow plugins to add or override global configuration settings.
-      if (!empty($plugins[$plugin]['options'])) {
-        $settings = array_merge($settings, $plugins[$plugin]['options']);
-      }
+  foreach ($config['plugins'] as $plugin => $enabled) {
+    if (!$enabled || !isset($plugins[$plugin])) {
+      continue;
+    }
+    // Allow plugins to add or override global configuration settings.
+    if (!empty($plugins[$plugin]['options'])) {
+      $settings = array_merge($settings, $plugins[$plugin]['options']);
     }
   }
 
   foreach ($config['toolbar'] as $row) {
     foreach ($row as $buttons) {
       $group = array();
-      foreach ($buttons as $button_config) {
-        $plugin = $button_config['plugin'];
-        $button = $button_config['button'];
-        if ($button == 'separator') {
-          $group[] = '-';
-          continue;
-        }
-        if (!isset($plugins[$plugin]['buttons'][$button])) {
-          continue;
-        }
-        $group[] = $button;
-        // Allow plugins to add or override global configuration settings.
-        if (!empty($plugins[$plugin]['options'])) {
-          $settings = array_merge($settings, $plugins[$plugin]['options']);
+      foreach ($buttons as $button_name) {
+        // Cross-editor plugin buttons are prefixed with the proxy plugin name.
+        if (strpos($button_name, '.') !== FALSE) {
+          list($plugin, $button_name) = explode('.', $button_name);
         }
+        $group[] = $button_name;
       }
       $toolbar[] = $group;
     }
@@ -232,6 +222,7 @@ function wysiwyg_fckeditor_proxy_plugin_settings($editor, $profile, $plugins) {
 function wysiwyg_fckeditor_plugins($editor) {
   $plugins = array(
     'default' => array(
+      'title' => t('FCKeditor core'),
       'buttons' => array(
         'Bold' => t('Bold'), 'Italic' => t('Italic'), 'Underline' => t('Underline'),
         'StrikeThrough' => t('Strike-through'),
index 232aaeb..ef6916e 100644 (file)
@@ -156,12 +156,8 @@ function wysiwyg_markitup_settings($editor, $config, $theme) {
   );
   $settings['markupSet'] = array();
   if (!empty($config['toolbar'])) {
-    foreach ($config['toolbar'] as $row) {
-      foreach ($row as $group) {
-        foreach ($group as $button) {
-          $settings['markupSet'][$button['button']] = $default_buttons[$button['button']];
-        }
-      }
+    foreach ($config['toolbar'] as $button) {
+      $settings['markupSet'][$button] = $default_buttons[$button];
     }
   }
 
@@ -174,6 +170,7 @@ function wysiwyg_markitup_settings($editor, $config, $theme) {
 function wysiwyg_markitup_plugins($editor) {
   return array(
     'default' => array(
+      'title' => t('markItUp core'),
       'buttons' => array(
         'bold' => t('Bold'), 'italic' => t('Italic'),
         'stroke' => t('Strike-through'),
index 4260d36..6189888 100644 (file)
@@ -67,15 +67,7 @@ function wysiwyg_nicedit_settings($editor, $config, $theme) {
   // Add configured buttons or all available.
   $settings['buttonList'] = array();
   if (!empty($config['toolbar'])) {
-    $buttons = array();
-    foreach ($config['toolbar'] as $row) {
-      foreach ($row as $group) {
-        foreach ($group as $button) {
-          $buttons[] = $button['button'];
-        }
-      }
-    }
-    $settings['buttonList'] = $buttons;
+    $settings['buttonList'] = $config['toolbar'];
   }
 
   // Add editor content stylesheet.
@@ -100,6 +92,7 @@ function wysiwyg_nicedit_settings($editor, $config, $theme) {
 function wysiwyg_nicedit_plugins($editor) {
   return array(
     'default' => array(
+      'title' => t('NicEdit core'),
       'buttons' => array(
         'bold' => t('Bold'), 'italic' => t('Italic'), 'underline' => t('Underline'),
         'strikethrough' => t('Strike-through'),
index dc5fd9a..480ee1c 100644 (file)
@@ -21,7 +21,7 @@ function wysiwyg_openwysiwyg_editor() {
       ),
     ),
     'toolbar rows' => TRUE,
-    'toolbar separator' => TRUE,
+    'toolbar separator' => 'seperator',
     'version callback' => 'wysiwyg_openwysiwyg_version',
     'themes callback' => 'wysiwyg_openwysiwyg_themes',
     'settings callback' => 'wysiwyg_openwysiwyg_settings',
@@ -112,22 +112,10 @@ function wysiwyg_openwysiwyg_settings($editor, $config, $theme) {
 
   $settings['Toolbar'] = array();
   if (!empty($config['toolbar'])) {
-    $plugins = wysiwyg_get_plugins($editor['name']);
     foreach ($config['toolbar'] as $row) {
       $toolbar_row = array();
-      foreach ($row as $buttons) {
-        foreach ($buttons as $button_config) {
-          // Skip unavailable plugins.
-          $plugin = $button_config['plugin'];
-          $button = $button_config['button'];
-          if ($button == 'separator') {
-            $toolbar_row[] = 'seperator';
-          }
-          elseif (!isset($plugins[$plugin]['buttons'][$button])) {
-            continue;
-          }
-          $toolbar_row[] = $button;
-        }
+      foreach ($row as $button) {
+        $toolbar_row[] = $button;
       }
       $settings['Toolbar'][] = $toolbar_row;
     }
@@ -147,6 +135,7 @@ function wysiwyg_openwysiwyg_settings($editor, $config, $theme) {
 function wysiwyg_openwysiwyg_plugins($editor) {
   $plugins = array(
     'default' => array(
+      'title' => t('openWYSIWYG core'),
       'buttons' => array(
         'bold' => t('Bold'), 'italic' => t('Italic'), 'underline' => t('Underline'),
         'strikethrough' => t('Strike-through'),
index fa7223d..e679703 100644 (file)
@@ -27,7 +27,7 @@ function wysiwyg_tinymce_editor() {
       ),
     ),
     'toolbar rows' => TRUE,
-    'toolbar separator' => TRUE,
+    'toolbar separator' => '|',
     'version callback' => 'wysiwyg_tinymce_version',
     'themes callback' => 'wysiwyg_tinymce_themes',
     'init callback' => 'wysiwyg_tinymce_init',
@@ -36,7 +36,8 @@ function wysiwyg_tinymce_editor() {
     'plugin settings callback' => 'wysiwyg_tinymce_plugin_settings',
     'proxy plugin' => array(
       'drupal' => array(
-        'load' => TRUE,
+        'title' => t('Drupal proxy plugin'),
+        'load' => FALSE,
         'proxy' => TRUE,
       ),
     ),
@@ -237,63 +238,40 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
   $settings['extended_valid_elements'] = array();
 
   $plugins = wysiwyg_get_plugins($editor['name']);
-  foreach ($config['extensions'] as $plugin => $buttons) {
-    foreach ($buttons as $button => $enabled) {
-      if (!isset($plugins[$plugin], $plugins[$plugin]['extensions'], $plugins[$plugin]['extensions'][$button])) {
-        continue;
-      }
-      // Add plain extensions.
-      if (!empty($plugins[$plugin]['load'])) {
+  foreach ($config['plugins'] as $plugin => $enabled) {
+    if (!$enabled || !isset($plugins[$plugin])) {
+      continue;
+    }
+    // Add plain extensions.
+    if (!empty($plugins[$plugin]['load'])) {
+      if (!empty($plugins[$plugin]['internal'])) {
         $extensions[$plugin] = 1;
       }
-      // Allow plugins to add valid HTML elements.
-      if (!empty($plugins[$plugin]['extended_valid_elements'])) {
-        $settings['extended_valid_elements'] = array_merge($settings['extended_valid_elements'], $plugins[$plugin]['extended_valid_elements']);
-      }
-      // Allow plugins to add or override global configuration settings.
-      if (!empty($plugins[$plugin]['options'])) {
-        $settings = array_merge($settings, $plugins[$plugin]['options']);
+      else {
+        $extensions[_wysiwyg_tinymce_plugin_name('add', $plugin)] = 1;
       }
     }
+    // Allow plugins to add valid HTML elements.
+    if (!empty($plugins[$plugin]['extended_valid_elements'])) {
+      $settings['extended_valid_elements'] = array_merge($settings['extended_valid_elements'], $plugins[$plugin]['extended_valid_elements']);
+    }
+    // Allow plugins to add or override global configuration settings.
+    if (!empty($plugins[$plugin]['options'])) {
+      $settings = array_merge($settings, $plugins[$plugin]['options']);
+    }
   }
 
-  foreach ($config['toolbar'] as $row) {
-    $group = array();
-    foreach ($row as $buttons) {
-      foreach ($buttons as $button_config) {
-        $plugin = $button_config['plugin'];
-        $button = $button_config['button'];
-        if ($button == 'separator') {
-          $group[] = '|';
-          continue;
-        }
-        if (!isset($plugins[$plugin]['buttons'][$button])) {
-          continue;
-        }
-        $group[] = $button;
-        // Add external Drupal plugins to the list of extensions.
-        if (!empty($plugins[$plugin]['proxy'])) {
-          $extensions[_wysiwyg_tinymce_plugin_name('add', $button)] = 1;
-        }
-        // Add external plugins to the list of extensions.
-        elseif (empty($plugins[$plugin]['internal'])) {
-          $extensions[_wysiwyg_tinymce_plugin_name('add', $plugin)] = 1;
-        }
-        // Add internal buttons that also need to be loaded as extension.
-        elseif (!empty($plugins[$plugin]['load'])) {
-          $extensions[$plugin] = 1;
-        }
-        // Allow plugins to add or override global configuration settings.
-        if (!empty($plugins[$plugin]['options'])) {
-          $settings = array_merge($settings, $plugins[$plugin]['options']);
-        }
-        // Allow plugins to add valid HTML elements.
-        if (!empty($plugins[$plugin]['extended_valid_elements'])) {
-          $settings['extended_valid_elements'] = array_merge($settings['extended_valid_elements'], $plugins[$plugin]['extended_valid_elements']);
-        }
+  foreach ($config['toolbar'] as $config_row) {
+    $row = array();
+    foreach ($config_row as $button) {
+      // Cross-editor plugin buttons are prefixed by the proxy plugin name.
+      if (strpos($button, '.') !== FALSE) {
+        list($plugin, $button) = explode('.', $button);
+        $extensions['-' . $button ] = 1;
       }
+      $row[] = $button;
     }
-    $toolbar[] = $group;
+    $toolbar[] = $row;
   }
   $settings['extended_valid_elements'] = array_unique($settings['extended_valid_elements']);
   if ($extensions) {
@@ -318,14 +296,12 @@ function wysiwyg_tinymce_settings($editor, $config, $theme) {
         // These rows explicitly need to be set to be empty, otherwise TinyMCE
         // loads its default buttons of the advanced theme for each row.
         $settings += array(
-          'theme_advanced_buttons1' => array(),
-          'theme_advanced_buttons2' => array(),
-          'theme_advanced_buttons3' => array(),
+          'theme_advanced_buttons1' => '',
+          'theme_advanced_buttons2' => '',
+          'theme_advanced_buttons3' => '',
         );
         for ($i = 0; $i < count($toolbar); $i++) {
-          foreach ($toolbar[$i] as $button) {
-            $settings['theme_advanced_buttons' . ($i + 1)][] = $button;
-          }
+          $settings['theme_advanced_buttons' . ($i + 1)] = $toolbar[$i];
         }
       }
       break;
@@ -416,6 +392,7 @@ function _wysiwyg_tinymce_plugin_name($op, $name) {
 function wysiwyg_tinymce_plugins($editor) {
   $plugins = array(
     'default' => array(
+      'title' => t('TinyMCE core'),
       'path' => $editor['library path'] . '/themes/advanced',
       'buttons' => array(
         'bold' => t('Bold'), 'italic' => t('Italic'), 'underline' => t('Underline'),
@@ -433,7 +410,7 @@ function wysiwyg_tinymce_plugins($editor) {
         'sup' => t('Superscript'), 'sub' => t('Subscript'),
         'blockquote' => t('Blockquote'), 'code' => t('Source code'),
         'hr' => t('Horizontal rule'),
-        'cut' => t('Cut'), 'copy' => t('Copy'), 'paste' => t('Paste'),
+        'cut' => t('Cut'), 'copy' => t('Copy'), 'pastetext' => t('Paste text'),
         'visualaid' => t('Visual aid'),
         'removeformat' => t('Remove format'),
         'charmap' => t('Character map'),
index 33f9e14..d8e9685 100644 (file)
@@ -22,7 +22,8 @@ function wysiwyg_whizzywig_editor() {
     'version callback' => 'wysiwyg_whizzywig_version',
     'settings callback' => 'wysiwyg_whizzywig_settings',
     'plugin callback' => 'wysiwyg_whizzywig_plugins',
-    'toolbar separator' => TRUE,
+    'toolbar separator' => '|',
+    'toolbar rows' => TRUE,
     'versions' => array(
       '55' => array(
         'js files' => array('whizzywig.js'),
@@ -94,21 +95,13 @@ function wysiwyg_whizzywig_settings($editor, $config, $theme) {
 
   // Add configured buttons or all available.
   $settings['buttons'] = array();
+  $toolbar = array();
   if (!empty($config['toolbar'])) {
-    // Whizzywig supports only one button group/row.
-    $group_config = $config['toolbar'][0][0];
-    $buttons = array();
-    foreach ($group_config as $button_config) {
-      $button = $button_config['button'];
-      if ($button == 'separator') {
-        $buttons[] = '|';
-      }
-      else {
-        $buttons[] = $button;
-      }
+    foreach ($config['toolbar'] as $config_row) {
+      $toolbar[] = implode(' ', $config_row);
     }
-    $settings['buttons'] = implode(' ', $buttons);
   }
+  $settings['buttons'] = implode(' newline ', $toolbar);
 
   // Add editor content stylesheet.
   if (isset($config['css_setting'])) {
@@ -132,6 +125,7 @@ function wysiwyg_whizzywig_settings($editor, $config, $theme) {
 function wysiwyg_whizzywig_plugins($editor) {
   return array(
     'default' => array(
+      'title' => t('Whizzywig core'),
       'buttons' => array(
         'formatblock' => t('HTML block format'), 'fontname' => t('Font'), 'fontsize' => t('Font size'),
         'bold' => t('Bold'), 'italic' => t('Italic'), 'underline' => t('Underline'),
index ea346bb..2f3b0e6 100644 (file)
@@ -114,17 +114,19 @@ function wysiwyg_wymeditor_settings($editor, $config, $theme) {
   // Add configured buttons.
   $settings['toolsItems'] = array();
   if (!empty($config['toolbar'])) {
-    // WYMeditor only supports one group/row of buttons.
-    $group_config = $config['toolbar'][0][0];
     $buttoninfo = _wysiwyg_wymeditor_button_info();
     $plugins = wysiwyg_get_plugins($editor['name']);
-    foreach ($group_config as $button_config) {
-      $button = $button_config['button'];
-      $plugin = $button_config['plugin'];
-      // Skip unavailable plugins.
-      if (!isset($plugins[$plugin]['buttons'][$button])) {
+    // Allow looking up which button is provided by which plugin.
+    $plugin_lookup = array();
+    foreach ($plugins as $plugin => $meta) {
+      if (empty($meta['buttons'])) {
         continue;
       }
+      foreach ($meta['buttons'] as $button_name => $button) {
+        $plugin_lookup[$button_name] = $plugin;
+      }
+    }
+    foreach ($config['toolbar'] as $button) {
       // Merge meta-data for internal default buttons.
       if (isset($buttoninfo[$button])) {
         $buttoninfo[$button] += array('name' => $button);
@@ -132,9 +134,10 @@ function wysiwyg_wymeditor_settings($editor, $config, $theme) {
       }
       // For custom buttons, try to provide a valid button definition.
       else {
+        $plugin = $plugin_lookup[$button];
         $settings['toolsItems'][] = array(
           'name' => $button,
-          'title' => $plugins[$plugin][$type][$button],
+          'title' => $plugins[$plugin]['buttons'][$button],
           'css' => 'wym_tools_' . $button,
         );
       }
index 72fd0a5..948f690 100644 (file)
@@ -50,6 +50,7 @@ function wysiwyg_yui_editor() {
     'plugin settings callback' => 'wysiwyg_yui_plugin_settings',
     'proxy plugin' => array(
       'drupal' => array(
+        'title' => t('Drupal proxy plugin'),
         'load' => TRUE,
         'proxy' => TRUE,
       ),
@@ -161,15 +162,21 @@ function wysiwyg_yui_settings($editor, $config, $theme) {
       'buttons' => array(),
     ),
   );
+  $plugins = wysiwyg_get_plugins($editor['name']);
+  foreach ($config['plugins'] as $plugin => $enabled) {
+    if (!$enabled || !isset($plugins[$plugin])) {
+      continue;
+    }
+    // Allow plugins to add or override global configuration settings.
+    if (!empty($plugins[$plugin]['options'])) {
+      $settings = array_merge($settings, $plugins[$plugin]['options']);
+    }
+  }
   if (!empty($config['toolbar'])) {
     $buttons = array();
-    // YUI Editor can only use one toolbar row.
-    $row = $config['toolbar'][0];
-    foreach ($row as $group_index => $group_config) {
+    foreach ($config['toolbar'] as $group_index => $group_config) {
       $group = array('group' => 'group' . $group_index, 'label' => '', 'buttons' => array());
-      foreach ($group_config as $button_config) {
-        $button = $button_config['button'];
-        $plugin = $button_config['plugin'];
+      foreach ($group_config as $button) {
         $extra = array();
         if ($button == 'heading') {
           $extra = array('menu' => array(
@@ -205,7 +212,7 @@ function wysiwyg_yui_settings($editor, $config, $theme) {
             array('text' => 'Verdana'),
           ));
         }
-        $group['buttons'][] = wysiwyg_yui_button_setting($editor, $plugin, $button, $extra);
+        $group['buttons'][] = wysiwyg_yui_button_setting($editor, $button, $extra);
       }
       $buttons[] = $group;
     }
@@ -235,25 +242,41 @@ function wysiwyg_yui_settings($editor, $config, $theme) {
  *
  * @param $editor
  *   A processed hook_editor() array of editor properties.
- * @param $plugin
- *   The internal name of a plugin.
  * @param $button
- *   The internal name of a button, defined by $plugin.
+ *   The internal name of a button, defined by a plugin.
  * @param $extra
  *   (optional) An array containing arbitrary other elements to add to the
  *   resulting button.
  */
-function wysiwyg_yui_button_setting($editor, $plugin, $button, $extra = array()) {
+function wysiwyg_yui_button_setting($editor, $button, $extra = array()) {
   static $plugins;
+  static $plugin_lookup;
 
   if (!isset($plugins)) {
     $plugins = wysiwyg_get_plugins($editor['name']);
+    // Allow looking up which button is provided by which plugin.
+    $plugin_lookup = array();
+    foreach ($plugins as $plugin => $meta) {
+      if (empty($meta['buttons'])) {
+        continue;
+      }
+      foreach ($meta['buttons'] as $button_name => $button_info) {
+        $plugin_lookup[$button_name] = $plugin;
+      }
+    }
   }
 
   // Return a simple separator.
   if ($button === 'separator') {
     return array('type' => 'separator');
   }
+  // Cross-editor plugin buttons are prefixed by the proxy plugin name.
+  if (strpos($button, '.') !== FALSE) {
+    list($plugin, $button) = explode('.', $button);
+  }
+  else {
+    $plugin = $plugin_lookup[$button];
+  }
   // Setup defaults.
   $type = 'push';
   $label = $plugins[$plugin]['buttons'][$button];
@@ -323,6 +346,7 @@ function wysiwyg_yui_proxy_plugin_settings($editor, $profile, $plugins) {
 function wysiwyg_yui_plugins($editor) {
   return array(
     'default' => array(
+      'title' => t('YUI Editor core'),
       'buttons' => array(
         'bold' => t('Bold'), 'italic' => t('Italic'), 'underline' => t('Underline'),
         'strikethrough' => t('Strike-through'),
index cca60c9..45015ef 100644 (file)
@@ -52,7 +52,6 @@ function wysiwyg_profile_default($profile) {
  */
 function wysiwyg_profile_form($form, &$form_state, $profile) {
   $profile = wysiwyg_profile_default($profile);
-  $module_path = drupal_get_path('module', 'wysiwyg');
 
   $formats = filter_formats();
   $editor = wysiwyg_get_editor($profile->editor);
@@ -120,123 +119,67 @@ function wysiwyg_profile_form($form, &$form_state, $profile) {
   asort($predefined);
   $form['basic']['language']['#options'] = $predefined;
 
-  $form['extensions'] = array(
+  // Retrieve all available plugins and buttons.
+  $plugins = wysiwyg_get_plugins($profile->editor);
+  $form['plugins'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Extensions'),
+    '#title' => t('Plugins'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
     '#tree' => TRUE,
-    '#theme' => 'wysiwyg_admin_button_table',
+    '#theme' => 'wysiwyg_admin_plugin_table',
+    '#access' => !empty($plugins),
   );
 
-  // Retrieve all available extensions and buttons.
-  $plugins = wysiwyg_get_plugins($profile->editor);
   $buttons = array();
+  $proxy = (isset($editor['proxy plugin']) ? key($editor['proxy plugin']) : FALSE);
   foreach ($plugins as $name => $meta) {
+    $title = (!empty($meta['title']) ? $meta['title'] : (!empty($meta['extensions']) ? $meta['extensions'][$name] : $name));
+    $form['plugins'][$name] = array(
+      '#type' => 'checkbox',
+      '#title' => check_plain($title),
+      '#default_value' => !empty($profile->settings['plugins'][$name]),
+      '#description' => isset($meta['url']) ? l($meta['url'], $meta['url']) : NULL,
+    );
     if (isset($meta['buttons']) && is_array($meta['buttons'])) {
-      foreach ($meta['buttons'] as $button => $title) {
-        $buttons[] = array(
+      foreach ($meta['buttons'] as $button_name => $button) {
+        $button_name = ($name === $proxy ? $name . '.' . $button_name : $button_name);
+        $buttons[$button_name] = (is_array($button) ? $button : array('title' => $button));
+        $buttons[$button_name] += array(
           'plugin' => $name,
-          'button' => $button,
-          'title' => $title,
         );
       }
     }
-    if (isset($meta['extensions']) && is_array($meta['extensions'])) {
-      foreach ($meta['extensions'] as $extension => $title) {
-        $form['extensions'][$name][$extension] = array(
-          '#type' => 'checkbox',
-          '#title' => check_plain($title),
-          '#default_value' => !empty($profile->settings['extensions'][$name][$extension]) ? $profile->settings['extensions'][$name][$extension] : 0,
-          '#description' => isset($meta['url']) ? l($meta['url'], $meta['url']) : NULL,
-        );
-      }
-    }
-  }
-  // Hide the extensions fieldset if there are no extensions.
-  if (!element_children($form['extensions'])) {
-    $form['extensions']['#access'] = FALSE;
   }
 
-  $toolbar_support = array(
-    'toolbar' => $profile->settings['toolbar'],
-    'toolbar rows' => !empty($editor['toolbar rows']),
-    'toolbar groups' => !empty($editor['toolbar groups']),
-    'toolbar separator' => !empty($editor['toolbar separator']),
+  $form['toolbar'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Toolbar definition'),
+    '#default_value' => json_encode($profile->settings['toolbar']),
+    '#access' => !empty($buttons),
   );
+
   // Separator.
-  if ($toolbar_support['toolbar separator']) {
-    array_unshift($buttons, array(
-      'plugin' => 'default',
-      'button' => 'separator',
+  if (!empty($editor['toolbar separator'])) {
+    $separator = $editor['toolbar separator'] === TRUE ? 'separator' : $editor['toolbar separator'];
+    $buttons[$separator] = array(
+      'plugin' => 'none',
       'title' => t('Separator'),
-    ));
-  }
-
-  $form['toolbar_designer'] = array(
-    '#type' => 'container',
-    '#id' => 'wysiwyg-toolbar-designer',
-    '#access' => !empty($buttons),
-  );
-  $form['toolbar_designer']['available'] = array(
-    '#type' => 'item',
-    '#title' => t('Available buttons'),
-    '#id' => 'toolbar-available-buttons',
-  );
-  foreach ($buttons as $button) {
-    $form['toolbar_designer']['available'][$button['plugin']][$button['button']] = array(
-      '#theme' => 'html_tag',
-      '#tag' => 'span',
-      '#value' => check_plain($button['title']),
-      '#attributes' => array('class' => array('wysiwyg-button', 'wysiwyg-button-' . $button['plugin'] . '-' . $button['button'])),
+      'multiple' => TRUE,
     );
   }
-  $form['toolbar_designer']['stage'] = array(
-    '#type' => 'item',
-    '#title' => t('Toolbar'),
-  );
-  $form['toolbar_designer']['stage']['rows'] = array(
-    '#markup' => '<div id="toolbar-rows"></div>',
-  );
-  $form['toolbar_designer']['stage']['actions'] = array(
-    '#type' => 'container',
-    '#id' => 'toolbar-actions',
-  );
-  $form['toolbar_designer']['stage']['actions']['add-row'] = array(
-    '#type' => 'link',
-    '#title' => t('Add new row'),
-    '#href' => '#',
-    '#attributes' => array(
-      'class' => array('add', 'add-toolbar-row'),
-    ),
-  );
-  $form['toolbar_designer']['stage']['templates'] = array(
-    '#markup' => '<div class="toolbar-row-template">
-  <a href="javascript:;" class="row-handler handler">&nbsp;</a>
-  <a href="javascript:;" class="add add-group">&nbsp;</a>
-</div>
-<div class="toolbar-group-template">
-  <a href="javascript:;" class="group-handler handler">&nbsp;</a>
-</div>
-',
-  );
-
-  $form['toolbar_designer']['change_notification'] = array(
-    '#markup' => '<div class="toolbar-changed-warning messages warning"><span class="warning">*</span>' . t('Changes made to this toolbar will not be saved until the form is submitted.') . '</div>', 
+  $toolbar_support = array(
+    'toolbar' => $profile->settings['toolbar'],
+    'toolbar rows' => !empty($editor['toolbar rows']),
+    'toolbar groups' => !empty($editor['toolbar groups']),
+    'toolbar separator' => !empty($editor['toolbar separator']) ? $editor['toolbar separator'] : FALSE,
+    'buttons' => $buttons,
   );
-
-  $form['toolbar_designer']['#attached']['js'][] = array(
+  $form['toolbar']['#attached']['js'][] = array(
     'data' => array('wysiwyg_toolbar' => $toolbar_support),
     'type' => 'setting',
   );
-  $form['toolbar_designer']['#attached']['library'][] = array('system', 'ui.droppable');
-  $form['toolbar_designer']['#attached']['library'][] = array('system', 'ui.sortable');
-  $form['toolbar_designer']['#attached']['js'][] = $module_path . '/wysiwyg.admin.js';
-  $form['toolbar_designer']['#attached']['css'][] = $module_path . '/wysiwyg.admin.css';
-  $form['toolbar_designer']['toolbar'] = array(
-    '#type' => 'hidden',
-    '#attributes' => array('id' => 'edit-toolbar'),
-  );
+  $form['toolbar']['#attached']['library'][] = array('wysiwyg', 'wysiwyg.admin');
 
   $form['appearance'] = array(
     '#type' => 'fieldset',
@@ -414,45 +357,71 @@ function wysiwyg_profile_form($form, &$form_state, $profile) {
  */
 function wysiwyg_profile_form_submit($form, &$form_state) {
   $values = &$form_state['values'];
-  if (isset($values['extensions'])) {
-    // Store only enabled buttons for each plugin.
-    foreach ($values['extensions'] as $plugin => $buttons) {
-      $values['extensions'][$plugin] = array_filter($values['extensions'][$plugin]);
-    }
+  $editor = $form_state['wysiwyg']['editor'];
+  if (isset($values['plugins'])) {
     // Store only enabled plugins.
-    $values['extensions'] = array_filter($values['extensions']);
+    $values['plugins'] = array_filter($values['plugins']);
   }
   else {
-    $values['extensions'] = array();
+    $values['plugins'] = array();
+  }
+  $values['toolbar'] = json_decode($values['toolbar'], FALSE);
+  $plugins = wysiwyg_get_plugins($values['editor']);
+  // Allow looking up which button is provided by which plugin.
+  $plugin_lookup = array();
+  foreach ($plugins as $plugin => $meta) {
+    if (empty($meta['buttons'])) {
+      continue;
+    }
+    foreach ($meta['buttons'] as $button_name => $button) {
+      $plugin_lookup[$button_name] = $plugin;
+    }
   }
 
-  // Restore toolbar array.
-  $raw_toolbar = explode("\n", trim(preg_replace('/\r/','', $values['toolbar'])));
-  $values['toolbar'] = array();
-  foreach ($raw_toolbar as $raw_row) {
-    $row = array();
-    foreach (explode('|', trim($raw_row, '|')) as $raw_group) {
-      $group = array();
-      foreach (explode(',', trim($raw_group, ',')) as $button) {
-        if (strpos($button, '.') === FALSE) {
-          continue;
+  // Verify all dependencies are also enabled.
+  $additional_plugins = array();
+  $dependencies = array();
+  $toolbar = (!empty($editor['toolbar rows']) ? $values['toolbar'] : array($values['toolbar']));
+  foreach ($toolbar as $row) {
+    if (empty($editor['toolbar groups'])) {
+      $row = array($row);
+    }
+    foreach ($row as $group) {
+      foreach ($group as $button) {
+        // Cross-editor plugin buttons are prefixed by the proxy plugin name.
+        if (strpos($button, '.') !== FALSE) {
+          list($plugin, $button_id) = explode('.', $button);
+        }
+        elseif (isset($plugin_lookup[$button]) && !isset($values['plugins'][$plugin_lookup[$button]])) {
+          $plugin = $plugin_lookup[$button];
+        }
+        if (!isset($values['plugins'][$plugin])) {
+          $additional_plugins[$plugin] = 1;
+        }
+        if (!empty($plugins[$plugin]['dependencies'])) {
+          $dependencies = array_unique(array_merge($dependencies, $plugins[$plugin]['dependencies']));
         }
-        list($plugin, $name) = explode('.', $button, 2);
-        $group[] = array(
-          'button' => $name,
-          'plugin' => $plugin,
-        );
-      }
-      if ($group) {
-        $row[] = $group;
       }
     }
-    if ($row) {
-      $values['toolbar'][] = $row;
+  }
+  foreach ($values['plugins'] as $plugin => $enabled) {
+    if (!empty($plugins[$plugin]['dependencies'])) {
+      $dependencies = array_unique(array_merge($dependencies, $plugins[$plugin]['dependencies']));
     }
   }
-  // Remove available plugins/button information.
-  unset($values['buttons']);
+  // Walk up the dependency chain until a dependency is already enabled.
+  while ($dependency = array_pop($dependencies)) {
+    if (!isset($values['plugins'][$dependency]) && !isset($additional_plugins[$dependency])) {
+      $additional_plugins[$dependency] = 1;
+      if (!empty($plugins[$dependency]['dependencies'])) {
+        $dependencies = array_unique(array_merge($dependencies, $plugins[$dependency]['dependencies']));
+      }
+    }
+  }
+  if (!empty($additional_plugins)) {
+    drupal_set_message(t('Additional plugins were automatically enabled because they were required by already enabled plugins or buttons.<br />The enabled plugins were: @plugins', array('@plugins' => implode(', ', array_keys($additional_plugins)))));
+    $values['plugins'] = array_merge($values['plugins'], $additional_plugins);
+  }
 
   // Remove any white-space from 'block_formats' setting, since editor
   // implementations rely on a comma-separated list to explode().
@@ -483,27 +452,25 @@ function wysiwyg_profile_form_submit($form, &$form_state) {
 }
 
 /**
- * Layout for the buttons in the Wysiwyg Editor profile form.
+ * Layout for the plugins in the Wysiwyg Editor profile form.
  */
-function theme_wysiwyg_admin_button_table($variables) {
+function theme_wysiwyg_admin_plugin_table($variables) {
   $form = $variables['form'];
-  $buttons = array();
+  $plugins = array();
 
   // Flatten forms array.
-  foreach (element_children($form) as $name) {
-    foreach (element_children($form[$name]) as $button) {
-      $buttons[] = drupal_render($form[$name][$button]);
-    }
+  foreach (element_children($form) as $plugin) {
+    $plugins[] = drupal_render($form[$plugin]);
   }
 
   // Split checkboxes into rows with 3 columns.
-  $total = count($buttons);
+  $total = count($plugins);
   $rows = array();
   for ($i = 0; $i < $total; $i += 3) {
     $row = array();
-    $row_buttons = array_slice($buttons, $i, 3) + array_fill(0, 3, array());
-    foreach ($row_buttons as $row_button) {
-      $row[] = array('data' => $row_button);
+    $row_plugins = array_slice($plugins, $i, 3) + array_fill(0, 3, array());
+    foreach ($row_plugins as $row_plugin) {
+      $row[] = array('data' => $row_plugin);
     }
     $rows[] = $row;
   }
@@ -686,7 +653,7 @@ function wysiwyg_profile_overview_submit($form, &$form_state) {
   // The settings handling relies on these to be defined and arrays.
   $settings = array(
     'toolbar' => array(),
-    'extensions' => array(),
+    'plugins' => array(),
   );
   foreach ($form_state['values']['formats'] as $format => $values) {
     db_merge('wysiwyg')
index 790447d..6b0d496 100644 (file)
@@ -3,13 +3,92 @@
 Drupal.behaviors.wysiwygToolbarDesigner = {
   attach: function (context, settings) {
     var settings = settings.wysiwyg_toolbar;
+    $('#edit-toolbar').parent().parent().hide();
+    if (!settings.buttons || settings.buttons.length == 0) {
+      return;
+    }
+    // Insert toolbar designer.
+    $('#edit-plugins').after(Drupal.theme('toolbar_designer', settings));
     var workspace = $('#wysiwyg-toolbar-designer');
     var designArea = $('#toolbar-rows');
     var changeNotification = $('#wysiwyg-toolbar-designer div.toolbar-changed-warning');
     var availableButtons = $('#toolbar-available-buttons');
-    var separator = $('.wysiwyg-button-default-separator', availableButtons);
 
-    var createRow = function(noGroup) {
+    // Set up sortables.
+    $('.wysiwyg-button',availableButtons).addClass('template-button').draggable({
+      handle: '.handler',
+      helper: 'clone',
+      connectToSortable: '.toolbar-group',
+      revert: 'invalid',
+      addClasses: false,
+      start: function(event, ui) {
+        // Workaround for jQuery UI bug fixed in version 1.8.11.
+        // @see http://bugs.jqueryui.com/ticket/5811
+        $('#toolbar-rows .toolbar-group').sortable('refreshPositions');
+      }
+    });
+
+    availableButtons.droppable({
+      accept: '.toolbar-button, .toolbar-group, .toolbar-row',
+      drop: function(event, ui) {
+        var item = ui.draggable;
+        var parent = item.parent();
+
+        // Guarantee there is at least 1 row and 1 group.
+        if (item.hasClass('toolbar-row') && parent.find('.toolbar-row').not('.ui-sortable-placeholder').length == 1) {
+          return;
+        } else if (item.hasClass('toolbar-group') && parent.find('.toolbar-group').not('.ui-sortable-placeholder').length == 1) {
+          return;
+        }
+
+        var buttons = $('.toolbar-button', item);
+        if (item.hasClass('toolbar-button')) {
+          buttons = buttons.add(item);
+        }
+
+        // Remove each button and enable in template.
+        buttons.each(function(){
+          var $button = $(this);
+          $('.wysiwyg-button[data-plugin="' + $button.attr('data-plugin')  + '"][data-button="' + $button.attr('data-button')  + '"]').show();
+        });
+
+        item.parent().sortable('refresh');
+        item.remove();
+        changeNotification.fadeIn();
+      }
+    });
+
+    $('#toolbar-rows').sortable({
+      items: '.toolbar-row',
+      handle: '.row-handler',
+      addClass: false,
+      stop: updateToolbarTextarea,
+    });
+
+    // Design actions buttons.
+    $('.add-toolbar-row',workspace).click(function(){
+      // Clone from toolbar template.
+      var row = createRow();
+
+      // Append row to design area.
+      designArea.append(row).sortable('refresh');
+      changeNotification.fadeIn();
+      return false;
+    });
+
+    $('#reset-design').click(function() {
+      if (!changeNotification.is(':hidden') && confirm(Drupal.t('Do you want to reset the changes ?')))
+        reset();
+      return false;
+    });
+
+    if (!settings['toolbar rows']) {
+      $('.add-toolbar-row').hide();
+    }
+
+    reset();
+
+    function createRow (noGroup) {
       var row = $('.toolbar-row-template',workspace).clone().removeClass('toolbar-row-template');
       row.addClass('toolbar-row').sortable({
         handle: '.group-handler',
@@ -17,9 +96,14 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
         items: '.toolbar-group',
         addClasses: false,
         connectWith: '#toolbar-rows .toolbar-row',
-        stop: function(event,ui) {
-          changeNotification.fadeIn();
-        }
+        receive: function(event, ui) {
+          // ui.sender is posibly the available button which was cloned and
+          // and dragged to this group. Separators can be used multiple times.
+          if (ui.sender.hasClass('template-button') && !ui.sender.attr('data-multiple-instances')) {
+            ui.sender.hide();
+          }
+        },
+        stop: updateToolbarTextarea
       });
       if (settings['toolbar groups']) {
         row.find('.add-group').click(function() {
@@ -34,7 +118,7 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
         row.find('.add-group').hide();
         row.addClass('single-group');
       }
-      // add required group
+      // Add required group.
       if (!noGroup) {
         var group = createGroup();
         row.append(group);
@@ -42,7 +126,7 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
       return row;
     };
 
-    var createGroup = function() {
+    function createGroup () {
       var group = $('.toolbar-group-template').clone().removeClass('toolbar-group-template');
       group.addClass('toolbar-group');
       group.sortable({
@@ -50,9 +134,7 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
         items: '.wysiwyg-button',
         connectWith: '#toolbar-rows .toolbar-group',
         addClasses: false,
-        stop: function(event,ui) {
-          changeNotification.fadeIn();
-        },
+        stop: updateToolbarTextarea,
         beforeStop: function(event, ui) {
           // ui.item is the clone of an available button dragged to this group.
           ui.item.removeClass('template-button').addClass('toolbar-button');
@@ -60,7 +142,7 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
         receive: function(event, ui) {
           // ui.sender is posibly the available button which was cloned and
           // and dragged to this group. Separators can be used multiple times.
-          if (ui.sender.hasClass('template-button') && !ui.sender.hasClass('wysiwyg-button-default-separator')) {
+          if (ui.sender.hasClass('template-button') && !ui.sender.attr('data-multiple-instances')) {
             ui.sender.hide();
           }
         }
@@ -69,28 +151,31 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
       return group;
     }
 
-    var reset = function() {
+    function reset () {
       $('.toolbar-row',designArea).remove();
       // Enable all buttons and then disable it later.
       $('.wysiwyg-button',availableButtons).show();
 
-      for (var i in settings.toolbar) {
-        var groups = settings.toolbar[i];
+      var rows = (settings['toolbar rows'] || !settings.toolbar ? settings.toolbar : [settings.toolbar]);
+      for (var i in rows) {
         var row = createRow(true);
+        var groups = (settings['toolbar groups'] ? rows[i] : [rows[i]]);
         for (var j in groups) {
           var group = createGroup();
           var buttons = groups[j];
 
           for (var k in buttons) {
-            var buttonClass = '.wysiwyg-button-' + buttons[k].plugin + '-' + buttons[k].button;
-            var template_button = $(buttonClass,$('#toolbar-available-buttons'));
+            var buttonInfo = settings.buttons[buttons[k]];
+            var template_button = $('.wysiwyg-button[data-plugin="' + buttonInfo.plugin + '"][data-button="' + buttons[k] + '"]', availableButtons);
             if (template_button.length) {
               button = template_button.clone().show();
               button.removeClass('template-button').addClass('toolbar-button');
               group.append(button);
 
-              // Disable button in template area.
-              template_button.hide();
+              if (!buttonInfo.multiple) {
+                // Disable button in template area.
+                template_button.hide();
+              }
             }
           }
           row.append(group);
@@ -98,115 +183,70 @@ Drupal.behaviors.wysiwygToolbarDesigner = {
         designArea.append(row);
       }
       // Make sure we always have at least one row.
-      if (!settings['toolbar rows']) {
-        if ($('.toolbar-row',designArea).length <= 0) {
-          var row = createRow();
-          designArea.append(row);
-        }
+      if ($('.toolbar-row',designArea).length <= 0) {
+        var row = createRow();
+        designArea.append(row);
       }
-      separator.show();
       changeNotification.fadeOut();
     }
 
-    $('.add-toolbar-row',workspace).click(function(){
-      // clone from toolbar template
-      var row = createRow();
-
-      // Append row to design area.
-      designArea.append(row).sortable('refresh');
-      changeNotification.fadeIn();
-      return false;
-    });
-
-    $('.wysiwyg-button',availableButtons).addClass('template-button').draggable({
-      handle: '.handler',
-      helper: 'clone',
-      connectToSortable: '.toolbar-group',
-      revert: 'invalid',
-      addClasses: false,
-      start: function(event, ui) {
-        // Workaround for jQuery UI bug fixed in version 1.8.11.
-        // @see http://bugs.jqueryui.com/ticket/5811
-        $('#toolbar-rows .toolbar-group').sortable('refreshPositions');
-      }
-    });
-
-    availableButtons.droppable({
-      accept: '.toolbar-button, .toolbar-group, .toolbar-row',
-      drop: function(event, ui) {
-        var item = ui.draggable;
-        var parent = item.parent();
-
-        // Guarantee there is at least 1 row and 1 group.
-        if (item.hasClass('toolbar-row') && parent.find('.toolbar-row').not('.ui-sortable-placeholder').length == 1) {
-          return;
-        } else if (item.hasClass('toolbar-group') && parent.find('.toolbar-group').not('.ui-sortable-placeholder').length == 1) {
-          return;
-        }
-
-        var buttons = $('.toolbar-button', item);
-        if (item.hasClass('toolbar-button')) {
-          buttons = buttons.add(item);
-        }
-
-        // Remove each button and enable in template.
-        buttons.each(function(){
-          var button_id = /wysiwyg-button-([^-]+-[^\s]+)/.exec($(this).attr('class'));
-          $('.wysiwyg-button-' + button_id[1]).show();
-        });
-
-        item.parent().sortable('refresh');
-        item.remove();
-
-        changeNotification.fadeIn();
-      }
-    });
-
-    $('#toolbar-rows').sortable({
-      items: '.toolbar-row',
-      handle: '.row-handler',
-      addClass: false,
-      stop: function(event, ui) {
-        changeNotification.fadeIn();
-      }
-    });
-
-    // Design actions buttons.
-    $('#reset-design').click(function() {
-      if (!changeNotification.is(':hidden') && confirm(Drupal.t('Do you want to reset the changes ?')))
-        reset();
-      return false;
-    });
-
-    $('#wysiwyg-profile-form').submit(function() {
+    function updateToolbarTextarea(event, ui) {
       // Prepare toolbar data to submit.
       var toolbar = [];
-      designArea.find('.toolbar-row').each(function(key,rowDom){
+      designArea.find('.toolbar-row').each(function (key, rowDom){
         var row = [];
-        $('.toolbar-group',rowDom).each(function(key,groupDom){
+        $('.toolbar-group',rowDom).each(function (key, groupDom){
           var group = [];
-          $('.wysiwyg-button',groupDom).each(function(key,button){
-            var cls = /wysiwyg-button-([^-]+)-([^\s]+)/.exec($(button).attr('class'));
-            group.push(cls[1] + "." + cls[2]);
+          $('.wysiwyg-button',groupDom).each( function(key, button){
+            group.push($(button).attr('data-button'));
           })
-          if (group.length > 0) {
-            row.push(group.join(','));
+          if (settings['toolbar groups']) {
+            row.push(group);
+          }
+          else {
+            row = group;
           }
         });
-        if (row.length > 0) {
-          toolbar.push(row.join('|'));
+        if (settings['toolbar rows']) {
+           toolbar.push(row);
+        }
+        else {
+          toolbar = row;
         }
       });
       // Assign to hidden field.
-      $('#edit-toolbar').val(toolbar.join('\n'));
-    });
-
-    reset();
-
-    if (!settings['toolbar rows']) {
-      $('.add-toolbar-row').hide();
+      $('#edit-toolbar').val(JSON.stringify(toolbar));
+      changeNotification.fadeIn();
     }
   }
 };
 
+Drupal.theme.prototype.toolbar_designer = function (settings) {
+  var markup = '<div id="wysiwyg-toolbar-designer">';
+  markup += '<div id="toolbar-available-buttons"><label for="toolbar-available-buttons">' + Drupal.t('Available buttons') + '</label>';
+  for (var button_name in settings.buttons) {
+    var button = settings.buttons[button_name];
+    markup += '<span class="wysiwyg-button" data-plugin="' + button.plugin + '" data-button="' + button_name
+      + (button.multiple ? '" data-multiple-instances="yes"' : '')
+      + '">' + Drupal.checkPlain(button.title) + '</span>';
+  }
+  markup += '</div><div id="stage"><label for="stage">' + Drupal.t('Toolbar') + '</label>'
+    + '<div id="tolbar-description">' + Drupal.t('Drag any buttons you need from the area above into the toolbar layout below. Drag any item back to the area above to remove them from the toolbar layout.') + '</div>'
+    + '<div id="toolbar-rows"></div>'
+    + '<div id="toolbar-actions">'
+      + '<a href="#" class="add add-toolbar-row">' + Drupal.t('Add new row') + '</a>'
+    + '</div>'
+    + '<div class="toolbar-row-template">'
+      + '<a href="javascript:;" class="row-handler handler">&nbsp;</a>'
+      + '<a href="javascript:;" class="add add-group">&nbsp;</a>'
+    + '</div>'
+    + '<div class="toolbar-group-template">'
+      + '<a href="javascript:;" class="group-handler handler">&nbsp;</a>'
+    + '</div>'
+  + '</div>'
+  + '<div class="toolbar-changed-warning messages warning"><span class="warning">*</span>'
+    + Drupal.t('Changes made to this toolbar will not be saved until the form is submitted.') + '</div>';
+  return markup;
+}
+
 })(jQuery);
index c4d8857..9dc9f63 100644 (file)
@@ -41,6 +41,10 @@ function hook_wysiwyg_plugin($editor, $version) {
       if ($version > 3) {
         return array(
           'myplugin' => array(
+            // The plugin's title; defaulting to its internal name ('myplugin'),
+            // or the value of the first item in the 'extensions' key, if it
+            // exists..
+            'title' => t('My plugin'),
             // A URL to the plugin's homepage.
             'url' => 'http://drupal.org/project/img_assist',
             // The full path to the native editor plugin, no trailing slash.
@@ -79,6 +83,10 @@ function hook_wysiwyg_plugin($editor, $version) {
             // other modules. TRUE means 'path' and 'filename' above are ignored
             // and the plugin is instead loaded from the editor's plugin folder.
             'internal' => TRUE,
+            // A lost of internal names of other native plugins this plugin
+            // depends on to function. These plugins will also be automatically
+            // enabled if this plugin or one of its buttons are enabled.
+            'dependencies' => array('dialog'),
             // TinyMCE-specific: Additional HTML elements to allow in the markup.
             'extended_valid_elements' => array(
               'img[class|src|border=0|alt|title|width|height|align|name|style]',
index 478139a..648caee 100644 (file)
@@ -92,6 +92,28 @@ function wysiwyg_menu() {
 }
 
 /**
+ * Implements hook_library().
+ */
+function wysiwyg_library() {
+  $path = drupal_get_path('module', 'wysiwyg');
+  $libraries['wysiwyg.admin'] = array(
+    'title' => 'Wysiwyg admin',
+    'version' => VERSION,
+    'js' => array(
+      $path . '/wysiwyg.admin.js' => array(),
+    ),
+    'css' => array(
+      $path . '/wysiwyg.admin.css' => array(),
+    ),
+    'dependencies' => array(
+      array('system', 'ui.droppable'),
+      array('system', 'ui.sortable'),
+    ),
+  );
+  return $libraries;
+}
+
+/**
  * Implements hook_element_info().
  */
 function wysiwyg_element_info() {
@@ -115,7 +137,7 @@ function wysiwyg_theme() {
     'wysiwyg_profile_overview' => array(
       'render element' => 'form',
     ),
-    'wysiwyg_admin_button_table' => array(
+    'wysiwyg_admin_plugin_table' => array(
       'render element' => 'form',
     ),
     // @see wysiwyg_dialog()
@@ -491,19 +513,17 @@ function wysiwyg_add_plugin_settings($profile) {
   $proxy = (isset($editor['proxy plugin']) ? key($editor['proxy plugin']) : '');
 
   // Process native editor plugins.
-  if (isset($editor['plugin settings callback'])) {
+  if (isset($editor['plugin settings callback']) && !empty($profile->settings['plugins'])) {
     $profile_plugins_native = array();
-    foreach ($profile->settings['toolbar'] as $row) {
-      foreach ($row as $group) {
-        foreach ($group as $button) {
-          $plugin = $button['plugin'];
-          // Skip Drupal plugins (handled below).
-          if ($plugin === $proxy) {
-            continue;
-          }
-          $profile_plugins_native[$plugin] = $plugins[$editor['name']][$plugin];
-        }
+    foreach ($profile->settings['plugins'] as $plugin => $enabled) {
+      if (!$enabled) {
+        continue;
       }
+      // Skip Drupal plugins (handled below).
+      if ($plugin === $proxy) {
+        continue;
+      }
+      $profile_plugins_native[$plugin] = $plugins[$editor['name']][$plugin];
     }
     // Invoke the editor's plugin settings callback, so it can populate the
     // settings for native external plugins with required values.
@@ -515,14 +535,22 @@ function wysiwyg_add_plugin_settings($profile) {
   }
 
   // Process Drupal plugins.
-  if ($proxy && isset($editor['proxy plugin settings callback'])) {
+  // @todo Perhaps introduce $profile->settings['proxy plugins'] instead of
+  // finding their buttons in the toolbar?
+  if ($proxy && isset($editor['proxy plugin settings callback']) && !empty($profile->settings['toolbar'])) {
     $drupal_plugins = wysiwyg_get_all_plugins();
     $profile_plugins_drupal = array();
-    foreach ($profile->settings['toolbar'] as $row) {
+    $toolbar = (!empty($editor['toolbar rows']) ? $profile->settings['toolbar'] : array($profile->settings['toolbar']));
+    foreach ($toolbar as $row) {
+      if (empty($editor['toolbar groups'])) {
+        $row = array($row);
+      }
       foreach ($row as $group) {
         foreach ($group as $button) {
-          $plugin = $button['plugin'];
-          $button_id = $button['button'];
+          if (strpos($button, '.') === FALSE) {
+            continue;
+          }
+          list($plugin, $button_id) = explode('.', $button);
           if ($plugin == $proxy && isset($drupal_plugins[$button_id])) {
             $meta = $drupal_plugins[$button_id];
             // JavaScript and plugin-specific settings for Drupal plugins must be