core/includes/form.inc | 2 +- core/modules/ckeditor/ckeditor.module | 5 +- core/modules/ckeditor/js/ckeditor.admin.js | 70 ++++++++++++++++++++ .../ckeditor/js/ckeditor.drupalimage.admin.js | 30 --------- .../ckeditor/js/ckeditor.stylescombo.admin.js | 27 ++------ .../lib/Drupal/ckeditor/CKEditorPluginManager.php | 12 ++++ .../lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php | 3 + 7 files changed, 96 insertions(+), 53 deletions(-) diff --git a/core/includes/form.inc b/core/includes/form.inc index 06ee164..bed069a 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -4069,7 +4069,7 @@ function form_pre_render_vertical_tabs($element) { */ function theme_vertical_tabs($variables) { $element = $variables['element']; - return '
' . $element['#children'] . '
'; + return '
' . $element['#children'] . '
'; } /** diff --git a/core/modules/ckeditor/ckeditor.module b/core/modules/ckeditor/ckeditor.module index 39c0707..bea61d4 100644 --- a/core/modules/ckeditor/ckeditor.module +++ b/core/modules/ckeditor/ckeditor.module @@ -78,7 +78,10 @@ function ckeditor_library_info() { array('system', 'jquery.ui.touch-punch'), array('ckeditor', 'ckeditor'), array('editor', 'drupal.editor.admin'), - array('system', 'underscore') + array('system', 'underscore'), + // Depend on Vertical Tabs, so that Vertical Tabs' JavaScript is executed + // first, which ensures its behavior runs first. + array('system', 'drupal.vertical-tabs'), ), ); $libraries['drupal.ckeditor.drupalimage.admin'] = array( diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js index 338ae6e..2a795de 100644 --- a/core/modules/ckeditor/js/ckeditor.admin.js +++ b/core/modules/ckeditor/js/ckeditor.admin.js @@ -516,4 +516,74 @@ function grantRowFocus (event) { } } +/** + * Automatically shows/hides settings of buttons-only CKEditor plugins. + */ +Drupal.behaviors.ckeditorAdminButtonPluginSettings = { + attach: function (context) { + var $context = $(context); + var $ckeditorPluginSettings = $context.find('#ckeditor-plugin-settings').once('ckeditor-plugin-settings'); + if ($ckeditorPluginSettings.length) { + // Hide all button-dependent plugin settings initially. + $ckeditorPluginSettings.find('[data-ckeditor-plugin-id]').each(function () { + if ($(this).data('verticalTab')) { + $(this).data('verticalTab').tabHide(); + } + else { + // On very narrow viewports, Vertical Tabs are disabled. + $(this).hide(); + } + $(this).data('ckeditorButtonPluginSettingsActiveButtons', []); + }); + + // Whenever a button is added or removed, check if we should show or hide + // the corresponding plugin settings. (Note that upon initialization, each + // button that already is part of the toolbar still is considered "added", + // hence it also works correctly for buttons that were added previously.) + $context + .find('.ckeditor-toolbar-active') + .off('CKEditorToolbarChanged.ckeditorAdminPluginSettings') + .on('CKEditorToolbarChanged.ckeditorAdminPluginSettings', function (event, action, button) { + var $pluginSettings = $ckeditorPluginSettings + .find('[data-ckeditor-buttons~=' + button + ']'); + + // No settings for this button. + if ($pluginSettings.length === 0) { + return; + } + + var verticalTab = $pluginSettings.data('verticalTab'); + var activeButtons = $pluginSettings.data('ckeditorButtonPluginSettingsActiveButtons'); + if (action === 'added') { + activeButtons.push(button); + // Show this plugin's settings if >=1 of its buttons are active. + if (verticalTab) { + verticalTab.tabShow(); + } + else { + // On very narrow viewports, Vertical Tabs remain fieldsets. + $pluginSettings.show(); + } + + } + else { + // Remove this button from the list of active buttons. + activeButtons.splice(activeButtons.indexOf(button), 1); + // Show this plugin's settings 0 of its buttons are active. + if (activeButtons.length === 0) { + if (verticalTab) { + verticalTab.tabHide(); + } + else { + // On very narrow viewports, Vertical Tabs are disabled. + $pluginSettings.hide(); + } + } + } + $pluginSettings.data('ckeditorButtonPluginSettingsActiveButtons', activeButtons); + }); + } + } +}; + })(jQuery, Drupal, drupalSettings, CKEDITOR, _); diff --git a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js index ec093ab..91ead76 100644 --- a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js +++ b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js @@ -3,36 +3,6 @@ "use strict"; /** - * Shows the "drupalimage" plugin settings only when the button is enabled. - */ -Drupal.behaviors.ckeditorDrupalImageSettings = { - attach: function (context) { - var $context = $(context); - var $drupalImageVerticalTab = $('#edit-editor-settings-plugins-drupalimage').data('verticalTab'); - - // Hide if the "DrupalImage" button is disabled. - if ($('.ckeditor-toolbar-disabled li[data-button-name="DrupalImage"]').length === 1) { - $drupalImageVerticalTab.tabHide(); - } - - // React to added/removed toolbar buttons. - $context - .find('.ckeditor-toolbar-active') - .on('CKEditorToolbarChanged.ckeditorDrupalImageSettings', function (e, action, button) { - if (button === 'DrupalImage') { - if (action === 'added') { - $drupalImageVerticalTab.tabShow(); - } - else { - $drupalImageVerticalTab.tabHide(); - } - } - }); - } - -}; - -/** * Provides the summary for the "drupalimage" plugin settings vertical tab. */ Drupal.behaviors.ckeditorDrupalImageSettingsSummary = { diff --git a/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js index 84e6e0a..c10b046 100644 --- a/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js +++ b/core/modules/ckeditor/js/ckeditor.stylescombo.admin.js @@ -3,31 +3,16 @@ "use strict"; /** - * Shows the "stylescombo" plugin settings only when the button is enabled. + * Ensures that the "stylescombo" button's metadata remains up-to-date. + * + * Triggers the CKEditorPluginSettingsChanged event whenever the "stylescombo" + * plugin settings change, to ensure that the corresponding feature metadata is + * immediately updated — i.e. ensure that HTML tags and classes entered here are + * known to be "required", which may affect filter settings. */ Drupal.behaviors.ckeditorStylesComboSettings = { attach: function (context) { var $context = $(context); - var $stylesComboVerticalTab = $('#edit-editor-settings-plugins-stylescombo').data('verticalTab'); - - // Hide if the "Styles" button is disabled. - if ($('.ckeditor-toolbar-disabled li[data-button-name="Styles"]').length === 1) { - $stylesComboVerticalTab.tabHide(); - } - - // React to added/removed toolbar buttons. - $context - .find('.ckeditor-toolbar-active') - .on('CKEditorToolbarChanged.ckeditorStylesComboSettings', function (e, action, button) { - if (button === 'Styles') { - if (action === 'added') { - $stylesComboVerticalTab.tabShow(); - } - else { - $stylesComboVerticalTab.tabHide(); - } - } - }); // React to changes in the list of user-defined styles: calculate the new // stylesSet setting up to 2 times per second, and if it is different, fire diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php index 636d82b..9c16741 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php @@ -150,7 +150,19 @@ public function injectPluginSettingsForm(array &$form, array &$form_state, Edito '#type' => 'details', '#title' => $definitions[$plugin_id]['label'], '#group' => 'editor][settings][plugin_settings', + '#attributes' => array( + 'data-ckeditor-plugin-id' => $plugin_id, + ), ); + // Provide enough metadata for the drupal.ckeditor.admin library to + // allow it to automatically show/hide the vertical tab containing the + // settings for this plugin. Only do this if it's a CKEditor plugin that + // just provides buttons, don't do this if it's a contextually enabled + // CKEditor plugin. After all, in the latter case, we can't know when + // its settings should be shown! + if ($plugin instanceof CKEditorPluginButtonsInterface and !$plugin instanceof CKEditorPluginContextualInterface) { + $form['plugins'][$plugin_id]['#attributes']['data-ckeditor-buttons'] = implode(' ', array_keys($plugin->getButtons())); + } $form['plugins'][$plugin_id] += $plugin->settingsForm($plugin_settings_form, $form_state, $editor); } } diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php index 0465cdf..9b7a55b 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php @@ -143,6 +143,9 @@ public function settingsForm(array $form, array &$form_state, EditorEntity $edit $form['plugin_settings'] = array( '#type' => 'vertical_tabs', '#title' => t('CKEditor plugin settings'), + '#attributes' => array( + 'id' => 'ckeditor-plugin-settings', + ), ); $this->ckeditorPluginManager->injectPluginSettingsForm($form, $form_state, $editor); if (count(element_children($form['plugins'])) === 0) {