Chromium Code Reviews| 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 function DownloadFocusRow() {} | |
| 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.addElementIfFocusable_(download.nodeFileLink_, 'name'); | |
| 103 focusRow.addElementIfFocusable_(download.nodeURL_, 'url'); | |
| 104 focusRow.addElementIfFocusable_(download.controlShow_, 'show'); | |
| 105 focusRow.addElementIfFocusable_(download.controlRetry_, 'retry'); | |
| 106 focusRow.addElementIfFocusable_(download.controlPause_, 'pause'); | |
| 107 focusRow.addElementIfFocusable_(download.controlResume_, 'resume'); | |
| 108 focusRow.addElementIfFocusable_(download.controlRemove_, 'remove'); | |
| 109 focusRow.addElementIfFocusable_(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.addElementIfFocusable_(download.malwareSave_, 'save'); | |
| 115 focusRow.addElementIfFocusable_(download.malwareDiscard_, 'discard'); | |
| 116 focusRow.addElementIfFocusable_(download.dangerSave_, 'save'); | |
| 117 focusRow.addElementIfFocusable_(download.dangerDiscard_, 'discard'); | |
| 118 | |
| 119 focusRow.addElementIfFocusable_(download.controlByExtensionLink_, | |
| 120 'extension'); | |
| 121 }; | |
| 122 | |
| 123 DownloadFocusRow.prototype = { | |
| 124 __proto__: cr.ui.FocusRow.prototype, | |
| 125 | |
| 126 /** @override */ | |
| 127 getEquivalentElement: function(element) { | |
| 128 if (this.contains(element)) | |
| 129 return element; | |
| 130 | |
| 131 // All elements default to another element with the same type. | |
| 132 var columnType = element.getAttribute('column-type'); | |
| 133 var equivalent = this.querySelector('[column-type=' + columnType + ']'); | |
| 134 | |
| 135 if (!equivalent) { | |
| 136 // The following element types are equivalent. | |
|
Dan Beam
2015/01/29 18:46:46
this comment doesn't seem useful now
hcarmona
2015/01/31 02:45:49
Done.
| |
| 137 var equivalentTypes = | |
| 138 ['show', 'retry', 'pause', 'resume', 'remove', 'cancel']; | |
| 139 if (equivalentTypes.indexOf(columnType) != -1) { | |
| 140 var query = equivalentTypes.map(function(type) { | |
|
Dan Beam
2015/01/29 18:46:46
s/query/allTypes/
hcarmona
2015/01/31 02:45:49
Done.
| |
| 141 return '[column-type=' + type + ']'; | |
| 142 }).join(', '); | |
| 143 equivalent = this.querySelector(query); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 // Return the first focusable element if no equivalent type is found. | |
| 148 return equivalent || this.focusableElements[0]; | |
| 149 }, | |
| 150 | |
| 151 /** | |
| 152 * @param {Element} element The element that should be added. | |
| 153 * @param {string} type The column type to use for the element. | |
| 154 * @private | |
| 155 */ | |
| 156 addElementIfFocusable_: function(element, type) { | |
| 157 if (this.shouldFocus_(element)) { | |
| 158 this.addFocusableElement(element); | |
| 159 element.setAttribute('column-type', type); | |
| 160 } | |
| 161 }, | |
| 162 | |
| 163 /** | |
| 164 * Determines if element should be focusable. | |
| 165 * @param {!Element} element | |
| 166 * @return {boolean} | |
| 167 * @private | |
| 168 */ | |
| 169 shouldFocus_: function(element) { | |
| 170 if (!element) | |
| 171 return false; | |
| 172 | |
| 173 // Hidden elements are not focusable. | |
| 174 var style = window.getComputedStyle(element); | |
| 175 if (style.visibility == 'hidden' || style.display == 'none') | |
| 176 return false; | |
| 177 | |
| 178 // Verify all ancestors are focusable. | |
| 179 return !element.parentElement || this.shouldFocus_(element.parentElement); | |
| 180 }, | |
| 181 }; | |
| 182 | |
| 183 /////////////////////////////////////////////////////////////////////////////// | |
| 80 // Downloads | 184 // Downloads |
| 81 /** | 185 /** |
| 82 * Class to hold all the information about the visible downloads. | 186 * Class to hold all the information about the visible downloads. |
| 83 * @constructor | 187 * @constructor |
| 84 */ | 188 */ |
| 85 function Downloads() { | 189 function Downloads() { |
| 86 /** | 190 /** |
| 87 * @type {!Object.<string, Download>} | 191 * @type {!Object.<string, Download>} |
| 88 * @private | 192 * @private |
| 89 */ | 193 */ |
| 90 this.downloads_ = {}; | 194 this.downloads_ = {}; |
| 91 this.node_ = $('downloads-display'); | 195 this.node_ = $('downloads-display'); |
| 92 this.summary_ = $('downloads-summary-text'); | 196 this.summary_ = $('downloads-summary-text'); |
| 93 this.searchText_ = ''; | 197 this.searchText_ = ''; |
| 198 this.focusGrid_ = new cr.ui.FocusGrid(); | |
| 94 | 199 |
| 95 // Keep track of the dates of the newest and oldest downloads so that we | 200 // Keep track of the dates of the newest and oldest downloads so that we |
| 96 // know where to insert them. | 201 // know where to insert them. |
| 97 this.newestTime_ = -1; | 202 this.newestTime_ = -1; |
| 98 | 203 |
| 99 // Icon load request queue. | 204 // Icon load request queue. |
| 100 this.iconLoadQueue_ = []; | 205 this.iconLoadQueue_ = []; |
| 101 this.isIconLoading_ = false; | 206 this.isIconLoading_ = false; |
| 102 | 207 |
| 103 this.progressForeground1_ = new Image(); | 208 this.progressForeground1_ = new Image(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 var noDownloadsOrResults = $('no-downloads-or-results'); | 274 var noDownloadsOrResults = $('no-downloads-or-results'); |
| 170 noDownloadsOrResults.textContent = loadTimeData.getString( | 275 noDownloadsOrResults.textContent = loadTimeData.getString( |
| 171 this.searchText_ ? 'no_search_results' : 'no_downloads'); | 276 this.searchText_ ? 'no_search_results' : 'no_downloads'); |
| 172 | 277 |
| 173 var hasDownloads = this.size() > 0; | 278 var hasDownloads = this.size() > 0; |
| 174 this.node_.hidden = !hasDownloads; | 279 this.node_.hidden = !hasDownloads; |
| 175 noDownloadsOrResults.hidden = hasDownloads; | 280 noDownloadsOrResults.hidden = hasDownloads; |
| 176 | 281 |
| 177 if (loadTimeData.getBoolean('allow_deleting_history')) | 282 if (loadTimeData.getBoolean('allow_deleting_history')) |
| 178 $('clear-all').hidden = !hasDownloads || this.searchText_.length > 0; | 283 $('clear-all').hidden = !hasDownloads || this.searchText_.length > 0; |
| 284 | |
| 285 this.rebuildFocusGrid_(); | |
| 179 }; | 286 }; |
| 180 | 287 |
| 181 /** | 288 /** |
| 289 * Rebuild the focusGrid_ using the elements that each download will have. | |
| 290 * @private | |
| 291 */ | |
| 292 Downloads.prototype.rebuildFocusGrid_ = function() { | |
| 293 // Destroy rows that are no longer in the document. | |
| 294 this.focusGrid_.rows.forEach(function(row) { | |
| 295 if (!document.contains(row)) | |
| 296 row.destroy(); | |
| 297 }); | |
| 298 | |
| 299 var keys = Object.keys(this.downloads_); | |
| 300 for (var i = 0; i < keys.length; ++i) { | |
| 301 var download = this.downloads_[keys[i]]; | |
| 302 // Only decorate nodes that are not decorated. | |
| 303 if (!download.node.isFocusRow) { | |
| 304 DownloadFocusRow.decorate(download.node, download, this.node_); | |
| 305 download.node.isFocusRow = true; | |
|
Dan Beam
2015/01/29 18:46:46
move this functionality into cr.ui.FocusRow, e.g.,
hcarmona
2015/01/31 02:45:49
Changed back to being "destructive". Decorating a
| |
| 306 } | |
| 307 } | |
| 308 | |
| 309 // The ordering of the keys is not guaranteed, and downloads should be added | |
| 310 // to the FocusGrid in the order they will be in the UI. | |
| 311 this.focusGrid_.rows.length = 0; | |
| 312 var downloads = document.querySelectorAll('.download'); | |
| 313 for (var i = 0; i < downloads.length; ++i) { | |
| 314 this.focusGrid_.addRow(downloads[i]); | |
| 315 } | |
| 316 }; | |
| 317 | |
| 318 /** | |
| 182 * Returns the number of downloads in the model. Used by tests. | 319 * Returns the number of downloads in the model. Used by tests. |
| 183 * @return {number} Returns the number of downloads shown on the page. | 320 * @return {number} Returns the number of downloads shown on the page. |
| 184 */ | 321 */ |
| 185 Downloads.prototype.size = function() { | 322 Downloads.prototype.size = function() { |
| 186 return Object.keys(this.downloads_).length; | 323 return Object.keys(this.downloads_).length; |
| 187 }; | 324 }; |
| 188 | 325 |
| 189 /** | 326 /** |
| 190 * Called whenever the downloads lists items have changed (either by being | 327 * Called whenever the downloads lists items have changed (either by being |
| 191 * updated, added, or removed). | 328 * updated, added, or removed). |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 if (Date.now() - start > 50) { | 1115 if (Date.now() - start > 50) { |
| 979 clearTimeout(resultsTimeout); | 1116 clearTimeout(resultsTimeout); |
| 980 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); | 1117 resultsTimeout = setTimeout(tryDownloadUpdatedPeriodically, 5); |
| 981 break; | 1118 break; |
| 982 } | 1119 } |
| 983 } | 1120 } |
| 984 } | 1121 } |
| 985 | 1122 |
| 986 // Add handlers to HTML elements. | 1123 // Add handlers to HTML elements. |
| 987 window.addEventListener('DOMContentLoaded', load); | 1124 window.addEventListener('DOMContentLoaded', load); |
| OLD | NEW |