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_tracker.js | 5 // require: event_tracker.js |
6 | 6 |
7 cr.define('cr.ui', function() { | 7 cr.define('cr.ui', function() { |
8 'use strict'; | 8 'use strict'; |
9 | 9 |
10 /** | 10 /** |
11 * ExpandableBubble is a free-floating compact informational bubble with an | 11 * ExpandableBubble is a free-floating compact informational bubble with an |
12 * arrow that points at a place of interest on the page. When clicked, the | 12 * arrow that points at a place of interest on the page. When clicked, the |
13 * bubble expands to show more of its content. Width of the bubble is the | 13 * bubble expands to show more of its content. Width of the bubble is the |
14 * width of the node it is overlapping when unexpanded. Expanded, it is of a | 14 * width of the node it is overlapping when unexpanded. Expanded, it is of a |
15 * fixed width, but variable height. Currently the arrow is always positioned | 15 * fixed width, but variable height. Currently the arrow is always positioned |
16 * at the bottom right and points down. | 16 * at the bottom right and points down. |
17 * @constructor | 17 * @constructor |
18 * @extends {HTMLDivElement} | 18 * @extends {HTMLDivElement} |
19 * @implements {EventListener} | 19 * @implements {EventListener} |
20 */ | 20 */ |
21 var ExpandableBubble = cr.ui.define('div'); | 21 var ExpandableBubble = cr.ui.define('div'); |
22 | 22 |
23 ExpandableBubble.prototype = { | 23 ExpandableBubble.prototype = { |
24 __proto__: HTMLDivElement.prototype, | 24 __proto__: HTMLDivElement.prototype, |
25 | 25 |
26 decorate: function() { | 26 decorate: function() { |
27 this.className = 'expandable-bubble'; | 27 this.className = 'expandable-bubble'; |
28 this.innerHTML = | 28 this.innerHTML = '<div class="expandable-bubble-contents">' + |
29 '<div class="expandable-bubble-contents">' + | 29 '<div class="expandable-bubble-title"></div>' + |
30 '<div class="expandable-bubble-title"></div>' + | 30 '<div class="expandable-bubble-main" hidden></div>' + |
31 '<div class="expandable-bubble-main" hidden></div>' + | |
32 '</div>' + | 31 '</div>' + |
33 '<div class="expandable-bubble-close" hidden></div>'; | 32 '<div class="expandable-bubble-close" hidden></div>'; |
34 | 33 |
35 this.hidden = true; | 34 this.hidden = true; |
36 this.bubbleSuppressed = false; | 35 this.bubbleSuppressed = false; |
37 this.handleCloseEvent = this.hide; | 36 this.handleCloseEvent = this.hide; |
38 }, | 37 }, |
39 | 38 |
40 /** | 39 /** |
41 * Sets the title of the bubble. The title is always visible when the | 40 * Sets the title of the bubble. The title is always visible when the |
(...skipping 27 matching lines...) Expand all Loading... |
69 | 68 |
70 if (!this.hidden) | 69 if (!this.hidden) |
71 this.resizeAndReposition(); | 70 this.resizeAndReposition(); |
72 }, | 71 }, |
73 | 72 |
74 /** | 73 /** |
75 * Handles the close event which is triggered when the close button | 74 * Handles the close event which is triggered when the close button |
76 * is clicked. By default is set to this.hide. | 75 * is clicked. By default is set to this.hide. |
77 * @param {Function} func A function with no parameters. | 76 * @param {Function} func A function with no parameters. |
78 */ | 77 */ |
79 set handleCloseEvent(func) { | 78 set handleCloseEvent(func) { this.handleCloseEvent_ = func; }, |
80 this.handleCloseEvent_ = func; | |
81 }, | |
82 | 79 |
83 /** | 80 /** |
84 * Temporarily suppresses the bubble from view (and toggles it back). | 81 * Temporarily suppresses the bubble from view (and toggles it back). |
85 * 'Suppressed' and 'hidden' are two bubble states that both indicate that | 82 * 'Suppressed' and 'hidden' are two bubble states that both indicate that |
86 * the bubble should not be visible, but when you 'un-suppress' a bubble, | 83 * the bubble should not be visible, but when you 'un-suppress' a bubble, |
87 * only a suppressed bubble becomes visible. This can be handy, for example, | 84 * only a suppressed bubble becomes visible. This can be handy, for example, |
88 * if the user switches away from the app card (then we need to know which | 85 * if the user switches away from the app card (then we need to know which |
89 * bubbles to show (only the suppressed ones, not the hidden ones). Hiding | 86 * bubbles to show (only the suppressed ones, not the hidden ones). Hiding |
90 * and un-hiding a bubble overrides the suppressed state (a bubble cannot | 87 * and un-hiding a bubble overrides the suppressed state (a bubble cannot |
91 * be suppressed but not hidden). | 88 * be suppressed but not hidden). |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 187 |
191 /** | 188 /** |
192 * The onclick handler for the notification (expands the bubble). | 189 * The onclick handler for the notification (expands the bubble). |
193 * @param {Event} e The event. | 190 * @param {Event} e The event. |
194 * @private | 191 * @private |
195 * @suppress {checkTypes} | 192 * @suppress {checkTypes} |
196 * TODO(vitalyp): remove suppression when the extern | 193 * TODO(vitalyp): remove suppression when the extern |
197 * Node.prototype.contains() will be fixed. | 194 * Node.prototype.contains() will be fixed. |
198 */ | 195 */ |
199 onNotificationClick_: function(e) { | 196 onNotificationClick_: function(e) { |
200 if (!this.contains(/** @type {!Node} */(e.target))) | 197 if (!this.contains(/** @type {!Node} */ (e.target))) |
201 return; | 198 return; |
202 | 199 |
203 if (!this.expanded) { | 200 if (!this.expanded) { |
204 // Save the height of the unexpanded bubble, so we can make sure to | 201 // Save the height of the unexpanded bubble, so we can make sure to |
205 // position it correctly (arrow points in the same location) after | 202 // position it correctly (arrow points in the same location) after |
206 // we expand it. | 203 // we expand it. |
207 this.unexpandedHeight = this.offsetHeight; | 204 this.unexpandedHeight = this.offsetHeight; |
208 } | 205 } |
209 | 206 |
210 this.expandBubble_(); | 207 this.expandBubble_(); |
211 }, | 208 }, |
212 | 209 |
213 /** | 210 /** |
214 * Shows the bubble. The bubble will start collapsed and expand when | 211 * Shows the bubble. The bubble will start collapsed and expand when |
215 * clicked. | 212 * clicked. |
216 */ | 213 */ |
217 show: function() { | 214 show: function() { |
218 if (!this.hidden) | 215 if (!this.hidden) |
219 return; | 216 return; |
220 | 217 |
221 document.body.appendChild(this); | 218 document.body.appendChild(this); |
222 this.hidden = false; | 219 this.hidden = false; |
223 this.resizeAndReposition(); | 220 this.resizeAndReposition(); |
224 | 221 |
225 this.eventTracker_ = new EventTracker; | 222 this.eventTracker_ = new EventTracker; |
226 this.eventTracker_.add(window, | 223 this.eventTracker_.add( |
227 'load', this.resizeAndReposition.bind(this)); | 224 window, 'load', this.resizeAndReposition.bind(this)); |
228 this.eventTracker_.add(window, | 225 this.eventTracker_.add( |
229 'resize', this.resizeAndReposition.bind(this)); | 226 window, 'resize', this.resizeAndReposition.bind(this)); |
230 this.eventTracker_.add(this, 'click', this.onNotificationClick_); | 227 this.eventTracker_.add(this, 'click', this.onNotificationClick_); |
231 | 228 |
232 var doc = this.ownerDocument; | 229 var doc = this.ownerDocument; |
233 this.eventTracker_.add(assert(doc), 'keydown', this, true); | 230 this.eventTracker_.add(assert(doc), 'keydown', this, true); |
234 this.eventTracker_.add(assert(doc), 'mousedown', this, true); | 231 this.eventTracker_.add(assert(doc), 'mousedown', this, true); |
235 }, | 232 }, |
236 | 233 |
237 /** | 234 /** |
238 * Hides the bubble from view. | 235 * Hides the bubble from view. |
239 */ | 236 */ |
(...skipping 22 matching lines...) Expand all Loading... |
262 this.collapseBubble_(); | 259 this.collapseBubble_(); |
263 handled = true; | 260 handled = true; |
264 } | 261 } |
265 } | 262 } |
266 break; | 263 break; |
267 | 264 |
268 case 'mousedown': | 265 case 'mousedown': |
269 if (e.target == this.querySelector('.expandable-bubble-close')) { | 266 if (e.target == this.querySelector('.expandable-bubble-close')) { |
270 this.handleCloseEvent_(); | 267 this.handleCloseEvent_(); |
271 handled = true; | 268 handled = true; |
272 } else if (!this.contains(/** @type {!Node} */(e.target))) { | 269 } else if (!this.contains(/** @type {!Node} */ (e.target))) { |
273 if (this.expanded) { | 270 if (this.expanded) { |
274 this.collapseBubble_(); | 271 this.collapseBubble_(); |
275 handled = true; | 272 handled = true; |
276 } | 273 } |
277 } | 274 } |
278 break; | 275 break; |
279 } | 276 } |
280 | 277 |
281 if (handled) { | 278 if (handled) { |
282 // The bubble emulates a focus grab when expanded, so when we've | 279 // The bubble emulates a focus grab when expanded, so when we've |
(...skipping 11 matching lines...) Expand all Loading... |
294 cr.defineProperty(ExpandableBubble, 'expanded', cr.PropertyKind.BOOL_ATTR); | 291 cr.defineProperty(ExpandableBubble, 'expanded', cr.PropertyKind.BOOL_ATTR); |
295 | 292 |
296 /** | 293 /** |
297 * Whether the title needs to be masked out towards the right, which indicates | 294 * Whether the title needs to be masked out towards the right, which indicates |
298 * to the user that part of the text is clipped. This is only used when the | 295 * to the user that part of the text is clipped. This is only used when the |
299 * bubble is collapsed and the title doesn't fit because it is maxed out in | 296 * bubble is collapsed and the title doesn't fit because it is maxed out in |
300 * width within the anchored node. | 297 * width within the anchored node. |
301 */ | 298 */ |
302 cr.defineProperty(ExpandableBubble, 'masked', cr.PropertyKind.BOOL_ATTR); | 299 cr.defineProperty(ExpandableBubble, 'masked', cr.PropertyKind.BOOL_ATTR); |
303 | 300 |
304 return { | 301 return {ExpandableBubble: ExpandableBubble}; |
305 ExpandableBubble: ExpandableBubble | |
306 }; | |
307 }); | 302 }); |
OLD | NEW |