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

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: '' Created 9 years, 1 month 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
« no previous file with comments | « chrome/browser/resources/shared/css/expandable_bubble.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
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 this.style.top = this.expanded ?
84 (top - this.offsetHeight + this.unexpandedHeight) + 'px' :
85 top + 'px';
86 },
87
88 /**
89 * Resizes the bubble and then repositions it.
90 * @private
91 */
92 resizeAndReposition_: function() {
93 var clientRect = this.anchorNode_.getBoundingClientRect();
94 var width = clientRect.width;
95 if (this.expanded) {
96 var expandedWidth = 250;
97 this.style.marginLeft = (width - expandedWidth) + 'px';
98 width = expandedWidth;
99 } else {
100 this.style.marginLeft = '0';
101 }
102
103 // Width is dynamic (when not expanded) based on the width of the anchor
104 // node, and the title and shadow need to follow suit.
105 this.style.width = width + 'px';
106 if (width > 0) {
107 var bubbleTitle = this.querySelector('.expandable-bubble-title');
108 bubbleTitle.style.width = width ? width - 2 + 'px' : 0 + 'px';
109 var bubbleContent = this.querySelector('.expandable-bubble-main');
110 bubbleContent.style.width = width ? width - 12 + 'px' : 0 + 'px';
111 var bubbleShadow = this.querySelector('.expandable-bubble-shadow');
112 bubbleShadow.style.width = width ? width + 2 + 'px' : 0 + 'px';
113 }
114
115 // Also reposition the bubble -- dimensions have potentially changed.
116 this.reposition_();
117 },
118
119 /*
120 * Expand the bubble (bringing the full content into view).
121 * @private
122 */
123 expandBubble_: function() {
124 this.querySelector('.expandable-bubble-main').hidden = false;
125 this.querySelector('.expandable-bubble-close').hidden = false;
126 this.expanded = true;
127 this.resizeAndReposition_();
128 },
129
130 /**
131 * Collapse the bubble, hiding the main content and the close button.
132 * This is automatically called when the window is resized.
133 * @private
134 */
135 collapseBubble_: function() {
136 this.querySelector('.expandable-bubble-main').hidden = true;
137 this.querySelector('.expandable-bubble-close').hidden = true;
138 this.expanded = false;
139 this.resizeAndReposition_();
140 },
141
142 /**
143 * The onclick handler for the notification (expands the bubble).
144 * @param {Event} e The event.
145 * @private
146 */
147 onNotificationClick_ : function(e) {
148 if (!this.contains(e.target))
149 return;
150
151 if (!this.expanded) {
152 // Save the height of the unexpanded bubble, so we can make sure to
153 // position it correctly (arrow points in the same location) after
154 // we expand it.
155 this.unexpandedHeight = this.offsetHeight;
156 }
157
158 this.expandBubble_();
159 },
160
161 /**
162 * Shows the bubble. The bubble will start collapsed and expand when
163 * clicked.
164 */
165 show: function() {
166 if (!this.hidden)
167 return;
168
169 document.body.appendChild(this);
170 this.hidden = false;
171 this.resizeAndReposition_();
172
173 this.eventTracker_ = new EventTracker;
174 this.eventTracker_.add(window,
175 'load', this.resizeAndReposition_.bind(this));
176 this.eventTracker_.add(window,
177 'resize', this.resizeAndReposition_.bind(this));
178 this.eventTracker_.add(this, 'click', this.onNotificationClick_);
179
180 var doc = this.ownerDocument;
181 this.eventTracker_.add(doc, 'keydown', this, true);
182 this.eventTracker_.add(doc, 'mousedown', this, true);
183 },
184
185 /**
186 * Hides the bubble from view.
187 */
188 hide: function() {
189 this.hidden = true;
190 this.eventTracker_.removeAll();
191 this.parentNode.removeChild(this);
192 },
193
194 /**
195 * Handles keydown and mousedown events, dismissing the bubble if
196 * necessary.
197 * @param {Event} e The event.
198 * @private
199 */
200 handleEvent: function(e) {
201 var handled = false;
202 switch (e.type) {
203 case 'keydown':
204 if (e.keyCode == 27) { // Esc.
205 if (this.expanded) {
206 this.collapseBubble_();
207 handled = true;
208 }
209 }
210 break;
211
212 case 'mousedown':
213 if (e.target == this.querySelector('.expandable-bubble-close')) {
214 this.hide();
215 handled = true;
216 } else if (!this.contains(e.target)) {
217 if (this.expanded) {
218 this.collapseBubble_();
219 handled = true;
220 }
221 }
222 break;
223 }
224
225 if (handled) {
226 // The bubble emulates a focus grab when expanded, so when we've
227 // collapsed/hide the bubble we consider the event handles and don't
228 // need to propagate it further.
229 e.stopPropagation();
230 e.preventDefault();
231 }
232 },
233 };
234
235 /**
236 * Whether the bubble is expanded or not.
237 * @type {boolean}
238 */
239 cr.defineProperty(ExpandableBubble, 'expanded', cr.PropertyKind.BOOL_ATTR);
240
241 return {
242 ExpandableBubble: ExpandableBubble
243 };
244 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/shared/css/expandable_bubble.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698