Commit 5fd14ba7 authored by webchick's avatar webchick

Issue #1872206 by jessebeach, quicksketch, Wim Leers, mgifford: Fixed Improve...

Issue #1872206 by jessebeach, quicksketch, Wim Leers, mgifford: Fixed Improve CKEditor toolbar configuration accessibility.
parent a6efca1d
...@@ -30,18 +30,29 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) { ...@@ -30,18 +30,29 @@ function template_preprocess_ckeditor_settings_toolbar(&$variables) {
$buttons[$button_name] = $button; $buttons[$button_name] = $button;
} }
} }
$button_groups = array();
$variables['active_buttons'] = array(); $variables['active_buttons'] = array();
foreach ($editor->settings['toolbar']['buttons'] as $row_number => $row) { foreach ($editor->settings['toolbar']['rows'] as $row_number => $row) {
foreach ($row as $button_name) { $button_groups[$row_number] = array();
if (isset($buttons[$button_name])) { foreach ($row as $group) {
$variables['active_buttons'][$row_number][] = $buttons[$button_name]; foreach ($group['items'] as $button_name) {
if (empty($buttons[$button_name]['multiple'])) { if (isset($buttons[$button_name])) {
unset($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['disabled_buttons'] = array_diff_key($buttons, $variables['multiple_buttons']);
$variables['button_groups'] = $button_groups;
} }
/** /**
...@@ -66,7 +77,7 @@ function theme_ckeditor_settings_toolbar($variables) { ...@@ -66,7 +77,7 @@ function theme_ckeditor_settings_toolbar($variables) {
'#uri' => $button['image' . $rtl], '#uri' => $button['image' . $rtl],
'#title' => $button['label'], '#title' => $button['label'],
); );
$value = '<a href="#" class="cke_button" role="button" title="' . $button['label'] . '" aria-label="' . $button['label'] . '"><span class="cke_button_icon">' . drupal_render($image) . '</span></a>'; $value = '<a href="#" role="button" title="' . $button['label'] . '" aria-label="' . $button['label'] . '"><span class="cke_button_icon">' . drupal_render($image) . '</span></a>';
} }
else { else {
$value = '?'; $value = '?';
...@@ -80,8 +91,13 @@ function theme_ckeditor_settings_toolbar($variables) { ...@@ -80,8 +91,13 @@ function theme_ckeditor_settings_toolbar($variables) {
// Build the button item. // Build the button item.
$button_item = array( $button_item = array(
'value' => $value, 'value' => $value,
'data-button-name' => $button['name'], 'data-drupal-ckeditor-button-name' => $button['name'],
'class' => array('ckeditor-button'),
); );
// If this button has group information, add it to the attributes.
if (!empty($button['group'])) {
$button_item['group'] = $button['group'];
}
if (!empty($button['attributes'])) { if (!empty($button['attributes'])) {
$button_item = array_merge($button_item, $button['attributes']); $button_item = array_merge($button_item, $button['attributes']);
} }
...@@ -110,6 +126,7 @@ function theme_ckeditor_settings_toolbar($variables) { ...@@ -110,6 +126,7 @@ function theme_ckeditor_settings_toolbar($variables) {
$print_buttons = function($buttons) { $print_buttons = function($buttons) {
$output = ''; $output = '';
foreach ($buttons as $button) { foreach ($buttons as $button) {
unset($button['group']);
$value = $button['value']; $value = $button['value'];
unset($button['value']); unset($button['value']);
$attributes = (string) new Attribute($button); $attributes = (string) new Attribute($button);
...@@ -118,6 +135,19 @@ function theme_ckeditor_settings_toolbar($variables) { ...@@ -118,6 +135,19 @@ function theme_ckeditor_settings_toolbar($variables) {
return $output; return $output;
}; };
$print_button_group = function($buttons, $group_name, $print_buttons) {
$group = drupal_html_class($group_name);
$output = '';
$output .= "<li class=\"ckeditor-toolbar-group\" role=\"presentation\" data-drupal-ckeditor-type=\"group\" data-drupal-ckeditor-toolbar-group-name=\"{$group_name}\" tabindex=\"0\">";
$output .= "<h3 class=\"ckeditor-toolbar-group-name\" id=\"ckeditor-toolbar-group-aria-label-for-{$group}\">{$group_name}</h3>";
$output .= "<ul class=\"ckeditor-buttons ckeditor-toolbar-group-buttons\" role=\"toolbar\" data-drupal-ckeditor-button-sorting=\"target\" aria-labelledby=\"ckeditor-toolbar-group-aria-label-for-{$group}\">";
$output .= $print_buttons($buttons);
$output .= "</ul></li>";
return $output;
};
// We don't use theme_item_list() below in case there are no buttons in the // 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. // active or disabled list, as theme_item_list() will not print an empty UL.
$output = ''; $output = '';
...@@ -125,43 +155,45 @@ function theme_ckeditor_settings_toolbar($variables) { ...@@ -125,43 +155,45 @@ function theme_ckeditor_settings_toolbar($variables) {
$output .= '<legend id="ckeditor-button-configuration">' . t('Toolbar configuration') . '</legend>'; $output .= '<legend id="ckeditor-button-configuration">' . t('Toolbar configuration') . '</legend>';
$output .= '<div class="fieldset-wrapper">'; $output .= '<div class="fieldset-wrapper">';
// aria-live region for outputing aural information about the state of the $output .= '<div id="ckeditor-button-description" class="fieldset-description">' . t('Move a button into the <em>Active toolbar</em> to enable it, or into the list of <em>Available buttons</em> to disable it. Buttons may be moved with the mouse or keyboard arrow keys. Toolbar group names are provided to support screen reader users. Empty toolbar groups will be removed upon save.') . '</div>';
// configuration.
$output .= '<div id="ckeditor-button-configuration-aria-live" class="visually-hidden" aria-live="polite"></div>';
$output .= '<div id="ckeditor-button-description" class="fieldset-description">' . t('Move a button into the <em>Active toolbar</em> to enable it, or into the list of <em>Available buttons</em> to disable it. Use dividers to create button groups. Buttons may be moved with the mouse or keyboard arrow keys.') . '</div>';
$output .= '<div class="ckeditor-toolbar-disabled clearfix">'; $output .= '<div class="ckeditor-toolbar-disabled clearfix">';
// Available buttons.
$output .= '<div class="ckeditor-toolbar-available">';
$output .= '<label for="ckeditor-available-buttons">' . t('Available buttons') . '</label>';
$output .= '<ul id="ckeditor-available-buttons" class="ckeditor-buttons" role="form" data-drupal-ckeditor-button-sorting="source">';
$output .= $print_buttons($disabled_buttons);
$output .= '</ul>';
$output .= '</div>';
// Dividers.
$output .= '<div class="ckeditor-toolbar-dividers">'; $output .= '<div class="ckeditor-toolbar-dividers">';
$output .= '<label id="ckeditor-multiple-label">' . t('Dividers') . '</label>'; $output .= '<label for="ckeditor-multiple-buttons">' . t('Button divider') . '</label>';
$output .= '<ul class="ckeditor-multiple-buttons" role="form" aria-labelledby="ckeditor-multiple-label">'; $output .= '<ul id="ckeditor-multiple-buttons" class="ckeditor-multiple-buttons" role="form" data-drupal-ckeditor-button-sorting="dividers">';
$output .= $print_buttons($multiple_buttons); $output .= $print_buttons($multiple_buttons);
$output .= '</ul>'; $output .= '</ul>';
$output .= '</div>'; $output .= '</div>';
$output .= '<label id="ckeditor-available-buttons">' . t('Available buttons') . '</label>';
$output .= '<ul class="ckeditor-buttons" role="form" aria-labelledby="ckeditor-available-buttons">';
$output .= $print_buttons($disabled_buttons);
$output .= '</ul>';
$output .= '</div>'; $output .= '</div>';
// Active toolbar.
$output .= '<label id="ckeditor-active-toolbar">' . t('Active toolbar') . '</label>'; $output .= '<div class="clearfix"><label id="ckeditor-active-toolbar">' . t('Active toolbar') . '</label></div>';
$output .= '<div data-toolbar="active" role="form" class="ckeditor-toolbar ckeditor-toolbar-active clearfix">';
$output .= '<div data-toolbar="active" class="ckeditor-toolbar-active clearfix">'; $output .= '<ul class="ckeditor-active-toolbar-configuration" role="presentation" aria-label="' . t('CKEditor toolbar and button configuration.') . '">';
foreach ($active_buttons as $button_row) { foreach ($active_buttons as $row_number => $button_row) {
$output .= '<ul class="ckeditor-buttons" role="form" aria-labelledby="ckeditor-active-toolbar">'; $output .= '<li class="ckeditor-row" role="group" aria-labelledby="ckeditor-active-toolbar">';
$output .= $print_buttons($button_row); $output .= '<ul class="ckeditor-toolbar-groups clearfix">';
foreach ($variables['button_groups'][$row_number] as $group_name) {
$buttons = array_filter($button_row, function ($button) use ($group_name) {
return $button['group'] === $group_name;
});
$output .= $print_button_group($buttons, $group_name, $print_buttons);
}
$output .= '</ul>'; $output .= '</ul>';
$output .= '</li>';
} }
if (empty($active_buttons)) { if (empty($active_buttons)) {
$output .= '<ul class="ckeditor-buttons">'; $output .= '<ul class="ckeditor-buttons">';
$output .= '</ul>'; $output .= '</ul>';
} }
$output .= '<div class="ckeditor-row-controls">';
$output .= '<a href="#" role="button" aria-label="' . t('Remove last button row') . '" class="ckeditor-row-remove" title="' . t('Remove row') . '">-</a>';
$output .= '<a href="#" role="button" aria-label="' . t('Add additional button row') . '" class="ckeditor-row-add" title="' . t('Add row') . '">+</a>';
$output .= '</div>';
$output .= '</div>'; $output .= '</div>';
$output .= '</div>'; $output .= '</div>';
......
...@@ -76,9 +76,11 @@ function ckeditor_library_info() { ...@@ -76,9 +76,11 @@ function ckeditor_library_info() {
array('system', 'jquery.ui.sortable'), array('system', 'jquery.ui.sortable'),
array('system', 'jquery.ui.draggable'), array('system', 'jquery.ui.draggable'),
array('system', 'jquery.ui.touch-punch'), array('system', 'jquery.ui.touch-punch'),
array('system', 'backbone'),
array('system', 'drupal.dialog'),
array('system', 'drupal.announce'),
array('ckeditor', 'ckeditor'), array('ckeditor', 'ckeditor'),
array('editor', 'drupal.editor.admin'), array('editor', 'drupal.editor.admin'),
array('system', 'underscore'),
// Depend on Vertical Tabs, so that Vertical Tabs' JavaScript is executed // Depend on Vertical Tabs, so that Vertical Tabs' JavaScript is executed
// first, which ensures its behavior runs first. // first, which ensures its behavior runs first.
array('system', 'drupal.vertical-tabs'), array('system', 'drupal.vertical-tabs'),
......
...@@ -8,15 +8,25 @@ editor.settings.ckeditor: ...@@ -8,15 +8,25 @@ editor.settings.ckeditor:
type: mapping type: mapping
label: 'Toolbar configuration' label: 'Toolbar configuration'
mapping: mapping:
buttons: rows:
type: sequence type: sequence
label: 'Rows' label: 'Rows'
sequence: sequence:
- type: sequence - type: sequence
label: 'Buttons' label: 'Button groups'
sequence: sequence:
- type: string - type: mapping
label: 'Button' label: 'Button group'
mapping:
name:
type: string
label: 'Button group name'
items:
type: sequence
label: 'Buttons'
sequence:
- type: string
label: 'Button'
plugins: plugins:
type: sequence type: sequence
label: 'Plugins' label: 'Plugins'
......
...@@ -6,151 +6,252 @@ ...@@ -6,151 +6,252 @@
* "moono". * "moono".
*/ */
.ckeditor-toolbar-active {
.ckeditor-toolbar {
border: 1px solid #b6b6b6; border: 1px solid #b6b6b6;
padding: 6px 8px 2px; padding: 0.1667em 0.1667em 0.08em;
box-shadow: 0 1px 0 white inset; box-shadow: 0 1px 0 white inset;
background: #cfd1cf; background: #cfd1cf;
background-image: -webkit-gradient(linear, left top, left bottom, from(whiteSmoke), to(#cfd1cf)); background-image: -webkit-linear-gradient(top, whiteSmoke, #cfd1cf);
background-image: -moz-linear-gradient(top, whiteSmoke, #cfd1cf); background-image: -moz-linear-gradient(top, whiteSmoke, #cfd1cf);
background-image: -o-linear-gradient(top, whiteSmoke, #cfd1cf);
background-image: -ms-linear-gradient(top, whiteSmoke, #cfd1cf);
background-image: linear-gradient(top, whiteSmoke, #cfd1cf); background-image: linear-gradient(top, whiteSmoke, #cfd1cf);
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#fff5f5f5', endColorstr='#ffcfd1cf');
margin: 5px 0; margin: 5px 0;
overflow: nowrap; /* Disallow any user selections in the drag-and-drop toolbar config UI. */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ckeditor-toolbar-active {
margin-top: 0.25em;
}
.ckeditor-toolbar-disabled {
margin-bottom: 0.5em;
}
.ckeditor-toolbar ul,
.ckeditor-toolbar-disabled ul {
list-style: none;
margin: 0;
padding: 0;
} }
.ckeditor-toolbar-active > ul { .ckeditor-row {
clear: left; /* LTR */ padding: 2px 0px 3px;
border-radius: 3px;
}
.ckeditor-group-names-are-visible .ckeditor-row {
border: 1px solid whitesmoke;
}
.ckeditor-row + .ckeditor-row {
margin-top: 0.25em;
}
.ckeditor-toolbar-group,
.ckeditor-toolbar-group-placeholder,
.ckeditor-add-new-group {
display: inline-block;
float: left; /* LTR */ float: left; /* LTR */
} }
[dir="rtl"] .ckeditor-toolbar-active > ul { [dir="rtl"] .ckeditor-toolbar-group,
clear: right; [dir="rtl"] .ckeditor-toolbar-group-placeholder,
[dir="rtl"] .ckeditor-add-new-group {
display: inline-block;
float: right; float: right;
} }
#ckeditor-button-description { .ckeditor-toolbar-groups {
margin-bottom: 1em; min-height: 2em;
} }
.ckeditor-toolbar-dividers { .ckeditor-toolbar-group {
margin: 0 0.3333em;
cursor: move;
}
.ckeditor-group-names-are-visible .ckeditor-toolbar-group,
.ckeditor-add-new-group {
border: 1px dotted #a6a6a6;
border-radius: 3px;
padding: 0.2em 0.4em;
}
.ckeditor-toolbar-group.placeholder,
.ckeditor-toolbar-group.placeholder .ckeditor-toolbar-group-name {
cursor: not-allowed;
}
.ckeditor-toolbar-group.placeholder .ckeditor-toolbar-group-name {
font-style: italic;
}
.ckeditor-toolbar-group-name {
display: none;
font-size: 1em;
font-weight: normal;
margin: 0.25em 0;
}
.ckeditor-group-names-are-visible .ckeditor-toolbar-group-name {
display: block;
cursor: pointer;
}
.ckeditor-toolbar-active .placeholder,
.ckeditor-toolbar-active .ckeditor-add-new-group {
display: none;
}
.ckeditor-group-names-are-visible .placeholder,
.ckeditor-group-names-are-visible .ckeditor-add-new-group {
display: block;
}
.ckeditor-toolbar-group-buttons {
float: left; /* LTR */
}
[dir="rtl"] .ckeditor-toolbar-group-buttons {
float: right;
}
.ckeditor-groupnames-toggle {
cursor: pointer;
float: right; /* LTR */ float: right; /* LTR */
} }
[dir="rtl"] .ckeditor-toolbar-dividers { [dir="rtl"] .ckeditor-groupnames-toggle {
float: left; float: left;
} }
.ckeditor-toolbar-disabled ul.ckeditor-buttons { .ckeditor-toolbar .ckeditor-toolbar-group > li {
border: 0; border: 1px solid white;
border-radius: 5px;
background-image: -webkit-linear-gradient(transparent 60%, rgba(0, 0, 0, 0.1));
background-image: -moz-linear-gradient(transparent 60%, rgba(0, 0, 0, 0.1));
background-image: linear-gradient(transparent 60%, rgba(0, 0, 0, 0.1));
margin: 3px 6px;
padding: 3px;
} }
.ckeditor-toolbar-disabled ul.ckeditor-buttons li { #ckeditor-button-description {
margin: 2px; margin-bottom: 1em;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-available,
.ckeditor-toolbar-disabled .ckeditor-toolbar-dividers {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-available {
float: left;
width: 80%;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-dividers {
float: right;
width: 20%;
} }
.ckeditor-toolbar-disabled ul.ckeditor-buttons li a, .ckeditor-toolbar-disabled .ckeditor-buttons li a,
ul.ckeditor-buttons { .ckeditor-toolbar .ckeditor-buttons,
.ckeditor-add-new-group button {
border: 1px solid #a6a6a6; border: 1px solid #a6a6a6;
border-bottom-color: #979797; border-bottom-color: #979797;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 1px 0 rgba(255, 255, 255, .5), 0 0 2px rgba(255, 255, 255, .15) inset, 0 1px 0 rgba(255, 255, 255, .15) inset; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 1px 0 rgba(255, 255, 255, 0.15) inset;
} }
.ckeditor-toolbar-disabled .ckeditor-buttons {
ul.ckeditor-buttons { border: 0;
}
.ckeditor-toolbar-disabled .ckeditor-buttons li {
margin: 2px;
}
.ckeditor-buttons {
min-height: 26px; min-height: 26px;
min-width: 26px; min-width: 26px;
list-style: none;
padding: 0;
margin: 0 6px 5px 0;
border: 1px solid #a6a6a6;
border-bottom-color: #979797;
border-radius: 3px;
box-shadow: 0 1px 0 rgba(255, 255, 255, .5), 0 0 2px rgba(255, 255, 255, .15) inset, 0 1px 0 rgba(255, 255, 255, .15) inset;
} }
ul.ckeditor-buttons li { .ckeditor-buttons li {
display: inline-block; display: inline-block;
padding: 0; padding: 0;
margin: 0; margin: 0;
float: left; /* LTR */ float: left; /* LTR */
} }
[dir="rtl"] ul.ckeditor-buttons li { [dir="rtl"] .ckeditor-buttons li {
float: right; float: right;
} }
ul.ckeditor-buttons li a { .ckeditor-buttons li a,
position: relative; .ckeditor-add-new-group button {
background: #e4e4e4;
background-image: -moz-linear-gradient(top, white, #e4e4e4);
background-image: -webkit-linear-gradient(top, white, #e4e4e4);
background-image: linear-gradient(top, white, #e4e4e4);
color: #474747;
}
.ckeditor-buttons li a {
border: 0;
cursor: move;
display: block; display: block;
height: 18px; height: 18px;
padding: 4px 6px; padding: 4px 6px;
cursor: move; position: relative;
border: 0;
white-space: nowrap;
text-decoration: none; text-decoration: none;
text-shadow: 0 1px 0 rgba(255,255,255,.5); text-shadow: 0 1px 0 rgba(255,255,255,.5);
color: #474747; white-space: nowrap;
background: #e4e4e4; }
background-image: -webkit-gradient(linear,left top,left bottom,from(white),to(#e4e4e4)); .ckeditor-toolbar-dividers {
background-image: -moz-linear-gradient(top,white,#e4e4e4); float: right; /* LTR */
background-image: -webkit-linear-gradient(top,white,#e4e4e4); }
background-image: -o-linear-gradient(top,white,#e4e4e4); [dir="rtl"] .ckeditor-toolbar-dividers {
background-image: -ms-linear-gradient(top,white,#e4e4e4); float: left;
background-image: linear-gradient(top,white,#e4e4e4); }
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffffff',endColorstr='#ffe4e4e4'); .ckeditor-buttons li .cke-icon-only {
}
ul.ckeditor-buttons li .cke-icon-only {
text-indent: -9999px; text-indent: -9999px;
width: 16px; width: 16px;
/* Firefox includes the offscreen text in the focus indicator, resulting in a
far too wide focus indicator. This fixes that. */
overflow: hidden;
} }
ul.ckeditor-buttons li a:focus, .ckeditor-buttons li a:focus,
ul.ckeditor-multiple-buttons li a:focus { .ckeditor-buttons li a:active,
.ckeditor-multiple-buttons li a:focus {
z-index: 11; /* Ensure focused buttons show their outline on all sides. */ z-index: 11; /* Ensure focused buttons show their outline on all sides. */
outline: 1px dotted #333;
} }
ul.ckeditor-buttons li:first-child a { .ckeditor-buttons li:first-child a {
border-top-left-radius: 2px; /* LTR */ border-top-left-radius: 2px; /* LTR */
border-bottom-left-radius: 2px; /* LTR */ border-bottom-left-radius: 2px; /* LTR */
} }
[dir="rtl"] ul.ckeditor-buttons li:first-child a { [dir="rtl"] .ckeditor-buttons li:first-child a {
border-top-right-radius: 2px; border-top-right-radius: 2px;
border-bottom-right-radius: 2px; border-bottom-right-radius: 2px;
} }
ul.ckeditor-buttons li:last-child a { .ckeditor-buttons li:last-child a {
border-top-right-radius: 2px; /* LTR */ border-top-right-radius: 2px; /* LTR */
border-bottom-right-radius: 2px; /* LTR */ border-bottom-right-radius: 2px; /* LTR */
} }
[dir="rtl"] ul.ckeditor-buttons li:last-child a { [dir="rtl"] .ckeditor-buttons li:last-child a {
border-top-left-radius: 2px; border-top-left-radius: 2px;
border-bottom-left-radius: 2px; border-bottom-left-radius: 2px;
} }
ul.ckeditor-buttons li.ckeditor-button-placeholder a { .ckeditor-button-placeholder,
background: #333; .ckeditor-toolbar-group-placeholder {
opacity: 0.3; background: #9dcae7;
} }
ul.ckeditor-multiple-buttons { .ckeditor-toolbar-group-placeholder {
border-radius: 4px;
}
.ckeditor-multiple-buttons {
padding: 1px 2px; padding: 1px 2px;
margin: 5px; margin: 5px;
list-style: none; list-style: none;
float: left; /* LTR */ float: left; /* LTR */
} }
[dir="rtl"] ul.ckeditor-multiple-buttons { [dir="rtl"] .ckeditor-multiple-buttons {
float: right; float: right;
} }
ul.ckeditor-multiple-buttons li { .ckeditor-multiple-buttons li {
display: inline-block; display: inline-block;