annotate core/modules/ckeditor/js/views/KeyboardView.es6.js @ 19:fa3358dc1485 tip

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