Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / ckeditor / js / views / KeyboardView.es6.js
diff --git a/web/core/modules/ckeditor/js/views/KeyboardView.es6.js b/web/core/modules/ckeditor/js/views/KeyboardView.es6.js
new file mode 100644 (file)
index 0000000..094f390
--- /dev/null
@@ -0,0 +1,260 @@
+/**
+ * @file
+ * Backbone View providing the aural view of CKEditor keyboard UX configuration.
+ */
+
+(function ($, Drupal, Backbone, _) {
+  Drupal.ckeditor.KeyboardView = Backbone.View.extend(/** @lends Drupal.ckeditor.KeyboardView# */{
+
+    /**
+     * Backbone View for CKEditor toolbar configuration; keyboard UX.
+     *
+     * @constructs
+     *
+     * @augments Backbone.View
+     */
+    initialize() {
+      // Add keyboard arrow support.
+      this.$el.on('keydown.ckeditor', '.ckeditor-buttons a, .ckeditor-multiple-buttons a', this.onPressButton.bind(this));
+      this.$el.on('keydown.ckeditor', '[data-drupal-ckeditor-type="group"]', this.onPressGroup.bind(this));
+    },
+
+    /**
+     * @inheritdoc
+     */
+    render() {
+    },
+
+    /**
+     * Handles keypresses on a CKEditor configuration button.
+     *
+     * @param {jQuery.Event} event
+     *   The keypress event triggered.
+     */
+    onPressButton(event) {
+      const upDownKeys = [
+        38, // Up arrow.
+        63232, // Safari up arrow.
+        40, // Down arrow.
+        63233, // Safari down arrow.
+      ];
+      const leftRightKeys = [
+        37, // Left arrow.
+        63234, // Safari left arrow.
+        39, // Right arrow.
+        63235, // Safari right arrow.
+      ];
+
+      // Respond to an enter key press. Prevent the bubbling of the enter key
+      // press to the button group parent element.
+      if (event.keyCode === 13) {
+        event.stopPropagation();
+      }
+
+      // Only take action when a direction key is pressed.
+      if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
+        let view = this;
+        let $target = $(event.currentTarget);
+        let $button = $target.parent();
+        const $container = $button.parent();
+        let $group = $button.closest('.ckeditor-toolbar-group');
+        let $row;
+        const containerType = $container.data('drupal-ckeditor-button-sorting');
+        const $availableButtons = this.$el.find('[data-drupal-ckeditor-button-sorting="source"]');
+        const $activeButtons = this.$el.find('.ckeditor-toolbar-active');
+        // The current location of the button, just in case it needs to be put
+        // back.
+        const $originalGroup = $group;
+        let dir;
+
+        // Move available buttons between their container and the active
+        // toolbar.
+        if (containerType === 'source') {
+          // Move the button to the active toolbar configuration when the down
+          // or up keys are pressed.
+          if (_.indexOf([40, 63233], event.keyCode) > -1) {
+            // Move the button to the first row, first button group index
+            // position.
+            $activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
+          }
+        }
+        else if (containerType === 'target') {
+          // Move buttons between sibling buttons in a group and between groups.
+          if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
+            // Move left.
+            const $siblings = $container.children();
+            const index = $siblings.index($button);
+            if (_.indexOf([37, 63234], event.keyCode) > -1) {
+              // Move between sibling buttons.
+              if (index > 0) {
+                $button.insertBefore($container.children().eq(index - 1));
+              }
+              // Move between button groups and rows.
+              else {
+                // Move between button groups.
+                $group = $container.parent().prev();
+                if ($group.length > 0) {
+                  $group.find('.ckeditor-toolbar-group-buttons').append($button);
+                }
+                // Wrap between rows.
+                else {
+                  $container.closest('.ckeditor-row').prev().find('.ckeditor-toolbar-group').not('.placeholder').find('.ckeditor-toolbar-group-buttons').eq(-1).append($button);
+                }
+              }
+            }
+            // Move right.
+            else if (_.indexOf([39, 63235], event.keyCode) > -1) {
+              // Move between sibling buttons.
+              if (index < ($siblings.length - 1)) {
+                $button.insertAfter($container.children().eq(index + 1));
+              }
+              // Move between button groups. Moving right at the end of a row
+              // will create a new group.
+              else {
+                $container.parent().next().find('.ckeditor-toolbar-group-buttons').prepend($button);
+              }
+            }
+          }
+          // Move buttons between rows and the available button set.
+          else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
+            dir = (_.indexOf([38, 63232], event.keyCode) > -1) ? 'prev' : 'next';
+            $row = $container.closest('.ckeditor-row')[dir]();
+            // Move the button back into the available button set.
+            if (dir === 'prev' && $row.length === 0) {
+              // If this is a divider, just destroy it.
+              if ($button.data('drupal-ckeditor-type') === 'separator') {
+                $button
+                  .off()
+                  .remove();
+                // Focus on the first button in the active toolbar.
+                $activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).children().eq(0).children().trigger('focus');
+              }
+              // Otherwise, move it.
+              else {
+                $availableButtons.prepend($button);
+              }
+            }
+            else {
+              $row.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
+            }
+          }
+        }
+        // Move dividers between their container and the active toolbar.
+        else if (containerType === 'dividers') {
+          // Move the button to the active toolbar configuration when the down
+          // or up keys are pressed.
+          if (_.indexOf([40, 63233], event.keyCode) > -1) {
+            // Move the button to the first row, first button group index
+            // position.
+            $button = $button.clone(true);
+            $activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
+            $target = $button.children();
+          }
+        }
+
+        view = this;
+        // Attempt to move the button to the new toolbar position.
+        Drupal.ckeditor.registerButtonMove(this, $button, (result) => {
+          // Put the button back if the registration failed.
+          // If the button was in a row, then it was in the active toolbar
+          // configuration. The button was probably placed in a new group, but
+          // that action was canceled.
+          if (!result && $originalGroup) {
+            $originalGroup.find('.ckeditor-buttons').append($button);
+          }
+          // Otherwise refresh the sortables to acknowledge the new button
+          // positions.
+          else {
+            view.$el.find('.ui-sortable').sortable('refresh');
+          }
+          // Refocus the target button so that the user can continue from a
+          // known place.
+          $target.trigger('focus');
+        });
+
+        event.preventDefault();
+        event.stopPropagation();
+      }
+    },
+
+    /**
+     * Handles keypresses on a CKEditor configuration group.
+     *
+     * @param {jQuery.Event} event
+     *   The keypress event triggered.
+     */
+    onPressGroup(event) {
+      const upDownKeys = [
+        38, // Up arrow.
+        63232, // Safari up arrow.
+        40, // Down arrow.
+        63233, // Safari down arrow.
+      ];
+      const leftRightKeys = [
+        37, // Left arrow.
+        63234, // Safari left arrow.
+        39, // Right arrow.
+        63235, // Safari right arrow.
+      ];
+
+      // Respond to an enter key press.
+      if (event.keyCode === 13) {
+        const view = this;
+        // Open the group renaming dialog in the next evaluation cycle so that
+        // this event can be cancelled and the bubbling wiped out. Otherwise,
+        // Firefox has issues because the page focus is shifted to the dialog
+        // along with the keydown event.
+        window.setTimeout(() => {
+          Drupal.ckeditor.openGroupNameDialog(view, $(event.currentTarget));
+        }, 0);
+        event.preventDefault();
+        event.stopPropagation();
+      }
+
+      // Respond to direction key presses.
+      if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
+        const $group = $(event.currentTarget);
+        const $container = $group.parent();
+        const $siblings = $container.children();
+        let index;
+        let dir;
+        // Move groups between sibling groups.
+        if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
+          index = $siblings.index($group);
+          // Move left between sibling groups.
+          if ((_.indexOf([37, 63234], event.keyCode) > -1)) {
+            if (index > 0) {
+              $group.insertBefore($siblings.eq(index - 1));
+            }
+            // Wrap between rows. Insert the group before the placeholder group
+            // at the end of the previous row.
+            else {
+              $group.insertBefore($container.closest('.ckeditor-row').prev().find('.ckeditor-toolbar-groups').children().eq(-1));
+            }
+          }
+          // Move right between sibling groups.
+          else if (_.indexOf([39, 63235], event.keyCode) > -1) {
+            // Move to the right if the next group is not a placeholder.
+            if (!$siblings.eq(index + 1).hasClass('placeholder')) {
+              $group.insertAfter($container.children().eq(index + 1));
+            }
+            // Wrap group between rows.
+            else {
+              $container.closest('.ckeditor-row').next().find('.ckeditor-toolbar-groups').prepend($group);
+            }
+          }
+        }
+        // Move groups between rows.
+        else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
+          dir = (_.indexOf([38, 63232], event.keyCode) > -1) ? 'prev' : 'next';
+          $group.closest('.ckeditor-row')[dir]().find('.ckeditor-toolbar-groups').eq(0).prepend($group);
+        }
+
+        Drupal.ckeditor.registerGroupMove(this, $group);
+        $group.trigger('focus');
+        event.preventDefault();
+        event.stopPropagation();
+      }
+    },
+  });
+}(jQuery, Drupal, Backbone, _));