Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: chrome/browser/resources/shared/js/cr/ui/expandable_bubble.js

Issue 8208014: Update the notification bubble. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Comments addressed Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 // require: event_tracker.js
6
7 cr.define('cr.ui', function() {
8 'use strict';
9
10 /**
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
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
15 * fixed width, but variable height. Currently the arrow is always positioned
16 * at the bottom right and points down.
17 * @constructor
18 * @extends {cr.ui.div}
19 */
20 var ExpandableBubble = cr.ui.define('div');
21
22 ExpandableBubble.prototype = {
23 __proto__: HTMLDivElement.prototype,
24
25 /** @inheritDoc */
26 decorate: function() {
27 this.className = 'expandable-bubble';
28 this.innerHTML =
29 '<div class="expandable-bubble-contents">' +
30 '<div class="expandable-bubble-title"></div>' +
31 '<div class="expandable-bubble-main" hidden></div>' +
32 '</div>' +
33 '<div class="expandable-bubble-close" hidden></div>' +
34 '<div class="expandable-bubble-shadow"></div>' +
35 '<div class="expandable-bubble-arrow"></div>';
36
37 this.hidden = true;
38 },
39
40 /**
41 * Sets the title of the bubble. The title is always visible when the
42 * bubble is visible.
43 * @type {node} An HTML element to set as the title.
arv (Not doing code reviews) 2011/10/18 16:50:30 {Node}
44 */
45 set contentTitle(node) {
46 var bubbleTitle = this.querySelector('.expandable-bubble-title');
47 bubbleTitle.textContent = '';
48 bubbleTitle.appendChild(node);
49 },
50
51 /**
52 * Sets the content node of the bubble. The content node is only visible
53 * when the bubble is expanded.
54 * @param {node} An HTML element.
55 */
56 set content(node) {
57 var bubbleMain = this.querySelector('.expandable-bubble-main');
58 bubbleMain.textContent = '';
59 bubbleMain.appendChild(node);
60 },
61
62 /**
63 * Sets the anchor node, i.e. the node that this bubble points at and
64 * partially overlaps.
65 * @param {HTMLElement} node The new anchor node.
66 */
67 set anchorNode(node) {
68 this.anchorNode_ = node;
69
70 if (!this.hidden)
71 this.resizeAndReposition_();
72 },
73
74 /**
75 * Updates the position of the bubble.
76 * @private
77 */
78 reposition_: function() {
79 var clientRect = this.anchorNode_.getBoundingClientRect();
80 this.style.left = this.style.right = clientRect.left + 'px';
81
82 var top = clientRect.top - 1;
83 if (this.getAttribute('expanded') != null) {
arv (Not doing code reviews) 2011/10/18 16:50:30 or hasAttribute There is also a "macro" in cr.js
Finnur 2011/10/19 15:12:30 Ooh, nice.
84 this.style.top =
85 (top - this.offsetHeight + this.unexpandedHeight) + 'px';
86 } else {
87 this.style.top = top + 'px';
88 }
89 },
90
91 /**
92 * Resizes the bubble and then repositions it.
93 * @private
94 */
95 resizeAndReposition_: function() {
96 var clientRect = this.anchorNode_.getBoundingClientRect();
97 var width = clientRect.width;
98 if (this.getAttribute('expanded') != null) {
99 var expandedWidth = 250;
100 this.style.marginLeft = (width - expandedWidth) + 'px';
101 width = expandedWidth;
102 } else {
103 this.style.marginLeft = '0';
104 }
105
106 // Width is dynamic (when not expanded) based on the width of the anchor
107 // node, and the title and shadow need to follow suit.
108 this.style.width = width + 'px';
109 var bubbleTitle = this.querySelector('.expandable-bubble-title');
110 bubbleTitle.style.width = width - 2 + 'px';
111 var bubbleContent = this.querySelector('.expandable-bubble-main');
112 bubbleContent.style.width = width - 12 + 'px';
113 var bubbleShadow = this.querySelector('.expandable-bubble-shadow');
114 bubbleShadow.style.width = width + 2 + 'px';
115
116 // Also reposition the bubble -- dimensions have potentially changed.
117 this.reposition_();
118 },
119
120 /*
121 * Expand the bubble (bringing the full content into view).
122 * @private
123 */
124 expandBubble_: function() {
125 this.querySelector('.expandable-bubble-main').hidden = false;
126 this.querySelector('.expandable-bubble-close').hidden = false;
127 this.setAttribute('expanded', '');
128 this.resizeAndReposition_();
129 },
130
131 /**
132 * Collapse the bubble, hiding the main content and the close button.
133 * This is automatically called when the window is resized.
134 * @private
135 */
136 collapseBubble_: function() {
137 this.querySelector('.expandable-bubble-main').hidden = true;
138 this.querySelector('.expandable-bubble-close').hidden = true;
139 this.removeAttribute('expanded');
140 this.resizeAndReposition_();
141 },
142
143 /**
144 * The onclick handler for the notification (expands the bubble).
145 * @param {Event} e The event.
146 * @private
147 */
148 onNotificationClick_ : function(e) {
149 if (!this.contains(e.target))
150 return;
151
152 if (this.getAttribute('expanded') == null) {
153 // Save the height of the unexpanded bubble, so we can make sure to
154 // position it correctly (arrow points in the same location) after
155 // we expand it.
156 this.unexpandedHeight = this.offsetHeight;
157 }
158
159 this.expandBubble_();
160 },
161
162 /**
163 * Starts showing the bubble. The bubble will grab input and show until the
164 * user clicks away.
165 */
166 show: function() {
167 if (!this.hidden)
168 return;
169
170 document.body.appendChild(this);
171 this.hidden = false;
172 this.resizeAndReposition_();
173
174 this.eventTracker_ = new EventTracker;
175 this.eventTracker_.add(window,
176 'load', this.resizeAndReposition_.bind(this));
177 this.eventTracker_.add(window,
178 'resize', this.collapseBubble_.bind(this));
179 this.eventTracker_.add(window,
180 'click', this.onNotificationClick_.bind(this));
181
182 var doc = this.ownerDocument;
183 this.eventTracker_.add(doc, 'keydown', this, true);
Finnur 2011/10/20 11:36:08 Silly question: arv & estade: How do I convert thi
Evan Stade 2011/10/20 17:08:50 change doc to the node you want to listen on
arv (Not doing code reviews) 2011/10/20 18:54:13 Remember that key events are dispatched from the f
184 this.eventTracker_.add(doc, 'mousedown', this, true);
185 },
186
187 /**
188 * Hides the bubble from view.
189 */
190 hide: function() {
191 this.hidden = true;
192 this.eventTracker_.removeAll();
193 this.parentNode.removeChild(this);
194 },
195
196 /**
197 * Handles keydown and mousedown events, dismissing the bubble if
198 * necessary.
199 * @param {Event} e The event.
200 * @private
201 */
202 handleEvent: function(e) {
203 switch (e.type) {
204 case 'keydown':
205 if (e.keyCode == 27) // Esc.
Evan Stade 2011/10/19 01:57:05 if escape hides, then don't you want blur() to hid
Finnur 2011/10/19 15:12:30 Good question. I think, since the key event is not
Evan Stade 2011/10/19 23:26:14 I agree. Your keyboard handler should only be conn
Finnur 2011/10/20 11:36:08 See question above... On 2011/10/19 23:26:14, Eva
206 this.hide();
207 break;
208
209 case 'mousedown':
210 if (e.target == this.querySelector('.expandable-bubble-close')) {
211 this.hide();
212 } else if (!this.contains(e.target)) {
213 if (this.getAttribute('expanded') != null)
214 this.collapseBubble_();
215 }
216 break;
217 }
218
219 e.stopPropagation();
Evan Stade 2011/10/19 01:57:05 I am not sure whether these are desired in the mou
Finnur 2011/10/19 15:12:30 Do you mean I don't need it for the keyboard event
Evan Stade 2011/10/19 23:26:14 no, I mean that you don't need it for mousedown
Finnur 2011/10/20 11:36:08 Ah, I see. On 2011/10/19 23:26:14, Evan Stade wr
220 e.preventDefault();
221 return;
222 },
223 };
224
225 return {
226 ExpandableBubble: ExpandableBubble
227 };
228 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698