Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 var BookmarksStore = Polymer({ | 5 var BookmarksStore = Polymer({ |
| 6 is: 'bookmarks-store', | 6 is: 'bookmarks-store', |
| 7 | 7 |
| 8 properties: { | 8 properties: { |
| 9 /** @type {BookmarkTreeNode} */ | 9 /** @type {BookmarkTreeNode} */ |
| 10 rootNode: { | 10 rootNode: { |
| 11 type: Object, | 11 type: Object, |
| 12 notify: true, | 12 notify: true, |
| 13 }, | 13 }, |
| 14 | 14 |
| 15 /** @type {?string} */ | 15 /** @type {string} */ |
| 16 selectedId: { | 16 selectedId: { |
| 17 type: String, | 17 type: String, |
| 18 observer: 'updateSelectedDisplay_', | |
| 19 notify: true, | 18 notify: true, |
| 20 }, | 19 }, |
| 21 | 20 |
| 22 searchTerm: { | 21 searchTerm: { |
| 23 type: String, | 22 type: String, |
| 24 value: '', | 23 value: '', |
| 25 observer: 'updateSearchDisplay_', | 24 observer: 'updateSearchDisplay_', |
| 26 notify: true, | 25 notify: true, |
| 27 }, | 26 }, |
| 28 | 27 |
| 29 /** | 28 /** |
| 30 * This updates to either the result of a search or the contents of the | 29 * This updates to either the result of a search or the contents of the |
| 31 * selected folder. | 30 * selected folder. |
| 32 * @type {Array<BookmarkTreeNode>} | 31 * @type {Array<BookmarkTreeNode>} |
| 33 */ | 32 */ |
| 34 displayedList: { | 33 displayedList: { |
| 35 type: Array, | 34 type: Array, |
| 36 notify: true, | 35 notify: true, |
| 37 readOnly: true, | 36 readOnly: true, |
| 38 }, | 37 }, |
| 39 | 38 |
| 40 /** @type {Object<?string, !BookmarkTreeNode>} */ | 39 /** @type {Object<?string, !BookmarkTreeNode>} */ |
| 41 idToNodeMap_: Object, | 40 idToNodeMap_: Object, |
| 42 | 41 |
| 43 /** @type {?number} */ | 42 /** @type {?number} */ |
| 44 anchorIndex_: Number, | 43 anchorIndex_: { |
|
tsergeant
2017/02/08 03:11:10
Any particular reason why this needed to change? N
angelayang
2017/02/09 04:17:36
Previously anchorIndex is set to null on initializ
| |
| 44 type: Number, | |
| 45 value: null, | |
| 46 }, | |
| 45 | 47 |
| 46 /** @type {Set<string>} */ | 48 /** @type {Set<string>} */ |
| 47 searchResultSet_: Object, | 49 searchResultSet_: Object, |
| 48 }, | 50 }, |
| 49 | 51 |
| 50 /** @private {Object} */ | 52 /** @private {Object} */ |
| 51 documentListeners_: null, | 53 documentListeners_: null, |
| 52 | 54 |
| 53 /** @override */ | 55 /** @override */ |
| 54 attached: function() { | 56 attached: function() { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 * @private | 91 * @private |
| 90 */ | 92 */ |
| 91 setupStore_: function(rootNode) { | 93 setupStore_: function(rootNode) { |
| 92 this.rootNode = rootNode; | 94 this.rootNode = rootNode; |
| 93 this.idToNodeMap_ = {}; | 95 this.idToNodeMap_ = {}; |
| 94 this.rootNode.path = 'rootNode'; | 96 this.rootNode.path = 'rootNode'; |
| 95 BookmarksStore.generatePaths(rootNode, 0); | 97 BookmarksStore.generatePaths(rootNode, 0); |
| 96 BookmarksStore.initNodes(this.rootNode, this.idToNodeMap_); | 98 BookmarksStore.initNodes(this.rootNode, this.idToNodeMap_); |
| 97 | 99 |
| 98 // Initialize the store's fields from the router. | 100 // Initialize the store's fields from the router. |
| 99 if (this.$.router.searchTerm) | 101 this.selectFolder_(this.$.router.selectedId); |
| 100 this.searchTerm = this.$.router.searchTerm; | 102 this.searchTerm = this.$.router.searchTerm; |
| 101 else | |
| 102 this.fire('selected-folder-changed', this.$.router.selectedId); | |
| 103 }, | 103 }, |
| 104 | 104 |
| 105 /** @private */ | 105 /** @private */ |
| 106 deselectFolders_: function() { | 106 deselectFolders_: function() { |
| 107 if (!this.idToNodeMap_[this.selectedId]) | |
| 108 return; | |
| 109 | |
| 107 this.unlinkPaths('displayedList'); | 110 this.unlinkPaths('displayedList'); |
| 108 this.set( | 111 this.set( |
| 109 this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false); | 112 this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false); |
| 110 this.selectedId = null; | |
| 111 }, | 113 }, |
| 112 | 114 |
| 113 /** | 115 /** |
| 114 * @param {BookmarkTreeNode} folder | 116 * @param {BookmarkTreeNode} folder |
| 115 * @private | 117 * @private |
| 116 * @return {boolean} | 118 * @return {boolean} |
| 117 */ | 119 */ |
| 118 isAncestorOfSelected_: function(folder) { | 120 isAncestorOfSelected_: function(folder) { |
| 119 if (!this.selectedId) | |
| 120 return false; | |
| 121 | |
| 122 var selectedNode = this.idToNodeMap_[this.selectedId]; | 121 var selectedNode = this.idToNodeMap_[this.selectedId]; |
| 123 return selectedNode.path.startsWith(folder.path); | 122 return selectedNode.path.startsWith(folder.path); |
| 124 }, | 123 }, |
| 125 | 124 |
| 126 /** @private */ | 125 /** @private */ |
| 127 updateSearchDisplay_: function() { | 126 updateSearchDisplay_: function() { |
| 128 if (!this.rootNode) | 127 if (!this.rootNode) |
| 129 return; | 128 return; |
| 130 | 129 |
| 131 if (!this.searchTerm) { | 130 if (!this.searchTerm) { |
| 132 this.fire('selected-folder-changed', this.rootNode.children[0].id); | 131 this.selectFolder_(this.selectedId); |
| 133 } else { | 132 } else { |
| 134 chrome.bookmarks.search(this.searchTerm, function(results) { | 133 chrome.bookmarks.search(this.searchTerm, function(results) { |
| 135 this.anchorIndex_ = null; | 134 this.anchorIndex_ = null; |
| 136 this.clearSelectedItems_(); | 135 this.clearSelectedItems_(); |
| 137 this.searchResultSet_ = new Set(); | 136 this.searchResultSet_ = new Set(); |
| 138 | 137 |
| 139 if (this.selectedId) | 138 this.deselectFolders_(); |
| 140 this.deselectFolders_(); | |
| 141 | |
| 142 this.setupSearchResults_(results); | 139 this.setupSearchResults_(results); |
| 143 }.bind(this)); | 140 }.bind(this)); |
| 144 } | 141 } |
| 145 }, | 142 }, |
| 146 | 143 |
| 147 /** @private */ | |
| 148 updateSelectedDisplay_: function() { | |
| 149 // Don't change to the selected display if ID was cleared. | |
| 150 if (!this.selectedId) | |
| 151 return; | |
| 152 | |
| 153 this.clearSelectedItems_(); | |
| 154 this.anchorIndex_ = null; | |
| 155 | |
| 156 var selectedNode = this.idToNodeMap_[this.selectedId]; | |
| 157 this.linkPaths('displayedList', selectedNode.path + '.children'); | |
| 158 this._setDisplayedList( | |
| 159 /** @type {Array<BookmarkTreeNode>} */ (selectedNode.children)); | |
| 160 }, | |
| 161 | |
| 162 /** | 144 /** |
| 163 * Remove all descendants of a given node from the map. | 145 * Remove all descendants of a given node from the map. |
| 164 * @param {string} id | 146 * @param {string} id |
| 165 * @private | 147 * @private |
| 166 */ | 148 */ |
| 167 removeDescendantsFromMap_: function(id) { | 149 removeDescendantsFromMap_: function(id) { |
| 168 var node = this.idToNodeMap_[id]; | 150 var node = this.idToNodeMap_[id]; |
| 169 if (!node) | 151 if (!node) |
| 170 return; | 152 return; |
| 171 | 153 |
| 172 if (node.children) { | 154 if (node.children) { |
| 173 for (var i = 0; i < node.children.length; i++) | 155 for (var i = 0; i < node.children.length; i++) |
| 174 this.removeDescendantsFromMap_(node.children[i].id); | 156 this.removeDescendantsFromMap_(node.children[i].id); |
| 175 } | 157 } |
| 176 delete this.idToNodeMap_[id]; | 158 delete this.idToNodeMap_[id]; |
| 177 }, | 159 }, |
| 178 | 160 |
| 179 /** | 161 /** |
| 162 * Changes the selected folder to that of the id or else defaults to the | |
| 163 * Bookmarks Bar. | |
| 164 * @param {string} id The id of the folder to be selected. | |
| 165 * @private | |
| 166 */ | |
| 167 selectFolder_: function(id) { | |
|
tsergeant
2017/02/08 03:11:10
I think we should make this a public method.
This
| |
| 168 if (!this.idToNodeMap_) | |
| 169 return; | |
| 170 | |
| 171 if (!this.idToNodeMap_[id] || this.idToNodeMap_[id].url) | |
| 172 id = this.rootNode.children[0].id; | |
| 173 | |
| 174 this.deselectFolders_(); | |
| 175 if (this.searchTerm) { | |
| 176 this.selectedId = id; | |
| 177 } else { | |
| 178 var newFolder = this.idToNodeMap_[id]; | |
| 179 this.set(newFolder.path + '.isSelectedFolder', true); | |
| 180 this.selectedId = id; | |
| 181 | |
| 182 // Update the displayed list to the selected folder. | |
| 183 var selectedNode = this.idToNodeMap_[this.selectedId]; | |
| 184 this.linkPaths('displayedList', selectedNode.path + '.children'); | |
| 185 this._setDisplayedList(selectedNode.children); | |
| 186 } | |
| 187 }, | |
| 188 | |
| 189 /** | |
| 180 * Remove all selected items in the list. | 190 * Remove all selected items in the list. |
| 181 * @private | 191 * @private |
| 182 */ | 192 */ |
| 183 clearSelectedItems_: function() { | 193 clearSelectedItems_: function() { |
| 184 if (!this.displayedList) | 194 if (!this.displayedList) |
| 185 return; | 195 return; |
| 186 | 196 |
| 187 for (var i = 0; i < this.displayedList.length; i++) { | 197 for (var i = 0; i < this.displayedList.length; i++) { |
| 188 if (!this.displayedList[i].isSelectedItem) | 198 if (!this.displayedList[i].isSelectedItem) |
| 189 continue; | 199 continue; |
| 190 | |
| 191 this.set('displayedList.#' + i + '.isSelectedItem', false); | 200 this.set('displayedList.#' + i + '.isSelectedItem', false); |
| 192 } | 201 } |
| 193 }, | 202 }, |
| 194 | 203 |
| 195 /** | 204 /** |
| 196 * Return the index in the search result of an item. | 205 * Return the index in the search result of an item. |
| 197 * @param {BookmarkTreeNode} item | 206 * @param {BookmarkTreeNode} item |
| 198 * @return {number} | 207 * @return {number} |
| 199 * @private | 208 * @private |
| 200 */ | 209 */ |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 // indexes will have changed and Polymer doesn't update them. | 292 // indexes will have changed and Polymer doesn't update them. |
| 284 this.removeDescendantsFromMap_(id); | 293 this.removeDescendantsFromMap_(id); |
| 285 parentNode.path = this.idToNodeMap_[parentNode.id].path; | 294 parentNode.path = this.idToNodeMap_[parentNode.id].path; |
| 286 BookmarksStore.generatePaths(parentNode, 0); | 295 BookmarksStore.generatePaths(parentNode, 0); |
| 287 BookmarksStore.initNodes(parentNode, this.idToNodeMap_); | 296 BookmarksStore.initNodes(parentNode, this.idToNodeMap_); |
| 288 this.set(parentNode.path, parentNode); | 297 this.set(parentNode.path, parentNode); |
| 289 | 298 |
| 290 // Updates selectedId if the removed node is an ancestor of the current | 299 // Updates selectedId if the removed node is an ancestor of the current |
| 291 // selected node. | 300 // selected node. |
| 292 if (isAncestor) | 301 if (isAncestor) |
| 293 this.fire('selected-folder-changed', removeInfo.parentId); | 302 this.selectFolder_(removeInfo.parentId); |
| 294 | 303 |
| 295 // Only update the displayedList if the removed node is in the | 304 // Only update the displayedList if the removed node is in the |
| 296 // displayedList. | 305 // displayedList. |
| 297 if (!wasInDisplayedList) | 306 if (!wasInDisplayedList) |
| 298 return; | 307 return; |
| 299 | 308 |
| 300 this.anchorIndex_ = null; | 309 this.anchorIndex_ = null; |
| 301 | 310 |
| 302 // Update the currently displayed list. | 311 // Update the currently displayed list. |
| 303 if (this.searchTerm) { | 312 if (this.searchTerm) { |
| 304 this.updateSearchDisplay_(); | 313 this.updateSearchDisplay_(); |
| 305 } else { | 314 } else { |
| 306 if (!isAncestor) | 315 if (!isAncestor) |
| 307 this.fire('selected-folder-changed', this.selectedId); | 316 this.selectFolder_(this.selectedId); |
| 308 | 317 |
| 309 this._setDisplayedList(parentNode.children); | 318 this._setDisplayedList(parentNode.children); |
| 310 } | 319 } |
| 311 }.bind(this)); | 320 }.bind(this)); |
| 312 }, | 321 }, |
| 313 | 322 |
| 314 /** | 323 /** |
| 315 * Called when the title of a bookmark changes. | 324 * Called when the title of a bookmark changes. |
| 316 * @param {string} id The id of changed bookmark node. | 325 * @param {string} id The id of changed bookmark node. |
| 317 * @param {!Object} changeInfo | 326 * @param {!Object} changeInfo |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 337 this.searchTerm = /** @type {string} */ (e.detail); | 346 this.searchTerm = /** @type {string} */ (e.detail); |
| 338 }, | 347 }, |
| 339 | 348 |
| 340 /** | 349 /** |
| 341 * Selects the folder specified by the event and deselects the previously | 350 * Selects the folder specified by the event and deselects the previously |
| 342 * selected folder. | 351 * selected folder. |
| 343 * @param {CustomEvent} e | 352 * @param {CustomEvent} e |
| 344 * @private | 353 * @private |
| 345 */ | 354 */ |
| 346 onSelectedFolderChanged_: function(e) { | 355 onSelectedFolderChanged_: function(e) { |
| 347 if (this.searchTerm) | 356 if (/** @type {boolean} */ (e.detail.clearSearch)) |
| 348 this.searchTerm = ''; | 357 this.searchTerm = ''; |
| 349 | 358 |
| 350 // Deselect the old folder if defined. | 359 this.selectFolder_(/** @type {string} */ (e.detail.id)); |
| 351 if (this.selectedId && this.idToNodeMap_[this.selectedId]) | |
| 352 this.set( | |
| 353 this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false); | |
| 354 | |
| 355 // Check if the selected id is that of a defined folder. | |
| 356 var id = /** @type {string} */ (e.detail); | |
| 357 if (!this.idToNodeMap_[id] || this.idToNodeMap_[id].url) | |
| 358 id = this.rootNode.children[0].id; | |
| 359 | |
| 360 var newFolder = this.idToNodeMap_[id]; | |
| 361 this.set(newFolder.path + '.isSelectedFolder', true); | |
| 362 this.selectedId = id; | |
| 363 }, | 360 }, |
| 364 | 361 |
| 365 /** | 362 /** |
| 366 * Handles events that open and close folders. | 363 * Handles events that open and close folders. |
| 367 * @param {CustomEvent} e | 364 * @param {CustomEvent} e |
| 368 * @private | 365 * @private |
| 369 */ | 366 */ |
| 370 onFolderOpenChanged_: function(e) { | 367 onFolderOpenChanged_: function(e) { |
| 371 var folder = this.idToNodeMap_[e.detail.id]; | 368 var folder = this.idToNodeMap_[e.detail.id]; |
| 372 this.set(folder.path + '.isOpen', e.detail.open); | 369 this.set(folder.path + '.isOpen', e.detail.open); |
| 373 if (!folder.isOpen && this.isAncestorOfSelected_(folder)) | 370 if (!folder.isOpen && this.isAncestorOfSelected_(folder)) |
| 374 this.fire('selected-folder-changed', folder.id); | 371 this.selectFolder_(folder.id); |
| 375 }, | 372 }, |
| 376 | 373 |
| 377 /** | 374 /** |
| 378 * Selects items according to keyboard behaviours. | 375 * Selects items according to keyboard behaviours. |
| 379 * @param {CustomEvent} e | 376 * @param {CustomEvent} e |
| 380 * @private | 377 * @private |
| 381 */ | 378 */ |
| 382 onItemSelected_: function(e) { | 379 onItemSelected_: function(e) { |
| 383 if (!e.detail.add) | 380 if (!e.detail.add) |
| 384 this.clearSelectedItems_(); | 381 this.clearSelectedItems_(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 422 idToNodeMap[bookmarkNode.id] = bookmarkNode; | 419 idToNodeMap[bookmarkNode.id] = bookmarkNode; |
| 423 | 420 |
| 424 if (bookmarkNode.url) | 421 if (bookmarkNode.url) |
| 425 return; | 422 return; |
| 426 | 423 |
| 427 bookmarkNode.isSelectedFolder = false; | 424 bookmarkNode.isSelectedFolder = false; |
| 428 bookmarkNode.isOpen = true; | 425 bookmarkNode.isOpen = true; |
| 429 for (var i = 0; i < bookmarkNode.children.length; i++) | 426 for (var i = 0; i < bookmarkNode.children.length; i++) |
| 430 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap); | 427 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap); |
| 431 }; | 428 }; |
| OLD | NEW |