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

Side by Side Diff: chrome/browser/resources/bluetooth_internals/snackbar.js

Issue 2568283003: bluetooth: Add notification system to internals page. (Closed)
Patch Set: Remove margin, fix bug where snackbar dismisses if shown with no focus Created 4 years 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
OLDNEW
(Empty)
1 // Copyright 2016 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 /**
6 * Javascript for Snackbar controls, served from chrome://bluetooth-internals/.
7 */
8
9 cr.define('snackbar', function() {
10 /** @typedef {{
11 * message: string,
12 * type: string,
13 * actionText: (string|undefined),
14 * action: (function()|undefined)
15 * }}
16 */
17 var SnackbarOptions;
18
19 /** @const {number} */ var SHOW_DURATION = 5000;
20
21 /**
22 * Enum of Snackbar types. Used by Snackbar to determine the styling for the
23 * Snackbar.
24 * @enum {string}
25 */
26 var SnackbarType = {
27 INFO: 'info',
28 SUCCESS: 'success',
29 WARNING: 'warning',
30 ERROR: 'error',
31 };
32
33 /**
34 * Notification bar for displaying a simple message with an action link.
35 * This element should not be instantiated directly. Instead, users should
36 * use the Snackbar.show and Snackbar.dismiss functions to ensure proper
37 * queuing of messages.
38 */
39 var Snackbar = cr.ui.define('div');
40
41 Snackbar.prototype = {
42 __proto__: HTMLDivElement.prototype,
43
44 /**
45 * Decorates an element as a UI element class. Creates the message div and
46 * action link for the new Snackbar.
47 */
48 decorate: function() {
49 this.classList.add('snackbar');
50 this.messageDiv_ = document.createElement('div');
51 this.appendChild(this.messageDiv_);
52 this.actionLink_ = document.createElement('a', 'action-link');
53 this.appendChild(this.actionLink_);
54
55 this.boundStartTimeout_ = this.startTimeout_.bind(this);
56 this.boundStopTimeout_ = this.stopTimeout_.bind(this);
57 this.addEventListener('mouseleave', this.boundStartTimeout_);
58 this.addEventListener('mouseenter', this.boundStopTimeout_);
59
60 this.timeoutId_ = null;
61 },
62
63 /**
64 * Initializes the content of the Snackbar with the given |options|
65 * including the message, action link text, and click action of the link.
66 * @param {!SnackbarOptions} options
67 */
68 initialize: function(options) {
69 this.messageDiv_.textContent = options.message;
70 this.classList.add(options.type);
71 this.actionLink_.textContent = options.actionText || 'Dismiss';
72
73 this.actionLink_.addEventListener('click', function() {
74 if (options.action) options.action();
75 this.dismiss();
76 }.bind(this));
77 },
78
79 /**
80 * Shows the Snackbar.
81 */
82 show: function() {
83 this.classList.add('open');
84 if (Snackbar.hasContentFocus_) this.startTimeout_();
85 else this.stopTimeout_();
86
87 document.addEventListener('contentfocus', this.boundStartTimeout_);
88 document.addEventListener('contentblur', this.boundStopTimeout_);
89 },
90
91 /**
92 * Dismisses the Snackbar. Once the Snackbar is completely hidden, the
93 * 'dismissed' event is fired.
94 */
95 dismiss: function() {
96 this.addEventListener('webkitTransitionEnd', function(event) {
97 if (event.propertyName === 'transform')
98 this.dispatchEvent(new CustomEvent('dismissed'));
99 }.bind(this));
100
101 ensureTransitionEndEvent(this, SHOW_DURATION);
102 this.classList.remove('open');
103
104 document.removeEventListener('contentfocus', this.boundStartTimeout_);
105 document.removeEventListener('contentblur', this.boundStopTimeout_);
106 },
107
108 /**
109 * Starts the timeout for dismissing the Snackbar.
110 * @private
111 */
112 startTimeout_: function() {
113 this.timeoutId_ = setTimeout(function() {
114 this.dismiss();
115 }.bind(this), SHOW_DURATION);
116 },
117
118 /**
119 * Stops the timeout for dismissing the Snackbar. Only clears the timeout
120 * when the Snackbar is open.
121 * @private
122 */
123 stopTimeout_: function() {
124 if (this.classList.contains('open')) {
125 clearTimeout(this.timeoutId_);
126 this.timeoutId_ = null;
127 }
128 },
129 };
130
131 /** @private {?Snackbar} */
132 Snackbar.current_ = null;
133
134 /** @private {!Array<!SnackbarOptions>} */
135 Snackbar.queue_ = [];
136
137 /** @private {boolean} */
138 Snackbar.hasContentFocus_ = true;
139
140 // There is a chance where the snackbar is shown but the content doesn't have
141 // focus. In this case, the current focus state must be tracked so the
142 // snackbar can pause the dismiss timeout.
143 document.addEventListener('contentfocus', function() {
144 Snackbar.hasContentFocus_ = true;
145 });
146 document.addEventListener('contentblur', function() {
147 Snackbar.hasContentFocus_ = false;
148 });
149
150 /**
151 * TODO(crbug.com/675299): Add ability to specify parent element to Snackbar.
152 * Creates a Snackbar and shows it if one is not showing already. If a
153 * Snackbar is already active, the next Snackbar is queued.
154 * @param {string} message The message to display in the Snackbar.
155 * @param {string=} opt_type A string determining the Snackbar type: info,
156 * success, warning, error. If not provided, info type is used.
157 * @param {string=} opt_actionText The text to display for the action link.
158 * @param {function()=} opt_action A function to be called when the user
159 * presses the action link.
160 * @return {!Snackbar}
161 */
162 Snackbar.show = function(message, opt_type, opt_actionText, opt_action) {
163 var options = {
164 message: message,
165 type: opt_type || SnackbarType.INFO,
166 actionText: opt_actionText,
167 action: opt_action,
168 };
169
170 var newSnackbar = new Snackbar();
171 newSnackbar.initialize(options);
172
173 if (Snackbar.current_)
174 Snackbar.queue_.push(newSnackbar);
175 else
176 Snackbar.show_(newSnackbar);
177
178 return newSnackbar;
179 };
180
181 /**
182 * TODO(crbug.com/675299): Add ability to specify parent element to Snackbar.
183 * Creates a Snackbar and sets events for queuing the next Snackbar to show.
184 * @param {!Snackbar} newSnackbar
185 * @private
186 */
187 Snackbar.show_ = function(newSnackbar) {
188 $('snackbar-container').appendChild(newSnackbar);
189
190 newSnackbar.addEventListener('dismissed', function() {
191 $('snackbar-container').removeChild(Snackbar.current_);
192
193 var newSnackbar = Snackbar.queue_.shift();
194 if (newSnackbar) {
195 Snackbar.show_(newSnackbar);
196 return;
197 }
198
199 Snackbar.current_ = null;
200 });
201
202 Snackbar.current_ = newSnackbar;
203
204 // Show the Snackbar after a slight delay to allow for a layout reflow.
205 setTimeout(function() {
206 newSnackbar.show();
207 }, 10);
208 };
209
210 /**
211 * Dismisses the Snackbar currently showing.
212 * @param {boolean} clearQueue If true, clears the Snackbar queue before
213 * dismissing.
214 */
215 Snackbar.dismiss = function(clearQueue) {
216 if (clearQueue) Snackbar.queue_ = [];
217 if (Snackbar.current_) Snackbar.current_.dismiss();
218 };
219
220
221
222 return {
223 Snackbar: Snackbar,
224 SnackbarType: SnackbarType,
225 };
226 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698