Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: chrome/browser/resources/file_manager/js/butter_bar.js

Issue 10826137: Fix CSS and timeout handling for the Files app butter bar (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * The minimum about of time to display the butter bar for, in ms. 6 * The minimum about of time to display the butter bar for, in ms.
7 * Justification is 1000ms for minimum display time plus 300ms for transition 7 * Justification is 1000ms for minimum display time plus 300ms for transition
8 * duration. 8 * duration.
9 */ 9 */
10 var MINIMUM_BUTTER_DISPLAY_TIME_MS = 1300; 10 var MINIMUM_BUTTER_DISPLAY_TIME_MS = 1300;
11 11
12 /** 12 /**
13 * Butter bar is shown on top of the file list and is used to show the copy 13 * Butter bar is shown on top of the file list and is used to show the copy
14 * progress and other messages. 14 * progress and other messages.
15 * @constructor 15 * @constructor
16 * @param {HTMLElement} dialogDom FileManager top-level div. 16 * @param {HTMLElement} dialogDom FileManager top-level div.
17 * @param {FileCopyManagerWrapper} copyManager The copy manager. 17 * @param {FileCopyManagerWrapper} copyManager The copy manager.
18 */ 18 */
19 function ButterBar(dialogDom, copyManager) { 19 function ButterBar(dialogDom, copyManager) {
20 this.dialogDom_ = dialogDom; 20 this.dialogDom_ = dialogDom;
21 this.butter_ = this.dialogDom_.querySelector('#butter-bar'); 21 this.butter_ = this.dialogDom_.querySelector('#butter-bar');
22 this.document_ = this.butter_.ownerDocument; 22 this.document_ = this.butter_.ownerDocument;
23 this.copyManager_ = copyManager; 23 this.copyManager_ = copyManager;
24 this.hideTimeout_ = null; 24 this.hideTimeout_ = null;
25 this.showTimeout_ = null; 25 this.showTimeout_ = null;
26 this.visible_ = false;
27 this.lastShowTime_ = 0; 26 this.lastShowTime_ = 0;
28 this.isError_ = false;
29 27
30 this.copyManager_.addEventListener('copy-progress', 28 this.copyManager_.addEventListener('copy-progress',
31 this.onCopyProgress_.bind(this)); 29 this.onCopyProgress_.bind(this));
32 } 30 }
33 31
34 /** 32 /**
33 * @return {boolean} True if visible.
34 * @private
35 */
36 ButterBar.prototype.isVisible_ = function() {
37 return this.butter_.classList.contains('visible');
38 };
39
40 /**
41 * @return {boolean} True if displaying an error.
42 * @private
43 */
44 ButterBar.prototype.isError_ = function() {
45 return this.butter_.classList.contains('error');
46 };
47
48 /**
35 * Show butter bar. 49 * Show butter bar.
36 * @param {string} message The message to be shown. 50 * @param {string} message The message to be shown.
37 * @param {object} opt_options Options: 'actions', 'progress', 'timeout'. 51 * @param {object} opt_options Options: 'actions', 'progress', 'timeout'.
38 */ 52 */
39 ButterBar.prototype.show = function(message, opt_options) { 53 ButterBar.prototype.show = function(message, opt_options) {
40 if (opt_options) { 54 if (this.hideTimeout_) {
Oleg Eterevsky 2012/08/03 07:36:13 These 4 lines appear at least 3 times. Maybe extra
Vladislav Kaznacheev 2012/08/03 08:20:04 Done.
41 if ('actions' in opt_options) { 55 clearTimeout(this.hideTimeout_);
42 var actions = this.butter_.querySelector('.actions'); 56 this.hideTimeout_ = null;
43 while (actions.childNodes.length) 57 }
44 actions.removeChild(actions.firstChild); 58 if (this.showTimeout_) {
45 for (var label in opt_options.actions) { 59 clearTimeout(this.showTimeout_);
46 var link = this.document_.createElement('a'); 60 this.showTimeout_ = null;
47 link.addEventListener('click', function() {
48 opt_options.actions[label]();
49 return false;
50 });
51 actions.appendChild(link);
52 }
53 actions.classList.remove('hide-in-butter');
54 }
55 if ('progress' in opt_options) {
56 this.butter_.querySelector('.progress-bar').classList.remove(
57 'hide-in-butter');
58 }
59 } 61 }
60 62
61 this.visible_ = true; 63 var actions = this.butter_.querySelector('.actions');
62 this.isError_ = false; 64 actions.textContent = '';
65 if (opt_options && 'actions' in opt_options) {
66 for (var label in opt_options.actions) {
67 var link = this.document_.createElement('a');
68 link.addEventListener('click', function(callback) {
Oleg Eterevsky 2012/08/03 07:36:13 Why did you change the way this function is writte
Vladislav Kaznacheev 2012/08/03 08:20:04 A closure inside a loop is bound to the last value
69 callback();
70 return false;
71 }.bind(null, opt_options.actions[label]));
72 actions.appendChild(link);
73 }
74 actions.hidden = false;
75 } else
76 actions.hidden = true;
Oleg Eterevsky 2012/08/03 07:36:13 Could you please add braces here? Otherwise it loo
Vladislav Kaznacheev 2012/08/03 08:20:04 Done.
77
78 this.butter_.querySelector('.progress-bar').hidden =
79 !(opt_options && 'progress' in opt_options);
80
81 this.butter_.classList.remove('error');
82 this.butter_.classList.remove('visible'); // Will be shown in update_
63 this.update_(message, opt_options); 83 this.update_(message, opt_options);
64 this.lastShowTime_ = Date.now();
65 }; 84 };
66 85
67 /** 86 /**
68 * Show error message in butter bar. 87 * Show error message in butter bar.
69 * @private 88 * @private
70 * @param {string} message Message. 89 * @param {string} message Message.
71 * @param {object} opt_options Same as in show(). 90 * @param {object} opt_options Same as in show().
72 */ 91 */
73 ButterBar.prototype.showError_ = function(message, opt_options) { 92 ButterBar.prototype.showError_ = function(message, opt_options) {
74 this.show(message, opt_options); 93 this.show(message, opt_options);
75 this.isError_ = true;
76 this.butter_.classList.add('error'); 94 this.butter_.classList.add('error');
77 }; 95 };
78 96
79 /** 97 /**
80 * Set message and/or progress. 98 * Set message and/or progress.
81 * @private 99 * @private
82 * @param {string} message Message. 100 * @param {string} message Message.
83 * @param {object} opt_options Same as in show(). 101 * @param {object} opt_options Same as in show().
84 */ 102 */
85 ButterBar.prototype.update_ = function(message, opt_options) { 103 ButterBar.prototype.update_ = function(message, opt_options) {
86 if (!opt_options) 104 if (!opt_options)
87 opt_options = {}; 105 opt_options = {};
88 106
89 var timeout = ('timeout' in opt_options) ? opt_options.timeout : 10 * 1000; 107 var timeout = ('timeout' in opt_options) ? opt_options.timeout : 10 * 1000;
Oleg Eterevsky 2012/08/03 07:36:13 Could you please swap this line and the next if, s
Vladislav Kaznacheev 2012/08/03 08:20:04 Done.
90 108
91 if (this.hideTimeout_) 109 if (this.hideTimeout_) {
92 clearTimeout(this.hideTimeout_); 110 clearTimeout(this.hideTimeout_);
111 this.hideTimeout_ = null;
112 }
93 113
94 if (timeout) { 114 if (timeout) {
95 this.hideTimeout_ = setTimeout(function() { 115 this.hideTimeout_ = setTimeout(function() {
96 this.hideButter(); 116 this.hideTimeout_ = null;
97 this.hideTimeout_ = null; 117 this.hide_();
Oleg Eterevsky 2012/08/03 07:36:13 I missed this while refactoring. Thanks!
98 }.bind(this), timeout); 118 }.bind(this), timeout);
99 } 119 }
100 120
101 this.butter_.querySelector('.butter-message').textContent = message; 121 this.butter_.querySelector('.butter-message').textContent = message;
102 if (message) { 122 if (message && !this.isVisible_()) {
103 // The butter bar is made visible on the first non-empty message. 123 // The butter bar is made visible on the first non-empty message.
104 this.butter_.classList.remove('before-show'); 124 this.butter_.classList.add('visible');
125 this.lastShowTime_ = Date.now();
105 } 126 }
106 if (opt_options && 'progress' in opt_options) { 127 if (opt_options && 'progress' in opt_options) {
107 this.butter_.querySelector('.progress-track').style.width = 128 this.butter_.querySelector('.progress-track').style.width =
108 (opt_options.progress * 100) + '%'; 129 (opt_options.progress * 100) + '%';
109 } 130 }
110 131
111 this.butter_.style.left = 132 this.butter_.style.left =
112 (this.dialogDom_.clientWidth - this.butter_.clientWidth) / 2 + 'px'; 133 (this.dialogDom_.clientWidth - this.butter_.clientWidth) / 2 + 'px';
113 }; 134 };
114 135
115 /** 136 /**
116 * Hide butter bar. There might be some delay before hiding so that butter bar 137 * Hide butter bar. There might be some delay before hiding so that butter bar
117 * would be shown for no less than the minimal time. 138 * would be shown for no less than the minimal time.
139 * @param {boolean} opt_force If true hide immediately.
118 * @private 140 * @private
119 */ 141 */
120 ButterBar.prototype.hide_ = function() { 142 ButterBar.prototype.hide_ = function(opt_force) {
121 if (this.visible_) { 143 if (this.hideTimeout_) {
122 var delay = Math.max( 144 clearTimeout(this.hideTimeout_);
123 MINIMUM_BUTTER_DISPLAY_TIME_MS - (Date.now() - this.lastShowTime_), 0); 145 this.hideTimeout_ = null;
146 }
124 147
125 var butter = this.butter_; 148 if (!this.isVisible_())
149 return;
126 150
127 function hideButter() { 151 var delay =
128 butter.classList.remove('error'); 152 MINIMUM_BUTTER_DISPLAY_TIME_MS - (Date.now() - this.lastShowTime_);
129 butter.classList.remove('after-show');
130 butter.classList.add('before-show');
131 butter.querySelector('.actions').classList.add('hide-in-butter');
132 butter.querySelector('.progress-bar').classList.add('hide-in-butter');
133 }
134 153
135 setTimeout(function() { butter.classList.add('after-show'); }, delay); 154 if (opt_force || delay <= 0) {
136 setTimeout(hideButter, delay + 1000); 155 this.butter_.classList.remove('visible');
137 this.visible_ = false; 156 } else {
157 // Reschedule hide to comply with the minimal display time.
158 this.hideTimeout_ = setTimeout(function() {
159 this.hideTimeout_ = null;
160 this.hide_(true);
161 }.bind(this), delay);
138 } 162 }
139 }; 163 };
140 164
141 /** 165 /**
142 * If butter bar shows an error message, close it. 166 * If butter bar shows an error message, close it.
143 * @return {boolean} True if butter bar was closed. 167 * @return {boolean} True if butter bar was closed.
144 */ 168 */
145 ButterBar.prototype.hideError = function() { 169 ButterBar.prototype.hideError = function() {
146 if (this.visible_ && this.isError_) { 170 if (this.isVisible_() && this.isError_()) {
147 this.hide_(); 171 this.hide_(true /* force */);
148 clearTimeout(this.hideTimeout_);
149 return true; 172 return true;
150 } else { 173 } else {
151 return false; 174 return false;
152 } 175 }
153 }; 176 };
154 177
155 /** 178 /**
156 * Init butter bar for showing copy progress. 179 * Set up butter bar for showing copy progress.
157 * @private 180 * @private
158 */ 181 */
159 ButterBar.prototype.init_ = function() { 182 ButterBar.prototype.showProgress_ = function() {
160 var progress = this.copyManager_.getProgress(); 183 var progress = this.copyManager_.getProgress();
161 var options = {progress: progress.percentage, actions: {}, timeout: 0}; 184 var options = {progress: progress.percentage, actions: {}, timeout: 0};
162 options.actions[str('CANCEL_LABEL')] = 185 options.actions[str('CANCEL_LABEL')] =
163 this.copyManager_.requestCancel.bind(this.copyManager_); 186 this.copyManager_.requestCancel.bind(this.copyManager_);
164 this.show(strf('PASTE_ITEMS_REMAINING', progress.pendingItems), options); 187 this.show(strf('PASTE_ITEMS_REMAINING', progress.pendingItems), options);
165 }; 188 };
166 189
167 /** 190 /**
168 * 'copy-progress' event handler. Show progress or an appropriate message. 191 * 'copy-progress' event handler. Show progress or an appropriate message.
169 * @private 192 * @private
170 * @param {cr.Event} event A 'copy-progress' event from FileCopyManager. 193 * @param {cr.Event} event A 'copy-progress' event from FileCopyManager.
171 */ 194 */
172 ButterBar.prototype.onCopyProgress_ = function(event) { 195 ButterBar.prototype.onCopyProgress_ = function(event) {
173 var progress = this.copyManager_.getProgress(); 196 var progress = this.copyManager_.getProgress();
174 197
198 if (this.showTimeout_ && event.reason != 'PROGRESS') {
199 clearTimeout(this.showTimeout_);
200 this.showTimeout_ = null;
201 }
202
175 switch (event.reason) { 203 switch (event.reason) {
176 case 'BEGIN': 204 case 'BEGIN':
177 this.hide_(); 205 this.showTimeout_ = setTimeout(function() {
178 clearTimeout(this.timeout_); 206 this.showTimeout_ = null;
179 // If the copy process lasts more than 500 ms, we show a progress bar. 207 this.showProgress_();
180 this.showTimeout_ = setTimeout(this.init_.bind(this), 500); 208 }.bind(this), 500);
181 break; 209 break;
182 210
183 case 'PROGRESS': 211 case 'PROGRESS':
184 if (this.visible_) { 212 if (this.isVisible_()) {
185 var options = {'progress': progress.percentage, timeout: 0}; 213 var options = {'progress': progress.percentage, timeout: 0};
186 this.update_(strf('PASTE_ITEMS_REMAINING', progress.pendingItems), 214 this.update_(strf('PASTE_ITEMS_REMAINING', progress.pendingItems),
187 options); 215 options);
188 } 216 }
189 break; 217 break;
190 218
191 case 'SUCCESS': 219 case 'SUCCESS':
192 clearTimeout(this.showTimeout_);
193 this.hide_(); 220 this.hide_();
194 break; 221 break;
195 222
196 case 'CANCELLED': 223 case 'CANCELLED':
197 this.show(str('PASTE_CANCELLED'), {timeout: 1000}); 224 this.show(str('PASTE_CANCELLED'), {timeout: 1000});
198 break; 225 break;
199 226
200 case 'ERROR': 227 case 'ERROR':
201 clearTimeout(this.showTimeout_);
202 if (event.error.reason === 'TARGET_EXISTS') { 228 if (event.error.reason === 'TARGET_EXISTS') {
203 var name = event.error.data.name; 229 var name = event.error.data.name;
204 if (event.error.data.isDirectory) 230 if (event.error.data.isDirectory)
205 name += '/'; 231 name += '/';
206 this.showError_(strf('PASTE_TARGET_EXISTS_ERROR', name)); 232 this.showError_(strf('PASTE_TARGET_EXISTS_ERROR', name));
207 } else if (event.error.reason === 'FILESYSTEM_ERROR') { 233 } else if (event.error.reason === 'FILESYSTEM_ERROR') {
208 if (event.error.data.toGDrive && 234 if (event.error.data.toGDrive &&
209 event.error.data.code === FileError.QUOTA_EXCEEDED_ERR) { 235 event.error.data.code === FileError.QUOTA_EXCEEDED_ERR) {
210 // The alert will be shown in FileManager.onCopyProgress_. 236 // The alert will be shown in FileManager.onCopyProgress_.
211 this.hide_(); 237 this.hide_();
212 } else { 238 } else {
213 this.showError_(strf('PASTE_FILESYSTEM_ERROR', 239 this.showError_(strf('PASTE_FILESYSTEM_ERROR',
214 getFileErrorString(event.error.data.code))); 240 getFileErrorString(event.error.data.code)));
215 } 241 }
216 } else { 242 } else {
217 this.showError_(strf('PASTE_UNEXPECTED_ERROR', event.error)); 243 this.showError_(strf('PASTE_UNEXPECTED_ERROR', event.error));
218 } 244 }
219 break; 245 break;
220 246
221 default: 247 default:
222 console.log('Unknown "copy-progress" event reason: ' + event.reason); 248 console.log('Unknown "copy-progress" event reason: ' + event.reason);
223 } 249 }
224 }; 250 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/css/file_manager.css ('k') | chrome/browser/resources/file_manager/main.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698