1// Copyright (c) 2013 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 * Monitor the downloading progress of a XMLHttpRequest |xhr_| and shows the
7 * progress on |progressBar_|.
8 * @constructor
9 */
10function ProgressManager() {
11  this.xhr_ = null;
12  this.progressBar_ = document.querySelector('.progress-bar');
13  this.selectedGridItem_ = null;
14}
15
16/**
17 * Sets the XMLHttpRequest |xhr| to monitor, and the wallpaper thumbnail grid
18 * item |selectedGridItem| to show a progress bar for. Cancels previous xhr and
19 * hides/removes previous progress bar if any.
20 * Note: this must be called before xhr.send() function. Otherwise, we wont get
21 * loadstart event.
22 * @param {XMLHttpRequest} xhr The XMLHttpRequest.
23 * @param {WallpaperThumbnailsGridItem} selectedGridItem The wallpaper thumbnail
24 *     grid item. It extends from cr.ui.ListItem.
25 */
26ProgressManager.prototype.reset = function(xhr, selectedGridItem) {
27  if (this.xhr_)
28    this.removeEventListeners_();
29  this.hideProgressBar(this.selectedGridItem_);
30  this.xhr_ = xhr;
31  this.selectedGridItem_ = selectedGridItem;
32  this.xhrListeners_ = {
33    'loadstart': this.onDownloadStart_.bind(this),
34    'progress': this.onDownloadProgress_.bind(this),
35    'abort': this.onDownloadErrorOrAbort_.bind(this),
36    'error': this.onDownloadErrorOrAbort_.bind(this),
37    'load': this.onDownloadComplete_.bind(this)
38  };
39  for (var eventType in this.xhrListeners_)
40    this.xhr_.addEventListener(eventType, this.xhrListeners_[eventType]);
41};
42
43/**
44 * Removes all event listeners progress manager currently registered.
45 * @private
46 */
47ProgressManager.prototype.removeEventListeners_ = function() {
48  for (var eventType in this.xhrListeners_)
49    this.xhr_.removeEventListener(eventType, this.xhrListeners_[eventType]);
50};
51
52/**
53 * Removes the progress bar in |selectedGridItem| if any. May be called
54 * asynchronously.
55 * @param {WallpaperThumbnailsGridItem} selectedGridItem The wallpaper thumbnail
56       grid item. It extends from cr.ui.ListItem.
57 */
58ProgressManager.prototype.hideProgressBar = function(selectedGridItem) {
59  if (selectedGridItem && selectedGridItem.querySelector('.progress-bar')) {
60    this.progressBar_.hidden = true;
61    selectedGridItem.removeChild(this.progressBar_);
62  }
63};
64
65/**
66 * Calculates and updates the width of progress track.
67 * @private
68 * @param {float} percentComplete The percent of loaded content.
69 */
70ProgressManager.prototype.setProgress_ = function(percentComplete) {
71  this.progressBar_.querySelector('.progress-track').style.width =
72      (percentComplete * 100) + '%';
73};
74
75/**
76 * Shows a 0% progress bar to indicate downloading starts.
77 * @private
78 * @param {Event} e A loadstart ProgressEvent from XMLHttpRequest.
79 */
80ProgressManager.prototype.onDownloadStart_ = function(e) {
81  this.setProgress_(0);
82  this.selectedGridItem_.appendChild(this.progressBar_);
83  this.progressBar_.hidden = false;
84};
85
86/**
87 * Hides progress bar when progression is terminated.
88 * @private
89 * @param {Event} e An error/abort ProgressEvent from XMLHttpRequest.
90 */
91ProgressManager.prototype.onDownloadErrorOrAbort_ = function(e) {
92  this.removeEventListeners_();
93  this.xhr_ = null;
94  this.hideProgressBar(this.selectedGridItem_);
95};
96
97/**
98 * Download completed successfully. Shows a 100% progress bar and clears |xhr_|.
99 * @private
100 * @param {Event} e A load ProgressEvent from XMLHttpRequest.
101 */
102ProgressManager.prototype.onDownloadComplete_ = function(e) {
103  this.setProgress_(1);
104  this.removeEventListeners_();
105  this.xhr_ = null;
106};
107
108/**
109 * Calculates downloading percentage and shows downloading progress.
110 * @private
111 * @param {Event} e A progress ProgressEvent from XMLHttpRequest.
112 */
113ProgressManager.prototype.onDownloadProgress_ = function(e) {
114  if (e.lengthComputable)
115    this.setProgress_(e.loaded / e.total);
116};
117