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 |