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