OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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 cr.define('cr.ui', function() { |
| 6 |
| 7 const MenuItem = cr.ui.MenuItem; |
| 8 |
| 9 /** |
| 10 * Creates a new menu element. |
| 11 * @param {Object=} opt_propertyBag Optional properties. |
| 12 * @constructor |
| 13 * @extends {HTMLMenuElement} |
| 14 */ |
| 15 var Menu = cr.ui.define('menu'); |
| 16 |
| 17 Menu.prototype = { |
| 18 __proto__: HTMLMenuElement.prototype, |
| 19 |
| 20 /** |
| 21 * Initializes the menu element. |
| 22 */ |
| 23 decorate: function() { |
| 24 this.addEventListener('mouseover', this.handleMouseOver_); |
| 25 this.addEventListener('mouseout', this.handleMouseOut_); |
| 26 |
| 27 // Decorate the children as menu items. |
| 28 var children = this.children; |
| 29 for (var i = 0, child; child = children[i]; i++) { |
| 30 cr.ui.decorate(child, MenuItem); |
| 31 } |
| 32 }, |
| 33 |
| 34 /** |
| 35 * Walks up the ancestors until a menu item belonging to this menu is found. |
| 36 * @param {Element} el |
| 37 * @return {cr.ui.MenuItem} The found menu item or null. |
| 38 * @private |
| 39 */ |
| 40 findMenuItem_: function(el) { |
| 41 while (el && el.parentNode != this) { |
| 42 el = el.parentNode; |
| 43 } |
| 44 return el; |
| 45 }, |
| 46 |
| 47 /** |
| 48 * Handles mouseover events and selects the hovered item. |
| 49 * @param {Event} e The mouseover event. |
| 50 * @private |
| 51 */ |
| 52 handleMouseOver_: function(e) { |
| 53 var overItem = this.findMenuItem_(e.target); |
| 54 this.selectedItem = overItem; |
| 55 }, |
| 56 |
| 57 /** |
| 58 * Handles mouseout events and deselects any selected item. |
| 59 * @param {Event} e The mouseout event. |
| 60 * @private |
| 61 */ |
| 62 handleMouseOut_: function(e) { |
| 63 this.selectedItem = null; |
| 64 }, |
| 65 |
| 66 /** |
| 67 * The index of the selected item. |
| 68 * @type {boolean} |
| 69 */ |
| 70 // getter and default value is defined using cr.defineProperty. |
| 71 set selectedIndex(selectedIndex) { |
| 72 if (this.selectedIndex_ != selectedIndex) { |
| 73 var oldSelectedItem = this.selectedItem; |
| 74 this.selectedIndex_ = selectedIndex; |
| 75 if (oldSelectedItem) |
| 76 oldSelectedItem.selected = false; |
| 77 var item = this.selectedItem; |
| 78 if (item) |
| 79 item.selected = true; |
| 80 |
| 81 cr.dispatchSimpleEvent(this, 'change'); |
| 82 } |
| 83 }, |
| 84 |
| 85 /** |
| 86 * The selected menu item or null if none. |
| 87 * @type {cr.ui.MenuItem} |
| 88 */ |
| 89 get selectedItem() { |
| 90 return this.children[this.selectedIndex]; |
| 91 }, |
| 92 set selectedItem(item) { |
| 93 var index = Array.prototype.indexOf.call(this.children, item); |
| 94 this.selectedIndex = index; |
| 95 }, |
| 96 |
| 97 /** |
| 98 * This is the function that handles keyboard navigation. This is usually |
| 99 * called by the element responsible for managing the menu. |
| 100 * @param {Event} e The keydown event object. |
| 101 * @return {boolean} Whether the event was handled be the menu. |
| 102 */ |
| 103 handleKeyDown: function(e) { |
| 104 var item = this.selectedItem; |
| 105 |
| 106 var self = this; |
| 107 function selectNextVisible(m) { |
| 108 var children = self.children; |
| 109 var len = children.length; |
| 110 var i = self.selectedIndex; |
| 111 if (i == -1 && m == -1) { |
| 112 // Edge case when we need to go the last item fisrt. |
| 113 i = 0; |
| 114 } |
| 115 while (true) { |
| 116 i = (i + m + len) % len; |
| 117 item = children[i]; |
| 118 if (item && !item.isSeparator() && !item.hidden) |
| 119 break; |
| 120 } |
| 121 if (item) |
| 122 self.selectedIndex = i; |
| 123 } |
| 124 |
| 125 switch (e.keyIdentifier) { |
| 126 case 'Down': |
| 127 selectNextVisible(1); |
| 128 return true; |
| 129 case 'Up': |
| 130 selectNextVisible(-1); |
| 131 return true; |
| 132 case 'Enter': |
| 133 case 'U+0020': // Space |
| 134 if (item) { |
| 135 if (cr.dispatchSimpleEvent(item, 'activate', true, true)) { |
| 136 if (item.command) |
| 137 item.command.execute(); |
| 138 } |
| 139 } |
| 140 return true; |
| 141 } |
| 142 |
| 143 return false; |
| 144 } |
| 145 }; |
| 146 |
| 147 /** |
| 148 * The selected menu item. |
| 149 * @type {number} |
| 150 */ |
| 151 cr.defineProperty(Menu, 'selectedIndex', cr.PropertyKind.JS, -1); |
| 152 |
| 153 // Export |
| 154 return { |
| 155 Menu: Menu |
| 156 }; |
| 157 }); |
OLD | NEW |