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
3 // found in the LICENSE file.
5 cr.define('downloads', function() {
6 var Manager = Polymer({
7 is: 'downloads-manager',
10 /** @private {!downloads.ActionService} */
11 this.actionService_ = new downloads.ActionService;
22 * @return {number} A guess at how many items could be visible at once.
25 guesstimateNumberOfVisibleItems_: function() {
26 var toolbarHeight = this.$.toolbar.offsetHeight;
27 return Math.floor((window.innerHeight - toolbarHeight) / 46) + 1;
34 onCanExecute_: function(e) {
35 e = /** @type {cr.ui.CanExecuteEvent} */(e);
36 switch (e.command.id) {
38 e.canExecute = this.$.toolbar.canUndo();
40 case 'clear-all-command':
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();
59 this.$.toolbar.setActionService(this.actionService_);
61 cr.ui.decorate('command', cr.ui.Command);
62 document.addEventListener('canExecute', this.onCanExecute_.bind(this));
63 document.addEventListener('command', this.onCommand_.bind(this));
65 // Shows all downloads.
66 this.actionService_.search('');
70 * @return {number} The number of downloads shown on the page.
74 return this.items_.length;
78 * Called when all items need to be updated.
79 * @param {!Array<!downloads.Data>} list A list of new download data.
82 updateAll_: function(list) {
83 var oldIdMap = this.idMap_ || {};
85 /** @private {!Object<!downloads.ItemView>} */
88 /** @private {!Array<!downloads.ItemView>} */
91 if (!this.iconLoader_) {
92 var guesstimate = Math.max(this.guesstimateNumberOfVisibleItems_(), 1);
93 /** @private {downloads.ThrottledIconLoader} */
94 this.iconLoader_ = new downloads.ThrottledIconLoader(guesstimate);
97 for (var i = 0; i < list.length; ++i) {
101 // Re-use old items when possible (saves work, preserves focus).
102 var item = oldIdMap[id] ||
103 new downloads.ItemView(this.iconLoader_, this.actionService_);
105 this.idMap_[id] = item; // Associated by ID for fast lookup.
106 this.items_.push(item); // Add to sorted list for order.
108 // Render |item| but don't actually add to the DOM yet. |this.items_|
109 // must be fully created to be able to find the right spot to insert.
112 // Collapse redundant dates.
113 var prev = list[i - 1];
114 item.hideDate = !!prev && prev.date_string == data.date_string;
119 // Remove stale, previously rendered items from the DOM.
120 for (var id in oldIdMap) {
121 if (oldIdMap[id].parentNode)
122 oldIdMap[id].parentNode.removeChild(oldIdMap[id]);
126 for (var i = 0; i < this.items_.length; ++i) {
127 var item = this.items_[i];
128 if (item.parentNode) // Already in the DOM; skip.
132 // Find the next rendered item after this one, and insert before it.
133 for (var j = i + 1; !before && j < this.items_.length; ++j) {
134 if (this.items_[j].parentNode)
135 before = this.items_[j];
137 // If |before| is null, |item| will just get added at the end.
138 this.$['downloads-list'].insertBefore(item, before);
141 this.hasDownloads_ = this.size_() > 0;
143 if (loadTimeData.getBoolean('allowDeletingHistory'))
144 this.$.toolbar.canClearAll = this.hasDownloads_;
148 * @param {!downloads.Data} data
151 updateItem_: function(data) {
152 this.idMap_[data.id].update(data);
156 Manager.size = function() {
157 return document.querySelector('downloads-manager').size_();
160 Manager.updateAll = function(list) {
161 document.querySelector('downloads-manager').updateAll_(list);
164 Manager.updateItem = function(item) {
165 document.querySelector('downloads-manager').updateItem_(item);
168 Manager.onLoad = function() {
169 document.querySelector('downloads-manager').onLoad_();
172 return {Manager: Manager};
175 window.addEventListener('load', downloads.Manager.onLoad);