| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // require: event_target.js | 5 // require: event_target.js |
| 6 | 6 |
| 7 cr.define('cr.ui', function() { | 7 cr.define('cr.ui', function() { |
| 8 /** @const */ var EventTarget = cr.EventTarget; | 8 /** @const */ var EventTarget = cr.EventTarget; |
| 9 /** @const */ var Menu = cr.ui.Menu; | 9 /** @const */ var Menu = cr.ui.Menu; |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * Handles context menus. | 12 * Handles context menus. |
| 13 * @constructor | 13 * @constructor |
| 14 * @extends {cr.EventTarget} | 14 * @extends {cr.EventTarget} |
| 15 * @implements {EventListener} | 15 * @implements {EventListener} |
| 16 */ | 16 */ |
| 17 function ContextMenuHandler() { | 17 function ContextMenuHandler() { this.showingEvents_ = new EventTracker(); } |
| 18 this.showingEvents_ = new EventTracker(); | |
| 19 } | |
| 20 | 18 |
| 21 ContextMenuHandler.prototype = { | 19 ContextMenuHandler.prototype = { |
| 22 __proto__: EventTarget.prototype, | 20 __proto__: EventTarget.prototype, |
| 23 | 21 |
| 24 /** | 22 /** |
| 25 * The menu that we are currently showing. | 23 * The menu that we are currently showing. |
| 26 * @type {cr.ui.Menu} | 24 * @type {cr.ui.Menu} |
| 27 */ | 25 */ |
| 28 menu_: null, | 26 menu_: null, get menu() { return this.menu_; }, |
| 29 get menu() { | |
| 30 return this.menu_; | |
| 31 }, | |
| 32 | 27 |
| 33 /** | 28 /** |
| 34 * Shows a menu as a context menu. | 29 * Shows a menu as a context menu. |
| 35 * @param {!Event} e The event triggering the show (usually a contextmenu | 30 * @param {!Event} e The event triggering the show (usually a contextmenu |
| 36 * event). | 31 * event). |
| 37 * @param {!cr.ui.Menu} menu The menu to show. | 32 * @param {!cr.ui.Menu} menu The menu to show. |
| 38 */ | 33 */ |
| 39 showMenu: function(e, menu) { | 34 showMenu: function(e, menu) { |
| 40 menu.updateCommands(assertInstanceof(e.currentTarget, Node)); | 35 menu.updateCommands(assertInstanceof(e.currentTarget, Node)); |
| 41 if (!menu.hasVisibleItems()) | 36 if (!menu.hasVisibleItems()) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 */ | 101 */ |
| 107 positionMenu_: function(e, menu) { | 102 positionMenu_: function(e, menu) { |
| 108 // TODO(arv): Handle scrolled documents when needed. | 103 // TODO(arv): Handle scrolled documents when needed. |
| 109 | 104 |
| 110 var element = e.currentTarget; | 105 var element = e.currentTarget; |
| 111 var x, y; | 106 var x, y; |
| 112 // When the user presses the context menu key (on the keyboard) we need | 107 // When the user presses the context menu key (on the keyboard) we need |
| 113 // to detect this. | 108 // to detect this. |
| 114 if (this.keyIsDown_) { | 109 if (this.keyIsDown_) { |
| 115 var rect = element.getRectForContextMenu ? | 110 var rect = element.getRectForContextMenu ? |
| 116 element.getRectForContextMenu() : | 111 element.getRectForContextMenu() : |
| 117 element.getBoundingClientRect(); | 112 element.getBoundingClientRect(); |
| 118 var offset = Math.min(rect.width, rect.height) / 2; | 113 var offset = Math.min(rect.width, rect.height) / 2; |
| 119 x = rect.left + offset; | 114 x = rect.left + offset; |
| 120 y = rect.top + offset; | 115 y = rect.top + offset; |
| 121 } else { | 116 } else { |
| 122 x = e.clientX; | 117 x = e.clientX; |
| 123 y = e.clientY; | 118 y = e.clientY; |
| 124 } | 119 } |
| 125 | 120 |
| 126 cr.ui.positionPopupAtPoint(x, y, menu); | 121 cr.ui.positionPopupAtPoint(x, y, menu); |
| 127 }, | 122 }, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 146 } | 141 } |
| 147 | 142 |
| 148 // Context menu is handled even when we have no menu. | 143 // Context menu is handled even when we have no menu. |
| 149 if (e.type != 'contextmenu' && !this.menu) | 144 if (e.type != 'contextmenu' && !this.menu) |
| 150 return; | 145 return; |
| 151 | 146 |
| 152 switch (e.type) { | 147 switch (e.type) { |
| 153 case 'mousedown': | 148 case 'mousedown': |
| 154 if (!this.menu.contains(e.target)) { | 149 if (!this.menu.contains(e.target)) { |
| 155 this.hideMenu(); | 150 this.hideMenu(); |
| 156 if(e.button == 0 /* Left click */) { | 151 if (e.button == 0 /* Left click */) { |
| 157 e.preventDefault(); | 152 e.preventDefault(); |
| 158 e.stopPropagation(); | 153 e.stopPropagation(); |
| 159 } | 154 } |
| 160 } | 155 } else |
| 161 else | |
| 162 e.preventDefault(); | 156 e.preventDefault(); |
| 163 break; | 157 break; |
| 164 | 158 |
| 165 case 'touchstart': | 159 case 'touchstart': |
| 166 if (!this.menu.contains(e.target)) | 160 if (!this.menu.contains(e.target)) |
| 167 this.hideMenu(); | 161 this.hideMenu(); |
| 168 break; | 162 break; |
| 169 | 163 |
| 170 case 'keydown': | 164 case 'keydown': |
| 171 if (e.key == 'Escape') { | 165 if (e.key == 'Escape') { |
| 172 this.hideMenu(); | 166 this.hideMenu(); |
| 173 e.stopPropagation(); | 167 e.stopPropagation(); |
| 174 e.preventDefault(); | 168 e.preventDefault(); |
| 175 | 169 |
| 176 // If the menu is visible we let it handle all the keyboard events. | 170 // If the menu is visible we let it handle all the keyboard events. |
| 177 } else if (this.menu) { | 171 } else if (this.menu) { |
| 178 this.menu.handleKeyDown(e); | 172 this.menu.handleKeyDown(e); |
| 179 e.preventDefault(); | 173 e.preventDefault(); |
| 180 e.stopPropagation(); | 174 e.stopPropagation(); |
| 181 } | 175 } |
| 182 break; | 176 break; |
| 183 | 177 |
| 184 case 'activate': | 178 case 'activate': |
| 185 var hideDelayed = e.target instanceof cr.ui.MenuItem && | 179 var hideDelayed = |
| 186 e.target.checkable; | 180 e.target instanceof cr.ui.MenuItem && e.target.checkable; |
| 187 this.hideMenu(hideDelayed ? cr.ui.HideType.DELAYED : | 181 this.hideMenu( |
| 188 cr.ui.HideType.INSTANT); | 182 hideDelayed ? cr.ui.HideType.DELAYED : cr.ui.HideType.INSTANT); |
| 189 break; | 183 break; |
| 190 | 184 |
| 191 case 'focus': | 185 case 'focus': |
| 192 if (!this.menu.contains(e.target)) | 186 if (!this.menu.contains(e.target)) |
| 193 this.hideMenu(); | 187 this.hideMenu(); |
| 194 break; | 188 break; |
| 195 | 189 |
| 196 case 'blur': | 190 case 'blur': |
| 197 this.hideMenu(); | 191 this.hideMenu(); |
| 198 break; | 192 break; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 213 } | 207 } |
| 214 }, | 208 }, |
| 215 | 209 |
| 216 /** | 210 /** |
| 217 * Adds a contextMenu property to an element or element class. | 211 * Adds a contextMenu property to an element or element class. |
| 218 * @param {!Element|!Function} elementOrClass The element or class to add | 212 * @param {!Element|!Function} elementOrClass The element or class to add |
| 219 * the contextMenu property to. | 213 * the contextMenu property to. |
| 220 */ | 214 */ |
| 221 addContextMenuProperty: function(elementOrClass) { | 215 addContextMenuProperty: function(elementOrClass) { |
| 222 var target = typeof elementOrClass == 'function' ? | 216 var target = typeof elementOrClass == 'function' ? |
| 223 elementOrClass.prototype : elementOrClass; | 217 elementOrClass.prototype : |
| 218 elementOrClass; |
| 224 | 219 |
| 225 target.__defineGetter__('contextMenu', function() { | 220 target.__defineGetter__( |
| 226 return this.contextMenu_; | 221 'contextMenu', function() { return this.contextMenu_; }); |
| 227 }); | |
| 228 target.__defineSetter__('contextMenu', function(menu) { | 222 target.__defineSetter__('contextMenu', function(menu) { |
| 229 var oldContextMenu = this.contextMenu; | 223 var oldContextMenu = this.contextMenu; |
| 230 | 224 |
| 231 if (typeof menu == 'string' && menu[0] == '#') { | 225 if (typeof menu == 'string' && menu[0] == '#') { |
| 232 menu = this.ownerDocument.getElementById(menu.slice(1)); | 226 menu = this.ownerDocument.getElementById(menu.slice(1)); |
| 233 cr.ui.decorate(menu, Menu); | 227 cr.ui.decorate(menu, Menu); |
| 234 } | 228 } |
| 235 | 229 |
| 236 if (menu === oldContextMenu) | 230 if (menu === oldContextMenu) |
| 237 return; | 231 return; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 * The singleton context menu handler. | 277 * The singleton context menu handler. |
| 284 * @type {!ContextMenuHandler} | 278 * @type {!ContextMenuHandler} |
| 285 */ | 279 */ |
| 286 var contextMenuHandler = new ContextMenuHandler; | 280 var contextMenuHandler = new ContextMenuHandler; |
| 287 | 281 |
| 288 // Export | 282 // Export |
| 289 return { | 283 return { |
| 290 contextMenuHandler: contextMenuHandler, | 284 contextMenuHandler: contextMenuHandler, |
| 291 }; | 285 }; |
| 292 }); | 286 }); |
| OLD | NEW |