From ea6c4a84d9325d6cc83ddcc69cfc54f362b22901 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?"J.=20Rene=CC=81e=20Beach"?= <splendidnoise@gmail.com>
Date: Wed, 30 Jan 2013 23:17:02 -0500
Subject: [PATCH] Issue #1872206 by quicksketch, jessebeach, Wim Leers:
 Toolbar configuration for a WYSIWYG editor is not keyboard
 accessible; touch suport missing; non-JS version not
 provided
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: J. Renée Beach <splendidnoise@gmail.com>
---
 core/modules/ckeditor/ckeditor.admin.inc           |   29 +++--
 core/modules/ckeditor/css/ckeditor.admin.css       |   91 ++++++++-------
 core/modules/ckeditor/js/ckeditor.admin.js         |  116 +++++++++++++++++++-
 .../ckeditor/Plugin/ckeditor/plugin/Internal.php   |   46 ++++----
 4 files changed, 208 insertions(+), 74 deletions(-)

diff --git a/core/modules/ckeditor/ckeditor.admin.inc b/core/modules/ckeditor/ckeditor.admin.inc
index f7e414d..bb60f85 100644
--- a/core/modules/ckeditor/ckeditor.admin.inc
+++ b/core/modules/ckeditor/ckeditor.admin.inc
@@ -111,11 +111,17 @@ function theme_ckeditor_settings_toolbar($variables) {
 
   // 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 = '';
-  $output .= '<strong>' . t('Active toolbar') . '</strong>';
+  $output = '<fieldset role="form" aria-labelledby="ckeditor-button-configuration ckeditor-button-description">';
+  $output .= '<legend id="ckeditor-button-configuration">' . t('Button configuration') . '</legend>';
+  // aria-live region for outputing aural information about the state of the
+  // configuration.
+  $output .= '<div id="ckeditor-button-configuration-aria-live" class="element-invisible" aria-live="polite"></div>';
+  $output .= '<p id="ckeditor-button-description">' . t('Toolbar buttons may be moved by drag and drop or with the keyboard arrow keys. Move a button up into the active toolbar to enable it, or down into the available buttons list to disable it. Dividers are available to create logical button groups.') . '</p>';
+  $output .= '<label id="ckeditor-active-toolbar">' . t('Active toolbar') . '</label>';
+
   $output .= '<div class="ckeditor-toolbar-active clearfix">';
   foreach ($active_buttons as $button_row) {
-    $output .= '<ul class="ckeditor-buttons">';
+    $output .= '<ul class="ckeditor-buttons" role="form" aria-labelledby="ckeditor-active-toolbar">';
     $output .= $print_buttons($button_row);
     $output .= '</ul>';
   }
@@ -125,22 +131,23 @@ function theme_ckeditor_settings_toolbar($variables) {
   }
 
   $output .= '<div class="ckeditor-row-controls">';
-  $output .= '<a href="#" class="ckeditor-row-remove" title="' . t('Remove row') . '">-</a>';
-  $output .= '<a href="#" class="ckeditor-row-add" title="' . t('Add row') . '">+</a>';
+  $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 .= '<strong>' . t('Available buttons') . '</strong>';
-  $output .= '<div class="ckeditor-toolbar-disabled clearfix">';
-  $output .= '<ul class="ckeditor-buttons">';
+  $output .= '<div class="ckeditor-toolbar-disabled">';
+  $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 .= '<strong class="ckeditor-multiple-label">' . t('Dividers') . ': </strong>';
-  $output .= '<ul class="ckeditor-multiple-buttons">';
+  $output .= '</ul>';  
+  $output .= '<label id="ckeditor-multiple-label">' . t('Dividers') . '</label>';
+  $output .= '<ul class="ckeditor-multiple-buttons" role="form" aria-labelledby="ckeditor-multiple-label">';
   $output .= $print_buttons($multiple_buttons);
   $output .= '</ul>';
   $output .= '</div>';
+  $output .= '</fieldset>';
 
   return $output;
 }
