annotate core/modules/ckeditor/js/views/AuralView.es6.js @ 4:a9cd425dd02b

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:11:55 +0000
parents c75dbcec494b
children
rev   line source
Chris@0 1 /**
Chris@0 2 * @file
Chris@0 3 * A Backbone View that provides the aural view of CKEditor toolbar
Chris@0 4 * configuration.
Chris@0 5 */
Chris@0 6
Chris@4 7 (function(Drupal, Backbone, $) {
Chris@4 8 Drupal.ckeditor.AuralView = Backbone.View.extend(
Chris@4 9 /** @lends Drupal.ckeditor.AuralView# */ {
Chris@4 10 /**
Chris@4 11 * @type {object}
Chris@4 12 */
Chris@4 13 events: {
Chris@4 14 'click .ckeditor-buttons a': 'announceButtonHelp',
Chris@4 15 'click .ckeditor-multiple-buttons a': 'announceSeparatorHelp',
Chris@4 16 'focus .ckeditor-button a': 'onFocus',
Chris@4 17 'focus .ckeditor-button-separator a': 'onFocus',
Chris@4 18 'focus .ckeditor-toolbar-group': 'onFocus',
Chris@4 19 },
Chris@0 20
Chris@4 21 /**
Chris@4 22 * Backbone View for CKEditor toolbar configuration; aural UX (output only).
Chris@4 23 *
Chris@4 24 * @constructs
Chris@4 25 *
Chris@4 26 * @augments Backbone.View
Chris@4 27 */
Chris@4 28 initialize() {
Chris@4 29 // Announce the button and group positions when the model is no longer
Chris@4 30 // dirty.
Chris@4 31 this.listenTo(this.model, 'change:isDirty', this.announceMove);
Chris@4 32 },
Chris@0 33
Chris@4 34 /**
Chris@4 35 * Calls announce on buttons and groups when their position is changed.
Chris@4 36 *
Chris@4 37 * @param {Drupal.ckeditor.ConfigurationModel} model
Chris@4 38 * The ckeditor configuration model.
Chris@4 39 * @param {bool} isDirty
Chris@4 40 * A model attribute that indicates if the changed toolbar configuration
Chris@4 41 * has been stored or not.
Chris@4 42 */
Chris@4 43 announceMove(model, isDirty) {
Chris@4 44 // Announce the position of a button or group after the model has been
Chris@4 45 // updated.
Chris@4 46 if (!isDirty) {
Chris@4 47 const item = document.activeElement || null;
Chris@4 48 if (item) {
Chris@4 49 const $item = $(item);
Chris@4 50 if ($item.hasClass('ckeditor-toolbar-group')) {
Chris@4 51 this.announceButtonGroupPosition($item);
Chris@4 52 } else if ($item.parent().hasClass('ckeditor-button')) {
Chris@4 53 this.announceButtonPosition($item.parent());
Chris@4 54 }
Chris@0 55 }
Chris@0 56 }
Chris@4 57 },
Chris@0 58
Chris@4 59 /**
Chris@4 60 * Handles the focus event of elements in the active and available toolbars.
Chris@4 61 *
Chris@4 62 * @param {jQuery.Event} event
Chris@4 63 * The focus event that was triggered.
Chris@4 64 */
Chris@4 65 onFocus(event) {
Chris@4 66 event.stopPropagation();
Chris@0 67
Chris@4 68 const $originalTarget = $(event.target);
Chris@4 69 const $currentTarget = $(event.currentTarget);
Chris@4 70 const $parent = $currentTarget.parent();
Chris@4 71 if (
Chris@4 72 $parent.hasClass('ckeditor-button') ||
Chris@4 73 $parent.hasClass('ckeditor-button-separator')
Chris@4 74 ) {
Chris@4 75 this.announceButtonPosition($currentTarget.parent());
Chris@4 76 } else if (
Chris@4 77 $originalTarget.attr('role') !== 'button' &&
Chris@4 78 $currentTarget.hasClass('ckeditor-toolbar-group')
Chris@4 79 ) {
Chris@4 80 this.announceButtonGroupPosition($currentTarget);
Chris@4 81 }
Chris@4 82 },
Chris@0 83
Chris@4 84 /**
Chris@4 85 * Announces the current position of a button group.
Chris@4 86 *
Chris@4 87 * @param {jQuery} $group
Chris@4 88 * A jQuery set that contains an li element that wraps a group of buttons.
Chris@4 89 */
Chris@4 90 announceButtonGroupPosition($group) {
Chris@4 91 const $groups = $group.parent().children();
Chris@4 92 const $row = $group.closest('.ckeditor-row');
Chris@4 93 const $rows = $row.parent().children();
Chris@4 94 const position = $groups.index($group) + 1;
Chris@4 95 const positionCount = $groups.not('.placeholder').length;
Chris@4 96 const row = $rows.index($row) + 1;
Chris@4 97 const rowCount = $rows.not('.placeholder').length;
Chris@4 98 let text = Drupal.t(
Chris@4 99 '@groupName button group in position @position of @positionCount in row @row of @rowCount.',
Chris@4 100 {
Chris@4 101 '@groupName': $group.attr(
Chris@4 102 'data-drupal-ckeditor-toolbar-group-name',
Chris@4 103 ),
Chris@4 104 '@position': position,
Chris@4 105 '@positionCount': positionCount,
Chris@4 106 '@row': row,
Chris@4 107 '@rowCount': rowCount,
Chris@4 108 },
Chris@4 109 );
Chris@0 110 // If this position is the first in the last row then tell the user that
Chris@0 111 // pressing the down arrow key will create a new row.
Chris@4 112 if (position === 1 && row === rowCount) {
Chris@0 113 text += '\n';
Chris@4 114 text += Drupal.t('Press the down arrow key to create a new row.');
Chris@0 115 }
Chris@0 116 Drupal.announce(text, 'assertive');
Chris@4 117 },
Chris@4 118
Chris@4 119 /**
Chris@4 120 * Announces current button position.
Chris@4 121 *
Chris@4 122 * @param {jQuery} $button
Chris@4 123 * A jQuery set that contains an li element that wraps a button.
Chris@4 124 */
Chris@4 125 announceButtonPosition($button) {
Chris@4 126 const $row = $button.closest('.ckeditor-row');
Chris@4 127 const $rows = $row.parent().children();
Chris@4 128 const $buttons = $button.closest('.ckeditor-buttons').children();
Chris@4 129 const $group = $button.closest('.ckeditor-toolbar-group');
Chris@4 130 const $groups = $group.parent().children();
Chris@4 131 const groupPosition = $groups.index($group) + 1;
Chris@4 132 const groupPositionCount = $groups.not('.placeholder').length;
Chris@4 133 const position = $buttons.index($button) + 1;
Chris@4 134 const positionCount = $buttons.length;
Chris@4 135 const row = $rows.index($row) + 1;
Chris@4 136 const rowCount = $rows.not('.placeholder').length;
Chris@4 137 // The name of the button separator is 'button separator' and its type
Chris@4 138 // is 'separator', so we do not want to print the type of this item,
Chris@4 139 // otherwise the UA will speak 'button separator separator'.
Chris@4 140 const type =
Chris@4 141 $button.attr('data-drupal-ckeditor-type') === 'separator'
Chris@4 142 ? ''
Chris@4 143 : Drupal.t('button');
Chris@4 144 let text;
Chris@4 145 // The button is located in the available button set.
Chris@4 146 if ($button.closest('.ckeditor-toolbar-disabled').length > 0) {
Chris@4 147 text = Drupal.t('@name @type.', {
Chris@4 148 '@name': $button.children().attr('aria-label'),
Chris@4 149 '@type': type,
Chris@4 150 });
Chris@4 151 text += `\n${Drupal.t('Press the down arrow key to activate.')}`;
Chris@4 152
Chris@4 153 Drupal.announce(text, 'assertive');
Chris@4 154 }
Chris@4 155 // The button is in the active toolbar.
Chris@4 156 else if ($group.not('.placeholder').length === 1) {
Chris@4 157 text = Drupal.t(
Chris@4 158 '@name @type in position @position of @positionCount in @groupName button group in row @row of @rowCount.',
Chris@4 159 {
Chris@4 160 '@name': $button.children().attr('aria-label'),
Chris@4 161 '@type': type,
Chris@4 162 '@position': position,
Chris@4 163 '@positionCount': positionCount,
Chris@4 164 '@groupName': $group.attr(
Chris@4 165 'data-drupal-ckeditor-toolbar-group-name',
Chris@4 166 ),
Chris@4 167 '@row': row,
Chris@4 168 '@rowCount': rowCount,
Chris@4 169 },
Chris@4 170 );
Chris@4 171 // If this position is the first in the last row then tell the user that
Chris@4 172 // pressing the down arrow key will create a new row.
Chris@4 173 if (groupPosition === 1 && position === 1 && row === rowCount) {
Chris@4 174 text += '\n';
Chris@4 175 text += Drupal.t(
Chris@4 176 'Press the down arrow key to create a new button group in a new row.',
Chris@4 177 );
Chris@4 178 }
Chris@4 179 // If this position is the last one in this row then tell the user that
Chris@4 180 // moving the button to the next group will create a new group.
Chris@4 181 if (
Chris@4 182 groupPosition === groupPositionCount &&
Chris@4 183 position === positionCount
Chris@4 184 ) {
Chris@4 185 text += '\n';
Chris@4 186 text += Drupal.t(
Chris@4 187 'This is the last group. Move the button forward to create a new group.',
Chris@4 188 );
Chris@4 189 }
Chris@4 190 Drupal.announce(text, 'assertive');
Chris@4 191 }
Chris@4 192 },
Chris@4 193
Chris@4 194 /**
Chris@4 195 * Provides help information when a button is clicked.
Chris@4 196 *
Chris@4 197 * @param {jQuery.Event} event
Chris@4 198 * The click event for the button click.
Chris@4 199 */
Chris@4 200 announceButtonHelp(event) {
Chris@4 201 const $link = $(event.currentTarget);
Chris@4 202 const $button = $link.parent();
Chris@4 203 const enabled = $button.closest('.ckeditor-toolbar-active').length > 0;
Chris@4 204 let message;
Chris@4 205
Chris@4 206 if (enabled) {
Chris@4 207 message = Drupal.t('The "@name" button is currently enabled.', {
Chris@4 208 '@name': $link.attr('aria-label'),
Chris@4 209 });
Chris@4 210 message += `\n${Drupal.t(
Chris@4 211 'Use the keyboard arrow keys to change the position of this button.',
Chris@4 212 )}`;
Chris@4 213 message += `\n${Drupal.t(
Chris@4 214 'Press the up arrow key on the top row to disable the button.',
Chris@4 215 )}`;
Chris@4 216 } else {
Chris@4 217 message = Drupal.t('The "@name" button is currently disabled.', {
Chris@4 218 '@name': $link.attr('aria-label'),
Chris@4 219 });
Chris@4 220 message += `\n${Drupal.t(
Chris@4 221 'Use the down arrow key to move this button into the active toolbar.',
Chris@4 222 )}`;
Chris@4 223 }
Chris@4 224 Drupal.announce(message);
Chris@4 225 event.preventDefault();
Chris@4 226 },
Chris@4 227
Chris@4 228 /**
Chris@4 229 * Provides help information when a separator is clicked.
Chris@4 230 *
Chris@4 231 * @param {jQuery.Event} event
Chris@4 232 * The click event for the separator click.
Chris@4 233 */
Chris@4 234 announceSeparatorHelp(event) {
Chris@4 235 const $link = $(event.currentTarget);
Chris@4 236 const $button = $link.parent();
Chris@4 237 const enabled = $button.closest('.ckeditor-toolbar-active').length > 0;
Chris@4 238 let message;
Chris@4 239
Chris@4 240 if (enabled) {
Chris@4 241 message = Drupal.t('This @name is currently enabled.', {
Chris@4 242 '@name': $link.attr('aria-label'),
Chris@4 243 });
Chris@4 244 message += `\n${Drupal.t(
Chris@4 245 'Use the keyboard arrow keys to change the position of this separator.',
Chris@4 246 )}`;
Chris@4 247 } else {
Chris@4 248 message = Drupal.t(
Chris@4 249 'Separators are used to visually split individual buttons.',
Chris@4 250 );
Chris@4 251 message += `\n${Drupal.t('This @name is currently disabled.', {
Chris@4 252 '@name': $link.attr('aria-label'),
Chris@4 253 })}`;
Chris@4 254 message += `\n${Drupal.t(
Chris@4 255 'Use the down arrow key to move this separator into the active toolbar.',
Chris@4 256 )}`;
Chris@4 257 message += `\n${Drupal.t(
Chris@4 258 'You may add multiple separators to each button group.',
Chris@4 259 )}`;
Chris@4 260 }
Chris@4 261 Drupal.announce(message);
Chris@4 262 event.preventDefault();
Chris@4 263 },
Chris@0 264 },
Chris@4 265 );
Chris@4 266 })(Drupal, Backbone, jQuery);