BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / resources / bookmark_manager / js / bmm.js
blob06fd50d97ea7d7332dbf273e7dcbacc0df0f52f0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr.define('bmm', function() {
6 'use strict';
8 /**
9 * Whether a node contains another node.
10 * TODO(yosin): Once JavaScript style guide is updated and linter follows
11 * that, we'll remove useless documentations for |parent| and |descendant|.
12 * TODO(yosin): bmm.contains() should be method of BookmarkTreeNode.
13 * @param {!BookmarkTreeNode} parent .
14 * @param {!BookmarkTreeNode} descendant .
15 * @return {boolean} Whether the parent contains the descendant.
17 function contains(parent, descendant) {
18 if (descendant.parentId == parent.id)
19 return true;
20 // the bmm.treeLookup contains all folders
21 var parentTreeItem = bmm.treeLookup[descendant.parentId];
22 if (!parentTreeItem || !parentTreeItem.bookmarkNode)
23 return false;
24 return this.contains(parent, parentTreeItem.bookmarkNode);
27 /**
28 * @param {!BookmarkTreeNode} node The node to test.
29 * @return {boolean} Whether a bookmark node is a folder.
31 function isFolder(node) {
32 return !('url' in node);
35 var loadingPromises = {};
37 /**
38 * Promise version of chrome.bookmarkManagerPrivate.getSubtree.
39 * @param {string} id .
40 * @param {boolean} foldersOnly .
41 * @return {!Promise<!Array<!BookmarkTreeNode>>} .
43 function getSubtreePromise(id, foldersOnly) {
44 return new Promise(function(resolve, reject) {
45 chrome.bookmarkManagerPrivate.getSubtree(id, foldersOnly, function(node) {
46 if (chrome.runtime.lastError) {
47 reject(new Error(chrome.runtime.lastError.message));
48 return;
50 resolve(node);
51 });
52 });
55 /**
56 * Loads a subtree of the bookmark tree and returns a {@code Promise} that
57 * will be fulfilled when done. This reuses multiple loads so that we do not
58 * load the same subtree more than once at the same time.
59 * @return {!Promise<!BookmarkTreeNode>} The future promise for the load.
61 function loadSubtree(id) {
62 if (!loadingPromises[id]) {
63 loadingPromises[id] = getSubtreePromise(id, false).then(function(nodes) {
64 return nodes && nodes[0];
65 }, function(error) {
66 console.error(error.message);
67 });
68 loadingPromises[id].then(function() {
69 delete loadingPromises[id];
70 });
72 return loadingPromises[id];
75 /**
76 * Loads the entire bookmark tree and returns a {@code Promise} that will
77 * be fulfilled when done. This reuses multiple loads so that we do not load
78 * the same tree more than once at the same time.
79 * @return {!Promise<!BookmarkTreeNode>} The future promise for the load.
81 function loadTree() {
82 return loadSubtree('');
85 var bookmarkCache = {
86 /**
87 * Removes the cached item from both the list and tree lookups.
89 remove: function(id) {
90 var treeItem = bmm.treeLookup[id];
91 if (treeItem) {
92 var items = treeItem.items; // is an HTMLCollection
93 for (var i = 0; i < items.length; ++i) {
94 var item = items[i];
95 var bookmarkNode = item.bookmarkNode;
96 delete bmm.treeLookup[bookmarkNode.id];
98 delete bmm.treeLookup[id];
103 * Updates the underlying bookmark node for the tree items and list items by
104 * querying the bookmark backend.
105 * @param {string} id The id of the node to update the children for.
106 * @param {Function=} opt_f A funciton to call when done.
108 updateChildren: function(id, opt_f) {
109 function updateItem(bookmarkNode) {
110 var treeItem = bmm.treeLookup[bookmarkNode.id];
111 if (treeItem) {
112 treeItem.bookmarkNode = bookmarkNode;
116 chrome.bookmarks.getChildren(id, function(children) {
117 if (children)
118 children.forEach(updateItem);
120 if (opt_f)
121 opt_f(children);
127 * Called when the title of a bookmark changes.
128 * @param {string} id The id of changed bookmark node.
129 * @param {!Object} changeInfo The information about how the node changed.
131 function handleBookmarkChanged(id, changeInfo) {
132 if (bmm.tree)
133 bmm.tree.handleBookmarkChanged(id, changeInfo);
134 if (bmm.list)
135 bmm.list.handleBookmarkChanged(id, changeInfo);
139 * Callback for when the user reorders by title.
140 * @param {string} id The id of the bookmark folder that was reordered.
141 * @param {!Object} reorderInfo The information about how the items where
142 * reordered.
144 function handleChildrenReordered(id, reorderInfo) {
145 if (bmm.tree)
146 bmm.tree.handleChildrenReordered(id, reorderInfo);
147 if (bmm.list)
148 bmm.list.handleChildrenReordered(id, reorderInfo);
149 bookmarkCache.updateChildren(id);
153 * Callback for when a bookmark node is created.
154 * @param {string} id The id of the newly created bookmark node.
155 * @param {!Object} bookmarkNode The new bookmark node.
157 function handleCreated(id, bookmarkNode) {
158 if (bmm.list)
159 bmm.list.handleCreated(id, bookmarkNode);
160 if (bmm.tree)
161 bmm.tree.handleCreated(id, bookmarkNode);
162 bookmarkCache.updateChildren(bookmarkNode.parentId);
166 * Callback for when a bookmark node is moved.
167 * @param {string} id The id of the moved bookmark node.
168 * @param {!Object} moveInfo The information about move.
170 function handleMoved(id, moveInfo) {
171 if (bmm.list)
172 bmm.list.handleMoved(id, moveInfo);
173 if (bmm.tree)
174 bmm.tree.handleMoved(id, moveInfo);
176 bookmarkCache.updateChildren(moveInfo.parentId);
177 if (moveInfo.parentId != moveInfo.oldParentId)
178 bookmarkCache.updateChildren(moveInfo.oldParentId);
182 * Callback for when a bookmark node is removed.
183 * @param {string} id The id of the removed bookmark node.
184 * @param {!Object} removeInfo The information about removed.
186 function handleRemoved(id, removeInfo) {
187 if (bmm.list)
188 bmm.list.handleRemoved(id, removeInfo);
189 if (bmm.tree)
190 bmm.tree.handleRemoved(id, removeInfo);
192 bookmarkCache.updateChildren(removeInfo.parentId);
193 bookmarkCache.remove(id);
197 * Callback for when all bookmark nodes have been deleted.
199 function handleRemoveAll() {
200 // Reload the list and the tree.
201 if (bmm.list)
202 bmm.list.reload();
203 if (bmm.tree)
204 bmm.tree.reload();
208 * Callback for when importing bookmark is started.
210 function handleImportBegan() {
211 chrome.bookmarks.onCreated.removeListener(handleCreated);
212 chrome.bookmarks.onChanged.removeListener(handleBookmarkChanged);
216 * Callback for when importing bookmark node is finished.
218 function handleImportEnded() {
219 // When importing is done we reload the tree and the list.
221 function f() {
222 bmm.tree.removeEventListener('load', f);
224 chrome.bookmarks.onCreated.addListener(handleCreated);
225 chrome.bookmarks.onChanged.addListener(handleBookmarkChanged);
227 if (!bmm.list)
228 return;
230 // TODO(estade): this should navigate to the newly imported folder, which
231 // may be the bookmark bar if there were no previous bookmarks.
232 bmm.list.reload();
235 if (bmm.tree) {
236 bmm.tree.addEventListener('load', f);
237 bmm.tree.reload();
242 * Adds the listeners for the bookmark model change events.
244 function addBookmarkModelListeners() {
245 chrome.bookmarks.onChanged.addListener(handleBookmarkChanged);
246 chrome.bookmarks.onChildrenReordered.addListener(handleChildrenReordered);
247 chrome.bookmarks.onCreated.addListener(handleCreated);
248 chrome.bookmarks.onMoved.addListener(handleMoved);
249 chrome.bookmarks.onRemoved.addListener(handleRemoved);
250 chrome.bookmarks.onImportBegan.addListener(handleImportBegan);
251 chrome.bookmarks.onImportEnded.addListener(handleImportEnded);
254 return {
255 contains: contains,
256 isFolder: isFolder,
257 loadSubtree: loadSubtree,
258 loadTree: loadTree,
259 addBookmarkModelListeners: addBookmarkModelListeners