| 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 selectedId: { | 15 selectedId: { |
| 16 type: String, | 16 type: String, |
| 17 observer: 'updateSelectedNode_', | 17 observer: 'updateSelectedDisplay_', |
| 18 notify: true, |
| 19 }, |
| 20 |
| 21 idToNodeMap_: Object, |
| 22 |
| 23 searchTerm: { |
| 24 type: String, |
| 25 observer: 'updateSearchDisplay_', |
| 18 notify: true, | 26 notify: true, |
| 19 }, | 27 }, |
| 20 | 28 |
| 21 /** @type {BookmarkTreeNode} */ | 29 /** @type {BookmarkTreeNode} */ |
| 22 selectedNode: { | 30 displayedList: { |
| 23 type: Object, | 31 type: Array, |
| 24 notify: true, | 32 notify: true, |
| 25 readOnly: true, | 33 readOnly: true, |
| 26 }, | 34 }, |
| 27 | |
| 28 idToNodeMap_: Object, | |
| 29 }, | 35 }, |
| 30 | 36 |
| 31 /** @private {Object} */ | 37 /** @private {Object} */ |
| 32 documentListeners_: null, | 38 documentListeners_: null, |
| 33 | 39 |
| 34 /** @override */ | 40 /** @override */ |
| 35 attached: function() { | 41 attached: function() { |
| 36 this.documentListeners_ = { | 42 this.documentListeners_ = { |
| 37 'selected-folder-changed': this.onSelectedFolderChanged_.bind(this), | 43 'selected-folder-changed': this.onSelectedFolderChanged_.bind(this), |
| 38 'folder-open-changed': this.onFolderOpenChanged_.bind(this), | 44 'folder-open-changed': this.onFolderOpenChanged_.bind(this), |
| 45 'search-term-changed': this.onSearchTermChanged_.bind(this), |
| 39 }; | 46 }; |
| 40 for (var event in this.documentListeners_) | 47 for (var event in this.documentListeners_) |
| 41 document.addEventListener(event, this.documentListeners_[event]); | 48 document.addEventListener(event, this.documentListeners_[event]); |
| 42 }, | 49 }, |
| 43 | 50 |
| 44 /** @override */ | 51 /** @override */ |
| 45 detached: function() { | 52 detached: function() { |
| 46 for (var event in this.documentListeners_) | 53 for (var event in this.documentListeners_) |
| 47 document.removeEventListener(event, this.documentListeners_[event]); | 54 document.removeEventListener(event, this.documentListeners_[event]); |
| 48 }, | 55 }, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 71 this.fire('selected-folder-changed', this.rootNode.children[0].id); | 78 this.fire('selected-folder-changed', this.rootNode.children[0].id); |
| 72 }, | 79 }, |
| 73 | 80 |
| 74 /** | 81 /** |
| 75 * Selects the folder specified by the event and deselects the previously | 82 * Selects the folder specified by the event and deselects the previously |
| 76 * selected folder. | 83 * selected folder. |
| 77 * @param {CustomEvent} e | 84 * @param {CustomEvent} e |
| 78 * @private | 85 * @private |
| 79 */ | 86 */ |
| 80 onSelectedFolderChanged_: function(e) { | 87 onSelectedFolderChanged_: function(e) { |
| 88 if (this.searchTerm) |
| 89 this.searchTerm = ''; |
| 90 |
| 81 // Deselect the old folder if defined. | 91 // Deselect the old folder if defined. |
| 82 if (this.selectedId) | 92 if (this.selectedId) |
| 83 this.set(this.idToNodeMap_[this.selectedId].path + '.isSelected', false); | 93 this.set(this.idToNodeMap_[this.selectedId].path + '.isSelected', false); |
| 84 | 94 |
| 85 var selectedId = /** @type {string} */ (e.detail); | 95 var selectedId = /** @type {string} */ (e.detail); |
| 86 var newFolder = this.idToNodeMap_[selectedId]; | 96 var newFolder = this.idToNodeMap_[selectedId]; |
| 87 this.set(newFolder.path + '.isSelected', true); | 97 this.set(newFolder.path + '.isSelected', true); |
| 88 this.selectedId = selectedId; | 98 this.selectedId = selectedId; |
| 89 }, | 99 }, |
| 90 | 100 |
| 101 /** @private */ |
| 102 deselectFolders_: function() { |
| 103 this.set(this.idToNodeMap_[this.selectedId].path + '.isSelected', false); |
| 104 this.selectedId = null; |
| 105 }, |
| 106 |
| 91 /** | 107 /** |
| 92 * Handles events that open and close folders. | 108 * Handles events that open and close folders. |
| 93 * @param {CustomEvent} e | 109 * @param {CustomEvent} e |
| 94 * @private | 110 * @private |
| 95 */ | 111 */ |
| 96 onFolderOpenChanged_: function(e) { | 112 onFolderOpenChanged_: function(e) { |
| 97 var folder = this.idToNodeMap_[e.detail.id]; | 113 var folder = this.idToNodeMap_[e.detail.id]; |
| 98 this.set(folder.path + '.isOpen', e.detail.open); | 114 this.set(folder.path + '.isOpen', e.detail.open); |
| 99 if (!folder.isOpen && this.isAncestorOfSelected_(folder)) | 115 if (!folder.isOpen && this.isAncestorOfSelected_(folder)) |
| 100 this.fire('selected-folder-changed', folder.id); | 116 this.fire('selected-folder-changed', folder.id); |
| 101 }, | 117 }, |
| 102 | 118 |
| 103 /** | 119 /** |
| 104 * @param {BookmarkTreeNode} folder | 120 * @param {BookmarkTreeNode} folder |
| 105 * @private | 121 * @private |
| 106 * @return {boolean} | 122 * @return {boolean} |
| 107 */ | 123 */ |
| 108 isAncestorOfSelected_: function(folder) { | 124 isAncestorOfSelected_: function(folder) { |
| 109 return this.selectedNode.path.startsWith(folder.path); | 125 if (!this.selectedId) |
| 126 return; |
| 127 |
| 128 var selectedNode = this.idToNodeMap_[this.selectedId]; |
| 129 return selectedNode.path.startsWith(folder.path); |
| 110 }, | 130 }, |
| 111 | 131 |
| 112 /** @private */ | 132 /** @private */ |
| 113 updateSelectedNode_: function() { | 133 updateSearchDisplay_: function() { |
| 134 if (this.searchTerm == '') { |
| 135 this.fire('selected-folder-changed', this.rootNode.children[0].id); |
| 136 } else { |
| 137 chrome.bookmarks.search(this.searchTerm, function(results) { |
| 138 if (this.selectedId) |
| 139 this.deselectFolders_(); |
| 140 |
| 141 this._setDisplayedList(results); |
| 142 }.bind(this)); |
| 143 } |
| 144 }, |
| 145 |
| 146 /** @private */ |
| 147 updateSelectedDisplay_: function() { |
| 148 // Don't do change to selected display if ID was cleared. |
| 149 if (!this.selectedId) |
| 150 return; |
| 151 |
| 114 var selectedNode = this.idToNodeMap_[this.selectedId]; | 152 var selectedNode = this.idToNodeMap_[this.selectedId]; |
| 115 this.linkPaths('selectedNode', selectedNode.path); | 153 this.linkPaths('displayedList', selectedNode.path + '.children'); |
| 116 this._setSelectedNode(selectedNode); | 154 this._setDisplayedList(selectedNode.children); |
| 117 }, | 155 }, |
| 118 | 156 |
| 119 /** | 157 /** |
| 120 * Callback for when a bookmark node is removed. | 158 * Callback for when a bookmark node is removed. |
| 121 * If a folder is selected or is an ancestor of a selected folder, the parent | 159 * If a folder is selected or is an ancestor of a selected folder, the parent |
| 122 * of the removed folder will be selected. | 160 * of the removed folder will be selected. |
| 123 * @param {string} id The id of the removed bookmark node. | 161 * @param {string} id The id of the removed bookmark node. |
| 124 * @param {!{index: number, | 162 * @param {!{index: number, |
| 125 * parentId: string, | 163 * parentId: string, |
| 126 * node: BookmarkTreeNode}} removeInfo | 164 * node: BookmarkTreeNode}} removeInfo |
| 127 */ | 165 */ |
| 128 onBookmarkRemoved_: function(id, removeInfo) { | 166 onBookmarkRemoved_: function(id, removeInfo) { |
| 129 if (this.isAncestorOfSelected_(this.idToNodeMap_[id])) | 167 if (this.isAncestorOfSelected_(this.idToNodeMap_[id])) { |
| 168 // TODO (angelayang): does this ever happen? |
| 130 this.fire('selected-folder-changed', removeInfo.parentId); | 169 this.fire('selected-folder-changed', removeInfo.parentId); |
| 170 } |
| 131 | 171 |
| 132 var parentNode = this.idToNodeMap_[removeInfo.parentId]; | 172 var parentNode = this.idToNodeMap_[removeInfo.parentId]; |
| 133 this.splice(parentNode.path + '.children', removeInfo.index, 1); | 173 this.splice(parentNode.path + '.children', removeInfo.index, 1); |
| 134 this.removeDescendantsFromMap_(id); | 174 this.removeDescendantsFromMap_(id); |
| 135 BookmarksStore.generatePaths(parentNode, removeInfo.index); | 175 BookmarksStore.generatePaths(parentNode, removeInfo.index); |
| 176 |
| 177 // Regenerate the search list if its displayed. |
| 178 if (this.searchTerm) |
| 179 this.updateSearchDisplay_(); |
| 136 }, | 180 }, |
| 137 | 181 |
| 138 /** | 182 /** |
| 183 * Initializes the nodes in the bookmarks tree as follows: |
| 184 * - Populates |idToNodeMap_| with a mapping of all node ids to their |
| 185 * corresponding BookmarkTreeNode. |
| 186 * - Sets all the nodes to not selected and open by default. |
| 187 * @param {BookmarkTreeNode} bookmarkNode |
| 188 * @private |
| 189 */ |
| 190 initNodes_: function(bookmarkNode) { |
| 191 this.idToNodeMap_[bookmarkNode.id] = bookmarkNode; |
| 192 if (bookmarkNode.url) |
| 193 return; |
| 194 |
| 195 bookmarkNode.isSelected = false; |
| 196 bookmarkNode.isOpen = true; |
| 197 for (var i = 0; i < bookmarkNode.children.length; i++) { |
| 198 this.initNodes_(bookmarkNode.children[i]); |
| 199 } |
| 200 }, |
| 201 |
| 202 /** |
| 203 * @param {Event} e |
| 204 * @private |
| 205 */ |
| 206 onSearchTermChanged_: function(e) { |
| 207 this.searchTerm = /** @type {string} */ (e.detail); |
| 208 }, |
| 209 |
| 210 /** |
| 139 * Remove all descendants of a given node from the map. | 211 * Remove all descendants of a given node from the map. |
| 140 * @param {string} id | 212 * @param {string} id |
| 141 * @private | 213 * @private |
| 142 */ | 214 */ |
| 143 removeDescendantsFromMap_: function(id) { | 215 removeDescendantsFromMap_: function(id) { |
| 144 var node = this.idToNodeMap_[id]; | 216 var node = this.idToNodeMap_[id]; |
| 145 if (!node) | 217 if (!node) |
| 146 return; | 218 return; |
| 147 | 219 |
| 148 if (node.children) { | 220 if (node.children) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 idToNodeMap[bookmarkNode.id] = bookmarkNode; | 253 idToNodeMap[bookmarkNode.id] = bookmarkNode; |
| 182 | 254 |
| 183 if (bookmarkNode.url) | 255 if (bookmarkNode.url) |
| 184 return; | 256 return; |
| 185 | 257 |
| 186 bookmarkNode.isSelected = false; | 258 bookmarkNode.isSelected = false; |
| 187 bookmarkNode.isOpen = true; | 259 bookmarkNode.isOpen = true; |
| 188 for (var i = 0; i < bookmarkNode.children.length; i++) | 260 for (var i = 0; i < bookmarkNode.children.length; i++) |
| 189 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap); | 261 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap); |
| 190 }; | 262 }; |
| OLD | NEW |