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 | |
166 bmm.tree = this; | |
167 }, | 170 }, |
168 | 171 |
169 handleBookmarkChanged: function(id, changeInfo) { | 172 handleBookmarkChanged: function(id, changeInfo) { |
170 var treeItem = treeLookup[id]; | 173 var treeItem = treeLookup[id]; |
171 if (treeItem) | 174 if (treeItem) |
172 treeItem.label = treeItem.bookmarkNode.title = changeInfo.title; | 175 treeItem.label = treeItem.bookmarkNode.title = changeInfo.title; |
173 }, | 176 }, |
174 | 177 |
| 178 /** |
| 179 * @param {string} id |
| 180 * @param {ReorderInfo} reorderInfo |
| 181 */ |
175 handleChildrenReordered: function(id, reorderInfo) { | 182 handleChildrenReordered: function(id, reorderInfo) { |
176 var parentItem = treeLookup[id]; | 183 var parentItem = treeLookup[id]; |
177 // The tree only contains folders. | 184 // The tree only contains folders. |
178 var dirIds = reorderInfo.childIds.filter(function(id) { | 185 var dirIds = reorderInfo.childIds.filter(function(id) { |
179 return id in treeLookup; | 186 return id in treeLookup; |
180 }).forEach(function(id, i) { | 187 }).forEach(function(id, i) { |
181 parentItem.addAt(treeLookup[id], i); | 188 parentItem.addAt(treeLookup[id], i); |
182 }); | 189 }); |
183 }, | 190 }, |
184 | 191 |
185 handleCreated: function(id, bookmarkNode) { | 192 handleCreated: function(id, bookmarkNode) { |
186 if (bmm.isFolder(bookmarkNode)) { | 193 if (bmm.isFolder(bookmarkNode)) { |
187 var parentItem = treeLookup[bookmarkNode.parentId]; | 194 var parentItem = treeLookup[bookmarkNode.parentId]; |
188 var newItem = new BookmarkTreeItem(bookmarkNode); | 195 var newItem = new BookmarkTreeItem(bookmarkNode); |
189 addTreeItem(parentItem, newItem); | 196 addTreeItem(parentItem, newItem); |
190 } | 197 } |
191 }, | 198 }, |
192 | 199 |
| 200 /** |
| 201 * @param {string} id |
| 202 * @param {MoveInfo} moveInfo |
| 203 */ |
193 handleMoved: function(id, moveInfo) { | 204 handleMoved: function(id, moveInfo) { |
194 var treeItem = treeLookup[id]; | 205 var treeItem = treeLookup[id]; |
195 if (treeItem) { | 206 if (treeItem) { |
196 var oldParentItem = treeLookup[moveInfo.oldParentId]; | 207 var oldParentItem = treeLookup[moveInfo.oldParentId]; |
197 oldParentItem.remove(treeItem); | 208 oldParentItem.remove(treeItem); |
198 var newParentItem = treeLookup[moveInfo.parentId]; | 209 var newParentItem = treeLookup[moveInfo.parentId]; |
199 // The tree only shows folders so the index is not the index we want. We | 210 // 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. | 211 // therefore get the children need to adjust the index. |
201 addTreeItem(newParentItem, treeItem); | 212 addTreeItem(newParentItem, treeItem); |
202 } | 213 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 * nodes to be added. | 266 * nodes to be added. |
256 * @return {boolean} Whether any directories where added. | 267 * @return {boolean} Whether any directories where added. |
257 */ | 268 */ |
258 function buildTreeItems(parentTreeItem, bookmarkNodes) { | 269 function buildTreeItems(parentTreeItem, bookmarkNodes) { |
259 var hasDirectories = false; | 270 var hasDirectories = false; |
260 for (var i = 0, bookmarkNode; bookmarkNode = bookmarkNodes[i]; i++) { | 271 for (var i = 0, bookmarkNode; bookmarkNode = bookmarkNodes[i]; i++) { |
261 if (bmm.isFolder(bookmarkNode)) { | 272 if (bmm.isFolder(bookmarkNode)) { |
262 hasDirectories = true; | 273 hasDirectories = true; |
263 var item = new BookmarkTreeItem(bookmarkNode); | 274 var item = new BookmarkTreeItem(bookmarkNode); |
264 parentTreeItem.add(item); | 275 parentTreeItem.add(item); |
265 var anyChildren = buildTreeItems(item, bookmarkNode.children); | 276 var children = assert(bookmarkNode.children); |
| 277 var anyChildren = buildTreeItems(item, children); |
266 item.expanded = anyChildren && expandedManager.get(bookmarkNode.id); | 278 item.expanded = anyChildren && expandedManager.get(bookmarkNode.id); |
267 } | 279 } |
268 } | 280 } |
269 return hasDirectories; | 281 return hasDirectories; |
270 } | 282 } |
271 | 283 |
272 var self = this; | 284 var self = this; |
273 chrome.bookmarkManagerPrivate.getSubtree('', true, function(root) { | 285 chrome.bookmarkManagerPrivate.getSubtree('', true, function(root) { |
274 self.clear(); | 286 self.clear(); |
275 buildTreeItems(self, root[0].children); | 287 buildTreeItems(self, root[0].children); |
(...skipping 18 matching lines...) Expand all Loading... |
294 Tree.prototype.remove.call(this, child); | 306 Tree.prototype.remove.call(this, child); |
295 if (child.bookmarkNode) | 307 if (child.bookmarkNode) |
296 delete treeLookup[child.bookmarkNode.id]; | 308 delete treeLookup[child.bookmarkNode.id]; |
297 } | 309 } |
298 }; | 310 }; |
299 | 311 |
300 return { | 312 return { |
301 BookmarkTree: BookmarkTree, | 313 BookmarkTree: BookmarkTree, |
302 BookmarkTreeItem: BookmarkTreeItem, | 314 BookmarkTreeItem: BookmarkTreeItem, |
303 treeLookup: treeLookup, | 315 treeLookup: treeLookup, |
304 tree: tree, | 316 get tree() { |
| 317 return $('tree'); |
| 318 }, |
305 ROOT_ID: ROOT_ID | 319 ROOT_ID: ROOT_ID |
306 }; | 320 }; |
307 }); | 321 }); |
OLD | NEW |