OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 (function() { | 5 (function() { |
6 /** @const */ var BookmarkList = bmm.BookmarkList; | 6 /** @const */ var BookmarkList = bmm.BookmarkList; |
7 /** @const */ var BookmarkTree = bmm.BookmarkTree; | 7 /** @const */ var BookmarkTree = bmm.BookmarkTree; |
8 /** @const */ var Command = cr.ui.Command; | 8 /** @const */ var Command = cr.ui.Command; |
9 /** @const */ var CommandBinding = cr.ui.CommandBinding; | |
10 /** @const */ var LinkKind = cr.LinkKind; | 9 /** @const */ var LinkKind = cr.LinkKind; |
11 /** @const */ var ListItem = cr.ui.ListItem; | 10 /** @const */ var ListItem = cr.ui.ListItem; |
12 /** @const */ var Menu = cr.ui.Menu; | 11 /** @const */ var Menu = cr.ui.Menu; |
13 /** @const */ var MenuButton = cr.ui.MenuButton; | 12 /** @const */ var MenuButton = cr.ui.MenuButton; |
14 /** @const */ var Splitter = cr.ui.Splitter; | 13 /** @const */ var Splitter = cr.ui.Splitter; |
15 /** @const */ var TreeItem = cr.ui.TreeItem; | 14 /** @const */ var TreeItem = cr.ui.TreeItem; |
16 | 15 |
17 /** | 16 /** |
18 * An array containing the BookmarkTreeNodes that were deleted in the last | 17 * An array containing the BookmarkTreeNodes that were deleted in the last |
19 * deletion action. This is used for implementing undo. | 18 * deletion action. This is used for implementing undo. |
20 * @type {Array.<BookmarkTreeNode>} | 19 * @type {Array.<Array.<BookmarkTreeNode>>} |
21 */ | 20 */ |
22 var lastDeletedNodes; | 21 var lastDeletedNodes; |
23 | 22 |
24 /** | 23 /** |
25 * | 24 * |
26 * Holds the last DOMTimeStamp when mouse pointer hovers on folder in tree | 25 * Holds the last DOMTimeStamp when mouse pointer hovers on folder in tree |
27 * view. Zero means pointer doesn't hover on folder. | 26 * view. Zero means pointer doesn't hover on folder. |
28 * @type {number} | 27 * @type {number} |
29 */ | 28 */ |
30 var lastHoverOnFolderTimeStamp = 0; | 29 var lastHoverOnFolderTimeStamp = 0; |
31 | 30 |
32 /** | 31 /** |
33 * Holds a function that will undo that last action, if global undo is enabled. | 32 * Holds a function that will undo that last action, if global undo is enabled. |
34 * @type {Function} | 33 * @type {Function} |
35 */ | 34 */ |
36 var performGlobalUndo; | 35 var performGlobalUndo; |
37 | 36 |
38 /** | 37 /** |
39 * Holds a link controller singleton. Use getLinkController() rarther than | 38 * Holds a link controller singleton. Use getLinkController() rarther than |
40 * accessing this variabie. | 39 * accessing this variabie. |
41 * @type {LinkController} | 40 * @type {cr.LinkController} |
42 */ | 41 */ |
43 var linkController; | 42 var linkController; |
44 | 43 |
45 /** | 44 /** |
46 * New Windows are not allowed in Windows 8 metro mode. | 45 * New Windows are not allowed in Windows 8 metro mode. |
47 */ | 46 */ |
48 var canOpenNewWindows = true; | 47 var canOpenNewWindows = true; |
49 | 48 |
50 /** | 49 /** |
51 * Incognito mode availability can take the following values: , | 50 * Incognito mode availability can take the following values: , |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 | 134 |
136 searchTreeItem.label = loadTimeData.getString('search'); | 135 searchTreeItem.label = loadTimeData.getString('search'); |
137 searchTreeItem.icon = isRTL() ? 'images/bookmark_manager_search_rtl.png' : | 136 searchTreeItem.icon = isRTL() ? 'images/bookmark_manager_search_rtl.png' : |
138 'images/bookmark_manager_search.png'; | 137 'images/bookmark_manager_search.png'; |
139 } | 138 } |
140 | 139 |
141 /** | 140 /** |
142 * Updates the location hash to reflect the current state of the application. | 141 * Updates the location hash to reflect the current state of the application. |
143 */ | 142 */ |
144 function updateHash() { | 143 function updateHash() { |
145 window.location.hash = tree.selectedItem.bookmarkId; | 144 window.location.hash = $('tree').selectedItem.bookmarkId; |
146 updateAllCommands(); | 145 updateAllCommands(); |
147 } | 146 } |
148 | 147 |
149 /** | 148 /** |
150 * Navigates to a bookmark ID. | 149 * Navigates to a bookmark ID. |
151 * @param {string} id The ID to navigate to. | 150 * @param {string} id The ID to navigate to. |
152 * @param {function()=} opt_callback Function called when list view loaded or | 151 * @param {function()=} opt_callback Function called when list view loaded or |
153 * displayed specified folder. | 152 * displayed specified folder. |
154 */ | 153 */ |
155 function navigateTo(id, opt_callback) { | 154 function navigateTo(id, opt_callback) { |
156 window.location.hash = id; | 155 window.location.hash = id; |
157 updateAllCommands(); | 156 updateAllCommands(); |
158 | 157 |
159 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] || | 158 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] || |
160 folderMetricsNameMap['subfolder']; | 159 folderMetricsNameMap['subfolder']; |
161 chrome.metricsPrivate.recordUserAction( | 160 chrome.metricsPrivate.recordUserAction( |
162 'BookmarkManager_NavigateTo_' + metricsId); | 161 'BookmarkManager_NavigateTo_' + metricsId); |
163 | 162 |
163 var list = getRequiredElement('list'); | |
164 if (opt_callback) { | 164 if (opt_callback) { |
165 if (list.parentId == id) | 165 if (list.parentId == id) { |
Dan Beam
2014/09/24 21:38:58
no curlies now
Vitaly Pavlenko
2014/09/24 22:18:23
Done.
| |
166 opt_callback(); | 166 opt_callback(); |
167 else | 167 } else { |
168 addOneShotEventListener(list, 'load', opt_callback); | 168 addOneShotEventListener(list, 'load', opt_callback); |
169 } | |
169 } | 170 } |
170 } | 171 } |
171 | 172 |
172 /** | 173 /** |
173 * Updates the parent ID of the bookmark list and selects the correct tree item. | 174 * Updates the parent ID of the bookmark list and selects the correct tree item. |
174 * @param {string} id The id. | 175 * @param {string} id The id. |
175 */ | 176 */ |
176 function updateParentId(id) { | 177 function updateParentId(id) { |
177 // Setting list.parentId fires 'load' event. | 178 // Setting list.parentId fires 'load' event. |
178 list.parentId = id; | 179 $('list').parentId = id; |
179 | 180 |
180 // When tree.selectedItem changed, tree view calls navigatTo() then it | 181 // When tree.selectedItem changed, tree view calls navigatTo() then it |
181 // calls updateHash() when list view displayed specified folder. | 182 // calls updateHash() when list view displayed specified folder. |
182 tree.selectedItem = bmm.treeLookup[id] || tree.selectedItem; | 183 $('tree').selectedItem = bmm.treeLookup[id] || $('tree').selectedItem; |
183 } | 184 } |
184 | 185 |
185 // Process the location hash. This is called by onhashchange and when the page | 186 // Process the location hash. This is called by onhashchange and when the page |
186 // is first loaded. | 187 // is first loaded. |
187 function processHash() { | 188 function processHash() { |
188 var id = window.location.hash.slice(1); | 189 var id = window.location.hash.slice(1); |
189 if (!id) { | 190 if (!id) { |
190 // If we do not have a hash, select first item in the tree. | 191 // If we do not have a hash, select first item in the tree. |
191 id = tree.items[0].bookmarkId; | 192 id = $('tree').items[0].bookmarkId; |
192 } | 193 } |
193 | 194 |
194 var valid = false; | 195 var valid = false; |
195 if (/^e=/.test(id)) { | 196 if (/^e=/.test(id)) { |
196 id = id.slice(2); | 197 id = id.slice(2); |
197 | 198 |
198 // If hash contains e=, edit the item specified. | 199 // If hash contains e=, edit the item specified. |
199 chrome.bookmarks.get(id, function(bookmarkNodes) { | 200 chrome.bookmarks.get(id, function(bookmarkNodes) { |
200 // Verify the node to edit is a valid node. | 201 // Verify the node to edit is a valid node. |
201 if (!bookmarkNodes || bookmarkNodes.length != 1) | 202 if (!bookmarkNodes || bookmarkNodes.length != 1) |
202 return; | 203 return; |
203 var bookmarkNode = bookmarkNodes[0]; | 204 var bookmarkNode = bookmarkNodes[0]; |
204 | 205 |
205 // After the list reloads, edit the desired bookmark. | 206 // After the list reloads, edit the desired bookmark. |
206 var editBookmark = function(e) { | 207 var editBookmark = function() { |
207 var index = list.dataModel.findIndexById(bookmarkNode.id); | 208 var index = $('list').dataModel.findIndexById(bookmarkNode.id); |
208 if (index != -1) { | 209 if (index != -1) { |
209 var sm = list.selectionModel; | 210 var sm = $('list').selectionModel; |
210 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; | 211 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; |
211 scrollIntoViewAndMakeEditable(index); | 212 scrollIntoViewAndMakeEditable(index); |
212 } | 213 } |
213 }; | 214 }; |
214 | 215 |
215 navigateTo(bookmarkNode.parentId, editBookmark); | 216 var parentId = assert(bookmarkNode.parentId); |
217 navigateTo(parentId, editBookmark); | |
216 }); | 218 }); |
217 | 219 |
218 // We handle the two cases of navigating to the bookmark to be edited | 220 // We handle the two cases of navigating to the bookmark to be edited |
219 // above. Don't run the standard navigation code below. | 221 // above. Don't run the standard navigation code below. |
220 return; | 222 return; |
221 } else if (/^q=/.test(id)) { | 223 } else if (/^q=/.test(id)) { |
222 // In case we got a search hash, update the text input and the | 224 // In case we got a search hash, update the text input and the |
223 // bmm.treeLookup to use the new id. | 225 // bmm.treeLookup to use the new id. |
224 setSearch(id.slice(2)); | 226 setSearch(id.slice(2)); |
225 valid = true; | 227 valid = true; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 var id = searchTreeItem.bookmarkId = 'q=' + searchText; | 268 var id = searchTreeItem.bookmarkId = 'q=' + searchText; |
267 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; | 269 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; |
268 } | 270 } |
269 | 271 |
270 var input = $('term'); | 272 var input = $('term'); |
271 // Do not update the input if the user is actively using the text input. | 273 // Do not update the input if the user is actively using the text input. |
272 if (document.activeElement != input) | 274 if (document.activeElement != input) |
273 input.value = searchText; | 275 input.value = searchText; |
274 | 276 |
275 if (searchText) { | 277 if (searchText) { |
276 tree.add(searchTreeItem); | 278 $('tree').add(searchTreeItem); |
277 tree.selectedItem = searchTreeItem; | 279 $('tree').selectedItem = searchTreeItem; |
278 } else { | 280 } else { |
279 // Go "home". | 281 // Go "home". |
280 tree.selectedItem = tree.items[0]; | 282 $('tree').selectedItem = $('tree').items[0]; |
281 id = tree.selectedItem.bookmarkId; | 283 id = $('tree').selectedItem.bookmarkId; |
282 } | 284 } |
283 | 285 |
284 navigateTo(id); | 286 navigateTo(id); |
285 } | 287 } |
286 | 288 |
287 /** | 289 /** |
288 * This returns the user visible path to the folder where the bookmark is | 290 * This returns the user visible path to the folder where the bookmark is |
289 * located. | 291 * located. |
290 * @param {number} parentId The ID of the parent folder. | 292 * @param {number} parentId The ID of the parent folder. |
291 * @return {string} The path to the the bookmark, | 293 * @return {string} The path to the the bookmark, |
292 */ | 294 */ |
293 function getFolder(parentId) { | 295 function getFolder(parentId) { |
294 var parentNode = tree.getBookmarkNodeById(parentId); | 296 var parentNode = $('tree').getBookmarkNodeById(parentId); |
295 if (parentNode) { | 297 if (parentNode) { |
296 var s = parentNode.title; | 298 var s = parentNode.title; |
297 if (parentNode.parentId != bmm.ROOT_ID) { | 299 if (parentNode.parentId != bmm.ROOT_ID) { |
298 return getFolder(parentNode.parentId) + '/' + s; | 300 return getFolder(parentNode.parentId) + '/' + s; |
299 } | 301 } |
300 return s; | 302 return s; |
301 } | 303 } |
302 } | 304 } |
303 | 305 |
304 function handleLoadForTree(e) { | 306 function handleLoadForTree(e) { |
(...skipping 19 matching lines...) Expand all Loading... | |
324 if (!bmm.isFolder(child)) | 326 if (!bmm.isFolder(child)) |
325 urls.push(child.url); | 327 urls.push(child.url); |
326 }); | 328 }); |
327 } else { | 329 } else { |
328 urls.push(node.url); | 330 urls.push(node.url); |
329 } | 331 } |
330 } | 332 } |
331 | 333 |
332 // Get a future promise for the nodes. | 334 // Get a future promise for the nodes. |
333 var promises = nodes.map(function(node) { | 335 var promises = nodes.map(function(node) { |
334 if (bmm.isFolder(node)) | 336 if (bmm.isFolder(assert(node))) |
335 return bmm.loadSubtree(node.id); | 337 return bmm.loadSubtree(node.id); |
336 // Not a folder so we already have all the data we need. | 338 // Not a folder so we already have all the data we need. |
337 return Promise.resolve(node); | 339 return Promise.resolve(node); |
338 }); | 340 }); |
339 | 341 |
340 return Promise.all(promises).then(function(nodes) { | 342 return Promise.all(promises).then(function(nodes) { |
341 nodes.forEach(addNodes); | 343 nodes.forEach(addNodes); |
342 return urls; | 344 return urls; |
343 }); | 345 }); |
344 } | 346 } |
345 | 347 |
346 /** | 348 /** |
347 * Returns the nodes (non recursive) to use for the open commands. | 349 * Returns the nodes (non recursive) to use for the open commands. |
348 * @param {HTMLElement} target . | 350 * @param {HTMLElement} target |
349 * @return {Array.<BookmarkTreeNode>} . | 351 * @return {!Array.<BookmarkTreeNode>} |
350 */ | 352 */ |
351 function getNodesForOpen(target) { | 353 function getNodesForOpen(target) { |
352 if (target == tree) { | 354 if (target == $('tree')) { |
353 if (tree.selectedItem != searchTreeItem) | 355 if ($('tree').selectedItem != searchTreeItem) |
354 return tree.selectedFolders; | 356 return $('tree').selectedFolders; |
355 // Fall through to use all nodes in the list. | 357 // Fall through to use all nodes in the list. |
356 } else { | 358 } else { |
357 var items = list.selectedItems; | 359 var items = $('list').selectedItems; |
358 if (items.length) | 360 if (items.length) |
359 return items; | 361 return items; |
360 } | 362 } |
361 | 363 |
362 // The list starts off with a null dataModel. We can get here during startup. | 364 // The list starts off with a null dataModel. We can get here during startup. |
363 if (!list.dataModel) | 365 if (!$('list').dataModel) |
364 return []; | 366 return []; |
365 | 367 |
366 // Return an array based on the dataModel. | 368 // Return an array based on the dataModel. |
367 return list.dataModel.slice(); | 369 return $('list').dataModel.slice(); |
368 } | 370 } |
369 | 371 |
370 /** | 372 /** |
371 * Returns a promise that will contain all URLs of all the selected bookmarks | 373 * Returns a promise that will contain all URLs of all the selected bookmarks |
372 * and the nested bookmarks for use with the open commands. | 374 * and the nested bookmarks for use with the open commands. |
373 * @param {HTMLElement} target The target list or tree. | 375 * @param {HTMLElement} target The target list or tree. |
374 * @return {Promise.<Array.<string>>} . | 376 * @return {Promise.<Array.<string>>} . |
375 */ | 377 */ |
376 function getUrlsForOpenCommands(target) { | 378 function getUrlsForOpenCommands(target) { |
377 return getAllUrls(getNodesForOpen(target)); | 379 return getAllUrls(getNodesForOpen(target)); |
(...skipping 12 matching lines...) Expand all Loading... | |
390 * @param {string} pluralId The string id of menu label if the singular form is | 392 * @param {string} pluralId The string id of menu label if the singular form is |
391 not used. | 393 not used. |
392 * @param {boolean} commandDisabled Whether the menu item should be disabled | 394 * @param {boolean} commandDisabled Whether the menu item should be disabled |
393 no matter what bookmarks are selected. | 395 no matter what bookmarks are selected. |
394 */ | 396 */ |
395 function updateOpenCommand(e, command, singularId, pluralId, commandDisabled) { | 397 function updateOpenCommand(e, command, singularId, pluralId, commandDisabled) { |
396 if (singularId) { | 398 if (singularId) { |
397 // The command label reflects the selection which might not reflect | 399 // The command label reflects the selection which might not reflect |
398 // how many bookmarks will be opened. For example if you right click an | 400 // how many bookmarks will be opened. For example if you right click an |
399 // empty area in a folder with 1 bookmark the text should still say "all". | 401 // empty area in a folder with 1 bookmark the text should still say "all". |
402 assert(!e.target || e.target instanceof BookmarkList || | |
403 e.target instanceof BookmarkTree); | |
400 var selectedNodes = getSelectedBookmarkNodes(e.target).filter(notNewNode); | 404 var selectedNodes = getSelectedBookmarkNodes(e.target).filter(notNewNode); |
401 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]); | 405 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]); |
402 command.label = loadTimeData.getString(singular ? singularId : pluralId); | 406 command.label = loadTimeData.getString(singular ? singularId : pluralId); |
403 } | 407 } |
404 | 408 |
405 if (commandDisabled) { | 409 if (commandDisabled) { |
406 command.disabled = true; | 410 command.disabled = true; |
407 e.canExecute = false; | 411 e.canExecute = false; |
408 return; | 412 return; |
409 } | 413 } |
410 | 414 |
411 getUrlsForOpenCommands(e.target).then(function(urls) { | 415 getUrlsForOpenCommands(assertInstanceof(e.target, HTMLElement)).then( |
416 function(urls) { | |
412 var disabled = !urls.length; | 417 var disabled = !urls.length; |
413 command.disabled = disabled; | 418 command.disabled = disabled; |
414 e.canExecute = !disabled; | 419 e.canExecute = !disabled; |
415 }); | 420 }); |
416 } | 421 } |
417 | 422 |
418 /** | 423 /** |
419 * Calls the backend to figure out if we can paste the clipboard into the active | 424 * Calls the backend to figure out if we can paste the clipboard into the active |
420 * folder. | 425 * folder. |
421 * @param {Function=} opt_f Function to call after the state has been updated. | 426 * @param {Function=} opt_f Function to call after the state has been updated. |
422 */ | 427 */ |
423 function updatePasteCommand(opt_f) { | 428 function updatePasteCommand(opt_f) { |
424 function update(canPaste) { | 429 function update(canPaste) { |
425 var organizeMenuCommand = $('paste-from-organize-menu-command'); | 430 var organizeMenuCommand = $('paste-from-organize-menu-command'); |
426 var contextMenuCommand = $('paste-from-context-menu-command'); | 431 var contextMenuCommand = $('paste-from-context-menu-command'); |
427 organizeMenuCommand.disabled = !canPaste; | 432 organizeMenuCommand.disabled = !canPaste; |
428 contextMenuCommand.disabled = !canPaste; | 433 contextMenuCommand.disabled = !canPaste; |
429 if (opt_f) | 434 if (opt_f) |
430 opt_f(); | 435 opt_f(); |
431 } | 436 } |
432 // We cannot paste into search view. | 437 // We cannot paste into search view. |
433 if (list.isSearch()) | 438 if ($('list').isSearch()) |
434 update(false); | 439 update(false); |
435 else | 440 else |
436 chrome.bookmarkManagerPrivate.canPaste(list.parentId, update); | 441 chrome.bookmarkManagerPrivate.canPaste($('list').parentId, update); |
437 } | 442 } |
438 | 443 |
439 function handleCanExecuteForDocument(e) { | 444 function handleCanExecuteForDocument(e) { |
440 var command = e.command; | 445 var command = e.command; |
441 switch (command.id) { | 446 switch (command.id) { |
442 case 'import-menu-command': | 447 case 'import-menu-command': |
443 e.canExecute = canEdit; | 448 e.canExecute = canEdit; |
444 break; | 449 break; |
445 case 'export-menu-command': | 450 case 'export-menu-command': |
446 // We can always execute the export-menu command. | 451 // We can always execute the export-menu command. |
447 e.canExecute = true; | 452 e.canExecute = true; |
448 break; | 453 break; |
449 case 'sort-command': | 454 case 'sort-command': |
450 e.canExecute = !list.isSearch() && | 455 e.canExecute = !$('list').isSearch() && |
451 list.dataModel && list.dataModel.length > 1 && | 456 $('list').dataModel && $('list').dataModel.length > 1 && |
452 !isUnmodifiable(tree.getBookmarkNodeById(list.parentId)); | 457 !isUnmodifiable($('tree').getBookmarkNodeById($('list').parentId)); |
453 break; | 458 break; |
454 case 'undo-command': | 459 case 'undo-command': |
455 // If the search box is active, pass the undo command through | 460 // If the search box is active, pass the undo command through |
456 // (fixes http://crbug.com/278112). Otherwise, because | 461 // (fixes http://crbug.com/278112). Otherwise, because |
457 // the global undo command has no visible UI, always enable it, and | 462 // the global undo command has no visible UI, always enable it, and |
458 // just make it a no-op if undo is not possible. | 463 // just make it a no-op if undo is not possible. |
459 e.canExecute = e.currentTarget.activeElement !== $('term'); | 464 e.canExecute = e.currentTarget.activeElement !== $('term'); |
460 break; | 465 break; |
461 default: | 466 default: |
462 canExecuteForList(e); | 467 canExecuteForList(e); |
463 break; | 468 break; |
464 } | 469 } |
465 } | 470 } |
466 | 471 |
467 /** | 472 /** |
468 * Helper function for handling canExecute for the list and the tree. | 473 * Helper function for handling canExecute for the list and the tree. |
469 * @param {!Event} e Can execute event object. | 474 * @param {!cr.ui.CanExecuteEvent} e Can execute event object. |
470 * @param {boolean} isSearch Whether the user is trying to do a command on | 475 * @param {boolean} isSearch Whether the user is trying to do a command on |
471 * search. | 476 * search. |
472 */ | 477 */ |
473 function canExecuteShared(e, isSearch) { | 478 function canExecuteShared(e, isSearch) { |
474 var command = e.command; | 479 var command = e.command; |
475 var commandId = command.id; | 480 var commandId = command.id; |
476 switch (commandId) { | 481 switch (commandId) { |
477 case 'paste-from-organize-menu-command': | 482 case 'paste-from-organize-menu-command': |
478 case 'paste-from-context-menu-command': | 483 case 'paste-from-context-menu-command': |
479 updatePasteCommand(); | 484 updatePasteCommand(); |
480 break; | 485 break; |
481 | 486 |
482 case 'add-new-bookmark-command': | 487 case 'add-new-bookmark-command': |
483 case 'new-folder-command': | 488 case 'new-folder-command': |
484 var parentId = computeParentFolderForNewItem(); | 489 var parentId = computeParentFolderForNewItem(); |
485 var unmodifiable = isUnmodifiable(tree.getBookmarkNodeById(parentId)); | 490 var unmodifiable = isUnmodifiable( |
491 $('tree').getBookmarkNodeById(parentId)); | |
486 e.canExecute = !isSearch && canEdit && !unmodifiable; | 492 e.canExecute = !isSearch && canEdit && !unmodifiable; |
487 break; | 493 break; |
488 | 494 |
489 case 'open-in-new-tab-command': | 495 case 'open-in-new-tab-command': |
490 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false); | 496 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false); |
491 break; | 497 break; |
492 case 'open-in-background-tab-command': | 498 case 'open-in-background-tab-command': |
493 updateOpenCommand(e, command, '', '', false); | 499 updateOpenCommand(e, command, '', '', false); |
494 break; | 500 break; |
495 case 'open-in-new-window-command': | 501 case 'open-in-new-window-command': |
(...skipping 10 matching lines...) Expand all Loading... | |
506 break; | 512 break; |
507 | 513 |
508 case 'undo-delete-command': | 514 case 'undo-delete-command': |
509 e.canExecute = !!lastDeletedNodes; | 515 e.canExecute = !!lastDeletedNodes; |
510 break; | 516 break; |
511 } | 517 } |
512 } | 518 } |
513 | 519 |
514 /** | 520 /** |
515 * Helper function for handling canExecute for the list and document. | 521 * Helper function for handling canExecute for the list and document. |
516 * @param {!Event} e Can execute event object. | 522 * @param {!cr.ui.CanExecuteEvent} e Can execute event object. |
517 */ | 523 */ |
518 function canExecuteForList(e) { | 524 function canExecuteForList(e) { |
519 var command = e.command; | 525 var command = e.command; |
520 var commandId = command.id; | 526 var commandId = command.id; |
521 | 527 |
522 function hasSelected() { | 528 function hasSelected() { |
523 return !!list.selectedItem; | 529 return !!$('list').selectedItem; |
524 } | 530 } |
525 | 531 |
526 function hasSingleSelected() { | 532 function hasSingleSelected() { |
527 return list.selectedItems.length == 1; | 533 return $('list').selectedItems.length == 1; |
528 } | 534 } |
529 | 535 |
530 function canCopyItem(item) { | 536 function canCopyItem(item) { |
531 return item.id != 'new'; | 537 return item.id != 'new'; |
532 } | 538 } |
533 | 539 |
534 function canCopyItems() { | 540 function canCopyItems() { |
535 var selectedItems = list.selectedItems; | 541 var selectedItems = $('list').selectedItems; |
536 return selectedItems && selectedItems.some(canCopyItem); | 542 return selectedItems && selectedItems.some(canCopyItem); |
537 } | 543 } |
538 | 544 |
539 function isSearch() { | 545 function isSearch() { |
540 return list.isSearch(); | 546 return $('list').isSearch(); |
541 } | 547 } |
542 | 548 |
543 switch (commandId) { | 549 switch (commandId) { |
544 case 'rename-folder-command': | 550 case 'rename-folder-command': |
545 // Show rename if a single folder is selected. | 551 // Show rename if a single folder is selected. |
546 var items = list.selectedItems; | 552 var items = $('list').selectedItems; |
547 if (items.length != 1) { | 553 if (items.length != 1) { |
548 e.canExecute = false; | 554 e.canExecute = false; |
549 command.hidden = true; | 555 command.hidden = true; |
550 } else { | 556 } else { |
551 var isFolder = bmm.isFolder(items[0]); | 557 var isFolder = bmm.isFolder(items[0]); |
552 e.canExecute = isFolder && canEdit && !hasUnmodifiable(items); | 558 e.canExecute = isFolder && canEdit && !hasUnmodifiable(items); |
553 command.hidden = !isFolder; | 559 command.hidden = !isFolder; |
554 } | 560 } |
555 break; | 561 break; |
556 | 562 |
557 case 'edit-command': | 563 case 'edit-command': |
558 // Show the edit command if not a folder. | 564 // Show the edit command if not a folder. |
559 var items = list.selectedItems; | 565 var items = $('list').selectedItems; |
560 if (items.length != 1) { | 566 if (items.length != 1) { |
561 e.canExecute = false; | 567 e.canExecute = false; |
562 command.hidden = false; | 568 command.hidden = false; |
563 } else { | 569 } else { |
564 var isFolder = bmm.isFolder(items[0]); | 570 var isFolder = bmm.isFolder(items[0]); |
565 e.canExecute = !isFolder && canEdit && !hasUnmodifiable(items); | 571 e.canExecute = !isFolder && canEdit && !hasUnmodifiable(items); |
566 command.hidden = isFolder; | 572 command.hidden = isFolder; |
567 } | 573 } |
568 break; | 574 break; |
569 | 575 |
570 case 'show-in-folder-command': | 576 case 'show-in-folder-command': |
571 e.canExecute = isSearch() && hasSingleSelected(); | 577 e.canExecute = isSearch() && hasSingleSelected(); |
572 break; | 578 break; |
573 | 579 |
574 case 'delete-command': | 580 case 'delete-command': |
575 case 'cut-command': | 581 case 'cut-command': |
576 e.canExecute = canCopyItems() && canEdit && | 582 e.canExecute = canCopyItems() && canEdit && |
577 !hasUnmodifiable(list.selectedItems); | 583 !hasUnmodifiable($('list').selectedItems); |
578 break; | 584 break; |
579 | 585 |
580 case 'copy-command': | 586 case 'copy-command': |
581 e.canExecute = canCopyItems(); | 587 e.canExecute = canCopyItems(); |
582 break; | 588 break; |
583 | 589 |
584 case 'open-in-same-window-command': | 590 case 'open-in-same-window-command': |
585 e.canExecute = hasSelected(); | 591 e.canExecute = hasSelected(); |
586 break; | 592 break; |
587 | 593 |
588 default: | 594 default: |
589 canExecuteShared(e, isSearch()); | 595 canExecuteShared(e, isSearch()); |
590 } | 596 } |
591 } | 597 } |
592 | 598 |
593 // Update canExecute for the commands when the list is the active element. | 599 // Update canExecute for the commands when the list is the active element. |
594 function handleCanExecuteForList(e) { | 600 function handleCanExecuteForList(e) { |
595 if (e.target != list) return; | 601 if (e.target != $('list')) return; |
596 canExecuteForList(e); | 602 canExecuteForList(e); |
597 } | 603 } |
598 | 604 |
599 // Update canExecute for the commands when the tree is the active element. | 605 // Update canExecute for the commands when the tree is the active element. |
600 function handleCanExecuteForTree(e) { | 606 function handleCanExecuteForTree(e) { |
601 if (e.target != tree) return; | 607 if (e.target != $('tree')) return; |
602 | 608 |
603 var command = e.command; | 609 var command = e.command; |
604 var commandId = command.id; | 610 var commandId = command.id; |
605 | 611 |
606 function hasSelected() { | 612 function hasSelected() { |
607 return !!e.target.selectedItem; | 613 return !!e.target.selectedItem; |
608 } | 614 } |
609 | 615 |
610 function isSearch() { | 616 function isSearch() { |
611 var item = e.target.selectedItem; | 617 var item = e.target.selectedItem; |
612 return item == searchTreeItem; | 618 return item == searchTreeItem; |
613 } | 619 } |
614 | 620 |
615 function isTopLevelItem() { | 621 function isTopLevelItem() { |
616 return e.target.selectedItem.parentNode == tree; | 622 return e.target.selectedItem.parentNode == $('tree'); |
617 } | 623 } |
618 | 624 |
619 switch (commandId) { | 625 switch (commandId) { |
620 case 'rename-folder-command': | 626 case 'rename-folder-command': |
621 command.hidden = false; | 627 command.hidden = false; |
622 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && | 628 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && |
623 !hasUnmodifiable(tree.selectedFolders); | 629 !hasUnmodifiable($('tree').selectedFolders); |
624 break; | 630 break; |
625 | 631 |
626 case 'edit-command': | 632 case 'edit-command': |
627 command.hidden = true; | 633 command.hidden = true; |
628 e.canExecute = false; | 634 e.canExecute = false; |
629 break; | 635 break; |
630 | 636 |
631 case 'delete-command': | 637 case 'delete-command': |
632 case 'cut-command': | 638 case 'cut-command': |
633 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && | 639 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && |
634 !hasUnmodifiable(tree.selectedFolders); | 640 !hasUnmodifiable($('tree').selectedFolders); |
635 break; | 641 break; |
636 | 642 |
637 case 'copy-command': | 643 case 'copy-command': |
638 e.canExecute = hasSelected() && !isTopLevelItem(); | 644 e.canExecute = hasSelected() && !isTopLevelItem(); |
639 break; | 645 break; |
640 | 646 |
641 default: | 647 default: |
642 canExecuteShared(e, isSearch()); | 648 canExecuteShared(e, isSearch()); |
643 } | 649 } |
644 } | 650 } |
(...skipping 17 matching lines...) Expand all Loading... | |
662 if (result != canEdit) { | 668 if (result != canEdit) { |
663 canEdit = result; | 669 canEdit = result; |
664 editingCommands.forEach(function(baseId) { | 670 editingCommands.forEach(function(baseId) { |
665 $(baseId + '-command').canExecuteChange(); | 671 $(baseId + '-command').canExecuteChange(); |
666 }); | 672 }); |
667 } | 673 } |
668 }); | 674 }); |
669 } | 675 } |
670 | 676 |
671 function handleChangeForTree(e) { | 677 function handleChangeForTree(e) { |
672 navigateTo(tree.selectedItem.bookmarkId); | 678 navigateTo($('tree').selectedItem.bookmarkId); |
673 } | 679 } |
674 | 680 |
675 function handleOrganizeButtonClick(e) { | 681 function handleOrganizeButtonClick(e) { |
676 updateEditingCommands(); | 682 updateEditingCommands(); |
677 $('add-new-bookmark-command').canExecuteChange(); | 683 $('add-new-bookmark-command').canExecuteChange(); |
678 $('new-folder-command').canExecuteChange(); | 684 $('new-folder-command').canExecuteChange(); |
679 $('sort-command').canExecuteChange(); | 685 $('sort-command').canExecuteChange(); |
680 } | 686 } |
681 | 687 |
682 function handleRename(e) { | 688 function handleRename(e) { |
683 var item = e.target; | 689 var item = e.target; |
684 var bookmarkNode = item.bookmarkNode; | 690 var bookmarkNode = item.bookmarkNode; |
685 chrome.bookmarks.update(bookmarkNode.id, {title: item.label}); | 691 chrome.bookmarks.update(bookmarkNode.id, {title: item.label}); |
686 performGlobalUndo = null; // This can't be undone, so disable global undo. | 692 performGlobalUndo = null; // This can't be undone, so disable global undo. |
687 } | 693 } |
688 | 694 |
689 function handleEdit(e) { | 695 function handleEdit(e) { |
690 var item = e.target; | 696 var item = e.target; |
691 var bookmarkNode = item.bookmarkNode; | 697 var bookmarkNode = item.bookmarkNode; |
692 var context = { | 698 var context = { |
693 title: bookmarkNode.title | 699 title: bookmarkNode.title |
694 }; | 700 }; |
695 if (!bmm.isFolder(bookmarkNode)) | 701 if (!bmm.isFolder(bookmarkNode)) |
696 context.url = bookmarkNode.url; | 702 context.url = bookmarkNode.url; |
697 | 703 |
698 if (bookmarkNode.id == 'new') { | 704 if (bookmarkNode.id == 'new') { |
699 selectItemsAfterUserAction(list); | 705 selectItemsAfterUserAction(/** @type {BookmarkList} */($('list'))); |
700 | 706 |
701 // New page | 707 // New page |
702 context.parentId = bookmarkNode.parentId; | 708 context.parentId = bookmarkNode.parentId; |
703 chrome.bookmarks.create(context, function(node) { | 709 chrome.bookmarks.create(context, function(node) { |
704 // A new node was created and will get added to the list due to the | 710 // A new node was created and will get added to the list due to the |
705 // handler. | 711 // handler. |
706 var dataModel = list.dataModel; | 712 var dataModel = $('list').dataModel; |
707 var index = dataModel.indexOf(bookmarkNode); | 713 var index = dataModel.indexOf(bookmarkNode); |
708 dataModel.splice(index, 1); | 714 dataModel.splice(index, 1); |
709 | 715 |
710 // Select new item. | 716 // Select new item. |
711 var newIndex = dataModel.findIndexById(node.id); | 717 var newIndex = dataModel.findIndexById(node.id); |
712 if (newIndex != -1) { | 718 if (newIndex != -1) { |
713 var sm = list.selectionModel; | 719 var sm = $('list').selectionModel; |
714 list.scrollIndexIntoView(newIndex); | 720 $('list').scrollIndexIntoView(newIndex); |
715 sm.leadIndex = sm.anchorIndex = sm.selectedIndex = newIndex; | 721 sm.leadIndex = sm.anchorIndex = sm.selectedIndex = newIndex; |
716 } | 722 } |
717 }); | 723 }); |
718 } else { | 724 } else { |
719 // Edit | 725 // Edit |
720 chrome.bookmarks.update(bookmarkNode.id, context); | 726 chrome.bookmarks.update(bookmarkNode.id, context); |
721 } | 727 } |
722 performGlobalUndo = null; // This can't be undone, so disable global undo. | 728 performGlobalUndo = null; // This can't be undone, so disable global undo. |
723 } | 729 } |
724 | 730 |
725 function handleCancelEdit(e) { | 731 function handleCancelEdit(e) { |
726 var item = e.target; | 732 var item = e.target; |
727 var bookmarkNode = item.bookmarkNode; | 733 var bookmarkNode = item.bookmarkNode; |
728 if (bookmarkNode.id == 'new') { | 734 if (bookmarkNode.id == 'new') { |
729 var dataModel = list.dataModel; | 735 var dataModel = $('list').dataModel; |
730 var index = dataModel.findIndexById('new'); | 736 var index = dataModel.findIndexById('new'); |
731 dataModel.splice(index, 1); | 737 dataModel.splice(index, 1); |
732 } | 738 } |
733 } | 739 } |
734 | 740 |
735 /** | 741 /** |
736 * Navigates to the folder that the selected item is in and selects it. This is | 742 * Navigates to the folder that the selected item is in and selects it. This is |
737 * used for the show-in-folder command. | 743 * used for the show-in-folder command. |
738 */ | 744 */ |
739 function showInFolder() { | 745 function showInFolder() { |
740 var bookmarkNode = list.selectedItem; | 746 var bookmarkNode = $('list').selectedItem; |
741 if (!bookmarkNode) | 747 if (!bookmarkNode) |
742 return; | 748 return; |
743 var parentId = bookmarkNode.parentId; | 749 var parentId = bookmarkNode.parentId; |
744 | 750 |
745 // After the list is loaded we should select the revealed item. | 751 // After the list is loaded we should select the revealed item. |
746 function selectItem() { | 752 function selectItem() { |
747 var index = list.dataModel.findIndexById(bookmarkNode.id); | 753 var index = $('list').dataModel.findIndexById(bookmarkNode.id); |
748 if (index == -1) | 754 if (index == -1) |
749 return; | 755 return; |
750 var sm = list.selectionModel; | 756 var sm = $('list').selectionModel; |
751 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; | 757 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; |
752 list.scrollIndexIntoView(index); | 758 $('list').scrollIndexIntoView(index); |
753 } | 759 } |
754 | 760 |
755 var treeItem = bmm.treeLookup[parentId]; | 761 var treeItem = bmm.treeLookup[parentId]; |
756 treeItem.reveal(); | 762 treeItem.reveal(); |
757 | 763 |
758 navigateTo(parentId, selectItem); | 764 navigateTo(parentId, selectItem); |
759 } | 765 } |
760 | 766 |
761 /** | 767 /** |
762 * @return {!cr.LinkController} The link controller used to open links based on | 768 * @return {!cr.LinkController} The link controller used to open links based on |
763 * user clicks and keyboard actions. | 769 * user clicks and keyboard actions. |
764 */ | 770 */ |
765 function getLinkController() { | 771 function getLinkController() { |
766 return linkController || | 772 return linkController || |
767 (linkController = new cr.LinkController(loadTimeData)); | 773 (linkController = new cr.LinkController(loadTimeData)); |
768 } | 774 } |
769 | 775 |
770 /** | 776 /** |
771 * Returns the selected bookmark nodes of the provided tree or list. | 777 * Returns the selected bookmark nodes of the provided tree or list. |
772 * If |opt_target| is not provided or null the active element is used. | 778 * If |opt_target| is not provided or null the active element is used. |
773 * Only call this if the list or the tree is focused. | 779 * Only call this if the list or the tree is focused. |
774 * @param {BookmarkList|BookmarkTree} opt_target The target list or tree. | 780 * @param {(BookmarkList|BookmarkTree)=} opt_target The target list or tree. |
775 * @return {!Array} Array of bookmark nodes. | 781 * @return {!Array} Array of bookmark nodes. |
776 */ | 782 */ |
777 function getSelectedBookmarkNodes(opt_target) { | 783 function getSelectedBookmarkNodes(opt_target) { |
778 return (opt_target || document.activeElement) == tree ? | 784 return (opt_target || document.activeElement) == $('tree') ? |
779 tree.selectedFolders : list.selectedItems; | 785 $('tree').selectedFolders : $('list').selectedItems; |
780 } | 786 } |
781 | 787 |
782 /** | 788 /** |
783 * @return {!Array.<string>} An array of the selected bookmark IDs. | 789 * @return {!Array.<string>} An array of the selected bookmark IDs. |
784 */ | 790 */ |
785 function getSelectedBookmarkIds() { | 791 function getSelectedBookmarkIds() { |
786 var selectedNodes = getSelectedBookmarkNodes(); | 792 var selectedNodes = getSelectedBookmarkNodes(); |
787 selectedNodes.sort(function(a, b) { return a.index - b.index }); | 793 selectedNodes.sort(function(a, b) { return a.index - b.index }); |
788 return selectedNodes.map(function(node) { | 794 return selectedNodes.map(function(node) { |
789 return node.id; | 795 return node.id; |
790 }); | 796 }); |
791 } | 797 } |
792 | 798 |
793 /** | 799 /** |
794 * @param {BookmarkTreeNode} node The node to test. | 800 * @param {BookmarkTreeNode} node The node to test. |
795 * @return {boolean} Whether the given node is unmodifiable. | 801 * @return {boolean} Whether the given node is unmodifiable. |
796 */ | 802 */ |
797 function isUnmodifiable(node) { | 803 function isUnmodifiable(node) { |
798 return node && node.unmodifiable; | 804 return !!(node && node.unmodifiable); |
799 } | 805 } |
800 | 806 |
801 /** | 807 /** |
802 * @param {BookmarkList} A list of BookmarkNodes. | 808 * @param {Array.<BookmarkTreeNode>} nodes A list of BookmarkTreeNodes. |
803 * @return {boolean} Whether any of the nodes is managed. | 809 * @return {boolean} Whether any of the nodes is managed. |
804 */ | 810 */ |
805 function hasUnmodifiable(nodes) { | 811 function hasUnmodifiable(nodes) { |
806 return nodes.some(isUnmodifiable); | 812 return nodes.some(isUnmodifiable); |
807 } | 813 } |
808 | 814 |
809 /** | 815 /** |
810 * Opens the selected bookmarks. | 816 * Opens the selected bookmarks. |
811 * @param {LinkKind} kind The kind of link we want to open. | 817 * @param {cr.LinkKind} kind The kind of link we want to open. |
812 * @param {HTMLElement} opt_eventTarget The target of the user initiated event. | 818 * @param {HTMLElement=} opt_eventTarget The target of the user initiated event. |
813 */ | 819 */ |
814 function openBookmarks(kind, opt_eventTarget) { | 820 function openBookmarks(kind, opt_eventTarget) { |
815 // If we have selected any folders, we need to find all the bookmarks one | 821 // If we have selected any folders, we need to find all the bookmarks one |
816 // level down. We use multiple async calls to getSubtree instead of getting | 822 // level down. We use multiple async calls to getSubtree instead of getting |
817 // the whole tree since we would like to minimize the amount of data sent. | 823 // the whole tree since we would like to minimize the amount of data sent. |
818 | 824 |
819 var urlsP = getUrlsForOpenCommands(opt_eventTarget); | 825 var urlsP = getUrlsForOpenCommands(opt_eventTarget ? opt_eventTarget : null); |
820 urlsP.then(function(urls) { | 826 urlsP.then(function(urls) { |
821 getLinkController().openUrls(urls, kind); | 827 getLinkController().openUrls(assert(urls), kind); |
822 chrome.bookmarkManagerPrivate.recordLaunch(); | 828 chrome.bookmarkManagerPrivate.recordLaunch(); |
823 }); | 829 }); |
824 } | 830 } |
825 | 831 |
826 /** | 832 /** |
827 * Opens an item in the list. | 833 * Opens an item in the list. |
828 */ | 834 */ |
829 function openItem() { | 835 function openItem() { |
830 var bookmarkNodes = getSelectedBookmarkNodes(); | 836 var bookmarkNodes = getSelectedBookmarkNodes(); |
831 // If we double clicked or pressed enter on a single folder, navigate to it. | 837 // If we double clicked or pressed enter on a single folder, navigate to it. |
832 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0])) | 838 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0])) |
833 navigateTo(bookmarkNodes[0].id); | 839 navigateTo(bookmarkNodes[0].id); |
834 else | 840 else |
835 openBookmarks(LinkKind.FOREGROUND_TAB); | 841 openBookmarks(LinkKind.FOREGROUND_TAB); |
836 } | 842 } |
837 | 843 |
838 /** | 844 /** |
839 * Refreshes search results after delete or undo-delete. | 845 * Refreshes search results after delete or undo-delete. |
840 * This ensures children of deleted folders do not remain in results | 846 * This ensures children of deleted folders do not remain in results |
841 */ | 847 */ |
842 function updateSearchResults() { | 848 function updateSearchResults() { |
843 if (list.isSearch()) { | 849 if ($('list').isSearch()) { |
844 list.reload(); | 850 $('list').reload(); |
845 } | 851 } |
846 } | 852 } |
847 | 853 |
848 /** | 854 /** |
849 * Deletes the selected bookmarks. The bookmarks are saved in memory in case | 855 * Deletes the selected bookmarks. The bookmarks are saved in memory in case |
850 * the user needs to undo the deletion. | 856 * the user needs to undo the deletion. |
851 */ | 857 */ |
852 function deleteBookmarks() { | 858 function deleteBookmarks() { |
853 var selectedIds = getSelectedBookmarkIds(); | 859 var selectedIds = getSelectedBookmarkIds(); |
854 var filteredIds = getFilteredSelectedBookmarkIds(); | 860 var filteredIds = getFilteredSelectedBookmarkIds(); |
(...skipping 17 matching lines...) Expand all Loading... | |
872 performDelete(); | 878 performDelete(); |
873 updateSearchResults(); | 879 updateSearchResults(); |
874 } | 880 } |
875 }); | 881 }); |
876 }); | 882 }); |
877 } | 883 } |
878 | 884 |
879 /** | 885 /** |
880 * Restores a tree of bookmarks under a specified folder. | 886 * Restores a tree of bookmarks under a specified folder. |
881 * @param {BookmarkTreeNode} node The node to restore. | 887 * @param {BookmarkTreeNode} node The node to restore. |
882 * @param {=string} parentId The ID of the folder to restore under. If not | 888 * @param {(string|number)=} opt_parentId If a string is passed, it's the ID of |
883 * specified, the original parentId of the node will be used. | 889 * the folder to restore under. If not specified or a number is passed (when |
890 * called by forEach), the original parentId of the node will be used. | |
884 */ | 891 */ |
885 function restoreTree(node, parentId) { | 892 function restoreTree(node, opt_parentId) { |
886 var bookmarkInfo = { | 893 var bookmarkInfo = { |
887 parentId: parentId || node.parentId, | 894 parentId: typeof opt_parentId == 'string' ? opt_parentId : node.parentId, |
888 title: node.title, | 895 title: node.title, |
889 index: node.index, | 896 index: node.index, |
890 url: node.url | 897 url: node.url |
891 }; | 898 }; |
892 | 899 |
893 chrome.bookmarks.create(bookmarkInfo, function(result) { | 900 chrome.bookmarks.create(bookmarkInfo, function(result) { |
894 if (!result) { | 901 if (!result) { |
895 console.error('Failed to restore bookmark.'); | 902 console.error('Failed to restore bookmark.'); |
896 return; | 903 return; |
897 } | 904 } |
(...skipping 21 matching lines...) Expand all Loading... | |
919 | 926 |
920 // Only a single level of undo is supported, so disable global undo now. | 927 // Only a single level of undo is supported, so disable global undo now. |
921 performGlobalUndo = null; | 928 performGlobalUndo = null; |
922 } | 929 } |
923 | 930 |
924 /** | 931 /** |
925 * Computes folder for "Add Page" and "Add Folder". | 932 * Computes folder for "Add Page" and "Add Folder". |
926 * @return {string} The id of folder node where we'll create new page/folder. | 933 * @return {string} The id of folder node where we'll create new page/folder. |
927 */ | 934 */ |
928 function computeParentFolderForNewItem() { | 935 function computeParentFolderForNewItem() { |
929 if (document.activeElement == tree) | 936 if (document.activeElement == $('tree')) |
930 return list.parentId; | 937 return $('list').parentId; |
931 var selectedItem = list.selectedItem; | 938 var selectedItem = $('list').selectedItem; |
932 return selectedItem && bmm.isFolder(selectedItem) ? | 939 return selectedItem && bmm.isFolder(selectedItem) ? |
933 selectedItem.id : list.parentId; | 940 selectedItem.id : $('list').parentId; |
934 } | 941 } |
935 | 942 |
936 /** | 943 /** |
937 * Callback for rename folder and edit command. This starts editing for | 944 * Callback for rename folder and edit command. This starts editing for |
938 * selected item. | 945 * selected item. |
939 */ | 946 */ |
940 function editSelectedItem() { | 947 function editSelectedItem() { |
941 if (document.activeElement == tree) { | 948 if (document.activeElement == $('tree')) { |
942 tree.selectedItem.editing = true; | 949 $('tree').selectedItem.editing = true; |
943 } else { | 950 } else { |
944 var li = list.getListItem(list.selectedItem); | 951 var li = $('list').getListItem($('list').selectedItem); |
945 if (li) | 952 if (li) |
946 li.editing = true; | 953 li.editing = true; |
947 } | 954 } |
948 } | 955 } |
949 | 956 |
950 /** | 957 /** |
951 * Callback for the new folder command. This creates a new folder and starts | 958 * Callback for the new folder command. This creates a new folder and starts |
952 * a rename of it. | 959 * a rename of it. |
953 */ | 960 */ |
954 function newFolder() { | 961 function newFolder() { |
955 performGlobalUndo = null; // This can't be undone, so disable global undo. | 962 performGlobalUndo = null; // This can't be undone, so disable global undo. |
956 | 963 |
957 var parentId = computeParentFolderForNewItem(); | 964 var parentId = computeParentFolderForNewItem(); |
958 | 965 |
959 // Callback is called after tree and list data model updated. | 966 // Callback is called after tree and list data model updated. |
960 function createFolder(callback) { | 967 function createFolder(callback) { |
961 chrome.bookmarks.create({ | 968 chrome.bookmarks.create({ |
962 title: loadTimeData.getString('new_folder_name'), | 969 title: loadTimeData.getString('new_folder_name'), |
963 parentId: parentId | 970 parentId: parentId |
964 }, callback); | 971 }, callback); |
965 } | 972 } |
966 | 973 |
967 if (document.activeElement == tree) { | 974 if (document.activeElement == $('tree')) { |
968 createFolder(function(newNode) { | 975 createFolder(function(newNode) { |
969 navigateTo(newNode.id, function() { | 976 navigateTo(newNode.id, function() { |
970 bmm.treeLookup[newNode.id].editing = true; | 977 bmm.treeLookup[newNode.id].editing = true; |
971 }); | 978 }); |
972 }); | 979 }); |
973 return; | 980 return; |
974 } | 981 } |
975 | 982 |
976 function editNewFolderInList() { | 983 function editNewFolderInList() { |
977 createFolder(function() { | 984 createFolder(function() { |
978 var index = list.dataModel.length - 1; | 985 var index = $('list').dataModel.length - 1; |
979 var sm = list.selectionModel; | 986 var sm = $('list').selectionModel; |
980 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; | 987 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; |
981 scrollIntoViewAndMakeEditable(index); | 988 scrollIntoViewAndMakeEditable(index); |
982 }); | 989 }); |
983 } | 990 } |
984 | 991 |
985 navigateTo(parentId, editNewFolderInList); | 992 navigateTo(parentId, editNewFolderInList); |
986 } | 993 } |
987 | 994 |
988 /** | 995 /** |
989 * Scrolls the list item into view and makes it editable. | 996 * Scrolls the list item into view and makes it editable. |
990 * @param {number} index The index of the item to make editable. | 997 * @param {number} index The index of the item to make editable. |
991 */ | 998 */ |
992 function scrollIntoViewAndMakeEditable(index) { | 999 function scrollIntoViewAndMakeEditable(index) { |
993 list.scrollIndexIntoView(index); | 1000 $('list').scrollIndexIntoView(index); |
994 // onscroll is now dispatched asynchronously so we have to postpone | 1001 // onscroll is now dispatched asynchronously so we have to postpone |
995 // the rest. | 1002 // the rest. |
996 setTimeout(function() { | 1003 setTimeout(function() { |
997 var item = list.getListItemByIndex(index); | 1004 var item = $('list').getListItemByIndex(index); |
998 if (item) | 1005 if (item) |
999 item.editing = true; | 1006 item.editing = true; |
1000 }); | 1007 }, 0); |
1001 } | 1008 } |
1002 | 1009 |
1003 /** | 1010 /** |
1004 * Adds a page to the current folder. This is called by the | 1011 * Adds a page to the current folder. This is called by the |
1005 * add-new-bookmark-command handler. | 1012 * add-new-bookmark-command handler. |
1006 */ | 1013 */ |
1007 function addPage() { | 1014 function addPage() { |
1008 var parentId = computeParentFolderForNewItem(); | 1015 var parentId = computeParentFolderForNewItem(); |
1009 | 1016 |
1010 function editNewBookmark() { | 1017 function editNewBookmark() { |
1011 var fakeNode = { | 1018 var fakeNode = { |
1012 title: '', | 1019 title: '', |
1013 url: '', | 1020 url: '', |
1014 parentId: parentId, | 1021 parentId: parentId, |
1015 id: 'new' | 1022 id: 'new' |
1016 }; | 1023 }; |
1017 var dataModel = list.dataModel; | 1024 var dataModel = $('list').dataModel; |
1018 var length = dataModel.length; | 1025 var length = dataModel.length; |
1019 dataModel.splice(length, 0, fakeNode); | 1026 dataModel.splice(length, 0, fakeNode); |
1020 var sm = list.selectionModel; | 1027 var sm = $('list').selectionModel; |
1021 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length; | 1028 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length; |
1022 scrollIntoViewAndMakeEditable(length); | 1029 scrollIntoViewAndMakeEditable(length); |
1023 }; | 1030 }; |
1024 | 1031 |
1025 navigateTo(parentId, editNewBookmark); | 1032 navigateTo(parentId, editNewBookmark); |
1026 } | 1033 } |
1027 | 1034 |
1028 /** | 1035 /** |
1029 * This function is used to select items after a user action such as paste, drop | 1036 * This function is used to select items after a user action such as paste, drop |
1030 * add page etc. | 1037 * add page etc. |
1031 * @param {BookmarkList|BookmarkTree} target The target of the user action. | 1038 * @param {BookmarkList|BookmarkTree} target The target of the user action. |
1032 * @param {=string} opt_selectedTreeId If provided, then select that tree id. | 1039 * @param {string=} opt_selectedTreeId If provided, then select that tree id. |
1033 */ | 1040 */ |
1034 function selectItemsAfterUserAction(target, opt_selectedTreeId) { | 1041 function selectItemsAfterUserAction(target, opt_selectedTreeId) { |
1035 // We get one onCreated event per item so we delay the handling until we get | 1042 // We get one onCreated event per item so we delay the handling until we get |
1036 // no more events coming. | 1043 // no more events coming. |
1037 | 1044 |
1038 var ids = []; | 1045 var ids = []; |
1039 var timer; | 1046 var timer; |
1040 | 1047 |
1041 function handle(id, bookmarkNode) { | 1048 function handle(id, bookmarkNode) { |
1042 clearTimeout(timer); | 1049 clearTimeout(timer); |
1043 if (opt_selectedTreeId || list.parentId == bookmarkNode.parentId) | 1050 if (opt_selectedTreeId || $('list').parentId == bookmarkNode.parentId) |
1044 ids.push(id); | 1051 ids.push(id); |
1045 timer = setTimeout(handleTimeout, 50); | 1052 timer = setTimeout(handleTimeout, 50); |
1046 } | 1053 } |
1047 | 1054 |
1048 function handleTimeout() { | 1055 function handleTimeout() { |
1049 chrome.bookmarks.onCreated.removeListener(handle); | 1056 chrome.bookmarks.onCreated.removeListener(handle); |
1050 chrome.bookmarks.onMoved.removeListener(handle); | 1057 chrome.bookmarks.onMoved.removeListener(handle); |
1051 | 1058 |
1052 if (opt_selectedTreeId && ids.indexOf(opt_selectedTreeId) != -1) { | 1059 if (opt_selectedTreeId && ids.indexOf(opt_selectedTreeId) != -1) { |
1053 var index = ids.indexOf(opt_selectedTreeId); | 1060 var index = ids.indexOf(opt_selectedTreeId); |
1054 if (index != -1 && opt_selectedTreeId in bmm.treeLookup) { | 1061 if (index != -1 && opt_selectedTreeId in bmm.treeLookup) { |
1055 tree.selectedItem = bmm.treeLookup[opt_selectedTreeId]; | 1062 $('tree').selectedItem = bmm.treeLookup[opt_selectedTreeId]; |
1056 } | 1063 } |
1057 } else if (target == list) { | 1064 } else if (target == $('list')) { |
1058 var dataModel = list.dataModel; | 1065 var dataModel = $('list').dataModel; |
1059 var firstIndex = dataModel.findIndexById(ids[0]); | 1066 var firstIndex = dataModel.findIndexById(ids[0]); |
1060 var lastIndex = dataModel.findIndexById(ids[ids.length - 1]); | 1067 var lastIndex = dataModel.findIndexById(ids[ids.length - 1]); |
1061 if (firstIndex != -1 && lastIndex != -1) { | 1068 if (firstIndex != -1 && lastIndex != -1) { |
1062 var selectionModel = list.selectionModel; | 1069 var selectionModel = $('list').selectionModel; |
1063 selectionModel.selectedIndex = -1; | 1070 selectionModel.selectedIndex = -1; |
1064 selectionModel.selectRange(firstIndex, lastIndex); | 1071 selectionModel.selectRange(firstIndex, lastIndex); |
1065 selectionModel.anchorIndex = selectionModel.leadIndex = lastIndex; | 1072 selectionModel.anchorIndex = selectionModel.leadIndex = lastIndex; |
1066 list.focus(); | 1073 $('list').focus(); |
1067 } | 1074 } |
1068 } | 1075 } |
1069 | 1076 |
1070 list.endBatchUpdates(); | 1077 $('list').endBatchUpdates(); |
1071 } | 1078 } |
1072 | 1079 |
1073 list.startBatchUpdates(); | 1080 $('list').startBatchUpdates(); |
1074 | 1081 |
1075 chrome.bookmarks.onCreated.addListener(handle); | 1082 chrome.bookmarks.onCreated.addListener(handle); |
1076 chrome.bookmarks.onMoved.addListener(handle); | 1083 chrome.bookmarks.onMoved.addListener(handle); |
1077 timer = setTimeout(handleTimeout, 300); | 1084 timer = setTimeout(handleTimeout, 300); |
1078 } | 1085 } |
1079 | 1086 |
1080 /** | 1087 /** |
1081 * Record user action. | 1088 * Record user action. |
1082 * @param {string} name An user action name. | 1089 * @param {string} name An user action name. |
1083 */ | 1090 */ |
1084 function recordUserAction(name) { | 1091 function recordUserAction(name) { |
1085 chrome.metricsPrivate.recordUserAction('BookmarkManager_Command_' + name); | 1092 chrome.metricsPrivate.recordUserAction('BookmarkManager_Command_' + name); |
1086 } | 1093 } |
1087 | 1094 |
1088 /** | 1095 /** |
1089 * The currently selected bookmark, based on where the user is clicking. | 1096 * The currently selected bookmark, based on where the user is clicking. |
1090 * @return {string} The ID of the currently selected bookmark (could be from | 1097 * @return {string} The ID of the currently selected bookmark (could be from |
1091 * tree view or list view). | 1098 * tree view or list view). |
1092 */ | 1099 */ |
1093 function getSelectedId() { | 1100 function getSelectedId() { |
1094 if (document.activeElement == tree) | 1101 if (document.activeElement == $('tree')) |
1095 return tree.selectedItem.bookmarkId; | 1102 return $('tree').selectedItem.bookmarkId; |
1096 var selectedItem = list.selectedItem; | 1103 var selectedItem = $('list').selectedItem; |
1097 return selectedItem && bmm.isFolder(selectedItem) ? | 1104 return selectedItem && bmm.isFolder(selectedItem) ? |
1098 selectedItem.id : tree.selectedItem.bookmarkId; | 1105 selectedItem.id : $('tree').selectedItem.bookmarkId; |
1099 } | 1106 } |
1100 | 1107 |
1101 /** | 1108 /** |
1102 * Pastes the copied/cutted bookmark into the right location depending whether | 1109 * Pastes the copied/cutted bookmark into the right location depending whether |
1103 * if it was called from Organize Menu or from Context Menu. | 1110 * if it was called from Organize Menu or from Context Menu. |
1104 * @param {string} id The id of the element being pasted from. | 1111 * @param {string} id The id of the element being pasted from. |
1105 */ | 1112 */ |
1106 function pasteBookmark(id) { | 1113 function pasteBookmark(id) { |
1107 recordUserAction('Paste'); | 1114 recordUserAction('Paste'); |
1108 selectItemsAfterUserAction(list); | 1115 selectItemsAfterUserAction(/** @type {BookmarkList} */($('list'))); |
1109 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds()); | 1116 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds()); |
1110 } | 1117 } |
1111 | 1118 |
1112 /** | 1119 /** |
1113 * Returns true if child is contained in another selected folder. | 1120 * Returns true if child is contained in another selected folder. |
1114 * Traces parent nodes up the tree until a selected ancestor or root is found. | 1121 * Traces parent nodes up the tree until a selected ancestor or root is found. |
1115 */ | 1122 */ |
1116 function hasSelectedAncestor(parentNode) { | 1123 function hasSelectedAncestor(parentNode) { |
1117 function contains(arr, item) { | 1124 function contains(arr, item) { |
1118 for (var i = 0; i < arr.length; i++) | 1125 for (var i = 0; i < arr.length; i++) |
1119 if (arr[i] === item) | 1126 if (arr[i] === item) |
1120 return true; | 1127 return true; |
1121 return false; | 1128 return false; |
1122 } | 1129 } |
1123 | 1130 |
1124 // Don't search top level, cannot select permanent nodes in search. | 1131 // Don't search top level, cannot select permanent nodes in search. |
1125 if (parentNode == null || parentNode.id <= 2) | 1132 if (parentNode == null || parentNode.id <= 2) |
1126 return false; | 1133 return false; |
1127 | 1134 |
1128 // Found selected ancestor. | 1135 // Found selected ancestor. |
1129 if (contains(getSelectedBookmarkNodes(), parentNode)) | 1136 if (contains(getSelectedBookmarkNodes(), parentNode)) |
1130 return true; | 1137 return true; |
1131 | 1138 |
1132 // Keep digging. | 1139 // Keep digging. |
1133 return hasSelectedAncestor(tree.getBookmarkNodeById(parentNode.parentId)); | 1140 return hasSelectedAncestor( |
1141 $('tree').getBookmarkNodeById(parentNode.parentId)); | |
1134 } | 1142 } |
1135 | 1143 |
1136 function getFilteredSelectedBookmarkIds() { | 1144 function getFilteredSelectedBookmarkIds() { |
1137 // Remove duplicates from filteredIds and return. | 1145 // Remove duplicates from filteredIds and return. |
1138 var filteredIds = new Array(); | 1146 var filteredIds = new Array(); |
1139 // Selected nodes to iterate through for matches. | 1147 // Selected nodes to iterate through for matches. |
1140 var nodes = getSelectedBookmarkNodes(); | 1148 var nodes = getSelectedBookmarkNodes(); |
1141 | 1149 |
1142 for (var i = 0; i < nodes.length; i++) | 1150 for (var i = 0; i < nodes.length; i++) |
1143 if (!hasSelectedAncestor(tree.getBookmarkNodeById(nodes[i].parentId))) | 1151 if (!hasSelectedAncestor($('tree').getBookmarkNodeById(nodes[i].parentId))) |
1144 filteredIds.splice(0, 0, nodes[i].id); | 1152 filteredIds.splice(0, 0, nodes[i].id); |
1145 | 1153 |
1146 return filteredIds; | 1154 return filteredIds; |
1147 } | 1155 } |
1148 | 1156 |
1149 /** | 1157 /** |
1150 * Handler for the command event. This is used for context menu of list/tree | 1158 * Handler for the command event. This is used for context menu of list/tree |
1151 * and organized menu. | 1159 * and organized menu. |
1152 * @param {!Event} e The event object. | 1160 * @param {!Event} e The event object. |
1153 */ | 1161 */ |
(...skipping 17 matching lines...) Expand all Loading... | |
1171 recordUserAction('UndoNone'); | 1179 recordUserAction('UndoNone'); |
1172 } | 1180 } |
1173 break; | 1181 break; |
1174 case 'show-in-folder-command': | 1182 case 'show-in-folder-command': |
1175 recordUserAction('ShowInFolder'); | 1183 recordUserAction('ShowInFolder'); |
1176 showInFolder(); | 1184 showInFolder(); |
1177 break; | 1185 break; |
1178 case 'open-in-new-tab-command': | 1186 case 'open-in-new-tab-command': |
1179 case 'open-in-background-tab-command': | 1187 case 'open-in-background-tab-command': |
1180 recordUserAction('OpenInNewTab'); | 1188 recordUserAction('OpenInNewTab'); |
1181 openBookmarks(LinkKind.BACKGROUND_TAB, e.target); | 1189 openBookmarks(LinkKind.BACKGROUND_TAB, |
1190 assertInstanceof(e.target, HTMLElement)); | |
1182 break; | 1191 break; |
1183 case 'open-in-new-window-command': | 1192 case 'open-in-new-window-command': |
1184 recordUserAction('OpenInNewWindow'); | 1193 recordUserAction('OpenInNewWindow'); |
1185 openBookmarks(LinkKind.WINDOW, e.target); | 1194 openBookmarks(LinkKind.WINDOW, |
1195 assertInstanceof(e.target, HTMLElement)); | |
1186 break; | 1196 break; |
1187 case 'open-incognito-window-command': | 1197 case 'open-incognito-window-command': |
1188 recordUserAction('OpenIncognito'); | 1198 recordUserAction('OpenIncognito'); |
1189 openBookmarks(LinkKind.INCOGNITO, e.target); | 1199 openBookmarks(LinkKind.INCOGNITO, |
1200 assertInstanceof(e.target, HTMLElement)); | |
1190 break; | 1201 break; |
1191 case 'delete-command': | 1202 case 'delete-command': |
1192 recordUserAction('Delete'); | 1203 recordUserAction('Delete'); |
1193 deleteBookmarks(); | 1204 deleteBookmarks(); |
1194 break; | 1205 break; |
1195 case 'copy-command': | 1206 case 'copy-command': |
1196 recordUserAction('Copy'); | 1207 recordUserAction('Copy'); |
1197 chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(), | 1208 chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(), |
1198 updatePasteCommand); | 1209 updatePasteCommand); |
1199 break; | 1210 break; |
1200 case 'cut-command': | 1211 case 'cut-command': |
1201 recordUserAction('Cut'); | 1212 recordUserAction('Cut'); |
1202 chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(), | 1213 chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(), |
1203 function() { | 1214 function() { |
1204 updatePasteCommand(); | 1215 updatePasteCommand(); |
1205 updateSearchResults(); | 1216 updateSearchResults(); |
1206 }); | 1217 }); |
1207 break; | 1218 break; |
1208 case 'paste-from-organize-menu-command': | 1219 case 'paste-from-organize-menu-command': |
1209 pasteBookmark(list.parentId); | 1220 pasteBookmark($('list').parentId); |
1210 break; | 1221 break; |
1211 case 'paste-from-context-menu-command': | 1222 case 'paste-from-context-menu-command': |
1212 pasteBookmark(getSelectedId()); | 1223 pasteBookmark(getSelectedId()); |
1213 break; | 1224 break; |
1214 case 'sort-command': | 1225 case 'sort-command': |
1215 recordUserAction('Sort'); | 1226 recordUserAction('Sort'); |
1216 chrome.bookmarkManagerPrivate.sortChildren(list.parentId); | 1227 chrome.bookmarkManagerPrivate.sortChildren($('list').parentId); |
1217 break; | 1228 break; |
1218 case 'rename-folder-command': | 1229 case 'rename-folder-command': |
1219 editSelectedItem(); | 1230 editSelectedItem(); |
1220 break; | 1231 break; |
1221 case 'edit-command': | 1232 case 'edit-command': |
1222 recordUserAction('Edit'); | 1233 recordUserAction('Edit'); |
1223 editSelectedItem(); | 1234 editSelectedItem(); |
1224 break; | 1235 break; |
1225 case 'new-folder-command': | 1236 case 'new-folder-command': |
1226 recordUserAction('NewFolder'); | 1237 recordUserAction('NewFolder'); |
(...skipping 12 matching lines...) Expand all Loading... | |
1239 undoDelete(); | 1250 undoDelete(); |
1240 break; | 1251 break; |
1241 } | 1252 } |
1242 } | 1253 } |
1243 | 1254 |
1244 // Execute the copy, cut and paste commands when those events are dispatched by | 1255 // Execute the copy, cut and paste commands when those events are dispatched by |
1245 // the browser. This allows us to rely on the browser to handle the keyboard | 1256 // the browser. This allows us to rely on the browser to handle the keyboard |
1246 // shortcuts for these commands. | 1257 // shortcuts for these commands. |
1247 function installEventHandlerForCommand(eventName, commandId) { | 1258 function installEventHandlerForCommand(eventName, commandId) { |
1248 function handle(e) { | 1259 function handle(e) { |
1249 if (document.activeElement != list && document.activeElement != tree) | 1260 if (document.activeElement != $('list') && |
1261 document.activeElement != $('tree')) | |
1250 return; | 1262 return; |
1251 var command = $(commandId); | 1263 var command = $(commandId); |
1252 if (!command.disabled) { | 1264 if (!command.disabled) { |
1253 command.execute(); | 1265 command.execute(); |
1254 if (e) | 1266 if (e) |
1255 e.preventDefault(); // Prevent the system beep. | 1267 e.preventDefault(); // Prevent the system beep. |
1256 } | 1268 } |
1257 } | 1269 } |
1258 if (eventName == 'paste') { | 1270 if (eventName == 'paste') { |
1259 // Paste is a bit special since we need to do an async call to see if we | 1271 // Paste is a bit special since we need to do an async call to see if we |
1260 // can paste because the paste command might not be up to date. | 1272 // can paste because the paste command might not be up to date. |
1261 document.addEventListener(eventName, function(e) { | 1273 document.addEventListener(eventName, function(e) { |
1262 updatePasteCommand(handle); | 1274 updatePasteCommand(handle); |
1263 }); | 1275 }); |
1264 } else { | 1276 } else { |
1265 document.addEventListener(eventName, handle); | 1277 document.addEventListener(eventName, handle); |
1266 } | 1278 } |
1267 } | 1279 } |
1268 | 1280 |
1269 function initializeSplitter() { | 1281 function initializeSplitter() { |
1270 var splitter = document.querySelector('.main > .splitter'); | 1282 var splitter = document.querySelector('.main > .splitter'); |
1271 Splitter.decorate(splitter); | 1283 Splitter.decorate(splitter); |
1272 | 1284 |
1273 // The splitter persists the size of the left component in the local store. | 1285 // The splitter persists the size of the left component in the local store. |
1274 if ('treeWidth' in localStorage) | 1286 if ('treeWidth' in window.localStorage) |
1275 splitter.previousElementSibling.style.width = localStorage['treeWidth']; | 1287 splitter.previousElementSibling.style.width = |
1288 window.localStorage['treeWidth']; | |
1276 | 1289 |
1277 splitter.addEventListener('resize', function(e) { | 1290 splitter.addEventListener('resize', function(e) { |
1278 localStorage['treeWidth'] = splitter.previousElementSibling.style.width; | 1291 window.localStorage['treeWidth'] = |
1292 splitter.previousElementSibling.style.width; | |
1279 }); | 1293 }); |
1280 } | 1294 } |
1281 | 1295 |
1282 function initializeBookmarkManager() { | 1296 function initializeBookmarkManager() { |
1283 // Sometimes the extension API is not initialized. | 1297 // Sometimes the extension API is not initialized. |
1284 if (!chrome.bookmarks) | 1298 if (!chrome.bookmarks) |
1285 console.error('Bookmarks extension API is not available'); | 1299 console.error('Bookmarks extension API is not available'); |
1286 | 1300 |
1287 chrome.bookmarkManagerPrivate.getStrings(continueInitializeBookmarkManager); | 1301 chrome.bookmarkManagerPrivate.getStrings(continueInitializeBookmarkManager); |
1288 } | 1302 } |
1289 | 1303 |
1290 function continueInitializeBookmarkManager(localizedStrings) { | 1304 function continueInitializeBookmarkManager(localizedStrings) { |
1291 loadLocalizedStrings(localizedStrings); | 1305 loadLocalizedStrings(localizedStrings); |
1292 | 1306 |
1293 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; | 1307 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; |
1294 | 1308 |
1295 cr.ui.decorate('menu', Menu); | 1309 cr.ui.decorate('menu', Menu); |
1296 cr.ui.decorate('button[menu]', MenuButton); | 1310 cr.ui.decorate('button[menu]', MenuButton); |
1297 cr.ui.decorate('command', Command); | 1311 cr.ui.decorate('command', Command); |
1298 BookmarkList.decorate(list); | 1312 BookmarkList.decorate($('list')); |
1299 BookmarkTree.decorate(tree); | 1313 BookmarkTree.decorate($('tree')); |
1300 | 1314 |
1301 list.addEventListener('canceledit', handleCancelEdit); | 1315 $('list').addEventListener('canceledit', handleCancelEdit); |
1302 list.addEventListener('canExecute', handleCanExecuteForList); | 1316 $('list').addEventListener('canExecute', handleCanExecuteForList); |
1303 list.addEventListener('change', updateAllCommands); | 1317 $('list').addEventListener('change', updateAllCommands); |
1304 list.addEventListener('contextmenu', updateEditingCommands); | 1318 $('list').addEventListener('contextmenu', updateEditingCommands); |
1305 list.addEventListener('dblclick', handleDoubleClickForList); | 1319 $('list').addEventListener('dblclick', handleDoubleClickForList); |
1306 list.addEventListener('edit', handleEdit); | 1320 $('list').addEventListener('edit', handleEdit); |
1307 list.addEventListener('rename', handleRename); | 1321 $('list').addEventListener('rename', handleRename); |
1308 list.addEventListener('urlClicked', handleUrlClickedForList); | 1322 $('list').addEventListener('urlClicked', handleUrlClickedForList); |
1309 | 1323 |
1310 tree.addEventListener('canExecute', handleCanExecuteForTree); | 1324 $('tree').addEventListener('canExecute', handleCanExecuteForTree); |
1311 tree.addEventListener('change', handleChangeForTree); | 1325 $('tree').addEventListener('change', handleChangeForTree); |
1312 tree.addEventListener('contextmenu', updateEditingCommands); | 1326 $('tree').addEventListener('contextmenu', updateEditingCommands); |
1313 tree.addEventListener('rename', handleRename); | 1327 $('tree').addEventListener('rename', handleRename); |
1314 tree.addEventListener('load', handleLoadForTree); | 1328 $('tree').addEventListener('load', handleLoadForTree); |
1315 | 1329 |
1316 cr.ui.contextMenuHandler.addContextMenuProperty(tree); | 1330 cr.ui.contextMenuHandler.addContextMenuProperty( |
1317 list.contextMenu = $('context-menu'); | 1331 /** @type {!Element} */($('tree'))); |
1318 tree.contextMenu = $('context-menu'); | 1332 $('list').contextMenu = $('context-menu'); |
1333 $('tree').contextMenu = $('context-menu'); | |
1319 | 1334 |
1320 // We listen to hashchange so that we can update the currently shown folder | 1335 // We listen to hashchange so that we can update the currently shown folder |
1321 // when // the user goes back and forward in the history. | 1336 // when // the user goes back and forward in the history. |
1322 window.addEventListener('hashchange', processHash); | 1337 window.addEventListener('hashchange', processHash); |
1323 | 1338 |
1324 document.querySelector('header form').onsubmit = function(e) { | 1339 document.querySelector('header form').onsubmit = |
1340 /** @type {function(Event=)} */(function(e) { | |
1325 setSearch($('term').value); | 1341 setSearch($('term').value); |
1326 e.preventDefault(); | 1342 e.preventDefault(); |
1327 }; | 1343 }); |
1328 | 1344 |
1329 $('term').addEventListener('search', handleSearch); | 1345 $('term').addEventListener('search', handleSearch); |
1330 | 1346 |
1331 document.querySelector('.summary button').addEventListener( | 1347 document.querySelector('.summary button').addEventListener( |
1332 'click', handleOrganizeButtonClick); | 1348 'click', handleOrganizeButtonClick); |
1333 | 1349 |
1334 document.addEventListener('canExecute', handleCanExecuteForDocument); | 1350 document.addEventListener('canExecute', handleCanExecuteForDocument); |
1335 document.addEventListener('command', handleCommand); | 1351 document.addEventListener('command', handleCommand); |
1336 | 1352 |
1337 // Listen to copy, cut and paste events and execute the associated commands. | 1353 // Listen to copy, cut and paste events and execute the associated commands. |
(...skipping 26 matching lines...) Expand all Loading... | |
1364 }); | 1380 }); |
1365 | 1381 |
1366 chrome.bookmarkManagerPrivate.canOpenNewWindows(function(result) { | 1382 chrome.bookmarkManagerPrivate.canOpenNewWindows(function(result) { |
1367 canOpenNewWindows = result; | 1383 canOpenNewWindows = result; |
1368 }); | 1384 }); |
1369 | 1385 |
1370 cr.ui.FocusOutlineManager.forDocument(document); | 1386 cr.ui.FocusOutlineManager.forDocument(document); |
1371 initializeSplitter(); | 1387 initializeSplitter(); |
1372 bmm.addBookmarkModelListeners(); | 1388 bmm.addBookmarkModelListeners(); |
1373 dnd.init(selectItemsAfterUserAction); | 1389 dnd.init(selectItemsAfterUserAction); |
1374 tree.reload(); | 1390 $('tree').reload(); |
1375 } | 1391 } |
1376 | 1392 |
1377 initializeBookmarkManager(); | 1393 initializeBookmarkManager(); |
1378 })(); | 1394 })(); |
OLD | NEW |