581 lines
16 KiB
JavaScript
581 lines
16 KiB
JavaScript
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
/**
|
|
* @fileoverview A card that displays the offline status of an app. It contains
|
|
* detailed information such as a progress bar the indicates the status of
|
|
* syncing and allows you to perform actions (such as manually go offline).
|
|
*
|
|
* @see ../demos/offline.html
|
|
*/
|
|
|
|
goog.provide('goog.ui.OfflineStatusCard');
|
|
goog.provide('goog.ui.OfflineStatusCard.EventType');
|
|
|
|
goog.require('goog.dom');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.gears.StatusType');
|
|
goog.require('goog.structs.Map');
|
|
goog.require('goog.style');
|
|
goog.require('goog.ui.Component');
|
|
goog.require('goog.ui.ProgressBar');
|
|
|
|
|
|
|
|
/**
|
|
* A offline status card.
|
|
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
|
|
* @constructor
|
|
* @extends {goog.ui.Component}
|
|
*/
|
|
goog.ui.OfflineStatusCard = function(opt_domHelper) {
|
|
goog.ui.Component.call(this, opt_domHelper);
|
|
|
|
/**
|
|
* The progress bar for showing the status of syncing.
|
|
* @type {goog.ui.ProgressBar}
|
|
* @private
|
|
*/
|
|
this.progressBar_ = new goog.ui.ProgressBar(opt_domHelper);
|
|
this.addChild(this.progressBar_);
|
|
|
|
/**
|
|
* A map of action element uid/action event type pairs.
|
|
* @type {goog.structs.Map}
|
|
* @private
|
|
*/
|
|
this.actionMap_ = new goog.structs.Map();
|
|
};
|
|
goog.inherits(goog.ui.OfflineStatusCard, goog.ui.Component);
|
|
|
|
|
|
/**
|
|
* Event types dispatched by the component.
|
|
* @enum {string}
|
|
*/
|
|
goog.ui.OfflineStatusCard.EventType = {
|
|
/** Dispatched when the user wants the card to be dismissed. */
|
|
DISMISS: 'dismiss'
|
|
};
|
|
|
|
|
|
/**
|
|
* Whether the component is dirty and requires an upate to its display.
|
|
* @type {boolean}
|
|
* @protected
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.dirty = false;
|
|
|
|
|
|
/**
|
|
* The status of the component.
|
|
* @type {goog.gears.StatusType}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.status_ =
|
|
goog.gears.StatusType.NOT_INSTALLED;
|
|
|
|
|
|
/**
|
|
* The element that holds the status message.
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.statusEl_ = null;
|
|
|
|
|
|
/**
|
|
* The element that, when clicked, performs the appropriate action (such as
|
|
* pausing synchronization).
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.actionEl_ = null;
|
|
|
|
|
|
/**
|
|
* The element that displays additional messaging.
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.messageEl_ = null;
|
|
|
|
|
|
/**
|
|
* The element that holds the progress bar and progress status.
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.progressEl_ = null;
|
|
|
|
|
|
/**
|
|
* The element that holds the progress status.
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.progressStatusEl_ = null;
|
|
|
|
|
|
/**
|
|
* The element that holds the close button.
|
|
* @type {Element}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.closeEl_ = null;
|
|
|
|
|
|
/**
|
|
* CSS class name for the element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.className_ =
|
|
goog.getCssName('goog-offlinestatuscard');
|
|
|
|
|
|
/**
|
|
* CSS class name for the shadow element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.shadowClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-shadow');
|
|
|
|
|
|
/**
|
|
* CSS class name for the content element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.contentClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-content');
|
|
|
|
|
|
/**
|
|
* CSS class name for the status element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.statusClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-status');
|
|
|
|
|
|
/**
|
|
* CSS class name for the action element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.actionClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-action');
|
|
|
|
|
|
/**
|
|
* CSS class name for each action item contained in the action element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.actionItemClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-action-item');
|
|
|
|
|
|
/**
|
|
* CSS class name for the last action item contained in the action element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.lastActionItemClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-action-item-last');
|
|
|
|
|
|
/**
|
|
* CSS class name for the message element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.messageClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-message');
|
|
|
|
|
|
/**
|
|
* CSS class name for the progress bar status element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.progressBarStatusClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-progressbarstatus');
|
|
|
|
|
|
/**
|
|
* CSS class name for the close card element.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.closeCardClassName_ =
|
|
goog.getCssName('goog-offlinestatuscard-closecard');
|
|
|
|
|
|
/**
|
|
* Gets the progress bar.
|
|
* @return {goog.ui.ProgressBar} The progress bar.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getProgressBar = function() {
|
|
return this.progressBar_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the status of the offline component of the app.
|
|
* @return {goog.gears.StatusType} The offline status.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getStatus = function() {
|
|
return this.status_;
|
|
};
|
|
|
|
|
|
/**
|
|
* Sets the status of the offline component of the app.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.setStatus = function(status) {
|
|
if (this.status_ != status) {
|
|
this.dirty = true;
|
|
}
|
|
this.status_ = status;
|
|
if (this.isInDocument()) {
|
|
this.update();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates the initial DOM representation for the component.
|
|
* @override
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.createDom = function() {
|
|
var dom = this.getDomHelper();
|
|
this.setElementInternal(dom.createDom('div', this.className_,
|
|
dom.createDom('div', this.shadowClassName_,
|
|
dom.createDom('div', this.contentClassName_,
|
|
this.closeEl_ = dom.createDom('div', this.closeCardClassName_),
|
|
this.statusEl_ = dom.createDom('div', this.statusClassName_),
|
|
this.progressEl_ = dom.createDom('div', null,
|
|
this.progressBarStatusEl_ =
|
|
dom.createDom('div', this.progressBarStatusClassName_)),
|
|
this.actionEl_ = dom.createDom('div', this.actionClassName_),
|
|
this.messageEl_ = dom.createDom('div',
|
|
this.messageClassName_)))));
|
|
|
|
// Create and append the DOM of the progress bar.
|
|
this.progressBar_.createDom();
|
|
dom.insertSiblingBefore(
|
|
this.progressBar_.getElement(), this.progressBarStatusEl_);
|
|
|
|
this.createAdditionalDom();
|
|
|
|
this.update();
|
|
};
|
|
|
|
|
|
/** @override */
|
|
goog.ui.OfflineStatusCard.prototype.enterDocument = function() {
|
|
goog.ui.OfflineStatusCard.superClass_.enterDocument.call(this);
|
|
|
|
// Listen for changes to the progress bar.
|
|
var handler = this.getHandler();
|
|
handler.listen(this.progressBar_, goog.ui.Component.EventType.CHANGE,
|
|
this.handleProgressChange_);
|
|
|
|
// Listen for a click on the action element.
|
|
handler.listen(
|
|
this.actionEl_, goog.events.EventType.CLICK, this.handleActionClick_);
|
|
|
|
// Listen for the click on the close element.
|
|
handler.listen(this.closeEl_, goog.events.EventType.CLICK, this.closePopup_);
|
|
|
|
// Update the component if it is dirty.
|
|
if (this.dirty) {
|
|
this.update();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Allows subclasses to initialize additional DOM structures during createDom.
|
|
* @protected
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.createAdditionalDom = function() {
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends an event to OfflineStatusComponent to dismiss the popup.
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.closePopup_ = function() {
|
|
this.dispatchEvent(goog.ui.OfflineStatusCard.EventType.DISMISS);
|
|
};
|
|
|
|
|
|
/**
|
|
* Updates the display of the component.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.update = function() {
|
|
if (this.getElement()) {
|
|
var status = this.getStatus();
|
|
var dom = this.getDomHelper();
|
|
|
|
this.configureStatusElement(status);
|
|
this.configureActionLinks(status);
|
|
this.configureProgressElement(status);
|
|
|
|
// Configure the message element.
|
|
var message = this.getAdditionalMessage(status);
|
|
var messageEl = this.messageEl_;
|
|
goog.style.setElementShown(messageEl, message);
|
|
if (message) {
|
|
dom.setTextContent(messageEl, message);
|
|
}
|
|
|
|
// Clear the dirty state.
|
|
this.dirty = false;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Set the message to display in the status portion of the card.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.configureStatusElement = function(status) {
|
|
/**
|
|
* @desc Tell the user whether they are online, offline, or syncing to
|
|
* Gears.
|
|
*/
|
|
var MSG_OFFLINE_STATUS = goog.getMsg(
|
|
'Status: {$msg}', {'msg': this.getStatusMessage(status)});
|
|
this.getDomHelper().setTextContent(this.statusEl_, MSG_OFFLINE_STATUS);
|
|
};
|
|
|
|
|
|
/**
|
|
* Set the action element to show correct action(s) for a particular status.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.configureActionLinks = function(status) {
|
|
// Configure the action element.
|
|
var actions = this.getActions(status);
|
|
goog.dom.removeChildren(this.actionEl_);
|
|
this.actionMap_.clear();
|
|
|
|
if (actions) {
|
|
var lastIdx = actions.length - 1;
|
|
for (var i = 0; i <= lastIdx; i++) {
|
|
// Ensure there is no padding to the right of the last action link.
|
|
this.createLinkNode_(actions[i], i == lastIdx ?
|
|
this.lastActionItemClassName_ : this.actionItemClassName_);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates an action link element and styles it.
|
|
* @param {Object} action An action object with message and event type.
|
|
* @param {string} className The css class name to style the link with.
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.createLinkNode_ = function(
|
|
action, className) {
|
|
var actionEl = this.actionEl_;
|
|
var dom = this.getDomHelper();
|
|
var a = dom.createDom('span', className);
|
|
dom.appendChild(actionEl, a);
|
|
// A text node is needed here in order for links to wrap.
|
|
dom.appendChild(actionEl, dom.createTextNode(' '));
|
|
this.actionMap_.set(goog.getUid(a), action.eventType);
|
|
goog.style.setElementShown(a, true);
|
|
dom.setTextContent(a, action.message);
|
|
};
|
|
|
|
|
|
/**
|
|
* Configure the progress bar element.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.configureProgressElement =
|
|
function(status) {
|
|
var showProgress = this.shouldShowProgressBar(status);
|
|
goog.style.setElementShown(this.progressEl_, showProgress);
|
|
if (showProgress) {
|
|
this.updateProgressStatus();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Returns true if we want to display a progress bar.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
* @return {boolean} Whether we want to display a progress bar.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.shouldShowProgressBar = function(status) {
|
|
return status == goog.gears.StatusType.SYNCING ||
|
|
status == goog.gears.StatusType.CAPTURING;
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles a CHANGE event of the progress bar. Updates the status.
|
|
* @param {goog.events.Event} e The event.
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.handleProgressChange_ = function(e) {
|
|
this.updateProgressStatus();
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles a CLICK event on the action element. Dispatches the appropriate
|
|
* action event type.
|
|
* @param {goog.events.BrowserEvent} e The event.
|
|
* @private
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.handleActionClick_ = function(e) {
|
|
var actionEventType = /** @type {string} */ (this.actionMap_.get(
|
|
goog.getUid(e.target)));
|
|
if (actionEventType) {
|
|
this.dispatchEvent(actionEventType);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Updates the status of the progress bar.
|
|
* @protected
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.updateProgressStatus = function() {
|
|
this.getDomHelper().setTextContent(
|
|
this.progressBarStatusEl_, this.getProgressStatusMessage());
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the status message for the progress bar.
|
|
* @return {string} The status message for the progress bar.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getProgressStatusMessage = function() {
|
|
var pb = this.progressBar_;
|
|
var percentValue = Math.round((pb.getValue() - pb.getMinimum()) /
|
|
(pb.getMaximum() - pb.getMinimum()) * 100);
|
|
/** @desc The percent complete status of the syncing. */
|
|
var MSG_OFFLINE_PERCENT_COMPLETE = goog.getMsg(
|
|
'{$num}% complete.', {'num': percentValue});
|
|
return MSG_OFFLINE_PERCENT_COMPLETE;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the status message for the given status.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
* @return {string} The status message.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getStatusMessage = function(status) {
|
|
var message = '';
|
|
|
|
switch (status) {
|
|
case goog.gears.StatusType.OFFLINE:
|
|
/** @desc Status shown when the app is offline. */
|
|
var MSG_OFFLINE_STATUS_OFFLINE_MESSAGE = goog.getMsg(
|
|
'Offline. No connection available.');
|
|
message = MSG_OFFLINE_STATUS_OFFLINE_MESSAGE;
|
|
break;
|
|
case goog.gears.StatusType.ONLINE:
|
|
/** @desc Status shown when the app is online. */
|
|
var MSG_OFFLINE_STATUS_ONLINE_MESSAGE = goog.getMsg('Online');
|
|
message = MSG_OFFLINE_STATUS_ONLINE_MESSAGE;
|
|
break;
|
|
case goog.gears.StatusType.SYNCING:
|
|
/** @desc Status shown when the app is synchronizing. */
|
|
var MSG_OFFLINE_STATUS_SYNCING_MESSAGE = goog.getMsg('Synchronizing...');
|
|
message = MSG_OFFLINE_STATUS_SYNCING_MESSAGE;
|
|
break;
|
|
case goog.gears.StatusType.CAPTURING:
|
|
/** @desc Status shown when the app is capturing resources. */
|
|
var MSG_OFFLINE_STATUS_CAPTURING_MESSAGE = goog.getMsg(
|
|
'Updating software...');
|
|
message = MSG_OFFLINE_STATUS_CAPTURING_MESSAGE;
|
|
break;
|
|
case goog.gears.StatusType.ERROR:
|
|
/** @desc Status shown when an error has occured. */
|
|
var MSG_OFFLINE_STATUS_ERROR_MESSAGE = goog.getMsg(
|
|
'Errors have been found.');
|
|
message = MSG_OFFLINE_STATUS_ERROR_MESSAGE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return message;
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the action to display for the given status.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
* @return {Array.<Object>?} An array of action objects to display.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getActions = function(status) {
|
|
return null;
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates an action object containing a message for the action and event
|
|
* type to dispatch if the action occurs.
|
|
* @param {string} actionMessage The action message.
|
|
* @param {string} actionEventType The action event type.
|
|
* @return {Object} An object containing message and eventType properties.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.createActionObject = function(
|
|
actionMessage, actionEventType) {
|
|
return {message: actionMessage, eventType: actionEventType};
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the additional message to display for the given status.
|
|
* @param {goog.gears.StatusType} status The offline status.
|
|
* @return {string} The additional message.
|
|
*/
|
|
goog.ui.OfflineStatusCard.prototype.getAdditionalMessage = function(status) {
|
|
return '';
|
|
};
|
|
|
|
|
|
/** @override */
|
|
goog.ui.OfflineStatusCard.prototype.disposeInternal = function() {
|
|
goog.ui.OfflineStatusCard.superClass_.disposeInternal.call(this);
|
|
|
|
this.progressBar_.dispose();
|
|
this.progressBar_ = null;
|
|
|
|
this.actionMap_.clear();
|
|
this.actionMap_ = null;
|
|
|
|
this.statusEl_ = null;
|
|
this.actionEl_ = null;
|
|
this.messageEl_ = null;
|
|
this.progressEl_ = null;
|
|
this.progressStatusEl_ = null;
|
|
};
|