summaryrefslogtreecommitdiff
path: root/chromium/ui/webui/resources/js/cr/ui/context_menu_button.js
blob: 7d324e3ce0fde81f7e45aac4e434ca55edb84bbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview This implements a special button that is useful for showing a
 * context menu.
 */

cr.define('cr.ui', function() {
  /** @const */ var MenuButton = cr.ui.MenuButton;

  /**
   * Helper function for ContextMenuButton to find the first ancestor of the
   * button that has a context menu.
   * @param {!MenuButton} el The button to start the search from.
   * @return {HTMLElement} The found element or null if not found.
   */
  function getContextMenuTarget(el) {
    do {
      el = el.parentNode;
    } while (el && !('contextMenu' in el));
    return el;
  }

  /**
   * Creates a new menu button which is used to show the context menu for an
   * ancestor that has a {@code contextMenu} property.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {MenuButton}
   */
  var ContextMenuButton = cr.ui.define('button');

  ContextMenuButton.prototype = {
    __proto__: MenuButton.prototype,

    /**
     * Override to return the contextMenu for the ancestor.
     * @override
     * @type {cr.ui.Menu}
     */
    get menu() {
      var target = getContextMenuTarget(this);
      return target && target.contextMenu;
    },

    /** @override */
    decorate: function() {
      this.tabIndex = -1;
      this.addEventListener('mouseup', this);
      MenuButton.prototype.decorate.call(this);
    },

    /** @override */
    handleEvent: function(e) {
      switch (e.type) {
        case 'mousedown':
          // Menu buttons prevent focus changes.
          var target = getContextMenuTarget(this);
          if (target)
            target.focus();
          break;
        case 'mouseup':
          // Stop mouseup to prevent selection changes.
          e.stopPropagation();
          break;
      }
      MenuButton.prototype.handleEvent.call(this, e);
    },

    /**
     * Override MenuButton showMenu to allow the mousedown to be fully handled
     * before the menu is shown. This is important in case the mousedown
     * triggers command changes.
     * @param {boolean} shouldSetFocus Whether the menu should be focused after
     *     the menu is shown.
     */
    showMenu: function(shouldSetFocus) {
      var self = this;
      window.setTimeout(function() {
        MenuButton.prototype.showMenu.call(self, shouldSetFocus);
      });
    }
  };

  // Export
  return {
    ContextMenuButton: ContextMenuButton
  };
});