diff --git a/core/modules/ckeditor/css/ckeditor.admin.css b/core/modules/ckeditor/css/ckeditor.admin.css
index 62f30b0..3f50e0c 100644
--- a/core/modules/ckeditor/css/ckeditor.admin.css
+++ b/core/modules/ckeditor/css/ckeditor.admin.css
@@ -28,7 +28,7 @@
   margin: 5px;
 }
 
-.ckeditor-toolbar-disabled ul.ckeditor-buttons li,
+.ckeditor-toolbar-disabled ul.ckeditor-buttons li a,
 ul.ckeditor-buttons {
   border: 1px solid #a6a6a6;
   border-bottom-color: #979797;
@@ -41,8 +41,8 @@ ul.ckeditor-buttons {
   min-width: 26px;
   list-style: none;
 
-  float: left;
-  clear: left;
+  float: left; /* RTL */
+  clear: left; /* RTL */
   padding: 0;
   margin: 0 6px 5px 0;
   border: 1px solid #a6a6a6;
@@ -52,13 +52,21 @@ ul.ckeditor-buttons {
 }
 ul.ckeditor-buttons li {
   display: inline-block;
+  padding: 0;
+  margin: 0;
+  float: left; /* RTL */
+}
+ul.ckeditor-buttons li a {
+  position: relative;
+  display: block;
   height: 18px;
   padding: 4px 6px;
-  outline: none;
   cursor: move;
-  float: left;
   border: 0;
   white-space: nowrap;
+  text-decoration: none;
+  text-shadow: 0 1px 0 rgba(255,255,255,.5);
+  color: #474747;
 
   background: #e4e4e4;
   background-image: -webkit-gradient(linear,left top,left bottom,from(white),to(#e4e4e4));
@@ -69,15 +77,22 @@ ul.ckeditor-buttons li {
   background-image: linear-gradient(top,white,#e4e4e4);
   filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffffff',endColorstr='#ffe4e4e4');
 }
-ul.ckeditor-buttons li:first-child {
-  border-top-left-radius: 2px;
-  border-bottom-left-radius: 2px;
+ul.ckeditor-buttons li .cke-icon-only {
+  text-indent: -9999px;
+  width: 1.333em;
+}
+ul.ckeditor-buttons li a:focus {
+  z-index: 11; /* Ensure focused buttons show their outline on all sides. */
 }
-ul.ckeditor-buttons li:last-child {
-  border-top-right-radius: 2px;
-  border-bottom-right-radius: 2px;
+ul.ckeditor-buttons li:first-child a {
+  border-top-left-radius: 2px; /* RTL */
+  border-bottom-left-radius: 2px; /* RTL */
 }
-ul.ckeditor-buttons li.ckeditor-button-placeholder {
+ul.ckeditor-buttons li:last-child a {
+  border-top-right-radius: 2px; /* RTL */
+  border-bottom-right-radius: 2px; /* RTL */
+}
+ul.ckeditor-buttons li.ckeditor-button-placeholder a {
   background: #333;
   opacity: 0.3;
 }
@@ -85,48 +100,46 @@ ul.ckeditor-multiple-buttons {
   padding: 1px 2px;
   margin: 5px;
   list-style: none;
-  float: left;
+  float: left; /* RTL */
 }
 ul.ckeditor-multiple-buttons li {
-  padding: 2px 0;
+  display: inline-block;
+  float: left; /* RTL */
   margin: 0;
+  padding: 0;
+}
+ul.ckeditor-multiple-buttons li a {
+  cursor: move;
   display: inline-block;
   height: 18px;
-  cursor: move;
-  float: left;
-}
-.ckeditor-multiple-label {
-  float: left;
-  padding: 10px 4px;
+  margin: 0;
+  padding: 2px 0;
 }
 ul.ckeditor-buttons li.ckeditor-group-button-separator,
 ul.ckeditor-multiple-buttons li.ckeditor-group-button-separator {
+  margin: -1px -3px -2px;
+}
+ul.ckeditor-buttons li.ckeditor-group-button-separator a,
+ul.ckeditor-multiple-buttons li.ckeditor-group-button-separator a {
   background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAdCAMAAABG4xbVAAAAhFBMVEUAAACmpqampqampqb////l5eX////5+fmmpqatra2urq6vr6+1tbW2tra4uLi6urq8vLzb29ve3t7i4uLl5eXn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz+/v7qIQO+AAAACHRSTlMATVmAi8XM29MuWToAAABjSURBVBiVrc5BCoAwDETRMKhtRBduev9LKm1xjItWRBBE6Nt9QkIwOTcUzk0Imi8aoMssxbgoTHMtqsFMLta0vPh2N49HyfdelPg6k9uvX/a+Bmggt1qJRNzQFVgjEnkUZDoBmH57VSypjg4AAAAASUVORK5CYII=) no-repeat center center;
   width: 13px;
   padding: 0;
   height: 29px;
-  margin: -1px -3px -2px;
   position: relative;
   z-index: 10;
 }
-ul.ckeditor-buttons li.ckeditor-button-separator {
-  width: 2px;
-  padding: 0 4px;
-  height: 26px;
-  margin: 0 -4px;
+ul.ckeditor-buttons li.ckeditor-button-separator a {
+  background: #e4e4e4;
+  background-image: -webkit-linear-gradient(#e4e4e4, #b4b4b4);
+  background-image: linear-gradient(#e4e4e4, #b4b4b4);
+  height: 24px;
+  margin: 1px 0 0;
+  padding: 0;
   position: relative;
+  width: 1px;
   z-index: 10;
-
-  background: #e4e4e4;
-  background-image: -webkit-gradient(linear, left top, left bottom, from(white), to(#e4e4e4));
-  background-image: -moz-linear-gradient(top, white, #e4e4e4);
-  background-image: -webkit-linear-gradient(top, white, #e4e4e4);
-  background-image: -o-linear-gradient(top, white, #e4e4e4);
-  background-image: -ms-linear-gradient(top, white, #e4e4e4);
-  background-image: linear-gradient(top, white, #e4e4e4);
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#ffffffff', endColorstr='#ffe4e4e4');
-}
-ul.ckeditor-multiple-buttons li.ckeditor-button-separator {
+}
+ul.ckeditor-multiple-buttons li.ckeditor-button-separator a {
   width: 2px;
   padding: 0;
   height: 26px;
@@ -154,10 +167,10 @@ ul.ckeditor-multiple-buttons li.ckeditor-button-separator {
 }
 
 .ckeditor-row-controls {
-  float: right;
+  float: right; /* RTL */
   font-size: 18px;
   width: 40px;
-  text-align: right;
+  text-align: right; /* RTL */
 }
 .ckeditor-row-controls a {
   display: inline-block;
diff --git a/core/modules/ckeditor/js/ckeditor.admin.js b/core/modules/ckeditor/js/ckeditor.admin.js
index d22ac6e..f026be0 100644
--- a/core/modules/ckeditor/js/ckeditor.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.admin.js
@@ -20,11 +20,29 @@ Drupal.behaviors.ckeditorAdmin = {
         cursor: 'move',
         stop: adminToolbarValue
       };
-      $toolbarAdmin.insertAfter($textareaWrapper).find('.ckeditor-buttons').sortable(sortableSettings);
+      // Add the toolbar to the page.
+      $toolbarAdmin.insertAfter($textareaWrapper);
+
+      // Then determine if this is RTL or not.
+      var rtl = $toolbarAdmin.css('direction') === 'rtl' ? -1 : 1;
+      var $toolbarRows = $toolbarAdmin.find('.ckeditor-buttons');
+
+      // Add the drag and drop functionality.
+      $toolbarRows.sortable(sortableSettings);
       $toolbarAdmin.find('.ckeditor-multiple-buttons li').draggable({
         connectToSortable: '.ckeditor-toolbar-active .ckeditor-buttons',
         helper: 'clone'
       });
+
+      // Add keyboard arrow support.
+      $toolbarAdmin.on('keyup.ckeditorMoveButton', '.ckeditor-buttons a', adminToolbarMoveButton);
+      $toolbarAdmin.on('keyup.ckeditorMoveSeparator', '.ckeditor-multiple-buttons a', adminToolbarMoveSeparator);
+
+      // Add click for help.
+      $toolbarAdmin.on('click.ckeditorClickButton', '.ckeditor-buttons a', { type: 'button' }, adminToolbarButtonHelp);
+      $toolbarAdmin.on('click.ckeditorClickSeparator', '.ckeditor-multiple-buttons a', { type: 'separator' }, adminToolbarButtonHelp);
+
+      // Add/remove row button functionality.
       $toolbarAdmin.on('click.ckeditorAddRow', 'a.ckeditor-row-add', adminToolbarAddRow);
       $toolbarAdmin.on('click.ckeditorAddRow', 'a.ckeditor-row-remove', adminToolbarRemoveRow);
       if ($toolbarAdmin.find('.ckeditor-toolbar-active ul').length > 1) {
@@ -32,12 +50,105 @@ Drupal.behaviors.ckeditorAdmin = {
       }
 
       /**
+       * Event callback for keypress. Move buttons based on arrow keys.
+       */
+      function adminToolbarMoveButton(event) {
+        var $button = $(this).parent();
+        var $currentRow = $button.closest('.ckeditor-buttons');
+        var $destinationRow = null;
+        var destinationPosition = $button.index();
+
+        switch (event.keyCode) {
+          case 37: // Left arrow.
+          case 63234: // Safari left arrow.
+            $destinationRow = $currentRow;
+            destinationPosition = destinationPosition - (1 * rtl);
+            break;
+          case 38: // Up arrow.
+          case 63232: // Safari up arrow.
+          console.log($toolbarRows);
+            $destinationRow = $($toolbarRows[$toolbarRows.index($currentRow) - 1]);
+            break;
+          case 39: // Right arrow.
+          case 63235: // Safari right arrow.
+            $destinationRow = $currentRow;
+            destinationPosition = destinationPosition + (1 * rtl);
+            break;
+          case 40: // Down arrow.
+          case 63233: // Safari down arrow.
+            $destinationRow = $($toolbarRows[$toolbarRows.index($currentRow) + 1]);
+        }
+
+        if ($destinationRow && $destinationRow.length) {
+          // Detach the button from the DOM so its position doesn't interfere.
+          $button.detach();
+          // Move the button before the button whose position it should occupy.
+          var $targetButton = $destinationRow.children(':eq(' + destinationPosition + ')');
+          if ($targetButton.length) {
+            $targetButton.before($button);
+          }
+          else {
+            $destinationRow.append($button);
+          }
+          // Update the toolbar value field.
+          adminToolbarValue(event, { item: $button });
+        }
+        event.preventDefault();
+      }
+
+      /**
+       * Event callback for keyup. Move a separator into the active toolbar.
+       */
+      function adminToolbarMoveSeparator(event) {
+        switch (event.keyCode) {
+          case 38: // Up arrow.
+          case 63232: // Safari up arrow.
+            var $button = $(this).parent().clone().appendTo($toolbarRows.eq(-2));
+            adminToolbarValue(event, { item: $button });
+            event.preventDefault();
+        }
+      }
+
+      /**
+       * Provide help when a button is clicked on.
+       */
+      function adminToolbarButtonHelp(event) {
+        var $link = $(this);
+        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 $info = $('#ckeditor-button-configuration-aria-live');
+        var type = event.data.type;
+        if (enabled) {
+          if (type === 'separator') {
+            $info.text(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.'));
+          }
+          else {
+            $info.text(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.'));
+          }
+        }
+        else {
+          if (type === 'separator') {
+            $info.text(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 {
+            $info.text(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.'));
+          }
+        }
+        $link.focus();
+        event.preventDefault();
+      }
+
+      /**
        * Add a new row of buttons.
        */
       function adminToolbarAddRow(event) {
         var $this = $(this);
         var $rows = $this.closest('.ckeditor-toolbar-active').find('.ckeditor-buttons');
         $rows.last().clone().empty().insertAfter($rows.last()).sortable(sortableSettings);
+        $toolbarRows = $toolbarAdmin.find('.ckeditor-buttons');
         $this.siblings('a').show();
         redrawToolbarGradient();
         event.preventDefault();
@@ -57,6 +168,7 @@ Drupal.behaviors.ckeditorAdmin = {
           var $disabledButtons = $wrapper.find('.ckeditor-toolbar-disabled .ckeditor-buttons');
           $lastRow.children(':not(.ckeditor-multiple-button)').prependTo($disabledButtons);
           $lastRow.sortable('destroy').remove();
+          $toolbarRows = $toolbarAdmin.find('.ckeditor-buttons');
           redrawToolbarGradient();
         }
         event.preventDefault();
@@ -78,6 +190,8 @@ Drupal.behaviors.ckeditorAdmin = {
       function adminToolbarValue(event, ui) {
         // Update the toolbar config after updating a sortable.
         var toolbarConfig = [];
+        var $button = ui.item;
+        $button.find('a').focus();
         $wrapper.find('.ckeditor-toolbar-active ul').each(function() {
           var $rowButtons = $(this).find('li');
           var rowConfig = [];
diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php
index fffed1d..3649803 100644
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/ckeditor/plugin/Internal.php
@@ -79,7 +79,7 @@ public function getConfig(Editor $editor) {
    */
   function getButtons() {
     $button = function($name, $direction = 'ltr') {
-      return '<span class="cke_' . $direction . '"><span class="cke_button_icon cke_button__' . $name . '_icon">&nbsp;</span></span>';
+      return '<a href="#" class="cke-icon-only cke_' . $direction . '" role="button" aria-label="' . $name . '"><span class="cke_button_icon cke_button__' . str_replace(' ', '', $name) . '_icon">' . $name . '</span></a>';
     };
 
     return array(
@@ -102,44 +102,44 @@ function getButtons() {
       ),
       'Superscript' => array(
         'label' => t('Superscript'),
-        'image_alternative' => $button('superscript'),
+        'image_alternative' => $button('super script'),
       ),
       'Subscript' => array(
         'label' => t('Subscript'),
-        'image_alternative' => $button('subscript'),
+        'image_alternative' => $button('sub script'),
       ),
       // "removeformat" plugin.
       'RemoveFormat' => array(
         'label' => t('Remove format'),
-        'image_alternative' => $button('removeformat'),
+        'image_alternative' => $button('remove format'),
       ),
       // "justify" plugin.
       'JustifyLeft' => array(
         'label' => t('Align left'),
-        'image_alternative' => $button('justifyleft'),
+        'image_alternative' => $button('justify left'),
       ),
       'JustifyCenter' => array(
         'label' => t('Align center'),
-        'image_alternative' => $button('justifycenter'),
+        'image_alternative' => $button('justify center'),
       ),
       'JustifyRight' => array(
         'label' => t('Align right'),
-        'image_alternative' => $button('justifyright'),
+        'image_alternative' => $button('justify right'),
       ),
       'JustifyBlock' => array(
         'label' => t('Justify'),
-        'image_alternative' => $button('justifyblock'),
+        'image_alternative' => $button('justify block'),
       ),
       // "list" plugin.
       'BulletedList' => array(
         'label' => t('Bullet list'),
-        'image_alternative' => $button('bulletedlist'),
-        'image_alternative_rtl' => $button('bulletedlist', 'rtl'),
+        'image_alternative' => $button('bulleted list'),
+        'image_alternative_rtl' => $button('bulleted list', 'rtl'),
       ),
       'NumberedList' => array(
         'label' => t('Numbered list'),
-        'image_alternative' => $button('numberedlist'),
-        'image_alternative_rtl' => $button('numberedlist', 'rtl'),
+        'image_alternative' => $button('numbered list'),
+        'image_alternative_rtl' => $button('numbered list', 'rtl'),
       ),
       // "indent" plugin.
       'Outdent' => array(
@@ -185,7 +185,7 @@ function getButtons() {
       // "horizontalrule" plugin
       'HorizontalRule' => array(
         'label' => t('Horizontal rule'),
-        'image_alternative' => $button('horizontalrule'),
+        'image_alternative' => $button('horizontal rule'),
       ),
       // "clipboard" plugin.
       'Cut' => array(
@@ -206,23 +206,23 @@ function getButtons() {
       // "pastetext" plugin.
       'PasteText' => array(
         'label' => t('Paste Text'),
-        'image_alternative' => $button('pastetext'),
-        'image_alternative_rtl' => $button('pastetext', 'rtl'),
+        'image_alternative' => $button('paste text'),
+        'image_alternative_rtl' => $button('paste text', 'rtl'),
       ),
       // "pastefromword" plugin.
       'PasteFromWord' => array(
         'label' => t('Paste from Word'),
-        'image_alternative' => $button('pastefromword'),
-        'image_alternative_rtl' => $button('pastefromword', 'rtl'),
+        'image_alternative' => $button('paste from word'),
+        'image_alternative_rtl' => $button('paste from word', 'rtl'),
       ),
       // "specialchar" plugin.
       'SpecialChar' => array(
         'label' => t('Character map'),
-        'image_alternative' => $button('specialchar'),
+        'image_alternative' => $button('special char'),
       ),
       'Format' => array(
         'label' => t('HTML block format'),
-        'image_alternative' => '<span class="ckeditor-button-dropdown">' . t('Format') . '<span class="ckeditor-button-arrow"></span></span>',
+        'image_alternative' => '<a href="#" role="button" aria-label="' . t('Format') . '"><span class="ckeditor-button-dropdown">' . t('Format') . '<span class="ckeditor-button-arrow"></span></span></a>',
       ),
       // "image" plugin.
       'Image' => array(
@@ -237,8 +237,8 @@ function getButtons() {
       // "showblocks" plugin.
       'ShowBlocks' => array(
         'label' => t('Show blocks'),
-        'image_alternative' => $button('showblocks'),
-        'image_alternative_rtl' => $button('showblocks', 'rtl'),
+        'image_alternative' => $button('show blocks'),
+        'image_alternative_rtl' => $button('show blocks', 'rtl'),
       ),
       // "sourcearea" plugin.
       'Source' => array(
@@ -253,13 +253,13 @@ function getButtons() {
       // No plugin, separator "buttons" for toolbar builder UI use only.
       '|' => array(
         'label' => t('Group separator'),
-        'image_alternative' => '<span class="ckeditor-group-separator">&nbsp;</span>',
+        'image_alternative' => '<a href="#" role="button" aria-label="' . t('Button group separator') . '" class="ckeditor-group-separator"></a>',
         'attributes' => array('class' => array('ckeditor-group-button-separator')),
         'multiple' => TRUE,
       ),
       '-' => array(
         'label' => t('Separator'),
-        'image_alternative' => '<span class="ckeditor-separator">&nbsp;</span>',
+        'image_alternative' => '<a href="#" role="button" aria-label="' . t('Button separator') . '" class="ckeditor-separator"></a>',
         'attributes' => array('class' => array('ckeditor-button-separator')),
         'multiple' => TRUE,
       ),
-- 
1.7.10.4

