• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview This implements a special button that is useful for showing a
7 * context menu.
8 */
9
10cr.define('cr.ui', function() {
11  /** @const */ var MenuButton = cr.ui.MenuButton;
12
13  /**
14   * Helper function for ContextMenuButton to find the first ancestor of the
15   * button that has a context menu.
16   * @param {!MenuButton} el The button to start the search from.
17   * @return {HTMLElement} The found element or null if not found.
18   */
19  function getContextMenuTarget(el) {
20    do {
21      el = el.parentNode;
22    } while (el && !('contextMenu' in el));
23    return el;
24  }
25
26  /**
27   * Creates a new menu button which is used to show the context menu for an
28   * ancestor that has a {@code contextMenu} property.
29   * @param {Object=} opt_propertyBag Optional properties.
30   * @constructor
31   * @extends {MenuButton}
32   */
33  var ContextMenuButton = cr.ui.define('button');
34
35  ContextMenuButton.prototype = {
36    __proto__: MenuButton.prototype,
37
38    /**
39     * Override to return the contextMenu for the ancestor.
40     * @override
41     * @type {cr.ui.Menu}
42     */
43    get menu() {
44      var target = getContextMenuTarget(this);
45      return target && target.contextMenu;
46    },
47
48    /** @override */
49    decorate: function() {
50      this.tabIndex = -1;
51      this.addEventListener('mouseup', this);
52      MenuButton.prototype.decorate.call(this);
53    },
54
55    /** @override */
56    handleEvent: function(e) {
57      switch (e.type) {
58        case 'mousedown':
59          // Menu buttons prevent focus changes.
60          var target = getContextMenuTarget(this);
61          if (target)
62            target.focus();
63          break;
64        case 'mouseup':
65          // Stop mouseup to prevent selection changes.
66          e.stopPropagation();
67          break;
68      }
69      MenuButton.prototype.handleEvent.call(this, e);
70    },
71
72    /**
73     * Override MenuButton showMenu to allow the mousedown to be fully handled
74     * before the menu is shown. This is important in case the mousedown
75     * triggers command changes.
76     * @param {boolean} shouldSetFocus Whether the menu should be focused after
77     *     the menu is shown.
78     */
79    showMenu: function(shouldSetFocus) {
80      var self = this;
81      window.setTimeout(function() {
82        MenuButton.prototype.showMenu.call(self, shouldSetFocus);
83      });
84    }
85  };
86
87  // Export
88  return {
89    ContextMenuButton: ContextMenuButton
90  };
91});
92