PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/prime/lib/closure-library/goog/ui/offlinestatuscomponent.js

https://github.com/ggppwx/heuristic-problem-solving-
JavaScript | 546 lines | 270 code | 89 blank | 187 comment | 33 complexity | f3422c228d8f04bcc1b707f525c30102 MD5 | raw file
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview A component that displays the offline status of an app.
  16. * Currently, it is used to show an icon with a tootip for the status.
  17. *
  18. * @see ../demos/offline.html
  19. */
  20. goog.provide('goog.ui.OfflineStatusComponent');
  21. goog.provide('goog.ui.OfflineStatusComponent.StatusClassNames');
  22. goog.require('goog.dom.classes');
  23. goog.require('goog.events.EventType');
  24. goog.require('goog.gears.StatusType');
  25. goog.require('goog.positioning');
  26. goog.require('goog.positioning.AnchoredPosition');
  27. goog.require('goog.positioning.Corner');
  28. goog.require('goog.positioning.Overflow');
  29. goog.require('goog.ui.Component');
  30. goog.require('goog.ui.OfflineStatusCard.EventType');
  31. goog.require('goog.ui.Popup');
  32. /**
  33. * An offline status component.
  34. * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
  35. * @constructor
  36. * @extends {goog.ui.Component}
  37. */
  38. goog.ui.OfflineStatusComponent = function(opt_domHelper) {
  39. goog.ui.Component.call(this, opt_domHelper);
  40. };
  41. goog.inherits(goog.ui.OfflineStatusComponent, goog.ui.Component);
  42. /**
  43. * The className's to use for the element of the component for each status type.
  44. * @enum {string}
  45. */
  46. goog.ui.OfflineStatusComponent.StatusClassNames = {
  47. NOT_INSTALLED: goog.getCssName('goog-offlinestatus-notinstalled'),
  48. INSTALLED: goog.getCssName('goog-offlinestatus-installed'),
  49. PAUSED: goog.getCssName('goog-offlinestatus-paused'),
  50. OFFLINE: goog.getCssName('goog-offlinestatus-offline'),
  51. ONLINE: goog.getCssName('goog-offlinestatus-online'),
  52. SYNCING: goog.getCssName('goog-offlinestatus-syncing'),
  53. ERROR: goog.getCssName('goog-offlinestatus-error')
  54. };
  55. /**
  56. * Whether the component is dirty and requires an upate to its display.
  57. * @type {boolean}
  58. * @private
  59. */
  60. goog.ui.OfflineStatusComponent.prototype.dirty_ = false;
  61. /**
  62. * The status of the component.
  63. * @type {goog.gears.StatusType}
  64. * @private
  65. */
  66. goog.ui.OfflineStatusComponent.prototype.status_ =
  67. goog.gears.StatusType.NOT_INSTALLED;
  68. /**
  69. * The status of the component that is displayed.
  70. * @type {goog.gears.StatusType?}
  71. * @private
  72. */
  73. goog.ui.OfflineStatusComponent.prototype.displayedStatus_ = null;
  74. /**
  75. * The dialog that manages the install flow.
  76. * @type {goog.ui.OfflineInstallDialog?}
  77. * @private
  78. */
  79. goog.ui.OfflineStatusComponent.prototype.dialog_ = null;
  80. /**
  81. * The card for displaying the detailed status.
  82. * @type {goog.ui.OfflineStatusCard?}
  83. * @private
  84. */
  85. goog.ui.OfflineStatusComponent.prototype.card_ = null;
  86. /**
  87. * The popup for the OfflineStatusCard.
  88. * @type {goog.ui.Popup?}
  89. * @private
  90. */
  91. goog.ui.OfflineStatusComponent.prototype.popup_ = null;
  92. /**
  93. * CSS class name for the element.
  94. * @type {string}
  95. * @private
  96. */
  97. goog.ui.OfflineStatusComponent.prototype.className_ =
  98. goog.getCssName('goog-offlinestatus');
  99. /**
  100. * @desc New feature text for the offline acces feature.
  101. * @type {string}
  102. * @private
  103. */
  104. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_NEW_FEATURE_ =
  105. goog.getMsg('New! Offline Access');
  106. /**
  107. * @desc Connectivity status of the app indicating the app is paused (user
  108. * initiated offline).
  109. * @type {string}
  110. * @private
  111. */
  112. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_STATUS_PAUSED_TITLE_ =
  113. goog.getMsg('Paused (offline). Click to connect.');
  114. /**
  115. * @desc Connectivity status of the app indicating the app is offline.
  116. * @type {string}
  117. * @private
  118. */
  119. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_STATUS_OFFLINE_TITLE_ =
  120. goog.getMsg('Offline. No connection available.');
  121. /**
  122. * @desc Connectivity status of the app indicating the app is online.
  123. * @type {string}
  124. * @private
  125. */
  126. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_STATUS_ONLINE_TITLE_ =
  127. goog.getMsg('Online. Click for details.');
  128. /**
  129. * @desc Connectivity status of the app indicating the app is synchronizing with
  130. * the server.
  131. * @type {string}
  132. * @private
  133. */
  134. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_STATUS_SYNCING_TITLE_ =
  135. goog.getMsg('Synchronizing. Click for details.');
  136. /**
  137. * @desc Connectivity status of the app indicating errors have been found.
  138. * @type {string}
  139. * @private
  140. */
  141. goog.ui.OfflineStatusComponent.prototype.MSG_OFFLINE_STATUS_ERROR_TITLE_ =
  142. goog.getMsg('Errors found. Click for details.');
  143. /**
  144. * Gets the status of the offline component of the app.
  145. * @return {goog.gears.StatusType} The offline status.
  146. */
  147. goog.ui.OfflineStatusComponent.prototype.getStatus = function() {
  148. return this.status_;
  149. };
  150. /**
  151. * Sets the status of the offline component of the app.
  152. * @param {goog.gears.StatusType} status The offline
  153. * status.
  154. */
  155. goog.ui.OfflineStatusComponent.prototype.setStatus = function(status) {
  156. if (this.isStatusDifferent(status)) {
  157. this.dirty_ = true;
  158. }
  159. this.status_ = status;
  160. if (this.isInDocument()) {
  161. this.update();
  162. }
  163. // Set the status of the card, if necessary.
  164. if (this.card_) {
  165. this.card_.setStatus(status);
  166. }
  167. };
  168. /**
  169. * Returns whether the given status is different from the currently
  170. * recorded status.
  171. * @param {goog.gears.StatusType} status The offline status.
  172. * @return {boolean} Whether the status is different.
  173. */
  174. goog.ui.OfflineStatusComponent.prototype.isStatusDifferent = function(status) {
  175. return this.status_ != status;
  176. };
  177. /**
  178. * Sets the install dialog.
  179. * @param {goog.ui.OfflineInstallDialog} dialog The dialog.
  180. */
  181. goog.ui.OfflineStatusComponent.prototype.setInstallDialog = function(dialog) {
  182. // If there is a current dialog, remove it.
  183. if (this.dialog_ && this.indexOfChild(this.dialog_) >= 0) {
  184. this.removeChild(this.dialog_);
  185. }
  186. this.dialog_ = dialog;
  187. };
  188. /**
  189. * Gets the install dialog.
  190. * @return {goog.ui.OfflineInstallDialog} dialog The dialog.
  191. */
  192. goog.ui.OfflineStatusComponent.prototype.getInstallDialog = function() {
  193. return this.dialog_;
  194. };
  195. /**
  196. * Sets the status card.
  197. * @param {goog.ui.OfflineStatusCard} card The card.
  198. */
  199. goog.ui.OfflineStatusComponent.prototype.setStatusCard = function(card) {
  200. // If there is a current card, remove it.
  201. if (this.card_) {
  202. this.getHandler().unlisten(this.card_,
  203. goog.ui.OfflineStatusCard.EventType.DISMISS,
  204. this.performStatusAction, false, this);
  205. this.popup_.dispose();
  206. if (this.indexOfChild(this.card_) >= 0) {
  207. this.removeChild(this.card_);
  208. }
  209. this.popup_ = null;
  210. this.card_ = null;
  211. }
  212. this.card_ = card;
  213. this.getHandler().listen(this.card_,
  214. goog.ui.OfflineStatusCard.EventType.DISMISS,
  215. this.performStatusAction, false, this);
  216. card.setStatus(this.status_);
  217. };
  218. /**
  219. * Gets the status card.
  220. * @return {goog.ui.OfflineStatusCard} The card.
  221. */
  222. goog.ui.OfflineStatusComponent.prototype.getStatusCard = function() {
  223. return this.card_;
  224. };
  225. /**
  226. * Creates the initial DOM representation for the component.
  227. */
  228. goog.ui.OfflineStatusComponent.prototype.createDom = function() {
  229. var anchorProps = {
  230. 'class': this.className_,
  231. 'href': '#'
  232. };
  233. this.setElementInternal(
  234. this.getDomHelper().createDom('a', anchorProps));
  235. this.update();
  236. };
  237. /** @override */
  238. goog.ui.OfflineStatusComponent.prototype.enterDocument = function() {
  239. goog.ui.OfflineStatusComponent.superClass_.enterDocument.call(this);
  240. this.getHandler().listen(
  241. this.getElement(), goog.events.EventType.CLICK, this.handleClick_);
  242. if (this.dirty_) {
  243. this.update();
  244. }
  245. };
  246. /**
  247. * Updates the display of the component.
  248. */
  249. goog.ui.OfflineStatusComponent.prototype.update = function() {
  250. if (this.getElement()) {
  251. var status = this.getStatus();
  252. var messageInfo = this.getMessageInfo(status);
  253. // Set the title.
  254. var element = this.getElement();
  255. element.title = messageInfo.title;
  256. // Set the appropriate class.
  257. var previousStatus = this.displayStatus_;
  258. var previousStatusClassName = this.getStatusClassName_(previousStatus);
  259. var currentStatusClassName = this.getStatusClassName_(status);
  260. if (previousStatus &&
  261. goog.dom.classes.has(element, previousStatusClassName)) {
  262. goog.dom.classes.swap(
  263. element, previousStatusClassName, currentStatusClassName);
  264. } else {
  265. goog.dom.classes.add(element, currentStatusClassName);
  266. }
  267. // Set the current display status
  268. this.displayStatus_ = status;
  269. // Set the text.
  270. if (messageInfo.textIsHtml) {
  271. element.innerHTML = messageInfo.text;
  272. } else {
  273. this.getDomHelper().setTextContent(element, messageInfo.text);
  274. }
  275. // Clear the dirty state.
  276. this.dirty_ = false;
  277. }
  278. };
  279. /**
  280. * Gets the messaging info for the given status.
  281. * @param {goog.gears.StatusType} status Status to get the message info for.
  282. * @return {Object} Object that has three properties - text (string),
  283. * textIsHtml (boolean), and title (string).
  284. */
  285. goog.ui.OfflineStatusComponent.prototype.getMessageInfo = function(status) {
  286. var title = '';
  287. var text = '   ';
  288. var textIsHtml = true;
  289. switch (status) {
  290. case goog.gears.StatusType.NOT_INSTALLED:
  291. case goog.gears.StatusType.INSTALLED:
  292. text = this.MSG_OFFLINE_NEW_FEATURE_;
  293. textIsHtml = false;
  294. break;
  295. case goog.gears.StatusType.PAUSED:
  296. title = this.MSG_OFFLINE_STATUS_PAUSED_TITLE_;
  297. break;
  298. case goog.gears.StatusType.OFFLINE:
  299. title = this.MSG_OFFLINE_STATUS_OFFLINE_TITLE_;
  300. break;
  301. case goog.gears.StatusType.ONLINE:
  302. title = this.MSG_OFFLINE_STATUS_ONLINE_TITLE_;
  303. break;
  304. case goog.gears.StatusType.SYNCING:
  305. title = this.MSG_OFFLINE_STATUS_SYNCING_TITLE_;
  306. break;
  307. case goog.gears.StatusType.ERROR:
  308. title = this.MSG_OFFLINE_STATUS_ERROR_TITLE_;
  309. break;
  310. default:
  311. break;
  312. }
  313. return {text: text, textIsHtml: textIsHtml, title: title};
  314. };
  315. /**
  316. * Gets the CSS className for the given status.
  317. * @param {goog.gears.StatusType} status Status to get the className for.
  318. * @return {string} The className.
  319. * @private
  320. */
  321. goog.ui.OfflineStatusComponent.prototype.getStatusClassName_ = function(
  322. status) {
  323. var className = '';
  324. switch (status) {
  325. case goog.gears.StatusType.NOT_INSTALLED:
  326. className =
  327. goog.ui.OfflineStatusComponent.StatusClassNames.NOT_INSTALLED;
  328. break;
  329. case goog.gears.StatusType.INSTALLED:
  330. className = goog.ui.OfflineStatusComponent.StatusClassNames.INSTALLED;
  331. break;
  332. case goog.gears.StatusType.PAUSED:
  333. className = goog.ui.OfflineStatusComponent.StatusClassNames.PAUSED;
  334. break;
  335. case goog.gears.StatusType.OFFLINE:
  336. className = goog.ui.OfflineStatusComponent.StatusClassNames.OFFLINE;
  337. break;
  338. case goog.gears.StatusType.ONLINE:
  339. className = goog.ui.OfflineStatusComponent.StatusClassNames.ONLINE;
  340. break;
  341. case goog.gears.StatusType.SYNCING:
  342. case goog.gears.StatusType.CAPTURING:
  343. className = goog.ui.OfflineStatusComponent.StatusClassNames.SYNCING;
  344. break;
  345. case goog.gears.StatusType.ERROR:
  346. className = goog.ui.OfflineStatusComponent.StatusClassNames.ERROR;
  347. break;
  348. default:
  349. break;
  350. }
  351. return className;
  352. };
  353. /**
  354. * Handles a click on the component. Opens the applicable install dialog or
  355. * status card.
  356. * @param {goog.events.BrowserEvent} e The event.
  357. * @private
  358. * @return {boolean|undefined} Always false to prevent the anchor navigation.
  359. */
  360. goog.ui.OfflineStatusComponent.prototype.handleClick_ = function(e) {
  361. this.performAction();
  362. return false;
  363. };
  364. /**
  365. * Performs the action as if the component was clicked.
  366. */
  367. goog.ui.OfflineStatusComponent.prototype.performAction = function() {
  368. var status = this.getStatus();
  369. if (status == goog.gears.StatusType.NOT_INSTALLED ||
  370. status == goog.gears.StatusType.INSTALLED) {
  371. this.performEnableAction();
  372. } else {
  373. this.performStatusAction();
  374. }
  375. };
  376. /**
  377. * Performs the action to start the flow of enabling the offline feature of
  378. * the application.
  379. */
  380. goog.ui.OfflineStatusComponent.prototype.performEnableAction = function() {
  381. // If Gears is not installed or if it is installed but not enabled, then
  382. // show the install dialog.
  383. var dialog = this.dialog_;
  384. if (dialog) {
  385. if (!dialog.isInDocument()) {
  386. this.addChild(dialog);
  387. dialog.render(this.getDomHelper().getDocument().body);
  388. }
  389. dialog.setVisible(true);
  390. }
  391. };
  392. /**
  393. * Performs the action to show the offline status.
  394. * @param {goog.events.Event=} opt_evt Event.
  395. * @param {Element=} opt_element Optional element to anchor the card against.
  396. */
  397. goog.ui.OfflineStatusComponent.prototype.performStatusAction = function(opt_evt,
  398. opt_element) {
  399. // Shows the offline status card.
  400. var card = this.card_;
  401. if (card) {
  402. if (!this.popup_) {
  403. if (!card.getElement()) {
  404. card.createDom();
  405. }
  406. this.insertCardElement(card);
  407. this.addChild(card);
  408. var popup = this.getPopupInternal();
  409. var anchorEl = opt_element || this.getElement();
  410. var pos = new goog.positioning.AnchoredPosition(
  411. anchorEl, goog.positioning.Corner.BOTTOM_START);
  412. // Override to pass in overflow
  413. pos.reposition = function(element, popupCorner, opt_margin) {
  414. goog.positioning.positionAtAnchor(this.element, this.corner, element,
  415. popupCorner, null, opt_margin, goog.positioning.Overflow.ADJUST_X);
  416. };
  417. popup.setPosition(pos);
  418. popup.setElement(card.getElement());
  419. }
  420. this.popup_.setVisible(!this.popup_.isOrWasRecentlyVisible());
  421. }
  422. };
  423. /**
  424. * Inserts the card into the document body.
  425. * @param {goog.ui.OfflineStatusCard} card The offline status card.
  426. * @protected
  427. */
  428. goog.ui.OfflineStatusComponent.prototype.insertCardElement = function(card) {
  429. this.getDomHelper().getDocument().body.appendChild(card.getElement());
  430. };
  431. /**
  432. * @return {goog.ui.Popup} A popup object, if none exists a new one is created.
  433. * @protected
  434. */
  435. goog.ui.OfflineStatusComponent.prototype.getPopupInternal = function() {
  436. if (!this.popup_) {
  437. this.popup_ = new goog.ui.Popup();
  438. this.popup_.setMargin(3, 0, 0, 0);
  439. }
  440. return this.popup_;
  441. };
  442. /** @override */
  443. goog.ui.OfflineStatusComponent.prototype.disposeInternal = function() {
  444. goog.ui.OfflineStatusComponent.superClass_.disposeInternal.call(this);
  445. if (this.dialog_) {
  446. this.dialog_.dispose();
  447. this.dialog_ = null;
  448. }
  449. if (this.card_) {
  450. this.card_.dispose();
  451. this.card_ = null;
  452. }
  453. if (this.popup_) {
  454. this.popup_.dispose();
  455. this.popup_ = null;
  456. }
  457. };