| 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 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 /** @const */ var BookmarkList = bmm.BookmarkList; | 8 /** @const */ var BookmarkList = bmm.BookmarkList; |
| 9 /** @const */ var BookmarkTree = bmm.BookmarkTree; | 9 /** @const */ var BookmarkTree = bmm.BookmarkTree; |
| 10 /** @const */ var Command = cr.ui.Command; | 10 /** @const */ var Command = cr.ui.Command; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 /** | 54 /** |
| 55 * Whether bookmarks can be modified. | 55 * Whether bookmarks can be modified. |
| 56 * @type {boolean} | 56 * @type {boolean} |
| 57 */ | 57 */ |
| 58 var canEdit = true; | 58 var canEdit = true; |
| 59 | 59 |
| 60 /** | 60 /** |
| 61 * @type {TreeItem} | 61 * @type {TreeItem} |
| 62 * @const | 62 * @const |
| 63 */ | 63 */ |
| 64 var searchTreeItem = new TreeItem({ | 64 var searchTreeItem = new TreeItem({bookmarkId: 'q='}); |
| 65 bookmarkId: 'q=' | |
| 66 }); | |
| 67 | 65 |
| 68 /** | 66 /** |
| 69 * @type {boolean} | 67 * @type {boolean} |
| 70 */ | 68 */ |
| 71 var firstLoad = true; | 69 var firstLoad = true; |
| 72 | 70 |
| 73 /** | 71 /** |
| 74 * Command shortcut mapping. | 72 * Command shortcut mapping. |
| 75 * @const | 73 * @const |
| 76 */ | 74 */ |
| 77 var commandShortcutMap = cr.isMac ? { | 75 var commandShortcutMap = cr.isMac ? |
| 78 'edit': 'Enter', | 76 { |
| 79 // On Mac we also allow Meta+Backspace. | 77 'edit': 'Enter', |
| 80 'delete': 'Delete Backspace Meta|Backspace', | 78 // On Mac we also allow Meta+Backspace. |
| 81 'open-in-background-tab': 'Meta|Enter', | 79 'delete': 'Delete Backspace Meta|Backspace', |
| 82 'open-in-new-tab': 'Shift|Meta|Enter', | 80 'open-in-background-tab': 'Meta|Enter', |
| 83 'open-in-same-window': 'Meta|Down', | 81 'open-in-new-tab': 'Shift|Meta|Enter', |
| 84 'open-in-new-window': 'Shift|Enter', | 82 'open-in-same-window': 'Meta|Down', |
| 85 'rename-folder': 'Enter', | 83 'open-in-new-window': 'Shift|Enter', |
| 86 // Global undo is Command-Z. It is not in any menu. | 84 'rename-folder': 'Enter', |
| 87 'undo': 'Meta|z', | 85 // Global undo is Command-Z. It is not in any menu. |
| 88 } : { | 86 'undo': 'Meta|z', |
| 89 'edit': 'F2', | 87 } : |
| 90 'delete': 'Delete', | 88 { |
| 91 'open-in-background-tab': 'Ctrl|Enter', | 89 'edit': 'F2', |
| 92 'open-in-new-tab': 'Shift|Ctrl|Enter', | 90 'delete': 'Delete', |
| 93 'open-in-same-window': 'Enter', | 91 'open-in-background-tab': 'Ctrl|Enter', |
| 94 'open-in-new-window': 'Shift|Enter', | 92 'open-in-new-tab': 'Shift|Ctrl|Enter', |
| 95 'rename-folder': 'F2', | 93 'open-in-same-window': 'Enter', |
| 96 // Global undo is Ctrl-Z. It is not in any menu. | 94 'open-in-new-window': 'Shift|Enter', |
| 97 'undo': 'Ctrl|z', | 95 'rename-folder': 'F2', |
| 98 }; | 96 // Global undo is Ctrl-Z. It is not in any menu. |
| 97 'undo': 'Ctrl|z', |
| 98 }; |
| 99 | 99 |
| 100 /** | 100 /** |
| 101 * Mapping for folder id to suffix of UMA. These names will be appeared | 101 * Mapping for folder id to suffix of UMA. These names will be appeared |
| 102 * after "BookmarkManager_NavigateTo_" in UMA dashboard. | 102 * after "BookmarkManager_NavigateTo_" in UMA dashboard. |
| 103 * @const | 103 * @const |
| 104 */ | 104 */ |
| 105 var folderMetricsNameMap = { | 105 var folderMetricsNameMap = { |
| 106 '1': 'BookmarkBar', | 106 '1': 'BookmarkBar', |
| 107 '2': 'Other', | 107 '2': 'Other', |
| 108 '3': 'Mobile', | 108 '3': 'Mobile', |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 function navigateTo(id, opt_callback) { | 156 function navigateTo(id, opt_callback) { |
| 157 window.location.hash = id; | 157 window.location.hash = id; |
| 158 | 158 |
| 159 var sameParent = bmm.list.parentId == id; | 159 var sameParent = bmm.list.parentId == id; |
| 160 if (!sameParent) | 160 if (!sameParent) |
| 161 updateParentId(id); | 161 updateParentId(id); |
| 162 | 162 |
| 163 updateAllCommands(); | 163 updateAllCommands(); |
| 164 | 164 |
| 165 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] || | 165 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] || |
| 166 folderMetricsNameMap['subfolder']; | 166 folderMetricsNameMap['subfolder']; |
| 167 chrome.metricsPrivate.recordUserAction( | 167 chrome.metricsPrivate.recordUserAction( |
| 168 'BookmarkManager_NavigateTo_' + metricsId); | 168 'BookmarkManager_NavigateTo_' + metricsId); |
| 169 | 169 |
| 170 if (opt_callback) { | 170 if (opt_callback) { |
| 171 if (sameParent) | 171 if (sameParent) |
| 172 opt_callback(); | 172 opt_callback(); |
| 173 else | 173 else |
| 174 addOneShotEventListener(bmm.list, 'load', opt_callback); | 174 addOneShotEventListener(bmm.list, 'load', opt_callback); |
| 175 } | 175 } |
| 176 } | 176 } |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]); | 422 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]); |
| 423 command.label = loadTimeData.getString(singular ? singularId : pluralId); | 423 command.label = loadTimeData.getString(singular ? singularId : pluralId); |
| 424 } | 424 } |
| 425 | 425 |
| 426 if (commandDisabled) { | 426 if (commandDisabled) { |
| 427 command.disabled = true; | 427 command.disabled = true; |
| 428 e.canExecute = false; | 428 e.canExecute = false; |
| 429 return; | 429 return; |
| 430 } | 430 } |
| 431 | 431 |
| 432 getUrlsForOpenCommands(assertInstanceof(e.target, HTMLElement)).then( | 432 getUrlsForOpenCommands(assertInstanceof(e.target, HTMLElement)) |
| 433 function(urls) { | 433 .then(function(urls) { |
| 434 var disabled = !urls.length; | 434 var disabled = !urls.length; |
| 435 command.disabled = disabled; | 435 command.disabled = disabled; |
| 436 e.canExecute = !disabled; | 436 e.canExecute = !disabled; |
| 437 }); | 437 }); |
| 438 } | 438 } |
| 439 | 439 |
| 440 /** | 440 /** |
| 441 * Calls the backend to figure out if we can paste the clipboard into the active | 441 * Calls the backend to figure out if we can paste the clipboard into the active |
| 442 * folder. | 442 * folder. |
| 443 * @param {Function=} opt_f Function to call after the state has been updated. | 443 * @param {Function=} opt_f Function to call after the state has been updated. |
| 444 */ | 444 */ |
| 445 function updatePasteCommand(opt_f) { | 445 function updatePasteCommand(opt_f) { |
| 446 function update(commandId, canPaste) { | 446 function update(commandId, canPaste) { |
| 447 $(commandId).disabled = !canPaste; | 447 $(commandId).disabled = !canPaste; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 Promise.all(promises).then(function() { | 481 Promise.all(promises).then(function() { |
| 482 var cmd; | 482 var cmd; |
| 483 if (document.activeElement == bmm.list) | 483 if (document.activeElement == bmm.list) |
| 484 cmd = 'paste-from-organize-menu-command'; | 484 cmd = 'paste-from-organize-menu-command'; |
| 485 else if (document.activeElement == bmm.tree) | 485 else if (document.activeElement == bmm.tree) |
| 486 cmd = 'paste-from-folders-menu-command'; | 486 cmd = 'paste-from-folders-menu-command'; |
| 487 | 487 |
| 488 if (cmd) | 488 if (cmd) |
| 489 update('paste-from-context-menu-command', !$(cmd).disabled); | 489 update('paste-from-context-menu-command', !$(cmd).disabled); |
| 490 | 490 |
| 491 if (opt_f) opt_f(); | 491 if (opt_f) |
| 492 opt_f(); |
| 492 }); | 493 }); |
| 493 } | 494 } |
| 494 | 495 |
| 495 function handleCanExecuteForSearchBox(e) { | 496 function handleCanExecuteForSearchBox(e) { |
| 496 var command = e.command; | 497 var command = e.command; |
| 497 switch (command.id) { | 498 switch (command.id) { |
| 498 case 'delete-command': | 499 case 'delete-command': |
| 499 case 'undo-command': | 500 case 'undo-command': |
| 500 // Pass the delete and undo commands through | 501 // Pass the delete and undo commands through |
| 501 // (fixes http://crbug.com/278112). | 502 // (fixes http://crbug.com/278112). |
| 502 e.canExecute = false; | 503 e.canExecute = false; |
| 503 break; | 504 break; |
| 504 } | 505 } |
| 505 } | 506 } |
| 506 | 507 |
| 507 function handleCanExecuteForDocument(e) { | 508 function handleCanExecuteForDocument(e) { |
| 508 var command = e.command; | 509 var command = e.command; |
| 509 switch (command.id) { | 510 switch (command.id) { |
| 510 case 'import-menu-command': | 511 case 'import-menu-command': |
| 511 e.canExecute = canEdit; | 512 e.canExecute = canEdit; |
| 512 break; | 513 break; |
| 513 | 514 |
| 514 case 'export-menu-command': | 515 case 'export-menu-command': |
| 515 // We can always execute the export-menu command. | 516 // We can always execute the export-menu command. |
| 516 e.canExecute = true; | 517 e.canExecute = true; |
| 517 break; | 518 break; |
| 518 | 519 |
| 519 case 'sort-command': | 520 case 'sort-command': |
| 520 e.canExecute = !bmm.list.isSearch() && | 521 e.canExecute = !bmm.list.isSearch() && bmm.list.dataModel && |
| 521 bmm.list.dataModel && bmm.list.dataModel.length > 1 && | 522 bmm.list.dataModel.length > 1 && |
| 522 !isUnmodifiable(bmm.tree.getBookmarkNodeById(bmm.list.parentId)); | 523 !isUnmodifiable(bmm.tree.getBookmarkNodeById(bmm.list.parentId)); |
| 523 break; | 524 break; |
| 524 | 525 |
| 525 case 'undo-command': | 526 case 'undo-command': |
| 526 // Because the global undo command has no visible UI, always enable it, | 527 // Because the global undo command has no visible UI, always enable it, |
| 527 // and just make it a no-op if undo is not possible. | 528 // and just make it a no-op if undo is not possible. |
| 528 e.canExecute = true; | 529 e.canExecute = true; |
| 529 break; | 530 break; |
| 530 | 531 |
| 531 default: | 532 default: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 548 case 'paste-from-folders-menu-command': | 549 case 'paste-from-folders-menu-command': |
| 549 case 'paste-from-organize-menu-command': | 550 case 'paste-from-organize-menu-command': |
| 550 case 'paste-from-context-menu-command': | 551 case 'paste-from-context-menu-command': |
| 551 updatePasteCommand(); | 552 updatePasteCommand(); |
| 552 break; | 553 break; |
| 553 | 554 |
| 554 case 'add-new-bookmark-command': | 555 case 'add-new-bookmark-command': |
| 555 case 'new-folder-command': | 556 case 'new-folder-command': |
| 556 case 'new-folder-from-folders-menu-command': | 557 case 'new-folder-from-folders-menu-command': |
| 557 var parentId = computeParentFolderForNewItem(); | 558 var parentId = computeParentFolderForNewItem(); |
| 558 var unmodifiable = isUnmodifiable( | 559 var unmodifiable = isUnmodifiable(bmm.tree.getBookmarkNodeById(parentId)); |
| 559 bmm.tree.getBookmarkNodeById(parentId)); | |
| 560 e.canExecute = !isSearch && canEdit && !unmodifiable; | 560 e.canExecute = !isSearch && canEdit && !unmodifiable; |
| 561 break; | 561 break; |
| 562 | 562 |
| 563 case 'open-in-new-tab-command': | 563 case 'open-in-new-tab-command': |
| 564 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false); | 564 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false); |
| 565 break; | 565 break; |
| 566 | 566 |
| 567 case 'open-in-background-tab-command': | 567 case 'open-in-background-tab-command': |
| 568 updateOpenCommand(e, command, '', '', false); | 568 updateOpenCommand(e, command, '', '', false); |
| 569 break; | 569 break; |
| 570 | 570 |
| 571 case 'open-in-new-window-command': | 571 case 'open-in-new-window-command': |
| 572 updateOpenCommand(e, command, | 572 updateOpenCommand( |
| 573 'open_in_new_window', 'open_all_new_window', | 573 e, command, 'open_in_new_window', 'open_all_new_window', |
| 574 // Disabled when incognito is forced. | 574 // Disabled when incognito is forced. |
| 575 incognitoModeAvailability == 'forced'); | 575 incognitoModeAvailability == 'forced'); |
| 576 break; | 576 break; |
| 577 | 577 |
| 578 case 'open-incognito-window-command': | 578 case 'open-incognito-window-command': |
| 579 updateOpenCommand(e, command, | 579 updateOpenCommand( |
| 580 'open_incognito', 'open_all_incognito', | 580 e, command, 'open_incognito', 'open_all_incognito', |
| 581 // Not available when incognito is disabled. | 581 // Not available when incognito is disabled. |
| 582 incognitoModeAvailability == 'disabled'); | 582 incognitoModeAvailability == 'disabled'); |
| 583 break; | 583 break; |
| 584 | 584 |
| 585 case 'undo-delete-command': | 585 case 'undo-delete-command': |
| 586 e.canExecute = !!lastDeleted; | 586 e.canExecute = !!lastDeleted; |
| 587 break; | 587 break; |
| 588 } | 588 } |
| 589 } | 589 } |
| 590 | 590 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 command.hidden = isFolder; | 641 command.hidden = isFolder; |
| 642 } | 642 } |
| 643 break; | 643 break; |
| 644 | 644 |
| 645 case 'show-in-folder-command': | 645 case 'show-in-folder-command': |
| 646 e.canExecute = isSearch() && hasSingleSelected(); | 646 e.canExecute = isSearch() && hasSingleSelected(); |
| 647 break; | 647 break; |
| 648 | 648 |
| 649 case 'delete-command': | 649 case 'delete-command': |
| 650 case 'cut-command': | 650 case 'cut-command': |
| 651 e.canExecute = canCopyItems() && canEdit && | 651 e.canExecute = |
| 652 !hasUnmodifiable(bmm.list.selectedItems); | 652 canCopyItems() && canEdit && !hasUnmodifiable(bmm.list.selectedItems); |
| 653 break; | 653 break; |
| 654 | 654 |
| 655 case 'copy-command': | 655 case 'copy-command': |
| 656 e.canExecute = canCopyItems(); | 656 e.canExecute = canCopyItems(); |
| 657 break; | 657 break; |
| 658 | 658 |
| 659 case 'open-in-same-window-command': | 659 case 'open-in-same-window-command': |
| 660 e.canExecute = (e.target == bmm.list) && hasSelected(); | 660 e.canExecute = (e.target == bmm.list) && hasSelected(); |
| 661 break; | 661 break; |
| 662 | 662 |
| 663 default: | 663 default: |
| 664 canExecuteShared(e, isSearch()); | 664 canExecuteShared(e, isSearch()); |
| 665 } | 665 } |
| 666 } | 666 } |
| 667 | 667 |
| 668 // Update canExecute for the commands when the list is the active element. | 668 // Update canExecute for the commands when the list is the active element. |
| 669 function handleCanExecuteForList(e) { | 669 function handleCanExecuteForList(e) { |
| 670 if (e.target != bmm.list) return; | 670 if (e.target != bmm.list) |
| 671 return; |
| 671 canExecuteForList(e); | 672 canExecuteForList(e); |
| 672 } | 673 } |
| 673 | 674 |
| 674 // Update canExecute for the commands when the tree is the active element. | 675 // Update canExecute for the commands when the tree is the active element. |
| 675 function handleCanExecuteForTree(e) { | 676 function handleCanExecuteForTree(e) { |
| 676 if (e.target != bmm.tree) return; | 677 if (e.target != bmm.tree) |
| 678 return; |
| 677 canExecuteForTree(e); | 679 canExecuteForTree(e); |
| 678 } | 680 } |
| 679 | 681 |
| 680 function canExecuteForTree(e) { | 682 function canExecuteForTree(e) { |
| 681 function hasSelected() { | 683 function hasSelected() { |
| 682 return !!bmm.tree.selectedItem; | 684 return !!bmm.tree.selectedItem; |
| 683 } | 685 } |
| 684 | 686 |
| 685 function isSearch() { | 687 function isSearch() { |
| 686 return bmm.tree.selectedItem == searchTreeItem; | 688 return bmm.tree.selectedItem == searchTreeItem; |
| 687 } | 689 } |
| 688 | 690 |
| 689 function isTopLevelItem() { | 691 function isTopLevelItem() { |
| 690 return bmm.tree.selectedItem && | 692 return bmm.tree.selectedItem && |
| 691 bmm.tree.selectedItem.parentNode == bmm.tree; | 693 bmm.tree.selectedItem.parentNode == bmm.tree; |
| 692 } | 694 } |
| 693 | 695 |
| 694 var command = e.command; | 696 var command = e.command; |
| 695 switch (command.id) { | 697 switch (command.id) { |
| 696 case 'rename-folder-command': | 698 case 'rename-folder-command': |
| 697 case 'rename-folder-from-folders-menu-command': | 699 case 'rename-folder-from-folders-menu-command': |
| 698 command.hidden = false; | 700 command.hidden = false; |
| 699 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && | 701 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && |
| 700 !hasUnmodifiable(bmm.tree.selectedFolders); | 702 !hasUnmodifiable(bmm.tree.selectedFolders); |
| 701 break; | 703 break; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 function handleRename(e) { | 782 function handleRename(e) { |
| 781 var item = e.target; | 783 var item = e.target; |
| 782 var bookmarkNode = item.bookmarkNode; | 784 var bookmarkNode = item.bookmarkNode; |
| 783 chrome.bookmarks.update(bookmarkNode.id, {title: item.label}); | 785 chrome.bookmarks.update(bookmarkNode.id, {title: item.label}); |
| 784 performGlobalUndo = null; // This can't be undone, so disable global undo. | 786 performGlobalUndo = null; // This can't be undone, so disable global undo. |
| 785 } | 787 } |
| 786 | 788 |
| 787 function handleEdit(e) { | 789 function handleEdit(e) { |
| 788 var item = e.target; | 790 var item = e.target; |
| 789 var bookmarkNode = item.bookmarkNode; | 791 var bookmarkNode = item.bookmarkNode; |
| 790 var context = { | 792 var context = {title: bookmarkNode.title}; |
| 791 title: bookmarkNode.title | |
| 792 }; | |
| 793 if (!bmm.isFolder(bookmarkNode)) | 793 if (!bmm.isFolder(bookmarkNode)) |
| 794 context.url = bookmarkNode.url; | 794 context.url = bookmarkNode.url; |
| 795 | 795 |
| 796 if (bookmarkNode.id == 'new') { | 796 if (bookmarkNode.id == 'new') { |
| 797 selectItemsAfterUserAction(/** @type {BookmarkList} */(bmm.list)); | 797 selectItemsAfterUserAction(/** @type {BookmarkList} */ (bmm.list)); |
| 798 | 798 |
| 799 // New page | 799 // New page |
| 800 context.parentId = bookmarkNode.parentId; | 800 context.parentId = bookmarkNode.parentId; |
| 801 chrome.bookmarks.create(context, function(node) { | 801 chrome.bookmarks.create(context, function(node) { |
| 802 // A new node was created and will get added to the list due to the | 802 // A new node was created and will get added to the list due to the |
| 803 // handler. | 803 // handler. |
| 804 var dataModel = bmm.list.dataModel; | 804 var dataModel = bmm.list.dataModel; |
| 805 var index = dataModel.indexOf(bookmarkNode); | 805 var index = dataModel.indexOf(bookmarkNode); |
| 806 dataModel.splice(index, 1); | 806 dataModel.splice(index, 1); |
| 807 | 807 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 | 867 |
| 868 /** | 868 /** |
| 869 * Returns the selected bookmark nodes of the provided tree or list. | 869 * Returns the selected bookmark nodes of the provided tree or list. |
| 870 * If |opt_target| is not provided or null the active element is used. | 870 * If |opt_target| is not provided or null the active element is used. |
| 871 * Only call this if the list or the tree is focused. | 871 * Only call this if the list or the tree is focused. |
| 872 * @param {EventTarget=} opt_target The target list or tree. | 872 * @param {EventTarget=} opt_target The target list or tree. |
| 873 * @return {!Array} Array of bookmark nodes. | 873 * @return {!Array} Array of bookmark nodes. |
| 874 */ | 874 */ |
| 875 function getSelectedBookmarkNodes(opt_target) { | 875 function getSelectedBookmarkNodes(opt_target) { |
| 876 return (opt_target || document.activeElement) == bmm.tree ? | 876 return (opt_target || document.activeElement) == bmm.tree ? |
| 877 bmm.tree.selectedFolders : bmm.list.selectedItems; | 877 bmm.tree.selectedFolders : |
| 878 bmm.list.selectedItems; |
| 878 } | 879 } |
| 879 | 880 |
| 880 /** | 881 /** |
| 881 * @param {EventTarget=} opt_target The target list or tree. | 882 * @param {EventTarget=} opt_target The target list or tree. |
| 882 * @return {!Array<string>} An array of the selected bookmark IDs. | 883 * @return {!Array<string>} An array of the selected bookmark IDs. |
| 883 */ | 884 */ |
| 884 function getSelectedBookmarkIds(opt_target) { | 885 function getSelectedBookmarkIds(opt_target) { |
| 885 var selectedNodes = getSelectedBookmarkNodes(opt_target); | 886 var selectedNodes = getSelectedBookmarkNodes(opt_target); |
| 886 selectedNodes.sort(function(a, b) { return a.index - b.index; }); | 887 selectedNodes.sort(function(a, b) { |
| 888 return a.index - b.index; |
| 889 }); |
| 887 return selectedNodes.map(function(node) { | 890 return selectedNodes.map(function(node) { |
| 888 return node.id; | 891 return node.id; |
| 889 }); | 892 }); |
| 890 } | 893 } |
| 891 | 894 |
| 892 /** | 895 /** |
| 893 * @param {BookmarkTreeNode} node The node to test. | 896 * @param {BookmarkTreeNode} node The node to test. |
| 894 * @return {boolean} Whether the given node is unmodifiable. | 897 * @return {boolean} Whether the given node is unmodifiable. |
| 895 */ | 898 */ |
| 896 function isUnmodifiable(node) { | 899 function isUnmodifiable(node) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 } | 1030 } |
| 1028 | 1031 |
| 1029 /** | 1032 /** |
| 1030 * Computes folder for "Add Page" and "Add Folder". | 1033 * Computes folder for "Add Page" and "Add Folder". |
| 1031 * @return {string} The id of folder node where we'll create new page/folder. | 1034 * @return {string} The id of folder node where we'll create new page/folder. |
| 1032 */ | 1035 */ |
| 1033 function computeParentFolderForNewItem() { | 1036 function computeParentFolderForNewItem() { |
| 1034 if (document.activeElement == bmm.tree) | 1037 if (document.activeElement == bmm.tree) |
| 1035 return bmm.list.parentId; | 1038 return bmm.list.parentId; |
| 1036 var selectedItem = bmm.list.selectedItem; | 1039 var selectedItem = bmm.list.selectedItem; |
| 1037 return selectedItem && bmm.isFolder(selectedItem) ? | 1040 return selectedItem && bmm.isFolder(selectedItem) ? selectedItem.id : |
| 1038 selectedItem.id : bmm.list.parentId; | 1041 bmm.list.parentId; |
| 1039 } | 1042 } |
| 1040 | 1043 |
| 1041 /** | 1044 /** |
| 1042 * Callback for rename folder and edit command. This starts editing for | 1045 * Callback for rename folder and edit command. This starts editing for |
| 1043 * the passed in target, or the selected item. | 1046 * the passed in target, or the selected item. |
| 1044 * @param {EventTarget=} opt_target The target to start editing. If absent or | 1047 * @param {EventTarget=} opt_target The target to start editing. If absent or |
| 1045 * null, the selected item will be edited instead. | 1048 * null, the selected item will be edited instead. |
| 1046 */ | 1049 */ |
| 1047 function editItem(opt_target) { | 1050 function editItem(opt_target) { |
| 1048 if ((opt_target || document.activeElement) == bmm.tree) { | 1051 if ((opt_target || document.activeElement) == bmm.tree) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1064 | 1067 |
| 1065 var parentId = computeParentFolderForNewItem(); | 1068 var parentId = computeParentFolderForNewItem(); |
| 1066 var selectedItems = bmm.list.selectedItems; | 1069 var selectedItems = bmm.list.selectedItems; |
| 1067 var newIndex; | 1070 var newIndex; |
| 1068 // Callback is called after tree and list data model updated. | 1071 // Callback is called after tree and list data model updated. |
| 1069 function createFolder(callback) { | 1072 function createFolder(callback) { |
| 1070 if (selectedItems.length == 1 && document.activeElement != bmm.tree && | 1073 if (selectedItems.length == 1 && document.activeElement != bmm.tree && |
| 1071 !bmm.isFolder(selectedItems[0]) && selectedItems[0].id != 'new') { | 1074 !bmm.isFolder(selectedItems[0]) && selectedItems[0].id != 'new') { |
| 1072 newIndex = bmm.list.dataModel.indexOf(selectedItems[0]) + 1; | 1075 newIndex = bmm.list.dataModel.indexOf(selectedItems[0]) + 1; |
| 1073 } | 1076 } |
| 1074 chrome.bookmarks.create({ | 1077 chrome.bookmarks.create( |
| 1075 title: loadTimeData.getString('new_folder_name'), | 1078 { |
| 1076 parentId: parentId, | 1079 title: loadTimeData.getString('new_folder_name'), |
| 1077 index: newIndex | 1080 parentId: parentId, |
| 1078 }, callback); | 1081 index: newIndex |
| 1082 }, |
| 1083 callback); |
| 1079 } | 1084 } |
| 1080 | 1085 |
| 1081 if ((opt_target || document.activeElement) == bmm.tree) { | 1086 if ((opt_target || document.activeElement) == bmm.tree) { |
| 1082 createFolder(function(newNode) { | 1087 createFolder(function(newNode) { |
| 1083 navigateTo(newNode.id, function() { | 1088 navigateTo(newNode.id, function() { |
| 1084 bmm.treeLookup[newNode.id].editing = true; | 1089 bmm.treeLookup[newNode.id].editing = true; |
| 1085 }); | 1090 }); |
| 1086 }); | 1091 }); |
| 1087 return; | 1092 return; |
| 1088 } | 1093 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 function addPage() { | 1126 function addPage() { |
| 1122 var parentId = computeParentFolderForNewItem(); | 1127 var parentId = computeParentFolderForNewItem(); |
| 1123 var selectedItems = bmm.list.selectedItems; | 1128 var selectedItems = bmm.list.selectedItems; |
| 1124 var newIndex; | 1129 var newIndex; |
| 1125 function editNewBookmark() { | 1130 function editNewBookmark() { |
| 1126 if (selectedItems.length == 1 && document.activeElement != bmm.tree && | 1131 if (selectedItems.length == 1 && document.activeElement != bmm.tree && |
| 1127 !bmm.isFolder(selectedItems[0])) { | 1132 !bmm.isFolder(selectedItems[0])) { |
| 1128 newIndex = bmm.list.dataModel.indexOf(selectedItems[0]) + 1; | 1133 newIndex = bmm.list.dataModel.indexOf(selectedItems[0]) + 1; |
| 1129 } | 1134 } |
| 1130 | 1135 |
| 1131 var fakeNode = { | 1136 var fakeNode = |
| 1132 title: '', | 1137 {title: '', url: '', parentId: parentId, index: newIndex, id: 'new'}; |
| 1133 url: '', | |
| 1134 parentId: parentId, | |
| 1135 index: newIndex, | |
| 1136 id: 'new' | |
| 1137 }; | |
| 1138 var dataModel = bmm.list.dataModel; | 1138 var dataModel = bmm.list.dataModel; |
| 1139 var index = dataModel.length; | 1139 var index = dataModel.length; |
| 1140 if (newIndex != undefined) | 1140 if (newIndex != undefined) |
| 1141 index = newIndex; | 1141 index = newIndex; |
| 1142 dataModel.splice(index, 0, fakeNode); | 1142 dataModel.splice(index, 0, fakeNode); |
| 1143 var sm = bmm.list.selectionModel; | 1143 var sm = bmm.list.selectionModel; |
| 1144 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; | 1144 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; |
| 1145 scrollIntoViewAndMakeEditable(index); | 1145 scrollIntoViewAndMakeEditable(index); |
| 1146 } | 1146 } |
| 1147 | 1147 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 /** | 1211 /** |
| 1212 * The currently selected bookmark, based on where the user is clicking. | 1212 * The currently selected bookmark, based on where the user is clicking. |
| 1213 * @return {string} The ID of the currently selected bookmark (could be from | 1213 * @return {string} The ID of the currently selected bookmark (could be from |
| 1214 * tree view or list view). | 1214 * tree view or list view). |
| 1215 */ | 1215 */ |
| 1216 function getSelectedId() { | 1216 function getSelectedId() { |
| 1217 if (document.activeElement == bmm.tree) | 1217 if (document.activeElement == bmm.tree) |
| 1218 return bmm.tree.selectedItem.bookmarkId; | 1218 return bmm.tree.selectedItem.bookmarkId; |
| 1219 var selectedItem = bmm.list.selectedItem; | 1219 var selectedItem = bmm.list.selectedItem; |
| 1220 return selectedItem && bmm.isFolder(selectedItem) ? | 1220 return selectedItem && bmm.isFolder(selectedItem) ? |
| 1221 selectedItem.id : bmm.tree.selectedItem.bookmarkId; | 1221 selectedItem.id : |
| 1222 bmm.tree.selectedItem.bookmarkId; |
| 1222 } | 1223 } |
| 1223 | 1224 |
| 1224 /** | 1225 /** |
| 1225 * Pastes the copied/cutted bookmark into the right location depending whether | 1226 * Pastes the copied/cutted bookmark into the right location depending whether |
| 1226 * if it was called from Organize Menu or from Context Menu. | 1227 * if it was called from Organize Menu or from Context Menu. |
| 1227 * @param {string} id The id of the element being pasted from. | 1228 * @param {string} id The id of the element being pasted from. |
| 1228 */ | 1229 */ |
| 1229 function pasteBookmark(id) { | 1230 function pasteBookmark(id) { |
| 1230 recordUserAction('Paste'); | 1231 recordUserAction('Paste'); |
| 1231 selectItemsAfterUserAction(/** @type {BookmarkList} */(bmm.list)); | 1232 selectItemsAfterUserAction(/** @type {BookmarkList} */ (bmm.list)); |
| 1232 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds()); | 1233 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds()); |
| 1233 } | 1234 } |
| 1234 | 1235 |
| 1235 /** | 1236 /** |
| 1236 * Returns true if child is contained in another selected folder. | 1237 * Returns true if child is contained in another selected folder. |
| 1237 * Traces parent nodes up the tree until a selected ancestor or root is found. | 1238 * Traces parent nodes up the tree until a selected ancestor or root is found. |
| 1238 */ | 1239 */ |
| 1239 function hasSelectedAncestor(parentNode) { | 1240 function hasSelectedAncestor(parentNode) { |
| 1240 function contains(arr, item) { | 1241 function contains(arr, item) { |
| 1241 for (var i = 0; i < arr.length; i++) | 1242 for (var i = 0; i < arr.length; i++) |
| 1242 if (arr[i] === item) | 1243 if (arr[i] === item) |
| 1243 return true; | 1244 return true; |
| 1244 return false; | 1245 return false; |
| 1245 } | 1246 } |
| 1246 | 1247 |
| 1247 // Don't search top level, cannot select permanent nodes in search. | 1248 // Don't search top level, cannot select permanent nodes in search. |
| 1248 if (parentNode == null || parentNode.id <= 2) | 1249 if (parentNode == null || parentNode.id <= 2) |
| 1249 return false; | 1250 return false; |
| 1250 | 1251 |
| 1251 // Found selected ancestor. | 1252 // Found selected ancestor. |
| 1252 if (contains(getSelectedBookmarkNodes(), parentNode)) | 1253 if (contains(getSelectedBookmarkNodes(), parentNode)) |
| 1253 return true; | 1254 return true; |
| 1254 | 1255 |
| 1255 // Keep digging. | 1256 // Keep digging. |
| 1256 return hasSelectedAncestor( | 1257 return hasSelectedAncestor(bmm.tree.getBookmarkNodeById(parentNode.parentId)); |
| 1257 bmm.tree.getBookmarkNodeById(parentNode.parentId)); | |
| 1258 } | 1258 } |
| 1259 | 1259 |
| 1260 /** | 1260 /** |
| 1261 * @param {EventTarget=} opt_target A target to get bookmark IDs from. | 1261 * @param {EventTarget=} opt_target A target to get bookmark IDs from. |
| 1262 * @return {Array<string>} An array of bookmarks IDs. | 1262 * @return {Array<string>} An array of bookmarks IDs. |
| 1263 */ | 1263 */ |
| 1264 function getFilteredSelectedBookmarkIds(opt_target) { | 1264 function getFilteredSelectedBookmarkIds(opt_target) { |
| 1265 // Remove duplicates from filteredIds and return. | 1265 // Remove duplicates from filteredIds and return. |
| 1266 var filteredIds = []; | 1266 var filteredIds = []; |
| 1267 // Selected nodes to iterate through for matches. | 1267 // Selected nodes to iterate through for matches. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 target = bmm.tree; | 1327 target = bmm.tree; |
| 1328 case 'delete-command': | 1328 case 'delete-command': |
| 1329 recordUserAction('Delete'); | 1329 recordUserAction('Delete'); |
| 1330 deleteBookmarks(target); | 1330 deleteBookmarks(target); |
| 1331 break; | 1331 break; |
| 1332 | 1332 |
| 1333 case 'copy-from-folders-menu-command': | 1333 case 'copy-from-folders-menu-command': |
| 1334 target = bmm.tree; | 1334 target = bmm.tree; |
| 1335 case 'copy-command': | 1335 case 'copy-command': |
| 1336 recordUserAction('Copy'); | 1336 recordUserAction('Copy'); |
| 1337 chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(target), | 1337 chrome.bookmarkManagerPrivate.copy( |
| 1338 updatePasteCommand); | 1338 getSelectedBookmarkIds(target), updatePasteCommand); |
| 1339 break; | 1339 break; |
| 1340 | 1340 |
| 1341 case 'cut-from-folders-menu-command': | 1341 case 'cut-from-folders-menu-command': |
| 1342 target = bmm.tree; | 1342 target = bmm.tree; |
| 1343 case 'cut-command': | 1343 case 'cut-command': |
| 1344 recordUserAction('Cut'); | 1344 recordUserAction('Cut'); |
| 1345 chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(target), | 1345 chrome.bookmarkManagerPrivate.cut( |
| 1346 function() { | 1346 getSelectedBookmarkIds(target), function() { |
| 1347 updatePasteCommand(); | 1347 updatePasteCommand(); |
| 1348 updateSearchResults(); | 1348 updateSearchResults(); |
| 1349 }); | 1349 }); |
| 1350 break; | 1350 break; |
| 1351 | 1351 |
| 1352 case 'paste-from-organize-menu-command': | 1352 case 'paste-from-organize-menu-command': |
| 1353 pasteBookmark(bmm.list.parentId); | 1353 pasteBookmark(bmm.list.parentId); |
| 1354 break; | 1354 break; |
| 1355 | 1355 |
| 1356 case 'paste-from-folders-menu-command': | 1356 case 'paste-from-folders-menu-command': |
| 1357 pasteBookmark(bmm.tree.selectedItem.bookmarkId); | 1357 pasteBookmark(bmm.tree.selectedItem.bookmarkId); |
| 1358 break; | 1358 break; |
| 1359 | 1359 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 bmm.list.addEventListener('rename', handleRename); | 1472 bmm.list.addEventListener('rename', handleRename); |
| 1473 bmm.list.addEventListener('urlClicked', handleUrlClickedForList); | 1473 bmm.list.addEventListener('urlClicked', handleUrlClickedForList); |
| 1474 | 1474 |
| 1475 bmm.tree.addEventListener('canExecute', handleCanExecuteForTree); | 1475 bmm.tree.addEventListener('canExecute', handleCanExecuteForTree); |
| 1476 bmm.tree.addEventListener('change', handleChangeForTree); | 1476 bmm.tree.addEventListener('change', handleChangeForTree); |
| 1477 bmm.tree.addEventListener('contextmenu', updateEditingCommands); | 1477 bmm.tree.addEventListener('contextmenu', updateEditingCommands); |
| 1478 bmm.tree.addEventListener('rename', handleRename); | 1478 bmm.tree.addEventListener('rename', handleRename); |
| 1479 bmm.tree.addEventListener('load', handleLoadForTree); | 1479 bmm.tree.addEventListener('load', handleLoadForTree); |
| 1480 | 1480 |
| 1481 cr.ui.contextMenuHandler.addContextMenuProperty( | 1481 cr.ui.contextMenuHandler.addContextMenuProperty( |
| 1482 /** @type {!Element} */(bmm.tree)); | 1482 /** @type {!Element} */ (bmm.tree)); |
| 1483 bmm.list.contextMenu = $('context-menu'); | 1483 bmm.list.contextMenu = $('context-menu'); |
| 1484 bmm.tree.contextMenu = $('context-menu'); | 1484 bmm.tree.contextMenu = $('context-menu'); |
| 1485 | 1485 |
| 1486 // We listen to hashchange so that we can update the currently shown folder | 1486 // We listen to hashchange so that we can update the currently shown folder |
| 1487 // when // the user goes back and forward in the history. | 1487 // when // the user goes back and forward in the history. |
| 1488 window.addEventListener('hashchange', processHash); | 1488 window.addEventListener('hashchange', processHash); |
| 1489 | 1489 |
| 1490 document.querySelector('header form').onsubmit = | 1490 document.querySelector('header form').onsubmit = |
| 1491 /** @type {function(Event=)} */(function(e) { | 1491 /** @type {function(Event=)} */ (function(e) { |
| 1492 setSearch($('term').value); | 1492 setSearch($('term').value); |
| 1493 e.preventDefault(); | 1493 e.preventDefault(); |
| 1494 }); | 1494 }); |
| 1495 | 1495 |
| 1496 $('term').addEventListener('search', handleSearch); | 1496 $('term').addEventListener('search', handleSearch); |
| 1497 $('term').addEventListener('canExecute', handleCanExecuteForSearchBox); | 1497 $('term').addEventListener('canExecute', handleCanExecuteForSearchBox); |
| 1498 | 1498 |
| 1499 $('folders-button').addEventListener('click', handleMenuButtonClicked); | 1499 $('folders-button').addEventListener('click', handleMenuButtonClicked); |
| 1500 $('organize-button').addEventListener('click', handleMenuButtonClicked); | 1500 $('organize-button').addEventListener('click', handleMenuButtonClicked); |
| 1501 | 1501 |
| 1502 document.addEventListener('canExecute', handleCanExecuteForDocument); | 1502 document.addEventListener('canExecute', handleCanExecuteForDocument); |
| 1503 document.addEventListener('command', handleCommand); | 1503 document.addEventListener('command', handleCommand); |
| 1504 | 1504 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1533 | 1533 |
| 1534 cr.ui.FocusOutlineManager.forDocument(document); | 1534 cr.ui.FocusOutlineManager.forDocument(document); |
| 1535 initializeSplitter(); | 1535 initializeSplitter(); |
| 1536 bmm.addBookmarkModelListeners(); | 1536 bmm.addBookmarkModelListeners(); |
| 1537 dnd.init(selectItemsAfterUserAction); | 1537 dnd.init(selectItemsAfterUserAction); |
| 1538 bmm.tree.reload(); | 1538 bmm.tree.reload(); |
| 1539 } | 1539 } |
| 1540 | 1540 |
| 1541 initializeBookmarkManager(); | 1541 initializeBookmarkManager(); |
| 1542 })(); | 1542 })(); |
| OLD | NEW |