text: /**
   * @file
   * A Backbone View that provides the aural view of CKEditor keyboard UX configuration.
   */
  
  (function (Drupal, Backbone, $) {
  
    "use strict";
  
    /**
     * Backbone View for CKEditor toolbar configuration; keyboard UX.
     */
    Drupal.ckeditor.KeyboardView = Backbone.View.extend({
  
      /**
       * {@inheritdoc}
       */
      initialize: function () {
        // 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: function () {
      },
  
      /**
       * Handles keypresses on a CKEditor configuration button.
       *
       * @param jQuery.Event event
       */
      onPressButton: function (event) {
        var upDownKeys = [
          38, // Up arrow.
          63232, // Safari up arrow.
          40, // Down arrow.
          63233 // Safari down arrow.
        ];
        var 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) {
          var view = this;
          var $target = $(event.currentTarget);
          var $button = $target.parent();
          var $container = $button.parent();
          var $group = $button.closest('.ckeditor-toolbar-group');
          var $row = $button.closest('.ckeditor-row');
          var containerType = $container.data('drupal-ckeditor-button-sorting');
          var $availableButtons = this.$el.find('[data-drupal-ckeditor-button-sorting="source"]');
          var $activeButtons = this.$el.find('.ckeditor-toolbar-active');
          // The current location of the button, just in case it needs to be put
          // back.
          var $originalGroup = $group;
          var 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.
              var $siblings = $container.children();
              var 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, function (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
       */
      onPressGroup: function (event) {
        var upDownKeys = [
          38, // Up arrow.
          63232, // Safari up arrow.
          40, // Down arrow.
          63233 // Safari down arrow.
        ];
        var 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) {
          var 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(function () {
            Drupal.ckeditor.openGroupNameDialog(view, $(event.currentTarget));
          }, 0);
          event.preventDefault();
          event.stopPropagation();
        }
  
        // Respond to direction key presses.
        if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
          var $group = $(event.currentTarget);
          var $container = $group.parent();
          var $siblings = $container.children();
          var index;
          var 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();
        }
      }
    });
  
  })(Drupal, Backbone, jQuery);
  