| Index: chrome/browser/resources/bluetooth_internals/snackbar.js
|
| diff --git a/chrome/browser/resources/bluetooth_internals/snackbar.js b/chrome/browser/resources/bluetooth_internals/snackbar.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9cca49e23420cdf81f5cd01551ce2acb0a2e3e16
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/bluetooth_internals/snackbar.js
|
| @@ -0,0 +1,226 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * Javascript for Snackbar controls, served from chrome://bluetooth-internals/.
|
| + */
|
| +
|
| +cr.define('snackbar', function() {
|
| + /** @typedef {{
|
| + * message: string,
|
| + * type: string,
|
| + * actionText: (string|undefined),
|
| + * action: (function()|undefined)
|
| + * }}
|
| + */
|
| + var SnackbarOptions;
|
| +
|
| + /** @const {number} */ var SHOW_DURATION = 5000;
|
| +
|
| + /**
|
| + * Enum of Snackbar types. Used by Snackbar to determine the styling for the
|
| + * Snackbar.
|
| + * @enum {string}
|
| + */
|
| + var SnackbarType = {
|
| + INFO: 'info',
|
| + SUCCESS: 'success',
|
| + WARNING: 'warning',
|
| + ERROR: 'error',
|
| + };
|
| +
|
| + /**
|
| + * Notification bar for displaying a simple message with an action link.
|
| + * This element should not be instantiated directly. Instead, users should
|
| + * use the Snackbar.show and Snackbar.dismiss functions to ensure proper
|
| + * queuing of messages.
|
| + */
|
| + var Snackbar = cr.ui.define('div');
|
| +
|
| + Snackbar.prototype = {
|
| + __proto__: HTMLDivElement.prototype,
|
| +
|
| + /**
|
| + * Decorates an element as a UI element class. Creates the message div and
|
| + * action link for the new Snackbar.
|
| + */
|
| + decorate: function() {
|
| + this.classList.add('snackbar');
|
| + this.messageDiv_ = document.createElement('div');
|
| + this.appendChild(this.messageDiv_);
|
| + this.actionLink_ = document.createElement('a', 'action-link');
|
| + this.appendChild(this.actionLink_);
|
| +
|
| + this.boundStartTimeout_ = this.startTimeout_.bind(this);
|
| + this.boundStopTimeout_ = this.stopTimeout_.bind(this);
|
| + this.addEventListener('mouseleave', this.boundStartTimeout_);
|
| + this.addEventListener('mouseenter', this.boundStopTimeout_);
|
| +
|
| + this.timeoutId_ = null;
|
| + },
|
| +
|
| + /**
|
| + * Initializes the content of the Snackbar with the given |options|
|
| + * including the message, action link text, and click action of the link.
|
| + * @param {!SnackbarOptions} options
|
| + */
|
| + initialize: function(options) {
|
| + this.messageDiv_.textContent = options.message;
|
| + this.classList.add(options.type);
|
| + this.actionLink_.textContent = options.actionText || 'Dismiss';
|
| +
|
| + this.actionLink_.addEventListener('click', function() {
|
| + if (options.action) options.action();
|
| + this.dismiss();
|
| + }.bind(this));
|
| + },
|
| +
|
| + /**
|
| + * Shows the Snackbar.
|
| + */
|
| + show: function() {
|
| + this.classList.add('open');
|
| + if (Snackbar.hasContentFocus_) this.startTimeout_();
|
| + else this.stopTimeout_();
|
| +
|
| + document.addEventListener('contentfocus', this.boundStartTimeout_);
|
| + document.addEventListener('contentblur', this.boundStopTimeout_);
|
| + },
|
| +
|
| + /**
|
| + * Dismisses the Snackbar. Once the Snackbar is completely hidden, the
|
| + * 'dismissed' event is fired.
|
| + */
|
| + dismiss: function() {
|
| + this.addEventListener('webkitTransitionEnd', function(event) {
|
| + if (event.propertyName === 'transform')
|
| + this.dispatchEvent(new CustomEvent('dismissed'));
|
| + }.bind(this));
|
| +
|
| + ensureTransitionEndEvent(this, SHOW_DURATION);
|
| + this.classList.remove('open');
|
| +
|
| + document.removeEventListener('contentfocus', this.boundStartTimeout_);
|
| + document.removeEventListener('contentblur', this.boundStopTimeout_);
|
| + },
|
| +
|
| + /**
|
| + * Starts the timeout for dismissing the Snackbar.
|
| + * @private
|
| + */
|
| + startTimeout_: function() {
|
| + this.timeoutId_ = setTimeout(function() {
|
| + this.dismiss();
|
| + }.bind(this), SHOW_DURATION);
|
| + },
|
| +
|
| + /**
|
| + * Stops the timeout for dismissing the Snackbar. Only clears the timeout
|
| + * when the Snackbar is open.
|
| + * @private
|
| + */
|
| + stopTimeout_: function() {
|
| + if (this.classList.contains('open')) {
|
| + clearTimeout(this.timeoutId_);
|
| + this.timeoutId_ = null;
|
| + }
|
| + },
|
| + };
|
| +
|
| + /** @private {?Snackbar} */
|
| + Snackbar.current_ = null;
|
| +
|
| + /** @private {!Array<!SnackbarOptions>} */
|
| + Snackbar.queue_ = [];
|
| +
|
| + /** @private {boolean} */
|
| + Snackbar.hasContentFocus_ = true;
|
| +
|
| + // There is a chance where the snackbar is shown but the content doesn't have
|
| + // focus. In this case, the current focus state must be tracked so the
|
| + // snackbar can pause the dismiss timeout.
|
| + document.addEventListener('contentfocus', function() {
|
| + Snackbar.hasContentFocus_ = true;
|
| + });
|
| + document.addEventListener('contentblur', function() {
|
| + Snackbar.hasContentFocus_ = false;
|
| + });
|
| +
|
| + /**
|
| + * TODO(crbug.com/675299): Add ability to specify parent element to Snackbar.
|
| + * Creates a Snackbar and shows it if one is not showing already. If a
|
| + * Snackbar is already active, the next Snackbar is queued.
|
| + * @param {string} message The message to display in the Snackbar.
|
| + * @param {string=} opt_type A string determining the Snackbar type: info,
|
| + * success, warning, error. If not provided, info type is used.
|
| + * @param {string=} opt_actionText The text to display for the action link.
|
| + * @param {function()=} opt_action A function to be called when the user
|
| + * presses the action link.
|
| + * @return {!Snackbar}
|
| + */
|
| + Snackbar.show = function(message, opt_type, opt_actionText, opt_action) {
|
| + var options = {
|
| + message: message,
|
| + type: opt_type || SnackbarType.INFO,
|
| + actionText: opt_actionText,
|
| + action: opt_action,
|
| + };
|
| +
|
| + var newSnackbar = new Snackbar();
|
| + newSnackbar.initialize(options);
|
| +
|
| + if (Snackbar.current_)
|
| + Snackbar.queue_.push(newSnackbar);
|
| + else
|
| + Snackbar.show_(newSnackbar);
|
| +
|
| + return newSnackbar;
|
| + };
|
| +
|
| + /**
|
| + * TODO(crbug.com/675299): Add ability to specify parent element to Snackbar.
|
| + * Creates a Snackbar and sets events for queuing the next Snackbar to show.
|
| + * @param {!Snackbar} newSnackbar
|
| + * @private
|
| + */
|
| + Snackbar.show_ = function(newSnackbar) {
|
| + $('snackbar-container').appendChild(newSnackbar);
|
| +
|
| + newSnackbar.addEventListener('dismissed', function() {
|
| + $('snackbar-container').removeChild(Snackbar.current_);
|
| +
|
| + var newSnackbar = Snackbar.queue_.shift();
|
| + if (newSnackbar) {
|
| + Snackbar.show_(newSnackbar);
|
| + return;
|
| + }
|
| +
|
| + Snackbar.current_ = null;
|
| + });
|
| +
|
| + Snackbar.current_ = newSnackbar;
|
| +
|
| + // Show the Snackbar after a slight delay to allow for a layout reflow.
|
| + setTimeout(function() {
|
| + newSnackbar.show();
|
| + }, 10);
|
| + };
|
| +
|
| + /**
|
| + * Dismisses the Snackbar currently showing.
|
| + * @param {boolean} clearQueue If true, clears the Snackbar queue before
|
| + * dismissing.
|
| + */
|
| + Snackbar.dismiss = function(clearQueue) {
|
| + if (clearQueue) Snackbar.queue_ = [];
|
| + if (Snackbar.current_) Snackbar.current_.dismiss();
|
| + };
|
| +
|
| +
|
| +
|
| + return {
|
| + Snackbar: Snackbar,
|
| + SnackbarType: SnackbarType,
|
| + };
|
| +});
|
|
|