- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / file_manager / foreground / js / ui / progress_center_panel.js
1 // Copyright 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 'use strict';
6
7 /**
8  * Progress center panel.
9  *
10  * @param {HTMLElement} element DOM Element of the process center panel.
11  * @param {function(string)} cancelCallback Callback to becalled with the ID of
12  *     the progress item when the cancel button is clicked.
13  * @constructor
14  */
15 var ProgressCenterPanel = function(element, cancelCallback) {
16   this.element_ = element;
17   this.openView_ = this.element_.querySelector('#progress-center-open-view');
18   this.closeView_ = this.element_.querySelector('#progress-center-close-view');
19   this.cancelCallback_ = cancelCallback;
20
21   /**
22    * Reset is requested but it is pending until the transition of progress bar
23    * is complete.
24    * @type {boolean}
25    * @private
26    */
27   this.resetRequested_ = false;
28
29   /**
30    * Only progress item in the close view.
31    * @type {!HTMLElement}
32    * @private
33    */
34   this.closeViewItem_ = this.closeView_.querySelector('li');
35
36   Object.seal(this);
37
38   // Register event handlers.
39   element.addEventListener('click', this.onClick_.bind(this));
40   element.addEventListener(
41       'webkitTransitionEnd', this.onItemTransitionEnd_.bind(this));
42 };
43
44 /**
45  * Whether to use the new progress center UI or not.
46  * TODO(hirono): Remove the flag after replacing the old butter bar with the new
47  * progress center.
48  * @type {boolean}
49  * @private
50  */
51 ProgressCenterPanel.ENABLED_ = true;
52
53 /**
54  * Updates attributes of the item element.
55  * @param {!HTMLElement} element Element to be updated.
56  * @param {!ProgressCenterItem} item Progress center item.
57  * @private
58  */
59 ProgressCenterPanel.updateItemElement_ = function(element, item) {
60   // Sets element attributes.
61   element.setAttribute('data-progress-id', item.id);
62   element.setAttribute('data-progress-max', item.progressMax);
63   element.setAttribute('data-progress-value', item.progressValue);
64   element.className = '';
65   if (item.state === ProgressItemState.ERROR)
66     element.classList.add('error');
67   if (item.cancelable)
68     element.classList.add('cancelable');
69
70   // If the transition animation is needed, apply it.
71   var previousWidthRate =
72       parseInt(element.querySelector('.progress-track').style.width);
73   if (item.state === ProgressItemState.COMPLETE &&
74       previousWidthRate !== item.progressRateByPercent) {
75     // The attribute pre-complete means that the actual operation is already
76     // done but the UI transition of progress bar is not complete.
77     element.setAttribute('pre-complete', '');
78   } else {
79     element.querySelector('label').textContent = item.message;
80   }
81
82   // To commit the property change and to trigger the transition even if the
83   // change is done synchronously, assign the width value asynchronously.
84   setTimeout(function() {
85     var track = element.querySelector('.progress-track');
86     // When the progress rate is reverted, we does not use the transition
87     // animation. Specifying '0' overrides the CSS settings and specifying null
88     // re-enables it.
89     track.style.transitionDuration =
90         previousWidthRate > item.progressRateByPercent ? '0' : null;
91     track.style.width = item.progressRateByPercent + '%';
92   }, 0);
93 };
94
95 /**
96  * Updates an item to the progress center panel.
97  * @param {!ProgressCenterItem} item Item including new contents.
98  * @param {!ProgressCenterItem} summarizedItem Item to be desplayed in the close
99  *     view.
100  */
101 ProgressCenterPanel.prototype.updateItem = function(item, summarizedItem) {
102   // If reset is requested, force to reset.
103   if (this.resetRequested_)
104     this.reset(true);
105
106   // Update the item.
107   var itemElement = this.getItemElement_(item.id);
108   var removed = false;
109
110   // Check whether the item should be displayed or not by referring its state.
111   switch (item.state) {
112     // Should show the item.
113     case ProgressItemState.PROGRESSING:
114     case ProgressItemState.ERROR:
115       // If the item has not been added yet, create a new element and add it.
116       if (!itemElement) {
117         itemElement = this.createNewItemElement_();
118         this.openView_.insertBefore(itemElement, this.openView_.firstNode);
119       }
120
121       // Update the element by referring the item model.
122       ProgressCenterPanel.updateItemElement_(itemElement, item);
123       this.element_.hidden = false;
124       break;
125
126     // Should not show the item.
127     case ProgressItemState.COMPLETE:
128     case ProgressItemState.CANCELED:
129       // If itemElement is not shown, just break.
130       if (!itemElement)
131         break;
132
133       // If the item is complete state, once update it because it may turn to
134       // have the pre-complete attribute.
135       if (item.state == ProgressItemState.COMPLETE)
136         ProgressCenterPanel.updateItemElement_(itemElement, item);
137
138       // If the item has the pre-complete attribute, keep showing it. Otherwise,
139       // just remove it.
140       if (item.state !== ProgressItemState.COMPLETE ||
141           !itemElement.hasAttribute('pre-complete')) {
142         this.openView_.removeChild(itemElement);
143       }
144       break;
145   }
146
147   // Update close view.
148   this.closeView_.classList.toggle('single', !summarizedItem.summarized);
149   ProgressCenterPanel.updateItemElement_(this.closeViewItem_, summarizedItem);
150 };
151
152 /**
153  * Remove all the items.
154  * @param {boolean=} opt_force True if we force to reset and do not wait the
155  *    transition of progress bar. False otherwise. False is default.
156  */
157 ProgressCenterPanel.prototype.reset = function(opt_force) {
158   if (!opt_force && this.element_.querySelector('[pre-complete]')) {
159     this.resetRequested_ = true;
160     return;
161   }
162
163   // Clear the flag.
164   this.resetRequested_ = false;
165
166   // Clear the all compete item.
167   this.openView_.innerHTML = '';
168
169   // Hide the progress center.
170   this.element_.hidden = true;
171   this.element_.classList.remove('opened');
172 };
173
174 /**
175  * Gets an item element having the specified ID.
176  * @param {string} id progress item ID.
177  * @return {HTMLElement} Item element having the ID.
178  * @private
179  */
180 ProgressCenterPanel.prototype.getItemElement_ = function(id) {
181   var query = 'li[data-progress-id="' + id + '"]';
182   return this.openView_.querySelector(query);
183 };
184
185 /**
186  * Creates an item element.
187  * @return {HTMLElement} Created item element.
188  * @private
189  */
190 ProgressCenterPanel.prototype.createNewItemElement_ = function() {
191   var label = this.element_.ownerDocument.createElement('label');
192   label.className = 'label';
193
194   var progressBarIndicator = this.element_.ownerDocument.createElement('div');
195   progressBarIndicator.className = 'progress-track';
196
197   var progressBar = this.element_.ownerDocument.createElement('div');
198   progressBar.className = 'progress-bar';
199   progressBar.appendChild(progressBarIndicator);
200
201   var cancelButton = this.element_.ownerDocument.createElement('button');
202   cancelButton.className = 'cancel';
203   cancelButton.setAttribute('tabindex', '-1');
204
205   var progressFrame = this.element_.ownerDocument.createElement('div');
206   progressFrame.className = 'progress-frame';
207   progressFrame.appendChild(progressBar);
208   progressFrame.appendChild(cancelButton);
209
210   var itemElement = this.element_.ownerDocument.createElement('li');
211   itemElement.appendChild(label);
212   itemElement.appendChild(progressFrame);
213
214   return itemElement;
215 };
216
217 /**
218  * Handles the transition end event of items.
219  * @param {Event} event Transition end event.
220  * @private
221  */
222 ProgressCenterPanel.prototype.onItemTransitionEnd_ = function(event) {
223   var itemElement = event.target.parentNode.parentNode.parentNode;
224   if (!itemElement.hasAttribute('pre-complete') ||
225       event.propertyName !== 'width')
226     return;
227   if (itemElement !== this.closeViewItem_)
228     this.openView_.removeChild(itemElement);
229   else
230     itemElement.removeAttribute('pre-complete');
231   if (this.resetRequested_)
232     this.reset();
233 };
234
235 /**
236  * Handles the click event.
237  * @param {Event} event Click event.
238  * @private
239  */
240 ProgressCenterPanel.prototype.onClick_ = function(event) {
241   if (event.target.classList.contains('toggle') &&
242       !this.closeView_.classList.contains('single'))
243     this.element_.classList.toggle('opened');
244   else if ((event.target.classList.contains('toggle') &&
245             this.closeView_.classList.contains('single')) ||
246            event.target.classList.contains('cancel'))
247     this.cancelCallback_(
248         event.target.parentNode.parentNode.getAttribute('data-progress-id'));
249 };