Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Side by Side Diff: chrome/browser/resources/md_bookmarks/store.js

Issue 2645273002: [MD Bookmarks] Modify search to retain the previously selected folder. (Closed)
Patch Set: Rebase and update test to use selectFolder. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_: {
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 19 matching lines...) Expand all
74 */ 76 */
75 initializeStore: function() { 77 initializeStore: function() {
76 chrome.bookmarks.getTree(function(results) { 78 chrome.bookmarks.getTree(function(results) {
77 this.setupStore_(results[0]); 79 this.setupStore_(results[0]);
78 }.bind(this)); 80 }.bind(this));
79 // Attach bookmarks API listeners. 81 // Attach bookmarks API listeners.
80 chrome.bookmarks.onRemoved.addListener(this.onBookmarkRemoved_.bind(this)); 82 chrome.bookmarks.onRemoved.addListener(this.onBookmarkRemoved_.bind(this));
81 chrome.bookmarks.onChanged.addListener(this.onBookmarkChanged_.bind(this)); 83 chrome.bookmarks.onChanged.addListener(this.onBookmarkChanged_.bind(this));
82 }, 84 },
83 85
86 /**
87 * Changes the selected folder to that of the id or else defaults to the
88 * Bookmarks Bar.
89 * @param {string} id The id of the folder to be selected.
90 */
91 selectFolder: function(id) {
92 if (!this.idToNodeMap_)
93 return;
94
95 if (!this.idToNodeMap_[id] || this.idToNodeMap_[id].url)
96 id = this.rootNode.children[0].id;
97
98 this.deselectFolders_();
99 this.selectedId = id;
100 if (this.searchTerm)
101 return;
102
103 // Update the folder node to selected.
104 this.selectedId = id;
105 var folder = this.idToNodeMap_[this.selectedId];
106 this.set(folder.path + '.isSelectedFolder', true);
107
108 // Update the displayed list to the selected folder.
109 this.linkPaths('displayedList', folder.path + '.children');
110 this._setDisplayedList(
111 /** @type {!Array<!BookmarkTreeNode>}*/ (folder.children));
112
113 // Open any closed ancestors of the selected in the sidebar.
114 if (folder.id == this.rootNode.id)
115 return;
116
117 var parent = this.idToNodeMap_[/** @type {?string} */ (folder.parentId)];
118 while (parent) {
119 if (!parent.isOpen) {
120 this.fire('folder-open-changed', {
121 id: parent.id,
122 open: true,
123 });
124 }
125 parent = this.idToNodeMap_[/** @type {?string} */ (parent.parentId)];
126 }
127 },
128
84 ////////////////////////////////////////////////////////////////////////////// 129 //////////////////////////////////////////////////////////////////////////////
85 // bookmarks-store, private: 130 // bookmarks-store, private:
86 131
87 /** 132 /**
88 * @param {BookmarkTreeNode} rootNode 133 * @param {BookmarkTreeNode} rootNode
89 * @private 134 * @private
90 */ 135 */
91 setupStore_: function(rootNode) { 136 setupStore_: function(rootNode) {
92 this.rootNode = rootNode; 137 this.rootNode = rootNode;
93 this.idToNodeMap_ = {}; 138 this.idToNodeMap_ = {};
94 this.rootNode.path = 'rootNode'; 139 this.rootNode.path = 'rootNode';
95 BookmarksStore.generatePaths(rootNode, 0); 140 BookmarksStore.generatePaths(rootNode, 0);
96 BookmarksStore.initNodes(this.rootNode, this.idToNodeMap_); 141 BookmarksStore.initNodes(this.rootNode, this.idToNodeMap_);
97 142
98 // Initialize the store's fields from the router. 143 // Initialize the store's fields from the router.
99 if (this.$.router.searchTerm) 144 this.selectFolder(this.$.router.selectedId);
100 this.searchTerm = this.$.router.searchTerm; 145 this.searchTerm = this.$.router.searchTerm;
101 else
102 this.fire('selected-folder-changed', this.$.router.selectedId);
103 }, 146 },
104 147
105 /** @private */ 148 /** @private */
106 deselectFolders_: function() { 149 deselectFolders_: function() {
150 if (!this.idToNodeMap_[this.selectedId])
151 return;
152
107 this.unlinkPaths('displayedList'); 153 this.unlinkPaths('displayedList');
108 this.set( 154 this.set(
109 this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false); 155 this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false);
110 this.selectedId = null;
111 }, 156 },
112 157
113 /** 158 /**
114 * @param {BookmarkTreeNode} folder 159 * @param {BookmarkTreeNode} folder
115 * @private 160 * @private
116 * @return {boolean} 161 * @return {boolean}
117 */ 162 */
118 isAncestorOfSelected_: function(folder) { 163 isAncestorOfSelected_: function(folder) {
119 if (!this.selectedId)
120 return false;
121
122 var selectedNode = this.idToNodeMap_[this.selectedId]; 164 var selectedNode = this.idToNodeMap_[this.selectedId];
123 return selectedNode.path.startsWith(folder.path); 165 return selectedNode.path.startsWith(folder.path);
124 }, 166 },
125 167
126 /** @private */ 168 /** @private */
127 updateSearchDisplay_: function() { 169 updateSearchDisplay_: function() {
128 if (!this.rootNode) 170 if (!this.rootNode)
129 return; 171 return;
130 172
131 if (!this.searchTerm) { 173 if (!this.searchTerm) {
132 this.fire('selected-folder-changed', this.rootNode.children[0].id); 174 this.selectFolder(this.selectedId);
133 } else { 175 } else {
134 chrome.bookmarks.search(this.searchTerm, function(results) { 176 chrome.bookmarks.search(this.searchTerm, function(results) {
135 this.anchorIndex_ = null; 177 this.anchorIndex_ = null;
136 this.clearSelectedItems_(); 178 this.clearSelectedItems_();
137 this.searchResultSet_ = new Set(); 179 this.searchResultSet_ = new Set();
138 180
139 if (this.selectedId) 181 this.deselectFolders_();
140 this.deselectFolders_();
141
142 this.setupSearchResults_(results); 182 this.setupSearchResults_(results);
143 }.bind(this)); 183 }.bind(this));
144 } 184 }
145 }, 185 },
146 186
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 /** 187 /**
163 * Remove all descendants of a given node from the map. 188 * Remove all descendants of a given node from the map.
164 * @param {string} id 189 * @param {string} id
165 * @private 190 * @private
166 */ 191 */
167 removeDescendantsFromMap_: function(id) { 192 removeDescendantsFromMap_: function(id) {
168 var node = this.idToNodeMap_[id]; 193 var node = this.idToNodeMap_[id];
169 if (!node) 194 if (!node)
170 return; 195 return;
171 196
172 if (node.children) { 197 if (node.children) {
173 for (var i = 0; i < node.children.length; i++) 198 for (var i = 0; i < node.children.length; i++)
174 this.removeDescendantsFromMap_(node.children[i].id); 199 this.removeDescendantsFromMap_(node.children[i].id);
175 } 200 }
176 delete this.idToNodeMap_[id]; 201 delete this.idToNodeMap_[id];
177 }, 202 },
178 203
204
179 /** 205 /**
180 * Remove all selected items in the list. 206 * Remove all selected items in the list.
181 * @private 207 * @private
182 */ 208 */
183 clearSelectedItems_: function() { 209 clearSelectedItems_: function() {
184 if (!this.displayedList) 210 if (!this.displayedList)
185 return; 211 return;
186 212
187 for (var i = 0; i < this.displayedList.length; i++) { 213 for (var i = 0; i < this.displayedList.length; i++) {
188 if (!this.displayedList[i].isSelectedItem) 214 if (!this.displayedList[i].isSelectedItem)
189 continue; 215 continue;
190
191 this.set('displayedList.#' + i + '.isSelectedItem', false); 216 this.set('displayedList.#' + i + '.isSelectedItem', false);
192 } 217 }
193 }, 218 },
194 219
195 /** 220 /**
196 * Return the index in the search result of an item. 221 * Return the index in the search result of an item.
197 * @param {BookmarkTreeNode} item 222 * @param {BookmarkTreeNode} item
198 * @return {number} 223 * @return {number}
199 * @private 224 * @private
200 */ 225 */
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // indexes will have changed and Polymer doesn't update them. 308 // indexes will have changed and Polymer doesn't update them.
284 this.removeDescendantsFromMap_(id); 309 this.removeDescendantsFromMap_(id);
285 parentNode.path = this.idToNodeMap_[parentNode.id].path; 310 parentNode.path = this.idToNodeMap_[parentNode.id].path;
286 BookmarksStore.generatePaths(parentNode, 0); 311 BookmarksStore.generatePaths(parentNode, 0);
287 BookmarksStore.initNodes(parentNode, this.idToNodeMap_); 312 BookmarksStore.initNodes(parentNode, this.idToNodeMap_);
288 this.set(parentNode.path, parentNode); 313 this.set(parentNode.path, parentNode);
289 314
290 // Updates selectedId if the removed node is an ancestor of the current 315 // Updates selectedId if the removed node is an ancestor of the current
291 // selected node. 316 // selected node.
292 if (isAncestor) 317 if (isAncestor)
293 this.fire('selected-folder-changed', removeInfo.parentId); 318 this.selectFolder(removeInfo.parentId);
294 319
295 // Only update the displayedList if the removed node is in the 320 // Only update the displayedList if the removed node is in the
296 // displayedList. 321 // displayedList.
297 if (!wasInDisplayedList) 322 if (!wasInDisplayedList)
298 return; 323 return;
299 324
300 this.anchorIndex_ = null; 325 this.anchorIndex_ = null;
301 326
302 // Update the currently displayed list. 327 // Update the currently displayed list.
303 if (this.searchTerm) { 328 if (this.searchTerm) {
304 this.updateSearchDisplay_(); 329 this.updateSearchDisplay_();
305 } else { 330 } else {
306 if (!isAncestor) 331 if (!isAncestor)
307 this.fire('selected-folder-changed', this.selectedId); 332 this.selectFolder(this.selectedId);
308 333
309 this._setDisplayedList(parentNode.children); 334 this._setDisplayedList(parentNode.children);
310 } 335 }
311 }.bind(this)); 336 }.bind(this));
312 }, 337 },
313 338
314 /** 339 /**
315 * Called when the title of a bookmark changes. 340 * Called when the title of a bookmark changes.
316 * @param {string} id The id of changed bookmark node. 341 * @param {string} id The id of changed bookmark node.
317 * @param {!Object} changeInfo 342 * @param {!Object} changeInfo
(...skipping 19 matching lines...) Expand all
337 this.searchTerm = /** @type {string} */ (e.detail); 362 this.searchTerm = /** @type {string} */ (e.detail);
338 }, 363 },
339 364
340 /** 365 /**
341 * Selects the folder specified by the event and deselects the previously 366 * Selects the folder specified by the event and deselects the previously
342 * selected folder. 367 * selected folder.
343 * @param {CustomEvent} e 368 * @param {CustomEvent} e
344 * @private 369 * @private
345 */ 370 */
346 onSelectedFolderChanged_: function(e) { 371 onSelectedFolderChanged_: function(e) {
347 if (this.searchTerm) 372 if (/** @type {boolean} */ (e.detail.clearSearch))
348 this.searchTerm = ''; 373 this.searchTerm = '';
349 374
350 // Deselect the old folder if defined. 375 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 folder = this.idToNodeMap_[id];
361 this.set(folder.path + '.isSelectedFolder', true);
362 this.selectedId = id;
363
364 if (folder.id == this.rootNode.id)
365 return;
366
367 var parent = this.idToNodeMap_[/** @type {?string} */ (folder.parentId)];
368 while (parent) {
369 if (!parent.isOpen) {
370 this.fire('folder-open-changed', {
371 id: parent.id,
372 open: true,
373 });
374 }
375
376 parent = this.idToNodeMap_[/** @type {?string} */ (parent.parentId)];
377 }
378 }, 376 },
379 377
380 /** 378 /**
381 * Handles events that open and close folders. 379 * Handles events that open and close folders.
382 * @param {CustomEvent} e 380 * @param {CustomEvent} e
383 * @private 381 * @private
384 */ 382 */
385 onFolderOpenChanged_: function(e) { 383 onFolderOpenChanged_: function(e) {
386 var folder = this.idToNodeMap_[e.detail.id]; 384 var folder = this.idToNodeMap_[e.detail.id];
387 this.set(folder.path + '.isOpen', e.detail.open); 385 this.set(folder.path + '.isOpen', e.detail.open);
388 if (!folder.isOpen && this.isAncestorOfSelected_(folder)) 386 if (!folder.isOpen && this.isAncestorOfSelected_(folder))
389 this.fire('selected-folder-changed', folder.id); 387 this.selectFolder(folder.id);
390 }, 388 },
391 389
392 /** 390 /**
393 * Selects items according to keyboard behaviours. 391 * Selects items according to keyboard behaviours.
394 * @param {CustomEvent} e 392 * @param {CustomEvent} e
395 * @private 393 * @private
396 */ 394 */
397 onItemSelected_: function(e) { 395 onItemSelected_: function(e) {
398 if (!e.detail.add) 396 if (!e.detail.add)
399 this.clearSelectedItems_(); 397 this.clearSelectedItems_();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 idToNodeMap[bookmarkNode.id] = bookmarkNode; 435 idToNodeMap[bookmarkNode.id] = bookmarkNode;
438 436
439 if (bookmarkNode.url) 437 if (bookmarkNode.url)
440 return; 438 return;
441 439
442 bookmarkNode.isSelectedFolder = false; 440 bookmarkNode.isSelectedFolder = false;
443 bookmarkNode.isOpen = true; 441 bookmarkNode.isOpen = true;
444 for (var i = 0; i < bookmarkNode.children.length; i++) 442 for (var i = 0; i < bookmarkNode.children.length; i++)
445 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap); 443 BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap);
446 }; 444 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/md_bookmarks/router.js ('k') | chrome/test/data/webui/md_bookmarks/sidebar_test.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698