| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 cr.define('downloads', function() { | 5 cr.define('downloads', function() { |
| 6 /** | 6 var Manager = Polymer({ |
| 7 * Class to own and manage download items. | 7 is: 'downloads-manager', |
| 8 * @constructor | |
| 9 */ | |
| 10 function Manager() {} | |
| 11 | 8 |
| 12 cr.addSingletonGetter(Manager); | 9 created: function() { |
| 10 /** @private {!downloads.ActionService} */ |
| 11 this.actionService_ = new downloads.ActionService; |
| 12 }, |
| 13 | 13 |
| 14 Manager.prototype = { | 14 properties: { |
| 15 /** @private {string} */ | 15 hasDownloads_: { |
| 16 searchText_: '', | 16 type: Boolean, |
| 17 | 17 value: false, |
| 18 /** | 18 }, |
| 19 * Sets the search text, updates related UIs, and tells the browser. | |
| 20 * @param {string} searchText Text we're searching for. | |
| 21 * @private | |
| 22 */ | |
| 23 setSearchText_: function(searchText) { | |
| 24 this.searchText_ = searchText; | |
| 25 | |
| 26 $('downloads-summary-text').textContent = this.searchText_ ? | |
| 27 loadTimeData.getStringF('searchResultsFor', this.searchText_) : ''; | |
| 28 | |
| 29 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']). | |
| 30 function trim(s) { return s.trim(); } | |
| 31 chrome.send('getDownloads', searchText.split(/"([^"]*)"/).map(trim)); | |
| 32 }, | 19 }, |
| 33 | 20 |
| 34 /** | 21 /** |
| 35 * @return {number} A guess at how many items could be visible at once. | 22 * @return {number} A guess at how many items could be visible at once. |
| 36 * @private | 23 * @private |
| 37 */ | 24 */ |
| 38 guesstimateNumberOfVisibleItems_: function() { | 25 guesstimateNumberOfVisibleItems_: function() { |
| 39 var toolbarHeight = $('downloads-toolbar').offsetHeight; | 26 var toolbarHeight = this.$.toolbar.offsetHeight; |
| 40 var summaryHeight = $('downloads-summary').offsetHeight; | 27 return Math.floor((window.innerHeight - toolbarHeight) / 46) + 1; |
| 41 var nonItemSpace = toolbarHeight + summaryHeight; | |
| 42 return Math.floor((window.innerHeight - nonItemSpace) / 46) + 1; | |
| 43 }, | 28 }, |
| 44 | 29 |
| 45 /** | 30 /** |
| 31 * @param {Event} e |
| 32 * @private |
| 33 */ |
| 34 onCanExecute_: function(e) { |
| 35 e = /** @type {cr.ui.CanExecuteEvent} */(e); |
| 36 switch (e.command.id) { |
| 37 case 'undo-command': |
| 38 e.canExecute = this.$.toolbar.canUndo(); |
| 39 break; |
| 40 case 'clear-all-command': |
| 41 e.canExecute = true; |
| 42 break; |
| 43 } |
| 44 }, |
| 45 |
| 46 /** |
| 47 * @param {Event} e |
| 48 * @private |
| 49 */ |
| 50 onCommand_: function(e) { |
| 51 if (e.command.id == 'clear-all-command') |
| 52 this.actionService_.clearAll(); |
| 53 else if (e.command.id == 'undo-command') |
| 54 this.actionService_.undo(); |
| 55 }, |
| 56 |
| 57 /** @private */ |
| 58 onLoad_: function() { |
| 59 this.$.toolbar.setActionService(this.actionService_); |
| 60 |
| 61 cr.ui.decorate('command', cr.ui.Command); |
| 62 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); |
| 63 document.addEventListener('command', this.onCommand_.bind(this)); |
| 64 |
| 65 // Shows all downloads. |
| 66 this.actionService_.search(''); |
| 67 }, |
| 68 |
| 69 /** |
| 70 * @return {number} The number of downloads shown on the page. |
| 71 * @private |
| 72 */ |
| 73 size_: function() { |
| 74 return this.items_.length; |
| 75 }, |
| 76 |
| 77 /** |
| 46 * Called when all items need to be updated. | 78 * Called when all items need to be updated. |
| 47 * @param {!Array<!downloads.Data>} list A list of new download data. | 79 * @param {!Array<!downloads.Data>} list A list of new download data. |
| 48 * @private | 80 * @private |
| 49 */ | 81 */ |
| 50 updateAll_: function(list) { | 82 updateAll_: function(list) { |
| 51 var oldIdMap = this.idMap_ || {}; | 83 var oldIdMap = this.idMap_ || {}; |
| 52 | 84 |
| 53 /** @private {!Object<!downloads.ItemView>} */ | 85 /** @private {!Object<!downloads.ItemView>} */ |
| 54 this.idMap_ = {}; | 86 this.idMap_ = {}; |
| 55 | 87 |
| 56 /** @private {!Array<!downloads.ItemView>} */ | 88 /** @private {!Array<!downloads.ItemView>} */ |
| 57 this.items_ = []; | 89 this.items_ = []; |
| 58 | 90 |
| 59 if (!this.iconLoader_) { | 91 if (!this.iconLoader_) { |
| 60 var guesstimate = Math.max(this.guesstimateNumberOfVisibleItems_(), 1); | 92 var guesstimate = Math.max(this.guesstimateNumberOfVisibleItems_(), 1); |
| 61 /** @private {downloads.ThrottledIconLoader} */ | 93 /** @private {downloads.ThrottledIconLoader} */ |
| 62 this.iconLoader_ = new downloads.ThrottledIconLoader(guesstimate); | 94 this.iconLoader_ = new downloads.ThrottledIconLoader(guesstimate); |
| 63 } | 95 } |
| 64 | 96 |
| 65 for (var i = 0; i < list.length; ++i) { | 97 for (var i = 0; i < list.length; ++i) { |
| 66 var data = list[i]; | 98 var data = list[i]; |
| 67 var id = data.id; | 99 var id = data.id; |
| 68 | 100 |
| 69 // Re-use old items when possible (saves work, preserves focus). | 101 // Re-use old items when possible (saves work, preserves focus). |
| 70 var item = oldIdMap[id] || new downloads.ItemView(this.iconLoader_); | 102 var item = oldIdMap[id] || |
| 103 new downloads.ItemView(this.iconLoader_, this.actionService_); |
| 71 | 104 |
| 72 this.idMap_[id] = item; // Associated by ID for fast lookup. | 105 this.idMap_[id] = item; // Associated by ID for fast lookup. |
| 73 this.items_.push(item); // Add to sorted list for order. | 106 this.items_.push(item); // Add to sorted list for order. |
| 74 | 107 |
| 75 // Render |item| but don't actually add to the DOM yet. |this.items_| | 108 // Render |item| but don't actually add to the DOM yet. |this.items_| |
| 76 // must be fully created to be able to find the right spot to insert. | 109 // must be fully created to be able to find the right spot to insert. |
| 77 item.update(data); | 110 item.update(data); |
| 78 | 111 |
| 79 // Collapse redundant dates. | 112 // Collapse redundant dates. |
| 80 var prev = list[i - 1]; | 113 var prev = list[i - 1]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 95 if (item.parentNode) // Already in the DOM; skip. | 128 if (item.parentNode) // Already in the DOM; skip. |
| 96 continue; | 129 continue; |
| 97 | 130 |
| 98 var before = null; | 131 var before = null; |
| 99 // Find the next rendered item after this one, and insert before it. | 132 // Find the next rendered item after this one, and insert before it. |
| 100 for (var j = i + 1; !before && j < this.items_.length; ++j) { | 133 for (var j = i + 1; !before && j < this.items_.length; ++j) { |
| 101 if (this.items_[j].parentNode) | 134 if (this.items_[j].parentNode) |
| 102 before = this.items_[j]; | 135 before = this.items_[j]; |
| 103 } | 136 } |
| 104 // If |before| is null, |item| will just get added at the end. | 137 // If |before| is null, |item| will just get added at the end. |
| 105 this.node_.insertBefore(item, before); | 138 this.$['downloads-list'].insertBefore(item, before); |
| 106 } | 139 } |
| 107 | 140 |
| 108 var noDownloadsOrResults = $('no-downloads-or-results'); | 141 this.hasDownloads_ = this.size_() > 0; |
| 109 noDownloadsOrResults.textContent = loadTimeData.getString( | |
| 110 this.searchText_ ? 'noSearchResults' : 'noDownloads'); | |
| 111 | |
| 112 var hasDownloads = this.size_() > 0; | |
| 113 this.node_.hidden = !hasDownloads; | |
| 114 noDownloadsOrResults.hidden = hasDownloads; | |
| 115 | 142 |
| 116 if (loadTimeData.getBoolean('allowDeletingHistory')) | 143 if (loadTimeData.getBoolean('allowDeletingHistory')) |
| 117 $('clear-all').hidden = !hasDownloads || this.searchText_.length > 0; | 144 this.$.toolbar.canClearAll = this.hasDownloads_; |
| 118 }, | 145 }, |
| 119 | 146 |
| 120 /** | 147 /** |
| 121 * @param {!downloads.Data} data | 148 * @param {!downloads.Data} data |
| 122 * @private | 149 * @private |
| 123 */ | 150 */ |
| 124 updateItem_: function(data) { | 151 updateItem_: function(data) { |
| 125 this.idMap_[data.id].update(data); | 152 this.idMap_[data.id].update(data); |
| 126 }, | 153 }, |
| 154 }); |
| 127 | 155 |
| 128 /** | 156 Manager.size = function() { |
| 129 * @return {number} The number of downloads shown on the page. | 157 return document.querySelector('downloads-manager').size_(); |
| 130 * @private | |
| 131 */ | |
| 132 size_: function() { | |
| 133 return this.items_.length; | |
| 134 }, | |
| 135 | |
| 136 /** @private */ | |
| 137 clearAll_: function() { | |
| 138 if (loadTimeData.getBoolean('allowDeletingHistory')) { | |
| 139 chrome.send('clearAll'); | |
| 140 this.setSearchText_(''); | |
| 141 } | |
| 142 }, | |
| 143 | |
| 144 /** @private */ | |
| 145 onLoad_: function() { | |
| 146 this.node_ = $('downloads-display'); | |
| 147 | |
| 148 $('clear-all').onclick = function() { | |
| 149 this.clearAll_(); | |
| 150 }.bind(this); | |
| 151 | |
| 152 $('open-downloads-folder').onclick = function() { | |
| 153 chrome.send('openDownloadsFolder'); | |
| 154 }; | |
| 155 | |
| 156 $('search-button').onclick = function() { | |
| 157 if (!$('search-term').hidden) | |
| 158 return; | |
| 159 $('clear-search').hidden = false; | |
| 160 $('search-term').hidden = false; | |
| 161 }; | |
| 162 | |
| 163 $('clear-search').onclick = function() { | |
| 164 $('clear-search').hidden = true; | |
| 165 $('search-term').hidden = true; | |
| 166 $('search-term').value = ''; | |
| 167 this.setSearchText_(''); | |
| 168 }.bind(this); | |
| 169 | |
| 170 // TODO(dbeam): this previously used onsearch, which batches keystrokes | |
| 171 // together. This should probably be re-instated eventually. | |
| 172 $('search-term').oninput = function(e) { | |
| 173 this.setSearchText_($('search-term').value); | |
| 174 }.bind(this); | |
| 175 | |
| 176 cr.ui.decorate('command', cr.ui.Command); | |
| 177 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); | |
| 178 document.addEventListener('command', this.onCommand_.bind(this)); | |
| 179 | |
| 180 this.setSearchText_(''); | |
| 181 }, | |
| 182 | |
| 183 /** | |
| 184 * @param {Event} e | |
| 185 * @private | |
| 186 */ | |
| 187 onCanExecute_: function(e) { | |
| 188 e = /** @type {cr.ui.CanExecuteEvent} */(e); | |
| 189 switch (e.command.id) { | |
| 190 case 'undo-command': | |
| 191 e.canExecute = !$('search-term').contains(document.activeElement); | |
| 192 break; | |
| 193 case 'clear-all-command': | |
| 194 e.canExecute = true; | |
| 195 break; | |
| 196 } | |
| 197 }, | |
| 198 | |
| 199 /** | |
| 200 * @param {Event} e | |
| 201 * @private | |
| 202 */ | |
| 203 onCommand_: function(e) { | |
| 204 if (e.command.id == 'undo-command') | |
| 205 chrome.send('undo'); | |
| 206 else if (e.command.id == 'clear-all-command') | |
| 207 this.clearAll_(); | |
| 208 }, | |
| 209 }; | 158 }; |
| 210 | 159 |
| 211 Manager.updateAll = function(list) { | 160 Manager.updateAll = function(list) { |
| 212 Manager.getInstance().updateAll_(list); | 161 document.querySelector('downloads-manager').updateAll_(list); |
| 213 }; | 162 }; |
| 214 | 163 |
| 215 Manager.updateItem = function(item) { | 164 Manager.updateItem = function(item) { |
| 216 Manager.getInstance().updateItem_(item); | 165 document.querySelector('downloads-manager').updateItem_(item); |
| 217 }; | |
| 218 | |
| 219 Manager.setSearchText = function(searchText) { | |
| 220 Manager.getInstance().setSearchText_(searchText); | |
| 221 }; | 166 }; |
| 222 | 167 |
| 223 Manager.onLoad = function() { | 168 Manager.onLoad = function() { |
| 224 Manager.getInstance().onLoad_(); | 169 document.querySelector('downloads-manager').onLoad_(); |
| 225 }; | |
| 226 | |
| 227 Manager.size = function() { | |
| 228 return Manager.getInstance().size_(); | |
| 229 }; | 170 }; |
| 230 | 171 |
| 231 return {Manager: Manager}; | 172 return {Manager: Manager}; |
| 232 }); | 173 }); |
| 233 | 174 |
| 234 window.addEventListener('load', downloads.Manager.onLoad); | 175 window.addEventListener('load', downloads.Manager.onLoad); |
| OLD | NEW |