<!--
@license
Copyright (C) 2016 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<!--

How to Add a Keyboard Shortcut
==============================

A keyboard shortcut is composed of the following parts:

  1. A semantic identifier (e.g. OPEN_CHANGE, NEXT_PAGE)
  2. Documentation for the keyboard shortcut help dialog
  3. A binding between key combos and the semantic identifier
  4. A binding between the semantic identifier and a listener

Parts (1) and (2) for all shortcuts are defined in this file. The semantic
identifier is declared in the Shortcut enum near the head of this script:

  const Shortcut = {
    // ...
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    // ...
  };

Immediately following the Shortcut enum definition, there is a _describe
function defined which is then invoked many times to populate the help dialog.
Add a new invocation here to document the shortcut:

  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');

When an attached view binds one or more key combos to this shortcut, the help
dialog will display this text in the given section (in this case, "Diffs"). See
the ShortcutSection enum immediately below for the list of supported sections.

Part (3), the actual key bindings, are declared by gr-app. In the future, this
system may be expanded to allow key binding customizations by plugins or user
preferences. Key bindings are defined in the following forms:

  // Ordinary shortcut with a single binding.
  this.bindShortcut(
      this.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');

  // Ordinary shortcut with multiple bindings.
  this.bindShortcut(
      this.Shortcut.CURSOR_NEXT_FILE, 'j', 'down');

  // A "go-key" keyboard shortcut, which is combined with a previously and
  // continuously pressed "go" key (the go-key is hard-coded as 'g').
  this.bindShortcut(
      this.Shortcut.GO_TO_OPENED_CHANGES, this.GO_KEY, 'o');

  // A "doc-only" keyboard shortcut. This declares the key-binding for help
  // dialog purposes, but doesn't actually implement the binding. It is up
  // to some element to implement this binding using iron-a11y-keys-behavior's
  // keyBindings property.
  this.bindShortcut(
      this.Shortcut.EXPAND_ALL_COMMENT_THREADS, this.DOC_ONLY, 'e');

Part (4), the listener definitions, are declared by the view or element that
implements the shortcut behavior. This is done by implementing a method named
keyboardShortcuts() in an element that mixes in this behavior, returning an
object that maps semantic identifiers (as property names) to listener method
names, like this:

  keyboardShortcuts() {
    return {
      [this.Shortcut.TOGGLE_LEFT_PANE]: '_handleToggleLeftPane',
    };
  },

You can implement key bindings in an element that is hosted by a view IF that
element is always attached exactly once under that view (e.g. the search bar in
gr-app). When that is not the case, you will have to define a doc-only binding
in gr-app, declare the shortcut in the view that hosts the element, and use
iron-a11y-keys-behavior's keyBindings attribute to implement the binding in the
element. An example of this is in comment threads. A diff view supports actions
on comment threads, but there may be zero or many comment threads attached at
any given point. So the shortcut is declared as doc-only by the diff view and
by gr-app, and actually implemented by gr-comment-thread.

NOTE: doc-only shortcuts will not be customizable in the same way that other
shortcuts are.
-->
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">

<script>
(function(window) {
  'use strict';

  const DOC_ONLY = 'DOC_ONLY';
  const GO_KEY = 'GO_KEY';

  // The maximum age of a keydown event to be used in a jump navigation. This
  // is only for cases when the keyup event is lost.
  const GO_KEY_TIMEOUT_MS = 1000;

  const ShortcutSection = {
    ACTIONS: 'Actions',
    DIFFS: 'Diffs',
    EVERYWHERE: 'Everywhere',
    FILE_LIST: 'File list',
    NAVIGATION: 'Navigation',
    REPLY_DIALOG: 'Reply dialog',
  };

  const Shortcut = {
    OPEN_SHORTCUT_HELP_DIALOG: 'OPEN_SHORTCUT_HELP_DIALOG',
    GO_TO_USER_DASHBOARD: 'GO_TO_USER_DASHBOARD',
    GO_TO_OPENED_CHANGES: 'GO_TO_OPENED_CHANGES',
    GO_TO_MERGED_CHANGES: 'GO_TO_MERGED_CHANGES',
    GO_TO_ABANDONED_CHANGES: 'GO_TO_ABANDONED_CHANGES',
    GO_TO_WATCHED_CHANGES: 'GO_TO_WATCHED_CHANGES',

    CURSOR_NEXT_CHANGE: 'CURSOR_NEXT_CHANGE',
    CURSOR_PREV_CHANGE: 'CURSOR_PREV_CHANGE',
    OPEN_CHANGE: 'OPEN_CHANGE',
    NEXT_PAGE: 'NEXT_PAGE',
    PREV_PAGE: 'PREV_PAGE',
    TOGGLE_CHANGE_REVIEWED: 'TOGGLE_CHANGE_REVIEWED',
    TOGGLE_CHANGE_STAR: 'TOGGLE_CHANGE_STAR',
    REFRESH_CHANGE_LIST: 'REFRESH_CHANGE_LIST',

    OPEN_REPLY_DIALOG: 'OPEN_REPLY_DIALOG',
    OPEN_DOWNLOAD_DIALOG: 'OPEN_DOWNLOAD_DIALOG',
    EXPAND_ALL_MESSAGES: 'EXPAND_ALL_MESSAGES',
    COLLAPSE_ALL_MESSAGES: 'COLLAPSE_ALL_MESSAGES',
    UP_TO_DASHBOARD: 'UP_TO_DASHBOARD',
    UP_TO_CHANGE: 'UP_TO_CHANGE',
    TOGGLE_DIFF_MODE: 'TOGGLE_DIFF_MODE',
    REFRESH_CHANGE: 'REFRESH_CHANGE',
    EDIT_TOPIC: 'EDIT_TOPIC',

    NEXT_LINE: 'NEXT_LINE',
    PREV_LINE: 'PREV_LINE',
    VISIBLE_LINE: 'VISIBLE_LINE',
    NEXT_CHUNK: 'NEXT_CHUNK',
    PREV_CHUNK: 'PREV_CHUNK',
    EXPAND_ALL_DIFF_CONTEXT: 'EXPAND_ALL_DIFF_CONTEXT',
    NEXT_COMMENT_THREAD: 'NEXT_COMMENT_THREAD',
    PREV_COMMENT_THREAD: 'PREV_COMMENT_THREAD',
    EXPAND_ALL_COMMENT_THREADS: 'EXPAND_ALL_COMMENT_THREADS',
    COLLAPSE_ALL_COMMENT_THREADS: 'COLLAPSE_ALL_COMMENT_THREADS',
    LEFT_PANE: 'LEFT_PANE',
    RIGHT_PANE: 'RIGHT_PANE',
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    NEW_COMMENT: 'NEW_COMMENT',
    SAVE_COMMENT: 'SAVE_COMMENT',
    OPEN_DIFF_PREFS: 'OPEN_DIFF_PREFS',
    TOGGLE_DIFF_REVIEWED: 'TOGGLE_DIFF_REVIEWED',

    NEXT_FILE: 'NEXT_FILE',
    PREV_FILE: 'PREV_FILE',
    NEXT_FILE_WITH_COMMENTS: 'NEXT_FILE_WITH_COMMENTS',
    PREV_FILE_WITH_COMMENTS: 'PREV_FILE_WITH_COMMENTS',
    NEXT_UNREVIEWED_FILE: 'NEXT_UNREVIEWED_FILE',
    CURSOR_NEXT_FILE: 'CURSOR_NEXT_FILE',
    CURSOR_PREV_FILE: 'CURSOR_PREV_FILE',
    OPEN_FILE: 'OPEN_FILE',
    TOGGLE_FILE_REVIEWED: 'TOGGLE_FILE_REVIEWED',
    TOGGLE_ALL_INLINE_DIFFS: 'TOGGLE_ALL_INLINE_DIFFS',
    TOGGLE_INLINE_DIFF: 'TOGGLE_INLINE_DIFF',

    OPEN_FIRST_FILE: 'OPEN_FIRST_FILE',
    OPEN_LAST_FILE: 'OPEN_LAST_FILE',

    SEARCH: 'SEARCH',
    SEND_REPLY: 'SEND_REPLY',
    EMOJI_DROPDOWN: 'EMOJI_DROPDOWN',
  };

  const _help = new Map();

  function _describe(shortcut, section, text) {
    if (!_help.has(section)) {
      _help.set(section, []);
    }
    _help.get(section).push({shortcut, text});
  }

  _describe(Shortcut.SEARCH, ShortcutSection.EVERYWHERE, 'Search');
  _describe(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, ShortcutSection.EVERYWHERE,
      'Show this dialog');
  _describe(Shortcut.GO_TO_USER_DASHBOARD, ShortcutSection.EVERYWHERE,
      'Go to User Dashboard');
  _describe(Shortcut.GO_TO_OPENED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Opened Changes');
  _describe(Shortcut.GO_TO_MERGED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Merged Changes');
  _describe(Shortcut.GO_TO_ABANDONED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Abandoned Changes');
  _describe(Shortcut.GO_TO_WATCHED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Watched Changes');

  _describe(Shortcut.CURSOR_NEXT_CHANGE, ShortcutSection.ACTIONS,
      'Select next change');
  _describe(Shortcut.CURSOR_PREV_CHANGE, ShortcutSection.ACTIONS,
      'Select previous change');
  _describe(Shortcut.OPEN_CHANGE, ShortcutSection.ACTIONS,
      'Show selected change');
  _describe(Shortcut.NEXT_PAGE, ShortcutSection.ACTIONS, 'Go to next page');
  _describe(Shortcut.PREV_PAGE, ShortcutSection.ACTIONS, 'Go to previous page');
  _describe(Shortcut.OPEN_REPLY_DIALOG, ShortcutSection.ACTIONS,
      'Open reply dialog to publish comments and add reviewers');
  _describe(Shortcut.OPEN_DOWNLOAD_DIALOG, ShortcutSection.ACTIONS,
      'Open download overlay');
  _describe(Shortcut.EXPAND_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Expand all messages');
  _describe(Shortcut.COLLAPSE_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Collapse all messages');
  _describe(Shortcut.REFRESH_CHANGE, ShortcutSection.ACTIONS,
      'Reload the change at the latest patch');
  _describe(Shortcut.TOGGLE_CHANGE_REVIEWED, ShortcutSection.ACTIONS,
      'Mark/unmark change as reviewed');
  _describe(Shortcut.TOGGLE_FILE_REVIEWED, ShortcutSection.ACTIONS,
      'Toggle review flag on selected file');
  _describe(Shortcut.REFRESH_CHANGE_LIST, ShortcutSection.ACTIONS,
      'Refresh list of changes');
  _describe(Shortcut.TOGGLE_CHANGE_STAR, ShortcutSection.ACTIONS,
      'Star/unstar change');
  _describe(Shortcut.EDIT_TOPIC, ShortcutSection.ACTIONS,
      'Add a change topic');

  _describe(Shortcut.NEXT_LINE, ShortcutSection.DIFFS, 'Go to next line');
  _describe(Shortcut.PREV_LINE, ShortcutSection.DIFFS, 'Go to previous line');
  _describe(Shortcut.VISIBLE_LINE, ShortcutSection.DIFFS,
      'Move cursor to currently visible code');
  _describe(Shortcut.NEXT_CHUNK, ShortcutSection.DIFFS,
      'Go to next diff chunk');
  _describe(Shortcut.PREV_CHUNK, ShortcutSection.DIFFS,
      'Go to previous diff chunk');
  _describe(Shortcut.EXPAND_ALL_DIFF_CONTEXT, ShortcutSection.DIFFS,
      'Expand all diff context');
  _describe(Shortcut.NEXT_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to next comment thread');
  _describe(Shortcut.PREV_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to previous comment thread');
  _describe(Shortcut.EXPAND_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Expand all comment threads');
  _describe(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Collapse all comment threads');
  _describe(Shortcut.LEFT_PANE, ShortcutSection.DIFFS, 'Select left pane');
  _describe(Shortcut.RIGHT_PANE, ShortcutSection.DIFFS, 'Select right pane');
  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');
  _describe(Shortcut.NEW_COMMENT, ShortcutSection.DIFFS, 'Draft new comment');
  _describe(Shortcut.SAVE_COMMENT, ShortcutSection.DIFFS, 'Save comment');
  _describe(Shortcut.OPEN_DIFF_PREFS, ShortcutSection.DIFFS,
      'Show diff preferences');
  _describe(Shortcut.TOGGLE_DIFF_REVIEWED, ShortcutSection.DIFFS,
      'Mark/unmark file as reviewed');
  _describe(Shortcut.TOGGLE_DIFF_MODE, ShortcutSection.DIFFS,
      'Toggle unified/side-by-side diff');
  _describe(Shortcut.NEXT_UNREVIEWED_FILE, ShortcutSection.DIFFS,
      'Mark file as reviewed and go to next unreviewed file');

  _describe(Shortcut.NEXT_FILE, ShortcutSection.NAVIGATION, 'Select next file');
  _describe(Shortcut.PREV_FILE, ShortcutSection.NAVIGATION,
      'Select previous file');
  _describe(Shortcut.NEXT_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select next file that has comments');
  _describe(Shortcut.PREV_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select previous file that has comments');
  _describe(Shortcut.OPEN_FIRST_FILE, ShortcutSection.NAVIGATION,
      'Show first file');
  _describe(Shortcut.OPEN_LAST_FILE, ShortcutSection.NAVIGATION,
      'Show last file');
  _describe(Shortcut.UP_TO_DASHBOARD, ShortcutSection.NAVIGATION,
      'Up to dashboard');
  _describe(Shortcut.UP_TO_CHANGE, ShortcutSection.NAVIGATION, 'Up to change');

  _describe(Shortcut.CURSOR_NEXT_FILE, ShortcutSection.FILE_LIST,
      'Select next file');
  _describe(Shortcut.CURSOR_PREV_FILE, ShortcutSection.FILE_LIST,
      'Select previous file');
  _describe(Shortcut.OPEN_FILE, ShortcutSection.FILE_LIST,
      'Go to selected file');
  _describe(Shortcut.TOGGLE_ALL_INLINE_DIFFS, ShortcutSection.FILE_LIST,
      'Show/hide all inline diffs');
  _describe(Shortcut.TOGGLE_INLINE_DIFF, ShortcutSection.FILE_LIST,
      'Show/hide selected inline diff');

  _describe(Shortcut.SEND_REPLY, ShortcutSection.REPLY_DIALOG, 'Send reply');
  _describe(Shortcut.EMOJI_DROPDOWN, ShortcutSection.REPLY_DIALOG,
      'Emoji dropdown');

  // Must be declared outside behavior implementation to be accessed inside
  // behavior functions.

  /** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
  const getKeyboardEvent = function(e) {
    e = Polymer.dom(e.detail ? e.detail.keyboardEvent : e);
    // When e is a keyboardEvent, e.event is not null.
    if (e.event) { e = e.event; }
    return e;
  };

  class ShortcutManager {
    constructor() {
      this.activeHosts = new Map();
      this.bindings = new Map();
      this.listeners = new Set();
    }

    bindShortcut(shortcut, ...bindings) {
      this.bindings.set(shortcut, bindings);
    }

    getBindingsForShortcut(shortcut) {
      return this.bindings.get(shortcut);
    }

    attachHost(host) {
      if (!host.keyboardShortcuts) { return; }
      const shortcuts = host.keyboardShortcuts();
      this.activeHosts.set(host, new Map(Object.entries(shortcuts)));
      this.notifyListeners();
      return shortcuts;
    }

    detachHost(host) {
      if (this.activeHosts.delete(host)) {
        this.notifyListeners();
        return true;
      }
      return false;
    }

    addListener(listener) {
      this.listeners.add(listener);
      listener(this.directoryView());
    }

    removeListener(listener) {
      return this.listeners.delete(listener);
    }

    activeShortcutsBySection() {
      const activeShortcuts = new Set();
      this.activeHosts.forEach(shortcuts => {
        shortcuts.forEach((_, shortcut) => activeShortcuts.add(shortcut));
      });

      const activeShortcutsBySection = new Map();
      _help.forEach((shortcutList, section) => {
        shortcutList.forEach(shortcutHelp => {
          if (activeShortcuts.has(shortcutHelp.shortcut)) {
            if (!activeShortcutsBySection.has(section)) {
              activeShortcutsBySection.set(section, []);
            }
            activeShortcutsBySection.get(section).push(shortcutHelp);
          }
        });
      });
      return activeShortcutsBySection;
    }

    directoryView() {
      const view = new Map();
      this.activeShortcutsBySection().forEach((shortcutHelps, section) => {
        const sectionView = [];
        shortcutHelps.forEach(shortcutHelp => {
          const bindingDesc = this.describeBindings(shortcutHelp.shortcut);
          if (!bindingDesc) { return; }
          this.distributeBindingDesc(bindingDesc).forEach(bindingDesc => {
            sectionView.push({
              binding: bindingDesc,
              text: shortcutHelp.text,
            });
          });
        });
        view.set(section, sectionView);
      });
      return view;
    }

    distributeBindingDesc(bindingDesc) {
      if (bindingDesc.length === 1 ||
          this.comboSetDisplayWidth(bindingDesc) < 21) {
        return [bindingDesc];
      }
      // Find the largest prefix of bindings that is under the
      // size threshold.
      const head = [bindingDesc[0]];
      for (let i = 1; i < bindingDesc.length; i++) {
        head.push(bindingDesc[i]);
        if (this.comboSetDisplayWidth(head) >= 21) {
          head.pop();
          return [head].concat(
              this.distributeBindingDesc(bindingDesc.slice(i)));
        }
      }
    }

    comboSetDisplayWidth(bindingDesc) {
      const bindingSizer = binding => binding.reduce(
          (acc, key) => acc + key.length, 0);
      // Width is the sum of strings + (n-1) * 2 to account for the word
      // "or" joining them.
      return bindingDesc.reduce(
          (acc, binding) => acc + bindingSizer(binding), 0) +
          2 * (bindingDesc.length - 1);
    }

    describeBindings(shortcut) {
      const bindings = this.bindings.get(shortcut);
      if (!bindings) { return null; }
      if (bindings[0] === GO_KEY) {
        return [['g'].concat(bindings.slice(1))];
      }
      return bindings
          .filter(binding => binding !== DOC_ONLY)
          .map(binding => this.describeBinding(binding));
    }

    describeBinding(binding) {
      if (binding.length === 1) {
        return [binding];
      }
      return binding.split(':')[0].split('+').map(part => {
        switch (part) {
          case 'shift':
            return 'Shift';
          case 'meta':
            return 'Meta';
          case 'ctrl':
            return 'Ctrl';
          case 'enter':
            return 'Enter';
          case 'up':
            return '↑';
          case 'down':
            return '↓';
          case 'left':
            return '←';
          case 'right':
            return '→';
          default:
            return part;
        }
      });
    }

    notifyListeners() {
      const view = this.directoryView();
      this.listeners.forEach(listener => listener(view));
    }
  }

  const shortcutManager = new ShortcutManager();

  window.Gerrit = window.Gerrit || {};

  /** @polymerBehavior Gerrit.KeyboardShortcutBehavior*/
  Gerrit.KeyboardShortcutBehavior = [
    Polymer.IronA11yKeysBehavior,
    {
      // Exports for convenience. Note: Closure compiler crashes when
      // object-shorthand syntax is used here.
      // eslint-disable-next-line object-shorthand
      DOC_ONLY: DOC_ONLY,
      // eslint-disable-next-line object-shorthand
      GO_KEY: GO_KEY,
      // eslint-disable-next-line object-shorthand
      Shortcut: Shortcut,

      properties: {
        _shortcut_go_key_last_pressed: {
          type: Number,
          value: null,
        },

        _shortcut_go_table: {
          type: Array,
          value() { return new Map(); },
        },
      },

      modifierPressed(e) {
        e = getKeyboardEvent(e);
        return e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
      },

      isModifierPressed(e, modifier) {
        return getKeyboardEvent(e)[modifier];
      },

      shouldSuppressKeyboardShortcut(e) {
        e = getKeyboardEvent(e);
        const tagName = Polymer.dom(e).rootTarget.tagName;
        if (tagName === 'INPUT' || tagName === 'TEXTAREA' ||
            (e.keyCode === 13 && tagName === 'A')) {
          // Suppress shortcuts if the key is 'enter' and target is an anchor.
          return true;
        }
        for (let i = 0; e.path && i < e.path.length; i++) {
          if (e.path[i].tagName === 'GR-OVERLAY') { return true; }
        }
        return false;
      },

      // Alias for getKeyboardEvent.
      /** @return {!Event} */
      getKeyboardEvent(e) {
        return getKeyboardEvent(e);
      },

      getRootTarget(e) {
        return Polymer.dom(getKeyboardEvent(e)).rootTarget;
      },

      bindShortcut(shortcut, ...bindings) {
        shortcutManager.bindShortcut(shortcut, ...bindings);
      },

      _addOwnKeyBindings(shortcut, handler) {
        const bindings = shortcutManager.getBindingsForShortcut(shortcut);
        if (!bindings) {
          return;
        }
        if (bindings[0] === DOC_ONLY) {
          return;
        }
        if (bindings[0] === GO_KEY) {
          this._shortcut_go_table.set(bindings[1], handler);
        } else {
          this.addOwnKeyBinding(bindings.join(' '), handler);
        }
      },

      /** @override */
      attached() {
        const shortcuts = shortcutManager.attachHost(this);
        if (!shortcuts) { return; }

        for (const key of Object.keys(shortcuts)) {
          this._addOwnKeyBindings(key, shortcuts[key]);
        }

        // If any of the shortcuts utilized GO_KEY, then they are handled
        // directly by this behavior.
        if (this._shortcut_go_table.size > 0) {
          this.addOwnKeyBinding('g:keydown', '_handleGoKeyDown');
          this.addOwnKeyBinding('g:keyup', '_handleGoKeyUp');
          this._shortcut_go_table.forEach((handler, key) => {
            this.addOwnKeyBinding(key, '_handleGoAction');
          });
        }
      },

      /** @override */
      detached() {
        if (shortcutManager.detachHost(this)) {
          this.removeOwnKeyBindings();
        }
      },

      keyboardShortcuts() {
        return {};
      },

      addKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.addListener(listener);
      },

      removeKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.removeListener(listener);
      },

      _handleGoKeyDown(e) {
        if (this.modifierPressed(e)) { return; }
        this._shortcut_go_key_last_pressed = Date.now();
      },

      _handleGoKeyUp(e) {
        this._shortcut_go_key_last_pressed = null;
      },

      _handleGoAction(e) {
        if (!this._shortcut_go_key_last_pressed ||
            (Date.now() - this._shortcut_go_key_last_pressed >
                GO_KEY_TIMEOUT_MS) ||
            !this._shortcut_go_table.has(e.detail.key) ||
            this.shouldSuppressKeyboardShortcut(e)) {
          return;
        }
        e.preventDefault();
        const handler = this._shortcut_go_table.get(e.detail.key);
        this[handler](e);
      },
    },
  ];

  Gerrit.KeyboardShortcutBinder = {
    DOC_ONLY,
    GO_KEY,
    Shortcut,
    ShortcutManager,
    ShortcutSection,

    bindShortcut(shortcut, ...bindings) {
      shortcutManager.bindShortcut(shortcut, ...bindings);
    },
  };

  // eslint-disable-next-line no-unused-vars
  function defineEmptyMixin() {
    // This is a temporary function.
    // Polymer linter doesn't process correctly the following code:
    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
    // To workaround this issue, the mock mixin is declared in this method.
    // In the following changes, legacy behaviors will be converted to mixins.

    /**
     * @polymer
     * @mixinFunction
     */
    Gerrit.KeyboardShortcutMixin = base =>
      class extends base {
      };
  }
})(window);
</script>
