Chromium Code Reviews| Index: chrome/browser/resources/md_history/history_list_behavior.js |
| diff --git a/chrome/browser/resources/md_history/history_list_behavior.js b/chrome/browser/resources/md_history/history_list_behavior.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9d6834ea12a4a2182440e86966441dd80746a1bf |
| --- /dev/null |
| +++ b/chrome/browser/resources/md_history/history_list_behavior.js |
| @@ -0,0 +1,176 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @constructor |
| + * @param {string} currentPath |
| + */ |
| +var SelectionTreeNode = function(currentPath) { |
| + /** @type {Array<number>} */ |
| + this.indexes = []; |
| + /** @type {Array<SelectionTreeNode>} */ |
| + this.children = []; |
| + /** @type {string} */ |
| + this.currentPath = currentPath; |
| + /** @type {boolean} */ |
| + this.leaf = false; |
| +}; |
| + |
| +/** |
| + * @param {number} index |
| + * @param {string} path |
| + */ |
| +SelectionTreeNode.prototype.addChild = function(index, path) { |
| + this.indexes.push(index); |
| + this.children[index] = new SelectionTreeNode(path); |
| +}; |
| + |
| +/** @polymerBehavior */ |
| +var HistoryListBehavior = { |
| + properties: { |
| + /** |
| + * Polymer paths to the history items contained in this list. |
| + * @type {Array<string>} selectedPaths |
| + * @return {Array<string>} |
| + */ |
| + selectedPaths: {type: Array, value: function() { return []; }}, |
|
tsergeant
2016/08/05 01:39:09
Yay! Now we can databind this through to the toolb
calamity
2016/08/09 02:56:00
Done.
|
| + }, |
| + |
| + listeners: { |
| + 'history-checkbox-select': 'itemSelected_', |
| + }, |
| + |
| + /** |
| + * Deselect each item in |selectedPaths|. |
| + */ |
| + unselectAllItems: function() { |
| + this.selectedPaths.forEach(function(path) { |
| + this.set(path + '.selected', false); |
| + }.bind(this)); |
| + |
| + this.selectedPaths = []; |
| + }, |
| + |
| + /** |
| + * Performs a request to the backend to delete all selected items. If |
| + * successful, removes them from the view. Does not prompt the user before |
| + * deleting -- see <history-list-container> for a version of this method which |
| + * does prompt. |
| + */ |
| + deleteSelected: function() { |
| + var toBeRemoved = this.selectedPaths.map(function(path) { |
| + return this.get(path); |
| + }.bind(this)); |
| + md_history.BrowserService.getInstance() |
| + .deleteItems(toBeRemoved) |
| + .then(function() { |
| + this.removeItemsByPath(this.selectedPaths); |
| + this.fire('unselect-all'); |
| + }.bind(this)); |
| + }, |
| + |
| + /** |
| + * Removes the history items in |paths|. Assumes paths are of a.0.b.0... |
| + * structure. |
| + * @param {Array<string>} paths |
| + * @private |
| + */ |
| + removeItemsByPath: function(paths) { |
|
tsergeant
2016/08/05 01:39:09
I think I've made my peace with this tree crazines
calamity
2016/08/09 02:56:00
Done.
|
| + if (paths.length == 0) |
| + return; |
| + |
| + var spliceTreeRoot = new SelectionTreeNode(paths[0].split('.')[0]); |
| + |
| + // Build a tree to each history item specified in |paths|. |
| + paths.forEach(function(path) { |
| + var components = path.split('.'); |
| + var node = spliceTreeRoot; |
| + components.shift(); |
| + while (components.length > 1) { |
| + var index = Number(components.shift()); |
| + var arrayName = components.shift(); |
| + |
| + if (!node.children[index]) |
| + node.addChild(index, [node.currentPath, index, arrayName].join('.')); |
| + |
| + node = node.children[index]; |
| + } |
| + node.leaf = true; |
| + node.indexes.push(Number(components.shift())); |
| + }); |
| + this.removeItemsBeneathNode_(spliceTreeRoot); |
| + }, |
| + |
| + /** |
| + * Removes the history items underneath |node| and deletes container arrays as |
| + * they become empty. |
| + * @param {SelectionTreeNode} node |
| + * @return {boolean} Whether this node's array should be deleted. |
| + * @private |
| + */ |
| + removeItemsBeneathNode_: function(node) { |
| + var array = this.get(node.currentPath); |
| + var splices = []; |
| + |
| + node.indexes.sort().reverse(); |
| + node.indexes.forEach(function(index) { |
| + if (node.leaf || this.removeItemsBeneathNode_(node.children[index])) { |
| + var item = array.splice(index, 1); |
| + splices.push({ |
| + index: index, |
| + removed: [item], |
| + addedCount: 0, |
| + object: array, |
| + type: 'splice' |
| + }); |
| + } |
| + }.bind(this)); |
| + |
| + if (array.length == 0) |
| + return true; |
| + |
| + // notifySplices gives better performance than individually splicing as it |
| + // batches all of the updates together. |
| + this.notifySplices(node.currentPath, splices); |
| + return false; |
| + }, |
| + |
| + /** |
| + * @param {number} historyDataLength |
| + * @return {boolean} |
| + * @private |
|
tsergeant
2016/08/05 01:39:09
Let's make this method and the next public.
I thi
calamity
2016/08/09 02:56:00
Done.
|
| + */ |
| + hasResults_: function(historyDataLength) { return historyDataLength > 0; }, |
| + |
| + /** |
| + * @param {string} searchedTerm |
| + * @param {boolean} isLoading |
| + * @return {string} |
| + * @private |
| + */ |
| + noResultsMessage_: function(searchedTerm, isLoading) { |
| + if (isLoading) |
| + return ''; |
| + |
| + var messageId = searchedTerm !== '' ? 'noSearchResults' : 'noResults'; |
| + return loadTimeData.getString(messageId); |
| + }, |
| + |
| + /** |
| + * @param {Event} e |
| + * @private |
| + */ |
| + itemSelected_: function(e) { |
| + var item = e.detail.element; |
| + var path = item.path; |
| + if (item.selected) { |
| + this.push('selectedPaths', path); |
| + return; |
| + } |
| + |
| + var index = this.selectedPaths.indexOf(path); |
| + if (index != -1) |
| + this.splice('selectedPaths', index, 1); |
| + }, |
| +}; |