OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 5 |
6 cr.define('bmm', function() { | 6 cr.define('bmm', function() { |
7 /** | 7 /** |
8 * The id of the bookmark root. | 8 * The id of the bookmark root. |
9 * @type {string} | 9 * @type {string} |
10 * @const | 10 * @const |
11 */ | 11 */ |
12 var ROOT_ID = '0'; | 12 var ROOT_ID = '0'; |
13 | 13 |
14 /** @const */ var Tree = cr.ui.Tree; | 14 /** @const */ var Tree = cr.ui.Tree; |
15 /** @const */ var TreeItem = cr.ui.TreeItem; | 15 /** @const */ var TreeItem = cr.ui.TreeItem; |
| 16 /** @const */ var localStorage = window.localStorage; |
16 | 17 |
17 var treeLookup = {}; | 18 var treeLookup = {}; |
18 var tree; | |
19 | 19 |
20 // Manager for persisting the expanded state. | 20 // Manager for persisting the expanded state. |
21 var expandedManager = { | 21 var expandedManager = /** @type {EventListener} */({ |
22 /** | 22 /** |
23 * A map of the collapsed IDs. | 23 * A map of the collapsed IDs. |
24 * @type {Object} | 24 * @type {Object} |
25 */ | 25 */ |
26 map: 'bookmarkTreeState' in localStorage ? | 26 map: 'bookmarkTreeState' in localStorage ? |
27 JSON.parse(localStorage['bookmarkTreeState']) : {}, | 27 /** @type {Object} */(JSON.parse(localStorage['bookmarkTreeState'])) : |
| 28 {}, |
28 | 29 |
29 /** | 30 /** |
30 * Set the collapsed state for an ID. | 31 * Set the collapsed state for an ID. |
31 * @param {string} The bookmark ID of the tree item that was expanded or | 32 * @param {string} id The bookmark ID of the tree item that was expanded or |
32 * collapsed. | 33 * collapsed. |
33 * @param {boolean} expanded Whether the tree item was expanded. | 34 * @param {boolean} expanded Whether the tree item was expanded. |
34 */ | 35 */ |
35 set: function(id, expanded) { | 36 set: function(id, expanded) { |
36 if (expanded) | 37 if (expanded) |
37 delete this.map[id]; | 38 delete this.map[id]; |
38 else | 39 else |
39 this.map[id] = 1; | 40 this.map[id] = 1; |
40 | 41 |
41 this.save(); | 42 this.save(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 * Saves the expanded state to the localStorage. | 77 * Saves the expanded state to the localStorage. |
77 */ | 78 */ |
78 save: function() { | 79 save: function() { |
79 clearTimeout(this.timer); | 80 clearTimeout(this.timer); |
80 var map = this.map; | 81 var map = this.map; |
81 // Save in a timeout so that we can coalesce multiple changes. | 82 // Save in a timeout so that we can coalesce multiple changes. |
82 this.timer = setTimeout(function() { | 83 this.timer = setTimeout(function() { |
83 localStorage['bookmarkTreeState'] = JSON.stringify(map); | 84 localStorage['bookmarkTreeState'] = JSON.stringify(map); |
84 }, 100); | 85 }, 100); |
85 } | 86 } |
86 }; | 87 }); |
87 | 88 |
88 // Clean up once per session but wait until things settle down a bit. | 89 // Clean up once per session but wait until things settle down a bit. |
89 setTimeout(expandedManager.cleanUp.bind(expandedManager), 1e4); | 90 setTimeout(expandedManager.cleanUp.bind(expandedManager), 1e4); |
90 | 91 |
91 /** | 92 /** |
92 * Creates a new tree item for a bookmark node. | 93 * Creates a new tree item for a bookmark node. |
93 * @param {!Object} bookmarkNode The bookmark node. | 94 * @param {!Object} bookmarkNode The bookmark node. |
94 * @constructor | 95 * @constructor |
95 * @extends {TreeItem} | 96 * @extends {TreeItem} |
96 */ | 97 */ |
(...skipping 27 matching lines...) Expand all Loading... |
124 * | 125 * |
125 * Since the bookmark tree only contains folders the index we get from certain | 126 * Since the bookmark tree only contains folders the index we get from certain |
126 * callbacks is not very useful so we therefore have this async call which | 127 * callbacks is not very useful so we therefore have this async call which |
127 * gets the children of the parent and adds the tree item at the desired | 128 * gets the children of the parent and adds the tree item at the desired |
128 * index. | 129 * index. |
129 * | 130 * |
130 * This also exoands the parent so that newly added children are revealed. | 131 * This also exoands the parent so that newly added children are revealed. |
131 * | 132 * |
132 * @param {!cr.ui.TreeItem} parent The parent tree item. | 133 * @param {!cr.ui.TreeItem} parent The parent tree item. |
133 * @param {!cr.ui.TreeItem} treeItem The tree item to add. | 134 * @param {!cr.ui.TreeItem} treeItem The tree item to add. |
134 * @param {Function=} f A function which gets called after the item has been | 135 * @param {Function=} opt_f A function which gets called after the item has |
135 * added at the right index. | 136 * been added at the right index. |
136 */ | 137 */ |
137 function addTreeItem(parent, treeItem, opt_f) { | 138 function addTreeItem(parent, treeItem, opt_f) { |
138 chrome.bookmarks.getChildren(parent.bookmarkNode.id, function(children) { | 139 chrome.bookmarks.getChildren(parent.bookmarkNode.id, function(children) { |
139 var index = children.filter(bmm.isFolder).map(function(item) { | 140 var isFolder = /** |
| 141 * @type {function (BookmarkTreeNode, number, |
| 142 * Array.<(BookmarkTreeNode)>)} |
| 143 */(bmm.isFolder); |
| 144 var index = children.filter(isFolder).map(function(item) { |
140 return item.id; | 145 return item.id; |
141 }).indexOf(treeItem.bookmarkNode.id); | 146 }).indexOf(treeItem.bookmarkNode.id); |
142 parent.addAt(treeItem, index); | 147 parent.addAt(treeItem, index); |
143 parent.expanded = true; | 148 parent.expanded = true; |
144 if (opt_f) | 149 if (opt_f) |
145 opt_f(); | 150 opt_f(); |
146 }); | 151 }); |
147 } | 152 } |
148 | 153 |
149 | 154 |
150 /** | 155 /** |
151 * Creates a new bookmark list. | 156 * Creates a new bookmark list. |
152 * @param {Object=} opt_propertyBag Optional properties. | 157 * @param {Object=} opt_propertyBag Optional properties. |
153 * @constructor | 158 * @constructor |
154 * @extends {HTMLButtonElement} | 159 * @extends {cr.ui.Tree} |
155 */ | 160 */ |
156 var BookmarkTree = cr.ui.define('tree'); | 161 var BookmarkTree = cr.ui.define('tree'); |
157 | 162 |
158 BookmarkTree.prototype = { | 163 BookmarkTree.prototype = { |
159 __proto__: Tree.prototype, | 164 __proto__: Tree.prototype, |
160 | 165 |
161 decorate: function() { | 166 decorate: function() { |
162 Tree.prototype.decorate.call(this); | 167 Tree.prototype.decorate.call(this); |
163 this.addEventListener('expand', expandedManager); | 168 this.addEventListener('expand', expandedManager); |
164 this.addEventListener('collapse', expandedManager); | 169 this.addEventListener('collapse', expandedManager); |
165 | 170 |
166 bmm.tree = this; | 171 bmm.tree = this; |
167 }, | 172 }, |
168 | 173 |
169 handleBookmarkChanged: function(id, changeInfo) { | 174 handleBookmarkChanged: function(id, changeInfo) { |
170 var treeItem = treeLookup[id]; | 175 var treeItem = treeLookup[id]; |
171 if (treeItem) | 176 if (treeItem) |
172 treeItem.label = treeItem.bookmarkNode.title = changeInfo.title; | 177 treeItem.label = treeItem.bookmarkNode.title = changeInfo.title; |
173 }, | 178 }, |
174 | 179 |
| 180 /** |
| 181 * @param {string} id |
| 182 * @param {ReorderInfo} reorderInfo |
| 183 */ |
175 handleChildrenReordered: function(id, reorderInfo) { | 184 handleChildrenReordered: function(id, reorderInfo) { |
176 var parentItem = treeLookup[id]; | 185 var parentItem = treeLookup[id]; |
177 // The tree only contains folders. | 186 // The tree only contains folders. |
178 var dirIds = reorderInfo.childIds.filter(function(id) { | 187 var dirIds = reorderInfo.childIds.filter(function(id) { |
179 return id in treeLookup; | 188 return id in treeLookup; |
180 }).forEach(function(id, i) { | 189 }).forEach(function(id, i) { |
181 parentItem.addAt(treeLookup[id], i); | 190 parentItem.addAt(treeLookup[id], i); |
182 }); | 191 }); |
183 }, | 192 }, |
184 | 193 |
185 handleCreated: function(id, bookmarkNode) { | 194 handleCreated: function(id, bookmarkNode) { |
186 if (bmm.isFolder(bookmarkNode)) { | 195 if (bmm.isFolder(bookmarkNode)) { |
187 var parentItem = treeLookup[bookmarkNode.parentId]; | 196 var parentItem = treeLookup[bookmarkNode.parentId]; |
188 var newItem = new BookmarkTreeItem(bookmarkNode); | 197 var newItem = new BookmarkTreeItem(bookmarkNode); |
189 addTreeItem(parentItem, newItem); | 198 addTreeItem(parentItem, newItem); |
190 } | 199 } |
191 }, | 200 }, |
192 | 201 |
| 202 /** |
| 203 * @param {string} id |
| 204 * @param {MoveInfo} moveInfo |
| 205 */ |
193 handleMoved: function(id, moveInfo) { | 206 handleMoved: function(id, moveInfo) { |
194 var treeItem = treeLookup[id]; | 207 var treeItem = treeLookup[id]; |
195 if (treeItem) { | 208 if (treeItem) { |
196 var oldParentItem = treeLookup[moveInfo.oldParentId]; | 209 var oldParentItem = treeLookup[moveInfo.oldParentId]; |
197 oldParentItem.remove(treeItem); | 210 oldParentItem.remove(treeItem); |
198 var newParentItem = treeLookup[moveInfo.parentId]; | 211 var newParentItem = treeLookup[moveInfo.parentId]; |
199 // The tree only shows folders so the index is not the index we want. We | 212 // The tree only shows folders so the index is not the index we want. We |
200 // therefore get the children need to adjust the index. | 213 // therefore get the children need to adjust the index. |
201 addTreeItem(newParentItem, treeItem); | 214 addTreeItem(newParentItem, treeItem); |
202 } | 215 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 * nodes to be added. | 268 * nodes to be added. |
256 * @return {boolean} Whether any directories where added. | 269 * @return {boolean} Whether any directories where added. |
257 */ | 270 */ |
258 function buildTreeItems(parentTreeItem, bookmarkNodes) { | 271 function buildTreeItems(parentTreeItem, bookmarkNodes) { |
259 var hasDirectories = false; | 272 var hasDirectories = false; |
260 for (var i = 0, bookmarkNode; bookmarkNode = bookmarkNodes[i]; i++) { | 273 for (var i = 0, bookmarkNode; bookmarkNode = bookmarkNodes[i]; i++) { |
261 if (bmm.isFolder(bookmarkNode)) { | 274 if (bmm.isFolder(bookmarkNode)) { |
262 hasDirectories = true; | 275 hasDirectories = true; |
263 var item = new BookmarkTreeItem(bookmarkNode); | 276 var item = new BookmarkTreeItem(bookmarkNode); |
264 parentTreeItem.add(item); | 277 parentTreeItem.add(item); |
265 var anyChildren = buildTreeItems(item, bookmarkNode.children); | 278 var children = assert(bookmarkNode.children); |
| 279 var anyChildren = buildTreeItems(item, children); |
266 item.expanded = anyChildren && expandedManager.get(bookmarkNode.id); | 280 item.expanded = anyChildren && expandedManager.get(bookmarkNode.id); |
267 } | 281 } |
268 } | 282 } |
269 return hasDirectories; | 283 return hasDirectories; |
270 } | 284 } |
271 | 285 |
272 var self = this; | 286 var self = this; |
273 chrome.bookmarkManagerPrivate.getSubtree('', true, function(root) { | 287 chrome.bookmarkManagerPrivate.getSubtree('', true, function(root) { |
274 self.clear(); | 288 self.clear(); |
275 buildTreeItems(self, root[0].children); | 289 buildTreeItems(self, root[0].children); |
(...skipping 18 matching lines...) Expand all Loading... |
294 Tree.prototype.remove.call(this, child); | 308 Tree.prototype.remove.call(this, child); |
295 if (child.bookmarkNode) | 309 if (child.bookmarkNode) |
296 delete treeLookup[child.bookmarkNode.id]; | 310 delete treeLookup[child.bookmarkNode.id]; |
297 } | 311 } |
298 }; | 312 }; |
299 | 313 |
300 return { | 314 return { |
301 BookmarkTree: BookmarkTree, | 315 BookmarkTree: BookmarkTree, |
302 BookmarkTreeItem: BookmarkTreeItem, | 316 BookmarkTreeItem: BookmarkTreeItem, |
303 treeLookup: treeLookup, | 317 treeLookup: treeLookup, |
304 tree: tree, | 318 tree: /** @type {Element} */(null), // Set when decorated. |
305 ROOT_ID: ROOT_ID | 319 ROOT_ID: ROOT_ID |
306 }; | 320 }; |
307 }); | 321 }); |
OLD | NEW |