diff --git a/core/modules/ckeditor/ckeditor.admin.inc b/core/modules/ckeditor/ckeditor.admin.inc index e99518a..c0992c0 100644 --- a/core/modules/ckeditor/ckeditor.admin.inc +++ b/core/modules/ckeditor/ckeditor.admin.inc @@ -30,18 +30,29 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) { $buttons[$button_name] = $button; } } + $button_groups = array(); $variables['active_buttons'] = array(); - foreach ($editor->settings['toolbar']['buttons'] as $row_number => $row) { - foreach ($row as $button_name) { - if (isset($buttons[$button_name])) { - $variables['active_buttons'][$row_number][] = $buttons[$button_name]; - if (empty($buttons[$button_name]['multiple'])) { - unset($buttons[$button_name]); + foreach ($editor->settings['toolbar']['rows'] as $row_number => $row) { + $button_groups[$row_number] = array(); + foreach ($row as $group) { + foreach ($group['items'] as $button_name) { + if (isset($buttons[$button_name])) { + // Save a reference to the button's configured toolbar group. + $buttons[$button_name]['group'] = $group['name']; + $variables['active_buttons'][$row_number][] = $buttons[$button_name]; + if (empty($buttons[$button_name]['multiple'])) { + unset($buttons[$button_name]); + } + // Create a list of all the toolbar button groups. + if (!in_array($group['name'], $button_groups[$row_number])) { + array_push($button_groups[$row_number], $group['name']); + } } } } } $variables['disabled_buttons'] = array_diff_key($buttons, $variables['multiple_buttons']); + $variables['button_groups'] = $button_groups; } /** @@ -82,6 +93,10 @@ function theme_ckeditor_settings_toolbar($variables) { 'value' => $value, 'data-button-name' => $button['name'], ); + // If this button has group information, add it to the attributes. + if (!empty($button['group'])) { + $button_item['data-button-group'] = $button['group']; + } if (!empty($button['attributes'])) { $button_item = array_merge($button_item, $button['attributes']); } @@ -118,6 +133,15 @@ function theme_ckeditor_settings_toolbar($variables) { return $output; }; + $print_button_group = function($buttons, $group_name, $print_buttons) { + $output = ''; + $output .= "
  • {$group_name}
  • "; + + return $output; + }; + // We don't use theme_item_list() below in case there are no buttons in the // active or disabled list, as theme_item_list() will not print an empty UL. $output = ''; @@ -125,31 +149,34 @@ function theme_ckeditor_settings_toolbar($variables) { $output .= '' . t('Toolbar configuration') . ''; $output .= '
    '; - // aria-live region for outputing aural information about the state of the - // configuration. - $output .= '
    '; - $output .= '
    ' . t('Move a button into the Active toolbar to enable it, or into the list of Available buttons to disable it. Use dividers to create button groups. Buttons may be moved with the mouse or keyboard arrow keys.') . '
    '; $output .= '
    '; $output .= '
    '; + // Dividers. $output .= ''; $output .= '
      '; $output .= $print_buttons($multiple_buttons); $output .= '
    '; $output .= '
    '; + // Available buttons. $output .= ''; $output .= ''; $output .= '
    '; - + // Active toolbar. $output .= ''; $output .= '
    '; - foreach ($active_buttons as $button_row) { + foreach ($active_buttons as $row_number => $button_row) { $output .= ''; } if (empty($active_buttons)) { diff --git a/core/modules/ckeditor/config/schema/ckeditor.schema.yml b/core/modules/ckeditor/config/schema/ckeditor.schema.yml index b201870..dc22281 100644 --- a/core/modules/ckeditor/config/schema/ckeditor.schema.yml +++ b/core/modules/ckeditor/config/schema/ckeditor.schema.yml @@ -8,15 +8,25 @@ editor.settings.ckeditor: type: mapping label: 'Toolbar configuration' mapping: - buttons: + rows: type: sequence label: 'Rows' sequence: - type: sequence - label: 'Buttons' + label: 'Button groups' sequence: - - type: string - label: 'Button' + - type: mapping + label: 'Button group' + mapping: + name: + type: string + label: 'Name' + items: + type: sequence + label: 'Buttons' + sequence: + - type: string + label: 'Button' plugins: type: sequence label: 'Plugins' diff --git a/core/modules/ckeditor/css/ckeditor.admin.css b/core/modules/ckeditor/css/ckeditor.admin.css index 5e1b2ab..0a5dd5b 100644 --- a/core/modules/ckeditor/css/ckeditor.admin.css +++ b/core/modules/ckeditor/css/ckeditor.admin.css @@ -28,6 +28,17 @@ clear: right; float: right; } +.ckeditor-toolbar-active .ckeditor-buttons > li { + border: 1px solid white; + border-radius: 5px; + background-image: linear-gradient(transparent 60%, rgba(0,0,0,0.1)); + margin: 3px 6px; + padding: 3px; +} +.ckeditor-toolbar-active .ckeditor-buttons ul { + margin: 0; + padding: 0; +} #ckeditor-button-description { margin-bottom: 1em; } @@ -96,9 +107,10 @@ ul.ckeditor-buttons li .cke-icon-only { width: 16px; } ul.ckeditor-buttons li a:focus, +ul.ckeditor-buttons li a:active, ul.ckeditor-multiple-buttons li a:focus { + outline: thin dotted; z-index: 11; /* Ensure focused buttons show their outline on all sides. */ - outline: 1px dotted #333; } ul.ckeditor-buttons li:first-child a { border-top-left-radius: 2px; /* LTR */ diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js index 338ae6e..330c600 100644 --- a/core/modules/ckeditor/js/ckeditor.admin.js +++ b/core/modules/ckeditor/js/ckeditor.admin.js @@ -4,9 +4,6 @@ Drupal.ckeditor = Drupal.ckeditor || {}; -// Aria-live element for speaking application state. -var $messages; - Drupal.behaviors.ckeditorAdmin = { attach: function (context) { var $context = $(context); @@ -58,14 +55,14 @@ Drupal.behaviors.ckeditorAdmin = { else { $destinationRow.append($button); } + // Update the toolbar value field. + adminToolbarValue(event, { item: $button }); // Post the update to the aria-live message element. - $messages.text(Drupal.t('moved to @row, position @position of @totalPositions', { - '@row': getRowInfo($destinationRow), + Drupal.announce(Drupal.t('Moved to @row, position @position of @totalPositions.', { + '@row': getRowName($destinationRow), '@position': (destinationPosition + 1), '@totalPositions': $destinationRow.children().length })); - // Update the toolbar value field. - adminToolbarValue(event, { item: $button }); } event.preventDefault(); } @@ -91,17 +88,15 @@ Drupal.behaviors.ckeditorAdmin = { var $button = $link.parent(); var $currentRow = $button.closest('.ckeditor-buttons'); var enabled = $button.closest('.ckeditor-toolbar-active').length > 0; - var position = $button.index() + 1; // 1-based index for humans. - var rowNumber = $toolbarRows.index($currentRow) + 1; var type = event.data.type; var message; if (enabled) { if (type === 'separator') { - message = Drupal.t('Separators are used to visually split individual buttons. This @name is currently enabled, in row @row and position @position.', { '@name': $link.attr('aria-label'), '@row': rowNumber, '@position': position }) + "\n\n" + Drupal.t('Drag and drop the separator or use the keyboard arrow keys to change the position of this separator.'); + message = Drupal.t('Separators are used to visually split individual buttons. This @name is currently enabled.', { '@name': $link.attr('aria-label') }) + "\n\n" + Drupal.t('Drag and drop the separator or use the keyboard arrow keys to change the position of this separator.'); } else { - message = Drupal.t('The @name button is currently enabled, in row @row and position @position.', { '@name': $link.attr('aria-label'), '@row': rowNumber, '@position': position }) + "\n\n" + Drupal.t('Drag and drop the buttons or use the keyboard arrow keys to change the position of this button.'); + message = Drupal.t('The "@name" button is currently enabled.', { '@name': $link.attr('aria-label') }) + "\n\n" + Drupal.t('Drag and drop the buttons or use the keyboard arrow keys to change the position of this button.'); } } else { @@ -109,10 +104,10 @@ Drupal.behaviors.ckeditorAdmin = { message = Drupal.t('Separators are used to visually split individual buttons. This @name is currently disabled.', { '@name': $link.attr('aria-label') }) + "\n\n" + Drupal.t('Drag the button or use the up arrow key to move this separator into the active toolbar. You may add multiple separators to each row.'); } else { - message = Drupal.t('The @name button is currently disabled.', { '@name': $link.attr('aria-label') }) + "\n\n" + Drupal.t('Drag the button or use the up arrow key to move this button into the active toolbar.'); + message = Drupal.t('The "@name" button is currently disabled.', { '@name': $link.attr('aria-label') }) + "\n\n" + Drupal.t('Drag the button or use the down arrow key to move this button into the active toolbar.'); } } - $messages.text(message); + alert(message); $link.focus(); event.preventDefault(); } @@ -129,7 +124,7 @@ Drupal.behaviors.ckeditorAdmin = { $this.siblings('a').show(); redrawToolbarGradient(); // Post the update to the aria-live message element. - $messages.text(Drupal.t('row number @count added.', {'@count': ($rows.length + 1)})); + Drupal.announce(Drupal.t('Row number @count added.', {'@count': ($rows.length + 1)})); event.preventDefault(); } @@ -151,7 +146,7 @@ Drupal.behaviors.ckeditorAdmin = { redrawToolbarGradient(); } // Post the update to the aria-live message element. - $messages.text(Drupal.formatPlural($rows.length - 1, 'row removed. 1 row remaining.', 'row removed. @count rows remaining.')); + Drupal.announce(Drupal.t('Row removed.') + ' ' + Drupal.formatPlural($rows.length - 1, 'One row remaining.', '@count rows remaining.')); event.preventDefault(); } @@ -166,8 +161,14 @@ Drupal.behaviors.ckeditorAdmin = { } /** - * jQuery Sortable stop event. Save updated toolbar positions to the - * textarea. + * jQuery Sortable start event. Remove focus from any other buttons. + */ + function adminToolbarStartDrag (event, ui) { + $toolbarRows.find('a:focus').blur(); + } + + /** + * jQuery Sortable stop event. Save new toolbar positions to the textarea. */ function adminToolbarValue (event, ui) { var oldToolbarConfig = JSON.parse($textarea.val()); @@ -361,7 +362,7 @@ Drupal.behaviors.ckeditorAdmin = { } if ($ckeditorToolbar.length) { - var $textareaWrapper = $ckeditorToolbar.find('.form-item-editor-settings-toolbar-buttons').hide(); + var $textareaWrapper = $ckeditorToolbar.find('.form-item-editor-settings-toolbar-button-groups').hide(); var $textarea = $textareaWrapper.find('textarea'); var $toolbarAdmin = $(drupalSettings.ckeditor.toolbarAdmin); var sortableSettings = { @@ -370,6 +371,7 @@ Drupal.behaviors.ckeditorAdmin = { forcePlaceholderSize: true, tolerance: 'pointer', cursor: 'move', + start: adminToolbarStartDrag, stop: adminToolbarValue }; // Add the toolbar to the page. @@ -402,10 +404,7 @@ Drupal.behaviors.ckeditorAdmin = { } // Add aural UI focus updates when for individual toolbars. - $toolbarAdmin.on('focus.ckeditor', '.ckeditor-buttons', grantRowFocus); - // Identify the aria-live element for interaction updates for screen - // readers. - $messages = $('#ckeditor-button-configuration-aria-live'); + $toolbarAdmin.on('focus.ckeditor', '.ckeditor-buttons a', announceButtonPosition); getCKEditorFeatures(hiddenCKEditorConfig, function (features) { featuresMetadata = features; @@ -418,11 +417,21 @@ Drupal.behaviors.ckeditorAdmin = { // buttons that require more permissive filter settings. The remaining // default toolbar buttons are marked as "added". var $activeToolbar = $ckeditorToolbar.find('.ckeditor-toolbar-active'); - var existingButtons = _.unique(_.flatten(JSON.parse($textarea.val()))); + var existingButtons = []; + // Loop through each button group after flattening the groups from the + // toolbar row arrays. + for (var i = 0, buttonGroups = _.flatten(JSON.parse($textarea.val())); i < buttonGroups.length; i++) { + // Pull the button names from each toolbar button group. + for (var k = 0, buttons = buttonGroups[i].items; k < buttons.length; k++) { + existingButtons.push(buttons[k]); + } + } + // Remove duplicate buttons. + existingButtons = _.unique(existingButtons); + // Prepare the active toolbar and available-button toolbars. for (var i = 0; i < existingButtons.length; i++) { var button = existingButtons[i]; var feature = getFeatureForButton(button); - // Skip dividers. if (feature === false) { continue; @@ -477,43 +486,36 @@ Drupal.behaviors.ckeditorAdmin = { * A jQuery object containing a .ckeditor-button row. * * @return {String} - * A string describing the type and index of a toolbar row. + * A string describing a toolbar row. */ -function getRowInfo ($row) { +function getRowName ($row) { var output = ''; var row; // Determine if this is an active row or an available row. if ($row.closest('.ckeditor-toolbar-disabled').length > 0) { - row = $('.ckeditor-toolbar-disabled').find('.ckeditor-buttons').index($row) + 1; - output += Drupal.t('available button row @row', {'@row': row}); + output += Drupal.t('available buttons row'); } else { row = $('.ckeditor-toolbar-active').find('.ckeditor-buttons').index($row) + 1; - output += Drupal.t('active button row @row', {'@row': row}); + output += Drupal.t('active buttons row @row', {'@row': row}); } return output; } /** - * Applies or removes the focused class to a toolbar row. - * - * When a button in a toolbar is focused, focus is triggered on the containing - * toolbar row. When a row is focused, the state change is announced through - * the aria-live message area. + * Announces current button position when a button receives focus. * * @param {jQuery} event * A jQuery event. */ -function grantRowFocus (event) { - var $row = $(event.currentTarget); - // Remove the focused class from all other toolbars. - $('.ckeditor-buttons.focused').not($row).removeClass('focused'); - // Post the update to the aria-live message element. - if (!$row.hasClass('focused')) { - // Indicate that the current row has focus. - $row.addClass('focused'); - $messages.text(Drupal.t('@row', {'@row': getRowInfo($row)})); - } +function announceButtonPosition (event) { + var $button = $(event.currentTarget); + var $row = $button.closest('.ckeditor-buttons'); + Drupal.announce(Drupal.t('Position @position of @totalPositions in @row.', { + '@position': $row.find('li a').index($button) + 1, + '@totalPositions': $row.children().length, + '@row': getRowName($row) + })); } })(jQuery, Drupal, drupalSettings, CKEDITOR, _); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php index dc69f7e..4cd57bc 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/CKEditorPluginManager.php @@ -66,7 +66,14 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac */ public function getEnabledPluginFiles(Editor $editor, $include_internal_plugins = FALSE) { $plugins = array_keys($this->getDefinitions()); - $toolbar_buttons = array_unique(NestedArray::mergeDeepArray($editor->settings['toolbar']['buttons'])); + // Flatten each row. + $toolbar_rows = array(); + foreach ($editor->settings['toolbar']['rows'] as $row_number => $row) { + $toolbar_rows[] = array_reduce($editor->settings['toolbar']['rows'][$row_number], function (&$result, $button_group) { + return array_merge($result, $button_group['items']); + }, array()); + } + $toolbar_buttons = array_unique(NestedArray::mergeDeepArray($toolbar_rows)); $enabled_plugins = array(); $additional_plugins = array(); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php index 75a97bf..5590ae6 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/Internal.php @@ -55,7 +55,13 @@ public function getConfig(Editor $editor) { $config['allowedContent'] = $this->generateAllowedContentSetting($editor); // Add the format_tags setting, if its button is enabled. - $toolbar_buttons = array_unique(NestedArray::mergeDeepArray($editor->settings['toolbar']['buttons'])); + $toolbar_rows = array(); + foreach ($editor->settings['toolbar']['rows'] as $row_number => $row) { + $toolbar_rows[] = array_reduce($editor->settings['toolbar']['rows'][$row_number], function (&$result, $button_group) { + return array_merge($result, $button_group['items']); + }, array()); + } + $toolbar_buttons = array_unique(NestedArray::mergeDeepArray($toolbar_rows)); if (in_array('Format', $toolbar_buttons)) { $config['format_tags'] = $this->generateFormatTagsSetting($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 345597c..1945536 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/Editor/CKEditor.php @@ -94,13 +94,29 @@ public static function create(ContainerInterface $container, array $configuratio public function getDefaultSettings() { return array( 'toolbar' => array( - 'buttons' => array( + 'rows' => array( + // Button groups array( - 'Bold', 'Italic', - '|', 'DrupalLink', 'DrupalUnlink', - '|', 'BulletedList', 'NumberedList', - '|', 'Blockquote', 'DrupalImage', - '|', 'Source', + array( + 'name' => t('Formatting'), + 'items' => array('Bold', 'Italic',), + ), + array( + 'name' => t('Links'), + 'items' => array('DrupalLink', 'DrupalUnlink',), + ), + array( + 'name' => t('Lists'), + 'items' => array('BulletedList', 'NumberedList',), + ), + array( + 'name' => t('Media'), + 'items' => array('Blockquote', 'DrupalImage',), + ), + array( + 'name' => t('Tools'), + 'items' => array('Source',), + ), ), ), ), @@ -132,10 +148,11 @@ public function settingsForm(array $form, array &$form_state, EditorEntity $edit ), '#attributes' => array('class' => array('ckeditor-toolbar-configuration')), ); - $form['toolbar']['buttons'] = array( + + $form['toolbar']['button_groups'] = array( '#type' => 'textarea', '#title' => t('Toolbar buttons'), - '#default_value' => json_encode($editor->settings['toolbar']['buttons']), + '#default_value' => json_encode($editor->settings['toolbar']['rows']), '#attributes' => array('class' => array('ckeditor-toolbar-textarea')), ); @@ -175,7 +192,7 @@ public function settingsForm(array $form, array &$form_state, EditorEntity $edit 'editor' => 'ckeditor', 'settings' => array( // Single toolbar row that contains all existing buttons. - 'toolbar' => array('buttons' => array(0 => $all_buttons)), + 'toolbar' => $editor->settings['toolbar'], 'plugins' => $editor->settings['plugins'], ), )); @@ -209,7 +226,10 @@ public function settingsFormSubmit(array $form, array &$form_state) { // editor_form_filter_admin_format_submit(). $toolbar_settings = &$form_state['values']['editor']['settings']['toolbar']; - $toolbar_settings['buttons'] = json_decode($toolbar_settings['buttons'], FALSE); + // The rows key is not built into the form structure, so decode the button + // groups data into this new key and remove the button_groups key. + $toolbar_settings['rows'] = json_decode($toolbar_settings['button_groups'], FALSE); + unset($toolbar_settings['button_groups']); // Remove the plugin settings' vertical tabs state; no need to save that. if (isset($form_state['values']['editor']['settings']['plugins'])) { @@ -349,22 +369,12 @@ public function getLibraries(EditorEntity $editor) { */ public function buildToolbarJSSetting(EditorEntity $editor) { $toolbar = array(); - foreach ($editor->settings['toolbar']['buttons'] as $row) { - $button_group = array(); - foreach ($row as $button_name) { - // Change the toolbar separators into groups. - if ($button_name === '|') { - $toolbar[] = $button_group; - $button_group = array(); - } - else { - $button_group['items'][] = $button_name; - } + foreach ($editor->settings['toolbar']['rows'] as $row) { + foreach ($row as $group) { + $toolbar[] = $group; } - $toolbar[] = $button_group; $toolbar[] = '/'; } - return $toolbar; } diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php index e0e3cac..b375d03 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorAdminTest.php @@ -77,13 +77,29 @@ function testAdmin() { // Ensure the CKEditor editor returns the expected default settings. $expected_default_settings = array( 'toolbar' => array( - 'buttons' => array( + 'rows' => array( + // Button groups array( - 'Bold', 'Italic', - '|', 'DrupalLink', 'DrupalUnlink', - '|', 'BulletedList', 'NumberedList', - '|', 'Blockquote', 'DrupalImage', - '|', 'Source', + array( + 'name' => t('Formatting'), + 'items' => array('Bold', 'Italic',), + ), + array( + 'name' => t('Links'), + 'items' => array('DrupalLink', 'DrupalUnlink',), + ), + array( + 'name' => t('Lists'), + 'items' => array('BulletedList', 'NumberedList',), + ), + array( + 'name' => t('Media'), + 'items' => array('Blockquote', 'DrupalImage',), + ), + array( + 'name' => t('Tools'), + 'items' => array('Source',), + ), ), ), ), @@ -98,8 +114,8 @@ function testAdmin() { // Ensure the toolbar buttons configuration value is initialized to the // expected default value. - $expected_buttons_value = json_encode($expected_default_settings['toolbar']['buttons']); - $this->assertFieldByName('editor[settings][toolbar][buttons]', $expected_buttons_value); + $expected_buttons_value = json_encode($expected_default_settings['toolbar']['rows']); + $this->assertFieldByName('editor[settings][toolbar][button_groups]', $expected_buttons_value); // Ensure the styles textarea exists and is initialized empty. $styles_textarea = $this->xpath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]'); @@ -131,12 +147,13 @@ function testAdmin() { // done via drag and drop, but here we can only emulate the end result of // that interaction). Test multiple toolbar rows and a divider within a row. $this->drupalGet('admin/config/content/formats/manage/filtered_html'); - $expected_settings['toolbar']['buttons'] = array( - array('Undo', '|', 'Redo'), - array('JustifyCenter'), + $expected_settings['toolbar']['rows'][0][] = array( + 'name' => 'Action history', + 'items' => array('Undo', '|', 'Redo'), + array('JustifyCenter') ); $edit = array( - 'editor[settings][toolbar][buttons]' => json_encode($expected_settings['toolbar']['buttons']), + 'editor[settings][toolbar][button_groups]' => json_encode($expected_settings['toolbar']['rows']), ); $this->drupalPost(NULL, $edit, t('Save configuration')); $editor = entity_load('editor', 'filtered_html'); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php index cee1e75..0661452 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorPluginManagerTest.php @@ -103,8 +103,8 @@ function testEnabledPlugins() { // cause the LlamaContextual and LlamaContextualAndButton plugins to be // enabled. Finally, we will add the "Strike" button back again, which would // cause all three plugins to be enabled. - $original_toolbar = $editor->settings['toolbar']['buttons'][0]; - $editor->settings['toolbar']['buttons'][0][] = 'Llama'; + $original_toolbar = $editor->settings['toolbar']; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Llama'; $editor->save(); $file = array(); $file['b'] = 'core/modules/ckeditor/tests/modules/js/llama_button.js'; @@ -113,13 +113,13 @@ function testEnabledPlugins() { $expected = $enabled_plugins + array('llama_button' => $file['b'], 'llama_contextual_and_button' => $file['cb']); $this->assertIdentical($expected, $this->manager->getEnabledPluginFiles($editor), 'The LlamaButton and LlamaContextualAndButton plugins are enabled.'); $this->assertIdentical(array('internal' => NULL) + $expected, $this->manager->getEnabledPluginFiles($editor, TRUE), 'The LlamaButton and LlamaContextualAndButton plugins are enabled.'); - $editor->settings['toolbar']['buttons'][0] = $original_toolbar; - $editor->settings['toolbar']['buttons'][0][] = 'Strike'; + $editor->settings['toolbar'] = $original_toolbar; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Strike'; $editor->save(); $expected = $enabled_plugins + array('llama_contextual' => $file['c'], 'llama_contextual_and_button' => $file['cb']); $this->assertIdentical($expected, $this->manager->getEnabledPluginFiles($editor), 'The LLamaContextual and LlamaContextualAndButton plugins are enabled.'); $this->assertIdentical(array('internal' => NULL) + $expected, $this->manager->getEnabledPluginFiles($editor, TRUE), 'The LlamaContextual and LlamaContextualAndButton plugins are enabled.'); - $editor->settings['toolbar']['buttons'][0][] = 'Llama'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Llama'; $editor->save(); $expected = $enabled_plugins + array('llama_button' => $file['b'], 'llama_contextual' => $file['c'], 'llama_contextual_and_button' => $file['cb']); $this->assertIdentical($expected, $this->manager->getEnabledPluginFiles($editor), 'The LlamaButton, LlamaContextual and LlamaContextualAndButton plugins are enabled.'); diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php index 782d590..e4e821f 100644 --- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php +++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php @@ -109,12 +109,11 @@ function testGetJSSettings() { $this->container->get('plugin.manager.editor')->clearCachedDefinitions(); $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor'); $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions(); - $editor->settings['toolbar']['buttons'][0][] = 'Strike'; - $editor->settings['toolbar']['buttons'][1][] = 'Format'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Strike'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Format'; $editor->save(); - $expected_config['toolbar'][count($expected_config['toolbar'])-2]['items'][] = 'Strike'; - $expected_config['toolbar'][]['items'][] = 'Format'; - $expected_config['toolbar'][] = '/'; + $expected_config['toolbar'][0]['items'][] = 'Strike'; + $expected_config['toolbar'][0]['items'][] = 'Format'; $expected_config['format_tags'] = 'p;h4;h5;h6'; $expected_config['extraPlugins'] .= ',llama_contextual,llama_contextual_and_button'; $expected_config['drupalExternalPlugins']['llama_contextual'] = file_create_url('core/modules/ckeditor/tests/modules/js/llama_contextual.js'); @@ -208,17 +207,20 @@ function testBuildToolbarJSSetting() { $this->assertIdentical($expected, $this->ckeditor->buildToolbarJSSetting($editor), '"toolbar" configuration part of JS settings built correctly for default toolbar.'); // Customize the configuration. - $editor->settings['toolbar']['buttons'][0][] = 'Strike'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Strike'; $editor->save(); - $expected[count($expected)-2]['items'][] = 'Strike'; + $expected[0]['items'][] = 'Strike'; $this->assertIdentical($expected, $this->ckeditor->buildToolbarJSSetting($editor), '"toolbar" configuration part of JS settings built correctly for customized toolbar.'); // Enable the editor_test module, customize further. $this->enableModules(array('ckeditor_test')); $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions(); - $editor->settings['toolbar']['buttons'][0][] = 'Llama'; + // Override the label of a toolbar component. + $editor->settings['toolbar']['rows'][0][0]['name'] = 'JunkScience'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Llama'; $editor->save(); - $expected[count($expected)-2]['items'][] = 'Llama'; + $expected[0]['name'] = 'JunkScience'; + $expected[0]['items'][] = 'Llama'; $this->assertIdentical($expected, $this->ckeditor->buildToolbarJSSetting($editor), '"toolbar" configuration part of JS settings built correctly for customized toolbar with contrib module-provided CKEditor plugin.'); } @@ -253,7 +255,7 @@ function testInternalGetConfig() { $this->assertIdentical($expected, $internal_plugin->getConfig($editor), '"Internal" plugin configuration built correctly for default toolbar.'); // Format dropdown/button enabled: new setting should be present. - $editor->settings['toolbar']['buttons'][0][] = 'Format'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Format'; $expected['format_tags'] = 'p;h4;h5;h6'; $this->assertIdentical($expected, $internal_plugin->getConfig($editor), '"Internal" plugin configuration built correctly for customized toolbar.'); } @@ -266,7 +268,7 @@ function testStylesComboGetConfig() { $stylescombo_plugin = $this->container->get('plugin.manager.ckeditor.plugin')->createInstance('stylescombo'); // Styles dropdown/button enabled: new setting should be present. - $editor->settings['toolbar']['buttons'][0][] = 'Styles'; + $editor->settings['toolbar']['rows'][0][0]['items'][] = 'Styles'; $editor->settings['plugins']['stylescombo']['styles'] = ''; $editor->save(); $expected['stylesSet'] = array(); @@ -367,12 +369,27 @@ protected function getDefaultAllowedContentConfig() { protected function getDefaultToolbarConfig() { return array( - 0 => array('items' => array('Bold', 'Italic')), - 1 => array('items' => array('DrupalLink', 'DrupalUnlink')), - 2 => array('items' => array('BulletedList', 'NumberedList')), - 3 => array('items' => array('Blockquote', 'DrupalImage')), - 4 => array('items' => array('Source')), - 5 => '/' + array( + 'name' => t('Formatting'), + 'items' => array('Bold', 'Italic',), + ), + array( + 'name' => t('Links'), + 'items' => array('DrupalLink', 'DrupalUnlink',), + ), + array( + 'name' => t('Lists'), + 'items' => array('BulletedList', 'NumberedList',), + ), + array( + 'name' => t('Media'), + 'items' => array('Blockquote', 'DrupalImage',), + ), + array( + 'name' => t('Tools'), + 'items' => array('Source',), + ), + '/', ); } diff --git a/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextual.php b/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextual.php index e2fb4b9..d73f910 100644 --- a/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextual.php +++ b/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextual.php @@ -28,9 +28,11 @@ class LlamaContextual extends Llama implements CKEditorPluginContextualInterface */ function isEnabled(Editor $editor) { // Automatically enable this plugin if the Underline button is enabled. - foreach ($editor->settings['toolbar']['buttons'] as $row) { - if (in_array('Strike', $row)) { - return TRUE; + foreach ($editor->settings['toolbar']['rows'] as $row) { + foreach ($row as $group) { + if (in_array('Strike', $group['items'])) { + return TRUE; + } } } return FALSE; diff --git a/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextualAndButton.php b/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextualAndButton.php index 87ec5a7..98f1c24 100644 --- a/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextualAndButton.php +++ b/core/modules/ckeditor/tests/modules/lib/Drupal/ckeditor_test/Plugin/CKEditorPlugin/LlamaContextualAndButton.php @@ -30,10 +30,12 @@ class LlamaContextualAndButton extends Llama implements CKEditorPluginContextual * Implements \Drupal\ckeditor\Plugin\CKEditorPluginContextualInterface::isEnabled(). */ function isEnabled(Editor $editor) { - // Automatically enable this plugin if the Strike button is enabled. - foreach ($editor->settings['toolbar']['buttons'] as $row) { - if (in_array('Strike', $row)) { - return TRUE; + // Automatically enable this plugin if the Underline button is enabled. + foreach ($editor->settings['toolbar']['rows'] as $row) { + foreach ($row as $group) { + if (in_array('Strike', $group['items'])) { + return TRUE; + } } } return FALSE; diff --git a/core/profiles/standard/config/editor.editor.basic_html.yml b/core/profiles/standard/config/editor.editor.basic_html.yml index e340685..e321d30 100644 --- a/core/profiles/standard/config/editor.editor.basic_html.yml +++ b/core/profiles/standard/config/editor.editor.basic_html.yml @@ -2,21 +2,32 @@ format: basic_html editor: ckeditor settings: toolbar: - buttons: + rows: - - - Bold - - Italic - - '|' - - DrupalLink - - DrupalUnlink - - '|' - - BulletedList - - NumberedList - - '|' - - Blockquote - - DrupalImage - - '|' - - Source + - + name: Formatting + items: + - Bold + - Italic + - + name: Linking + items: + - DrupalLink + - DrupalUnlink + - + name: Lists + items: + - BulletedList + - NumberedList + - + name: Media + items: + - Blockquote + - DrupalImage + - + name: Tools + items: + - Source plugins: stylescombo: styles: '' @@ -29,4 +40,4 @@ image_upload: width: '' height: '' status: '1' -langcode: und +langcode: en diff --git a/core/profiles/standard/config/editor.editor.full_html.yml b/core/profiles/standard/config/editor.editor.full_html.yml index eb01c1c..3a61cf8 100644 --- a/core/profiles/standard/config/editor.editor.full_html.yml +++ b/core/profiles/standard/config/editor.editor.full_html.yml @@ -2,31 +2,45 @@ format: full_html editor: ckeditor settings: toolbar: - buttons: + rows: - - - Bold - - Italic - - Strike - - Superscript - - Subscript - - - - - RemoveFormat - - '|' - - DrupalLink - - DrupalUnlink - - '|' - - BulletedList - - NumberedList - - '|' - - Blockquote - - DrupalImage - - Table - - HorizontalRule - - '|' - - Format - - '|' - - ShowBlocks - - Source + - + name: Formatting + items: + - Bold + - Italic + - Strike + - Superscript + - Subscript + - - + - RemoveFormat + - + name: Linking + items: + - DrupalLink + - DrupalUnlink + - + name: Lists + items: + - BulletedList + - NumberedList + - + name: Media + items: + - Blockquote + - DrupalImage + - Table + - HorizontalRule + - + name: Block Formatting + items: + - Format + - + name: Tools + items: + - ShowBlocks + - Source + plugins: stylescombo: styles: '' @@ -39,4 +53,4 @@ image_upload: width: '' height: '' status: '1' -langcode: und +langcode: en