OLD | NEW |
---|---|
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 // TODO(jhawkins): Use hidden instead of showInline* and display:none. | 5 // TODO(jhawkins): Use hidden instead of showInline* and display:none. |
6 // TODO(hcarmona): This file is big: it may be good to split it up. | |
6 | 7 |
7 /** | 8 /** |
8 * The type of the download object. The definition is based on | 9 * The type of the download object. The definition is based on |
9 * chrome/browser/ui/webui/downloads_dom_handler.cc:CreateDownloadItemValue() | 10 * chrome/browser/ui/webui/downloads_dom_handler.cc:CreateDownloadItemValue() |
10 * @typedef {{by_ext_id: (string|undefined), | 11 * @typedef {{by_ext_id: (string|undefined), |
11 * by_ext_name: (string|undefined), | 12 * by_ext_name: (string|undefined), |
12 * danger_type: (string|undefined), | 13 * danger_type: (string|undefined), |
13 * date_string: string, | 14 * date_string: string, |
14 * file_externally_removed: boolean, | 15 * file_externally_removed: boolean, |
15 * file_name: string, | 16 * file_name: string, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 */ | 71 */ |
71 function createButton(onclick, value) { | 72 function createButton(onclick, value) { |
72 var button = document.createElement('input'); | 73 var button = document.createElement('input'); |
73 button.type = 'button'; | 74 button.type = 'button'; |
74 button.value = value; | 75 button.value = value; |
75 button.onclick = onclick; | 76 button.onclick = onclick; |
76 return button; | 77 return button; |
77 } | 78 } |
78 | 79 |
79 /////////////////////////////////////////////////////////////////////////////// | 80 /////////////////////////////////////////////////////////////////////////////// |
81 // DownloadFocusRow: | |
82 | |
83 /** | |
84 * Provides an implementation for a single column grid. | |
85 * @constructor | |
86 * @extends {cr.ui.FocusRow} | |
87 */ | |
88 DownloadFocusRow = function() {}; | |
Dan Beam
2015/01/27 22:32:23
function DownloadFocusRow() {}
is the more typica
hcarmona
2015/01/29 00:00:37
Done.
| |
89 | |
90 /** | |
91 * Decorates |focusRow| so that it can be treated as a DownloadFocusRow. | |
92 * @param {Element} focusRow The element that has all the columns represented | |
93 * by |download|. | |
94 * @param {Download} download The Download representing this row. | |
95 * @param {Node} boundary Focus events are ignored outside of this node. | |
96 */ | |
97 DownloadFocusRow.decorate = function(focusRow, download, boundary) { | |
98 focusRow.__proto__ = DownloadFocusRow.prototype; | |
99 focusRow.decorate(boundary); | |
100 | |
101 // Add all clickable elements as a row into the grid. | |
102 focusRow.addFocusRow_(download.nodeFileLink_, 'name'); | |
103 focusRow.addFocusRow_(download.nodeURL_, 'url'); | |
104 focusRow.addFocusRow_(download.controlShow_, 'show'); | |
105 focusRow.addFocusRow_(download.controlRetry_, 'retry'); | |
106 focusRow.addFocusRow_(download.controlPause_, 'pause'); | |
107 focusRow.addFocusRow_(download.controlResume_, 'resume'); | |
108 focusRow.addFocusRow_(download.controlRemove_, 'remove'); | |
109 focusRow.addFocusRow_(download.controlCancel_, 'cancel'); | |
110 | |
111 // Only one set of these two buttons will be added to a download row at a | |
112 // time. They have the same type so that focus is handled well in case | |
113 // there is a dangerous download right next to a malicious download. | |
114 focusRow.addFocusRow_(download.malwareSave_, 'save'); | |
115 focusRow.addFocusRow_(download.malwareDiscard_, 'discard'); | |
116 focusRow.addFocusRow_(download.dangerSave_, 'save'); | |
117 focusRow.addFocusRow_(download.dangerDiscard_, 'discard'); | |
118 | |
119 focusRow.addFocusRow_(download.controlByExtensionLink_, 'extension'); | |
120 }; | |
121 | |
122 DownloadFocusRow.prototype = { | |
123 __proto__: cr.ui.FocusRow.prototype, | |
124 | |
125 /** @override */ | |
126 getEquivalentElement: function(element) { | |
127 if (this.contains(element)) | |
128 return element; | |
129 | |
130 // All elements default to another element with the same type. | |
Dan Beam
2015/01/27 22:32:23
nit: arguably
var columnType = element.getAttribu
hcarmona
2015/01/29 00:00:37
Done.
| |
131 var query = '[column-type=' + element.getAttribute('column-type') + ']'; | |
132 var ret = this.querySelector(query); | |
Dan Beam
2015/01/27 22:32:23
nit: ret -> el, element, equiv, equivalent (all se
hcarmona
2015/01/29 00:00:37
Done.
| |
133 | |
134 if (!ret) { | |
135 // The following element types are at the same UI level. | |
136 var grayLinks = ['show', 'retry', 'pause', 'resume', 'remove', 'cancel']; | |
Dan Beam
2015/01/27 22:32:23
nit: grayLinks -> equivalents (or rename so this i
hcarmona
2015/01/29 00:00:37
Done.
| |
137 if (grayLinks.indexOf(element.getAttribute('column-type')) != -1) { | |
138 ret = this.querySelector( | |
139 '[column-type=show], [column-type=retry], ' + | |
140 '[column-type=pause], [column-type=resume], ' + | |
141 '[column-type=remove], [column-type=cancel]'); | |
Dan Beam
2015/01/27 22:32:23
why are we duplicating this list of types?
hcarmona
2015/01/29 00:00:37
Done. Not duplicated anymore.
| |
142 } | |
143 } | |
144 | |
145 // Any other miss should return the first focusable element. | |
Dan Beam
2015/01/27 22:32:23
nit: // Return the first focusable element if no e
hcarmona
2015/01/29 00:00:37
Done.
| |
146 return ret || this.focusableElements[0]; | |
147 }, | |
148 | |
149 /** | |
150 * Add an element if it exists in this FocusRow and is focusable. | |
151 * @param {Element} element The element that should be added. | |
152 * @param {string} type The type to use for the element. | |
Dan Beam
2015/01/27 22:32:23
can we make these doc strings more useful or remov
hcarmona
2015/01/29 00:00:37
Done.
| |
153 * @private | |
154 */ | |
155 addFocusRow_: function(element, type) { | |
156 if (this.shouldFocus_(element)) { | |
157 this.addFocusableElement(element); | |
158 element.setAttribute('column-type', type); | |
159 } | |
160 }, | |
161 | |
162 /** | |
163 * Determines if element should be focusable. | |
164 * @param {!Element} element | |
165 * @return {boolean} | |
166 * @private | |
167 */ | |
168 shouldFocus_: function(element) { | |
169 if (!element) | |
170 return false; | |
171 | |
172 // Hidden elements are not focusable. | |
173 var style = window.getComputedStyle(element); | |
174 if (style.visibility == 'hidden' || style.display == 'none') | |
Dan Beam
2015/01/27 22:32:23
here's the full amount of checks that blink does,
hcarmona
2015/01/29 00:00:37
This check is sufficient for the downloads page. D
| |
175 return false; | |
176 | |
177 // Verify that all ancestors are focusable. This is necessary because of the | |
178 // case where a node has display set to something other than 'none', but it | |
179 // has an ancestor with display == 'none'. | |
180 if (element.parentElement) | |
181 return this.shouldFocus_(element.parentElement); | |
182 | |
183 return true; | |
Dan Beam
2015/01/27 22:32:23
nit:
// Verify all ancestors are focusable.
r
hcarmona
2015/01/29 00:00:37
Done.
| |
184 }, | |
185 }; | |
186 | |
187 /////////////////////////////////////////////////////////////////////////////// | |
80 // Downloads | 188 // Downloads |
81 /** | 189 /** |
82 * Class to hold all the information about the visible downloads. | 190 * Class to hold all the information about the visible downloads. |
83 * @constructor | 191 * @constructor |
84 */ | 192 */ |
85 function Downloads() { | 193 function Downloads() { |
86 /** | 194 /** |
87 * @type {!Object.<string, Download>} | 195 * @type {!Object.<string, Download>} |
88 * @private | 196 * @private |
89 */ | 197 */ |
90 this.downloads_ = {}; | 198 this.downloads_ = {}; |
91 this.node_ = $('downloads-display'); | 199 this.node_ = $('downloads-display'); |
92 this.summary_ = $('downloads-summary-text'); | 200 this.summary_ = $('downloads-summary-text'); |
93 this.searchText_ = ''; | 201 this.searchText_ = ''; |
202 this.focusGrid_ = new cr.ui.FocusGrid(); | |
94 | 203 |
95 // Keep track of the dates of the newest and oldest downloads so that we | 204 // Keep track of the dates of the newest and oldest downloads so that we |
96 // know where to insert them. | 205 // know where to insert them. |
97 this.newestTime_ = -1; | 206 this.newestTime_ = -1; |
98 | 207 |
99 // Icon load request queue. | 208 // Icon load request queue. |
100 this.iconLoadQueue_ = []; | 209 this.iconLoadQueue_ = []; |
101 this.isIconLoading_ = false; | 210 this.isIconLoading_ = false; |
102 | 211 |
103 this.progressForeground1_ = new Image(); | 212 this.progressForeground1_ = new Image(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 var noDownloadsOrResults = $('no-downloads-or-results'); | 278 var noDownloadsOrResults = $('no-downloads-or-results'); |
170 noDownloadsOrResults.textContent = loadTimeData.getString( | 279 noDownloadsOrResults.textContent = loadTimeData.getString( |
171 this.searchText_ ? 'no_search_results' : 'no_downloads'); | 280 this.searchText_ ? 'no_search_results' : 'no_downloads'); |
172 | 281 |
173 var hasDownloads = this.size() > 0; | 282 var hasDownloads = this.size() > 0; |
174 this.node_.hidden = !hasDownloads; | 283 this.node_.hidden = !hasDownloads; |
175 noDownloadsOrResults.hidden = hasDownloads; | 284 noDownloadsOrResults.hidden = hasDownloads; |
176 | 285 |
177 if (loadTimeData.getBoolean('allow_deleting_history')) | 286 if (loadTimeData.getBoolean('allow_deleting_history')) |
178 $('clear-all').hidden = !hasDownloads || this.searchText_.length > 0; | 287 $('clear-all').hidden = !hasDownloads || this.searchText_.length > 0; |
288 | |
289 this.rebuildFocusGrid_(); | |
179 }; | 290 }; |
180 | 291 |
181 /** | 292 /** |
293 * Rebuild the focusGrid_ using the elements that each download will have. | |
294 * @private | |
295 */ | |
296 Downloads.prototype.rebuildFocusGrid_ = function() { | |
297 this.focusGrid_.destroy(); | |
298 | |
299 // Keys for downloads are in the reverse order of what is displayed. | |
300 var keys = Object.keys(this.downloads_); | |
Dan Beam
2015/01/27 22:32:23
I'm not sure that the order of keys returned from
hcarmona
2015/01/29 00:00:37
The order does matter. Updated code so that it is
| |
301 for (var i = keys.length - 1; i >= 0; --i) { | |
302 var download = this.downloads_[keys[i]]; | |
303 DownloadFocusRow.decorate(download.node, download, this.node_); | |
Dan Beam
2015/01/27 22:32:23
are all the rows always blasted away and rebuilt?
hcarmona
2015/01/29 00:00:37
Changed so that rows are only decorated once.
| |
304 this.focusGrid_.addRow(download.node); | |
305 } | |
306 }; | |
307 | |
308 /** | |
182 * Returns the number of downloads in the model. Used by tests. | 309 * Returns the number of downloads in the model. Used by tests. |
183 * @return {number} Returns the number of downloads shown on the page. | 310 * @return {number} Returns the number of downloads shown on the page. |
184 */ | 311 */ |
185 Downloads.prototype.size = function() { | 312 Downloads.prototype.size = function() { |
186 return Object.keys(this.downloads_).length; | 313 return Object.keys(this.downloads_).length; |
187 }; | 314 }; |
188 | 315 |
189 /** | 316 /** |
190 * Called whenever the downloads lists items have changed (either by being | 317 * Called whenever the downloads lists items have changed (either by being |
191 * updated, added, or removed). | 318 * updated, added, or removed). |
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 if (Date.now() - start > 50) { | 1105 if (Date.now() - start > 50) { |
979 clearTimeout(resultsTimeout); | 1106 clearTimeout(resultsTimeout); |
980 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); | 1107 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); |
981 break; | 1108 break; |
982 } | 1109 } |
983 } | 1110 } |
984 } | 1111 } |
985 | 1112 |
986 // Add handlers to HTML elements. | 1113 // Add handlers to HTML elements. |
987 window.addEventListener('DOMContentLoaded', load); | 1114 window.addEventListener('DOMContentLoaded', load); |
OLD | NEW |