OLD | NEW |
| (Empty) |
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 * Only progress item in the close view. | |
23 * @type {!HTMLElement} | |
24 * @private | |
25 */ | |
26 this.closeViewItem_ = this.closeView_.querySelector('li'); | |
27 | |
28 Object.freeze(this); | |
29 | |
30 // Register event handlers. | |
31 element.addEventListener('click', this.onClick_.bind(this)); | |
32 element.addEventListener( | |
33 'webkitTransitionEnd', this.onItemTransitionEnd_.bind(this)); | |
34 }; | |
35 | |
36 /** | |
37 * Whether to use the new progress center UI or not. | |
38 * TODO(hirono): Remove the flag after replacing the old butter bar with the new | |
39 * progress center. | |
40 * @type {boolean} | |
41 * @private | |
42 */ | |
43 ProgressCenterPanel.ENABLED_ = true; | |
44 | |
45 /** | |
46 * Update item element. | |
47 * @param {HTMLElement} element Element to be updated. | |
48 * @param {ProgressCenterItem} item Progress center item. | |
49 * @private | |
50 */ | |
51 ProgressCenterPanel.updateItemElement_ = function(element, item) { | |
52 var additionalClass = item.state === ProgressItemState.COMPLETE ? 'complete' : | |
53 item.state === ProgressItemState.ERROR ? 'error' : | |
54 item.state === ProgressItemState.CANCELED ? 'canceled' : | |
55 ''; | |
56 if (item.cancelable) | |
57 additionalClass += ' cancelable'; | |
58 var previousWidthRate = | |
59 parseInt(element.querySelector('.progress-track').style.width); | |
60 if (item.state === ProgressItemState.COMPLETE && | |
61 previousWidthRate === item.progressRateByPercent) { | |
62 // Stop to update the message until the transition ends. | |
63 element.setAttribute('data-complete-message', item.message); | |
64 // The class pre-complete means that the actual operation is already done | |
65 // but the UI transition of progress bar is not complete. | |
66 additionalClass = 'pre-complete'; | |
67 } else { | |
68 element.querySelector('label').textContent = item.message; | |
69 element.removeAttribute('data-complete-message'); | |
70 } | |
71 // To commit the property change and to trigger the transition even if the | |
72 // change is done synchronously, assign the width value asynchronously. | |
73 setTimeout(function() { | |
74 var track = element.querySelector('.progress-track'); | |
75 // When the progress rate is reverted, we does not use the transition | |
76 // animation. Specifying '0' overrides the CSS settings and specifying null | |
77 // re-enables it. | |
78 track.style.transitionDuration = | |
79 previousWidthRate > item.progressRateByPercent ? '0' : null; | |
80 track.style.width = item.progressRateByPercent + '%'; | |
81 }, 0); | |
82 element.setAttribute('data-progress-id', item.id); | |
83 element.setAttribute('data-progress-max', item.progressMax); | |
84 element.setAttribute('data-progress-value', item.progressValue); | |
85 element.className = additionalClass; | |
86 }; | |
87 | |
88 /** | |
89 * Updates an item to the progress center panel. | |
90 * @param {ProgressCenterItem} item Item including new contents. | |
91 * @param {ProgressCenterItem} summarizedItem Item to be desplayed in the close | |
92 * view. | |
93 */ | |
94 ProgressCenterPanel.prototype.updateItem = function(item, summarizedItem) { | |
95 var itemElement = this.getItemElement_(item.id); | |
96 if (!itemElement) { | |
97 itemElement = this.createNewItemElement_(); | |
98 this.openView_.insertBefore(itemElement, this.openView_.firstNode); | |
99 } | |
100 ProgressCenterPanel.updateItemElement_(itemElement, item); | |
101 | |
102 // Update close view. | |
103 this.closeView_.classList.toggle('single', !summarizedItem.summarized); | |
104 ProgressCenterPanel.updateItemElement_(this.closeViewItem_, summarizedItem); | |
105 | |
106 if (ProgressCenterPanel.ENABLED_) | |
107 this.element_.hidden = false; | |
108 }; | |
109 | |
110 /** | |
111 * Remove all the items. | |
112 */ | |
113 ProgressCenterPanel.prototype.reset = function() { | |
114 // Clear the all compete item. | |
115 this.openView_.innerHTML = ''; | |
116 | |
117 // Hide the progress center. | |
118 this.element_.hidden = true; | |
119 this.element_.classList.remove('opened'); | |
120 }; | |
121 | |
122 /** | |
123 * Gets an item element having the specified ID. | |
124 * @param {string} id progress item ID. | |
125 * @return {HTMLElement} Item element having the ID. | |
126 * @private | |
127 */ | |
128 ProgressCenterPanel.prototype.getItemElement_ = function(id) { | |
129 var query = 'li[data-progress-id="' + id + '"]'; | |
130 return this.openView_.querySelector(query); | |
131 }; | |
132 | |
133 /** | |
134 * Creates an item element. | |
135 * @return {HTMLElement} Created item element. | |
136 * @private | |
137 */ | |
138 ProgressCenterPanel.prototype.createNewItemElement_ = function() { | |
139 var label = this.element_.ownerDocument.createElement('label'); | |
140 label.className = 'label'; | |
141 | |
142 var progressBarIndicator = this.element_.ownerDocument.createElement('div'); | |
143 progressBarIndicator.className = 'progress-track'; | |
144 | |
145 var progressBar = this.element_.ownerDocument.createElement('div'); | |
146 progressBar.className = 'progress-bar'; | |
147 progressBar.appendChild(progressBarIndicator); | |
148 | |
149 var cancelButton = this.element_.ownerDocument.createElement('button'); | |
150 cancelButton.className = 'cancel'; | |
151 cancelButton.setAttribute('tabindex', '-1'); | |
152 | |
153 var progressFrame = this.element_.ownerDocument.createElement('div'); | |
154 progressFrame.className = 'progress-frame'; | |
155 progressFrame.appendChild(progressBar); | |
156 progressFrame.appendChild(cancelButton); | |
157 | |
158 var itemElement = this.element_.ownerDocument.createElement('li'); | |
159 itemElement.appendChild(label); | |
160 itemElement.appendChild(progressFrame); | |
161 | |
162 return itemElement; | |
163 }; | |
164 | |
165 /** | |
166 * Handles the transition end event of items. | |
167 * @param {Event} event Transition end event. | |
168 * @private | |
169 */ | |
170 ProgressCenterPanel.prototype.onItemTransitionEnd_ = function(event) { | |
171 var itemElement = event.target.parentNode.parentNode.parentNode; | |
172 if (itemElement.className !== 'pre-complete' || | |
173 event.propertyName !== 'width') | |
174 return; | |
175 var completeMessage = itemElement.getAttribute('data-complete-message'); | |
176 if (!completeMessage) | |
177 return; | |
178 itemElement.className = 'complete'; | |
179 itemElement.querySelector('label').textContent = completeMessage; | |
180 }; | |
181 | |
182 /** | |
183 * Handles the click event. | |
184 * @param {Event} event Click event. | |
185 * @private | |
186 */ | |
187 ProgressCenterPanel.prototype.onClick_ = function(event) { | |
188 if (event.target.classList.contains('toggle') && | |
189 !this.closeView_.classList.contains('single')) | |
190 this.element_.classList.toggle('opened'); | |
191 else if ((event.target.classList.contains('toggle') && | |
192 this.closeView_.classList.contains('single')) || | |
193 event.target.classList.contains('cancel')) | |
194 this.cancelCallback_( | |
195 event.target.parentNode.parentNode.getAttribute('data-progress-id')); | |
196 }; | |
OLD | NEW |