annotate core/modules/ckeditor/js/views/KeyboardView.es6.js @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents a9cd425dd02b
children
rev   line source
Chris@0 1 /**
Chris@0 2 * @file
Chris@0 3 * Backbone View providing the aural view of CKEditor keyboard UX configuration.
Chris@0 4 */
Chris@0 5
Chris@4 6 (function($, Drupal, Backbone, _) {
Chris@4 7 Drupal.ckeditor.KeyboardView = Backbone.View.extend(
Chris@4 8 /** @lends Drupal.ckeditor.KeyboardView# */ {
Chris@4 9 /**
Chris@4 10 * Backbone View for CKEditor toolbar configuration; keyboard UX.
Chris@4 11 *
Chris@4 12 * @constructs
Chris@4 13 *
Chris@4 14 * @augments Backbone.View
Chris@4 15 */
Chris@4 16 initialize() {
Chris@4 17 // Add keyboard arrow support.
Chris@4 18 this.$el.on(
Chris@4 19 'keydown.ckeditor',
Chris@4 20 '.ckeditor-buttons a, .ckeditor-multiple-buttons a',
Chris@4 21 this.onPressButton.bind(this),
Chris@4 22 );
Chris@4 23 this.$el.on(
Chris@4 24 'keydown.ckeditor',
Chris@4 25 '[data-drupal-ckeditor-type="group"]',
Chris@4 26 this.onPressGroup.bind(this),
Chris@4 27 );
Chris@4 28 },
Chris@0 29
Chris@4 30 /**
Chris@4 31 * @inheritdoc
Chris@4 32 */
Chris@4 33 render() {},
Chris@0 34
Chris@4 35 /**
Chris@4 36 * Handles keypresses on a CKEditor configuration button.
Chris@4 37 *
Chris@4 38 * @param {jQuery.Event} event
Chris@4 39 * The keypress event triggered.
Chris@4 40 */
Chris@4 41 onPressButton(event) {
Chris@4 42 const upDownKeys = [
Chris@4 43 38, // Up arrow.
Chris@4 44 63232, // Safari up arrow.
Chris@4 45 40, // Down arrow.
Chris@4 46 63233, // Safari down arrow.
Chris@4 47 ];
Chris@4 48 const leftRightKeys = [
Chris@4 49 37, // Left arrow.
Chris@4 50 63234, // Safari left arrow.
Chris@4 51 39, // Right arrow.
Chris@4 52 63235, // Safari right arrow.
Chris@4 53 ];
Chris@0 54
Chris@4 55 // Respond to an enter key press. Prevent the bubbling of the enter key
Chris@4 56 // press to the button group parent element.
Chris@4 57 if (event.keyCode === 13) {
Chris@4 58 event.stopPropagation();
Chris@4 59 }
Chris@0 60
Chris@4 61 // Only take action when a direction key is pressed.
Chris@4 62 if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
Chris@4 63 let view = this;
Chris@4 64 let $target = $(event.currentTarget);
Chris@4 65 let $button = $target.parent();
Chris@4 66 const $container = $button.parent();
Chris@4 67 let $group = $button.closest('.ckeditor-toolbar-group');
Chris@4 68 let $row;
Chris@4 69 const containerType = $container.data(
Chris@4 70 'drupal-ckeditor-button-sorting',
Chris@4 71 );
Chris@4 72 const $availableButtons = this.$el.find(
Chris@4 73 '[data-drupal-ckeditor-button-sorting="source"]',
Chris@4 74 );
Chris@4 75 const $activeButtons = this.$el.find('.ckeditor-toolbar-active');
Chris@4 76 // The current location of the button, just in case it needs to be put
Chris@4 77 // back.
Chris@4 78 const $originalGroup = $group;
Chris@4 79 let dir;
Chris@0 80
Chris@4 81 // Move available buttons between their container and the active
Chris@4 82 // toolbar.
Chris@4 83 if (containerType === 'source') {
Chris@4 84 // Move the button to the active toolbar configuration when the down
Chris@4 85 // or up keys are pressed.
Chris@4 86 if (_.indexOf([40, 63233], event.keyCode) > -1) {
Chris@4 87 // Move the button to the first row, first button group index
Chris@4 88 // position.
Chris@4 89 $activeButtons
Chris@4 90 .find('.ckeditor-toolbar-group-buttons')
Chris@4 91 .eq(0)
Chris@4 92 .prepend($button);
Chris@4 93 }
Chris@4 94 } else if (containerType === 'target') {
Chris@4 95 // Move buttons between sibling buttons in a group and between groups.
Chris@4 96 if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
Chris@4 97 // Move left.
Chris@4 98 const $siblings = $container.children();
Chris@4 99 const index = $siblings.index($button);
Chris@4 100 if (_.indexOf([37, 63234], event.keyCode) > -1) {
Chris@4 101 // Move between sibling buttons.
Chris@4 102 if (index > 0) {
Chris@4 103 $button.insertBefore($container.children().eq(index - 1));
Chris@4 104 }
Chris@4 105 // Move between button groups and rows.
Chris@4 106 else {
Chris@4 107 // Move between button groups.
Chris@4 108 $group = $container.parent().prev();
Chris@4 109 if ($group.length > 0) {
Chris@4 110 $group
Chris@4 111 .find('.ckeditor-toolbar-group-buttons')
Chris@4 112 .append($button);
Chris@4 113 }
Chris@4 114 // Wrap between rows.
Chris@4 115 else {
Chris@4 116 $container
Chris@4 117 .closest('.ckeditor-row')
Chris@4 118 .prev()
Chris@4 119 .find('.ckeditor-toolbar-group')
Chris@4 120 .not('.placeholder')
Chris@4 121 .find('.ckeditor-toolbar-group-buttons')
Chris@4 122 .eq(-1)
Chris@4 123 .append($button);
Chris@4 124 }
Chris@4 125 }
Chris@0 126 }
Chris@4 127 // Move right.
Chris@4 128 else if (_.indexOf([39, 63235], event.keyCode) > -1) {
Chris@4 129 // Move between sibling buttons.
Chris@4 130 if (index < $siblings.length - 1) {
Chris@4 131 $button.insertAfter($container.children().eq(index + 1));
Chris@0 132 }
Chris@4 133 // Move between button groups. Moving right at the end of a row
Chris@4 134 // will create a new group.
Chris@0 135 else {
Chris@0 136 $container
Chris@4 137 .parent()
Chris@4 138 .next()
Chris@0 139 .find('.ckeditor-toolbar-group-buttons')
Chris@4 140 .prepend($button);
Chris@0 141 }
Chris@0 142 }
Chris@0 143 }
Chris@4 144 // Move buttons between rows and the available button set.
Chris@4 145 else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
Chris@4 146 dir =
Chris@4 147 _.indexOf([38, 63232], event.keyCode) > -1 ? 'prev' : 'next';
Chris@4 148 $row = $container.closest('.ckeditor-row')[dir]();
Chris@4 149 // Move the button back into the available button set.
Chris@4 150 if (dir === 'prev' && $row.length === 0) {
Chris@4 151 // If this is a divider, just destroy it.
Chris@4 152 if ($button.data('drupal-ckeditor-type') === 'separator') {
Chris@4 153 $button.off().remove();
Chris@4 154 // Focus on the first button in the active toolbar.
Chris@4 155 $activeButtons
Chris@4 156 .find('.ckeditor-toolbar-group-buttons')
Chris@4 157 .eq(0)
Chris@4 158 .children()
Chris@4 159 .eq(0)
Chris@4 160 .children()
Chris@4 161 .trigger('focus');
Chris@4 162 }
Chris@4 163 // Otherwise, move it.
Chris@4 164 else {
Chris@4 165 $availableButtons.prepend($button);
Chris@4 166 }
Chris@4 167 } else {
Chris@4 168 $row
Chris@4 169 .find('.ckeditor-toolbar-group-buttons')
Chris@4 170 .eq(0)
Chris@4 171 .prepend($button);
Chris@0 172 }
Chris@0 173 }
Chris@0 174 }
Chris@4 175 // Move dividers between their container and the active toolbar.
Chris@4 176 else if (containerType === 'dividers') {
Chris@4 177 // Move the button to the active toolbar configuration when the down
Chris@4 178 // or up keys are pressed.
Chris@4 179 if (_.indexOf([40, 63233], event.keyCode) > -1) {
Chris@4 180 // Move the button to the first row, first button group index
Chris@4 181 // position.
Chris@4 182 $button = $button.clone(true);
Chris@4 183 $activeButtons
Chris@4 184 .find('.ckeditor-toolbar-group-buttons')
Chris@4 185 .eq(0)
Chris@4 186 .prepend($button);
Chris@4 187 $target = $button.children();
Chris@4 188 }
Chris@4 189 }
Chris@4 190
Chris@4 191 view = this;
Chris@4 192 // Attempt to move the button to the new toolbar position.
Chris@4 193 Drupal.ckeditor.registerButtonMove(this, $button, result => {
Chris@4 194 // Put the button back if the registration failed.
Chris@4 195 // If the button was in a row, then it was in the active toolbar
Chris@4 196 // configuration. The button was probably placed in a new group, but
Chris@4 197 // that action was canceled.
Chris@4 198 if (!result && $originalGroup) {
Chris@4 199 $originalGroup.find('.ckeditor-buttons').append($button);
Chris@4 200 }
Chris@4 201 // Otherwise refresh the sortables to acknowledge the new button
Chris@4 202 // positions.
Chris@4 203 else {
Chris@4 204 view.$el.find('.ui-sortable').sortable('refresh');
Chris@4 205 }
Chris@4 206 // Refocus the target button so that the user can continue from a
Chris@4 207 // known place.
Chris@4 208 $target.trigger('focus');
Chris@4 209 });
Chris@4 210
Chris@4 211 event.preventDefault();
Chris@4 212 event.stopPropagation();
Chris@4 213 }
Chris@4 214 },
Chris@4 215
Chris@4 216 /**
Chris@4 217 * Handles keypresses on a CKEditor configuration group.
Chris@4 218 *
Chris@4 219 * @param {jQuery.Event} event
Chris@4 220 * The keypress event triggered.
Chris@4 221 */
Chris@4 222 onPressGroup(event) {
Chris@4 223 const upDownKeys = [
Chris@4 224 38, // Up arrow.
Chris@4 225 63232, // Safari up arrow.
Chris@4 226 40, // Down arrow.
Chris@4 227 63233, // Safari down arrow.
Chris@4 228 ];
Chris@4 229 const leftRightKeys = [
Chris@4 230 37, // Left arrow.
Chris@4 231 63234, // Safari left arrow.
Chris@4 232 39, // Right arrow.
Chris@4 233 63235, // Safari right arrow.
Chris@4 234 ];
Chris@4 235
Chris@4 236 // Respond to an enter key press.
Chris@4 237 if (event.keyCode === 13) {
Chris@4 238 const view = this;
Chris@4 239 // Open the group renaming dialog in the next evaluation cycle so that
Chris@4 240 // this event can be cancelled and the bubbling wiped out. Otherwise,
Chris@4 241 // Firefox has issues because the page focus is shifted to the dialog
Chris@4 242 // along with the keydown event.
Chris@4 243 window.setTimeout(() => {
Chris@4 244 Drupal.ckeditor.openGroupNameDialog(view, $(event.currentTarget));
Chris@4 245 }, 0);
Chris@4 246 event.preventDefault();
Chris@4 247 event.stopPropagation();
Chris@4 248 }
Chris@4 249
Chris@4 250 // Respond to direction key presses.
Chris@4 251 if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
Chris@4 252 const $group = $(event.currentTarget);
Chris@4 253 const $container = $group.parent();
Chris@4 254 const $siblings = $container.children();
Chris@4 255 let index;
Chris@4 256 let dir;
Chris@4 257 // Move groups between sibling groups.
Chris@4 258 if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
Chris@4 259 index = $siblings.index($group);
Chris@4 260 // Move left between sibling groups.
Chris@4 261 if (_.indexOf([37, 63234], event.keyCode) > -1) {
Chris@4 262 if (index > 0) {
Chris@4 263 $group.insertBefore($siblings.eq(index - 1));
Chris@4 264 }
Chris@4 265 // Wrap between rows. Insert the group before the placeholder group
Chris@4 266 // at the end of the previous row.
Chris@4 267 else {
Chris@4 268 const $rowChildElement = $container
Chris@4 269 .closest('.ckeditor-row')
Chris@4 270 .prev()
Chris@4 271 .find('.ckeditor-toolbar-groups')
Chris@0 272 .children()
Chris@4 273 .eq(-1);
Chris@4 274 $group.insertBefore($rowChildElement);
Chris@0 275 }
Chris@0 276 }
Chris@4 277 // Move right between sibling groups.
Chris@4 278 else if (_.indexOf([39, 63235], event.keyCode) > -1) {
Chris@4 279 // Move to the right if the next group is not a placeholder.
Chris@4 280 if (!$siblings.eq(index + 1).hasClass('placeholder')) {
Chris@4 281 $group.insertAfter($container.children().eq(index + 1));
Chris@4 282 }
Chris@4 283 // Wrap group between rows.
Chris@4 284 else {
Chris@4 285 $container
Chris@4 286 .closest('.ckeditor-row')
Chris@4 287 .next()
Chris@4 288 .find('.ckeditor-toolbar-groups')
Chris@4 289 .prepend($group);
Chris@4 290 }
Chris@0 291 }
Chris@0 292 }
Chris@4 293 // Move groups between rows.
Chris@4 294 else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
Chris@4 295 dir = _.indexOf([38, 63232], event.keyCode) > -1 ? 'prev' : 'next';
Chris@4 296 $group
Chris@4 297 .closest('.ckeditor-row')
Chris@4 298 [dir]()
Chris@4 299 .find('.ckeditor-toolbar-groups')
Chris@4 300 .eq(0)
Chris@4 301 .prepend($group);
Chris@4 302 }
Chris@4 303
Chris@4 304 Drupal.ckeditor.registerGroupMove(this, $group);
Chris@4 305 $group.trigger('focus');
Chris@4 306 event.preventDefault();
Chris@4 307 event.stopPropagation();
Chris@0 308 }
Chris@4 309 },
Chris@0 310 },
Chris@4 311 );
Chris@4 312 })(jQuery, Drupal, Backbone, _);