Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <!-- | 3 <!-- |
| 4 | 4 |
| 5 Copyright (c) 2010 The Chromium Authors. All rights reserved. | 5 Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
| 7 found in the LICENSE file. | 7 found in the LICENSE file. |
| 8 | 8 |
| 9 | 9 |
| 10 This is work in progress: | 10 This is work in progress: |
| 11 | 11 |
| 12 i18n: Expose a chrome.experimental.bookmarkManager.getLocalStrings | |
| 13 | |
| 14 import/export: Expose in experimental extension API. | |
| 15 | |
| 16 Internal DnD: Buggy when dragging multiple items (the order of the dropped items | |
| 17 is not correct. | |
| 18 | |
| 19 External DnD: Chrome doesn't follow HTML5 and it limits the data types to text | |
| 20 and a single URL. Fixing Chrome is unreasonable given our current time frame. | |
| 21 There are two options here. Disable external DnD or expose enough hooks in the | |
| 22 experimental bookmarks manager extension API. | |
| 23 | |
| 24 Clipboard: Once again Chrome does not correctly implement HTML5 and it only | |
| 25 allows text and url. We can either disable the clipboard actions, only allow | |
| 26 internal clipboard or expose the hooks in the extension api. | |
| 27 | |
| 28 Favicons: chrome-extension: is not allowed to access chrome://favicon. We need | 12 Favicons: chrome-extension: is not allowed to access chrome://favicon. We need |
| 29 to whitelist it or expose a way to get the data URI for the favicon (slow and | 13 to whitelist it or expose a way to get the data URI for the favicon (slow and |
| 30 sucky). | 14 sucky). |
| 31 | 15 |
| 32 Favicon of bmm does not work. No icon is showed. | 16 Favicon of bmm does not work. No icon is showed. |
| 33 | 17 |
| 34 --> | 18 --> |
| 35 <head> | 19 <head> |
| 36 <title i18n-content="title"></title> | 20 <title i18n-content="title"></title> |
| 37 <link rel="stylesheet" href="css/list.css"> | 21 <link rel="stylesheet" href="css/list.css"> |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 60 <script src="js/bmm.js"></script> | 44 <script src="js/bmm.js"></script> |
| 61 <script src="js/bmm/bookmarklist.js"></script> | 45 <script src="js/bmm/bookmarklist.js"></script> |
| 62 <script src="js/bmm/bookmarktree.js"></script> | 46 <script src="js/bmm/bookmarktree.js"></script> |
| 63 | 47 |
| 64 <style> | 48 <style> |
| 65 | 49 |
| 66 html, body { | 50 html, body { |
| 67 margin: 0; | 51 margin: 0; |
| 68 width: 100%; | 52 width: 100%; |
| 69 height: 100%; | 53 height: 100%; |
| 70 /*-webkit-user-select: none;*/ | |
| 71 cursor: default; | 54 cursor: default; |
| 72 font: 13px arial; | 55 font: 13px arial; |
| 73 } | 56 } |
| 74 | 57 |
| 75 list { | 58 list { |
| 76 display: block; | 59 display: block; |
| 77 overflow-x: hidden; | 60 overflow-x: hidden; |
| 78 overflow-y: visible; /* let the container do the scrolling */ | 61 overflow-y: visible; /* let the container do the scrolling */ |
| 79 } | 62 } |
| 80 | 63 |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 bookmarkId: 'recent' | 429 bookmarkId: 'recent' |
| 447 }); | 430 }); |
| 448 bmm.treeLookup[recentTreeItem.bookmarkId] = recentTreeItem; | 431 bmm.treeLookup[recentTreeItem.bookmarkId] = recentTreeItem; |
| 449 | 432 |
| 450 BookmarkTree.decorate(tree); | 433 BookmarkTree.decorate(tree); |
| 451 | 434 |
| 452 tree.addEventListener('change', function() { | 435 tree.addEventListener('change', function() { |
| 453 navigateTo(tree.selectedItem.bookmarkId); | 436 navigateTo(tree.selectedItem.bookmarkId); |
| 454 }); | 437 }); |
| 455 | 438 |
| 456 </script> | |
| 457 <script> | |
| 458 | |
| 459 /** | 439 /** |
| 460 * Navigates to a bookmark ID. | 440 * Navigates to a bookmark ID. |
| 461 * @param {string} id The ID to navigate to. | 441 * @param {string} id The ID to navigate to. |
| 462 */ | 442 */ |
| 463 function navigateTo(id) { | 443 function navigateTo(id) { |
| 464 console.info('navigateTo', window.location.hash, id); | 444 console.info('navigateTo', window.location.hash, id); |
| 465 window.location.hash = id; | 445 window.location.hash = id; |
| 466 updateParentId(id); | 446 updateParentId(id); |
| 467 } | 447 } |
| 468 | 448 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 } | 650 } |
| 671 | 651 |
| 672 if (/^q=/.test(hash)) | 652 if (/^q=/.test(hash)) |
| 673 $('term').value = hash.slice(2); | 653 $('term').value = hash.slice(2); |
| 674 navigateTo(hash); | 654 navigateTo(hash); |
| 675 }); | 655 }); |
| 676 | 656 |
| 677 tree.buildTree(); | 657 tree.buildTree(); |
| 678 addBookmarkModelListeners(); | 658 addBookmarkModelListeners(); |
| 679 | 659 |
| 680 </script> | 660 var dnd = { |
| 681 <script> | 661 DND_EFFECT_COPY: 'copy', |
| 662 DND_EFFECT_MOVE: cr.isMac ? 'move' : 'copy', // http://crbug.com/14654 | |
| 682 | 663 |
| 683 var dnd = { | 664 dragData: null, |
| 684 | |
| 685 DND_EFFECT: cr.isMac ? 'move' : 'copy', // http://crbug.com/14654 | |
| 686 | |
| 687 dragBookmarkNodes: [], | |
| 688 | 665 |
| 689 getBookmarkElement: function(el) { | 666 getBookmarkElement: function(el) { |
| 690 while (el && !el.bookmarkNode) { | 667 while (el && !el.bookmarkNode) { |
| 691 el = el.parentNode; | 668 el = el.parentNode; |
| 692 } | 669 } |
| 693 return el; | 670 return el; |
| 694 }, | 671 }, |
| 695 | 672 |
| 696 // If we are over the list and the list is showing recent or search result | 673 // If we are over the list and the list is showing recent or search result |
| 697 // we cannot drop. | 674 // we cannot drop. |
| 698 isOverRecentOrSearch: function(overElement) { | 675 isOverRecentOrSearch: function(overElement) { |
| 699 return (list.isRecent() || list.isSearch()) && list.contains(overElement); | 676 return (list.isRecent() || list.isSearch()) && list.contains(overElement); |
| 700 }, | 677 }, |
| 701 | 678 |
| 702 checkEvery_: function(f, dragBookmarkNodes, overBookmarkNode, overElement) { | 679 checkEvery_: function(f, overBookmarkNode, overElement) { |
| 703 return dragBookmarkNodes.every(function(dragBookmarkNode) { | 680 return this.dragData.elements.every(function(element) { |
| 704 return f.call(this, dragBookmarkNode, overBookmarkNode, overElement); | 681 return f.call(this, element, overBookmarkNode, overElement); |
| 705 }, this); | 682 }, this); |
| 706 }, | 683 }, |
| 707 | 684 |
| 708 /** | 685 /** |
| 686 * @return {boolean} Whether we are currently dragging any folders. | |
| 687 */ | |
| 688 isDraggingFolders: function() { | |
| 689 return !!this.dragData && this.dragData.elements.some(function(node) { | |
| 690 return !node.url; | |
| 691 }); | |
| 692 }, | |
| 693 | |
| 694 /** | |
| 709 * This is a first pass wether we can drop the dragged items. | 695 * This is a first pass wether we can drop the dragged items. |
| 710 * | 696 * |
| 711 * @param {!Array.<BookmarkTreeNode>} dragBookmarkNodes The bookmarks that are | |
| 712 * currently being dragged. | |
| 713 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are | 697 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are |
| 714 * currently dragging over. | 698 * currently dragging over. |
| 715 * @param {!HTMLElement} overElement The element that we are currently | 699 * @param {!HTMLElement} overElement The element that we are currently |
| 716 * dragging over. | 700 * dragging over. |
| 717 * @return {boolean} If this returns false then we know we should not drop | 701 * @return {boolean} If this returns false then we know we should not drop |
| 718 * the items. If it returns true we still have to call canDropOn, | 702 * the items. If it returns true we still have to call canDropOn, |
| 719 * canDropAbove and canDropBelow. | 703 * canDropAbove and canDropBelow. |
| 720 */ | 704 */ |
| 721 canDrop: function(dragBookmarkNodes, overBookmarkNode, overElement) { | 705 canDrop: function(overBookmarkNode, overElement) { |
| 722 return this.checkEvery_(this.canDrop_, dragBookmarkNodes, | 706 var dragData = this.dragData; |
| 723 overBookmarkNode, overElement); | 707 if (!dragData) |
| 708 return false; | |
| 709 if (!dragData.sameProfile) | |
| 710 return true; | |
|
feldstein
2010/02/22 19:13:58
Will this allow the user to drop from a different
arv (Not doing code reviews)
2010/02/22 19:42:09
canDrop is a first pass. If it returns true we cal
| |
| 711 | |
| 712 return this.checkEvery_(this.canDrop_, overBookmarkNode, overElement); | |
| 724 }, | 713 }, |
| 725 | 714 |
| 726 /** | 715 /** |
| 727 * Helper for canDrop that only checks one bookmark node. | 716 * Helper for canDrop that only checks one bookmark node. |
| 728 * @private | 717 * @private |
| 729 */ | 718 */ |
| 730 canDrop_: function(dragBookmarkNode, overBookmarkNode, overElement) { | 719 canDrop_: function(dragNode, overBookmarkNode, overElement) { |
| 731 if (overBookmarkNode.id == dragBookmarkNode.id) | 720 var dragId = dragNode.id; |
| 721 | |
| 722 if (overBookmarkNode.id == dragId) | |
| 732 return false; | 723 return false; |
| 733 | 724 |
| 734 if (this.isOverRecentOrSearch(overElement)) | 725 if (this.isOverRecentOrSearch(overElement)) |
| 735 return false; | 726 return false; |
| 736 | 727 |
| 737 if (dragBookmarkNode.id == overBookmarkNode.id) | |
| 738 return false; | |
| 739 | |
| 740 // If we are dragging a folder we cannot drop it on any of its descendants | 728 // If we are dragging a folder we cannot drop it on any of its descendants |
| 741 if (bmm.isFolder(dragBookmarkNode) && | 729 var dragBookmarkNode = bmm.treeLookup[dragId]; |
| 730 if (dragBookmarkNode && bmm.isFolder(dragBookmarkNode) && | |
| 742 bmm.contains(dragBookmarkNode, overBookmarkNode)) { | 731 bmm.contains(dragBookmarkNode, overBookmarkNode)) { |
| 743 return false; | 732 return false; |
| 744 } | 733 } |
| 745 | 734 |
| 746 return true; | 735 return true; |
| 747 }, | 736 }, |
| 748 | 737 |
| 749 /** | 738 /** |
| 750 * Whether we can drop the dragged items above the drop target. | 739 * Whether we can drop the dragged items above the drop target. |
| 751 * | 740 * |
| 752 * @param {!Array.<BookmarkTreeNode>} dragBookmarkNodes The bookmarks that are | |
| 753 * currently being dragged. | |
| 754 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are | 741 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are |
| 755 * currently dragging over. | 742 * currently dragging over. |
| 756 * @param {!HTMLElement} overElement The element that we are currently | 743 * @param {!HTMLElement} overElement The element that we are currently |
| 757 * dragging over. | 744 * dragging over. |
| 758 * @return {boolean} Whether we can drop the dragged items above the drop | 745 * @return {boolean} Whether we can drop the dragged items above the drop |
| 759 * target. | 746 * target. |
| 760 */ | 747 */ |
| 761 canDropAbove: function(dragBookmarkNodes, overBookmarkNode, overElement) { | 748 canDropAbove: function(overBookmarkNode, overElement) { |
| 762 return this.checkEvery_(this.canDropAbove_, dragBookmarkNodes, | 749 if (overElement instanceof BookmarkList) |
| 763 overBookmarkNode, overElement); | 750 return false; |
| 751 | |
| 752 // We cannot drop between Bookmarks bar and Other bookmarks | |
| 753 if (overBookmarkNode.parentId == ROOT_ID) | |
| 754 return false; | |
| 755 | |
| 756 var isOverTreeItem = overElement instanceof TreeItem; | |
| 757 | |
| 758 // We can only drop between items in the tree if we have any folders. | |
| 759 if (isOverTreeItem && !this.isDraggingFolders()) | |
| 760 return false; | |
| 761 | |
| 762 if (!this.dragData.sameProfile) | |
| 763 return this.isDraggingFolders() || !isOverTreeItem; | |
| 764 | |
| 765 return this.checkEvery_(this.canDropAbove_, overBookmarkNode, overElement); | |
| 764 }, | 766 }, |
| 765 | 767 |
| 766 /** | 768 /** |
| 767 * Helper for canDropAbove that only checks one bookmark node. | 769 * Helper for canDropAbove that only checks one bookmark node. |
| 768 * @private | 770 * @private |
| 769 */ | 771 */ |
| 770 canDropAbove_: function(dragBookmarkNode, overBookmarkNode, overElement) { | 772 canDropAbove_: function(dragNode, overBookmarkNode, overElement) { |
| 771 if (overElement instanceof BookmarkList) | 773 var dragId = dragNode.id; |
| 772 return false; | |
| 773 | |
| 774 // If dragBookmarkNode is a non folder and overElement is a tree item we | |
| 775 // cannot drop it above or below. | |
| 776 if (!bmm.isFolder(dragBookmarkNode) && overElement instanceof TreeItem) | |
| 777 return false; | |
| 778 | |
| 779 // We cannot drop between Bookmarks bar and Other bookmarks | |
| 780 if (overBookmarkNode.parentId == ROOT_ID) | |
| 781 return false; | |
| 782 | 774 |
| 783 // We cannot drop above if the item below is already in the drag source | 775 // We cannot drop above if the item below is already in the drag source |
| 784 var previousElement = overElement.previousElementSibling; | 776 var previousElement = overElement.previousElementSibling; |
| 785 if (previousElement && | 777 if (previousElement && |
| 786 previousElement.bookmarkNode.id == dragBookmarkNode.id) | 778 previousElement.bookmarkId == dragId) |
| 787 return false; | 779 return false; |
| 788 | 780 |
| 789 return true; | 781 return true; |
| 790 }, | 782 }, |
| 791 | 783 |
| 792 /** | 784 /** |
| 793 * Whether we can drop the dragged items below the drop target. | 785 * Whether we can drop the dragged items below the drop target. |
| 794 * | 786 * |
| 795 * @param {!Array.<BookmarkTreeNode>} dragBookmarkNodes The bookmarks that are | |
| 796 * currently being dragged. | |
| 797 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are | 787 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are |
| 798 * currently dragging over. | 788 * currently dragging over. |
| 799 * @param {!HTMLElement} overElement The element that we are currently | 789 * @param {!HTMLElement} overElement The element that we are currently |
| 800 * dragging over. | 790 * dragging over. |
| 801 * @return {boolean} Whether we can drop the dragged items below the drop | 791 * @return {boolean} Whether we can drop the dragged items below the drop |
| 802 * target. | 792 * target. |
| 803 */ | 793 */ |
| 804 canDropBelow: function(dragBookmarkNodes, overBookmarkNode, overElement) { | 794 canDropBelow: function(overBookmarkNode, overElement) { |
| 805 return this.checkEvery_(this.canDropBelow_, dragBookmarkNodes, | 795 if (overElement instanceof BookmarkList) |
| 806 overBookmarkNode, overElement); | 796 return false; |
| 797 | |
| 798 // We cannot drop between Bookmarks bar and Other bookmarks | |
| 799 if (overBookmarkNode.parentId == ROOT_ID) | |
| 800 return false; | |
| 801 | |
| 802 // We can only drop between items in the tree if we have any folders. | |
| 803 if (!this.isDraggingFolders() && overElement instanceof TreeItem) | |
| 804 return false; | |
| 805 | |
| 806 var isOverTreeItem = overElement instanceof TreeItem; | |
| 807 | |
| 808 // Don't allow dropping below an expanded tree item since it is confusing | |
| 809 // to the user anyway. | |
| 810 if (isOverTreeItem && overElement.expanded) | |
| 811 return false; | |
| 812 | |
| 813 if (!this.dragData.sameProfile) | |
| 814 return this.isDraggingFolders() || !isOverTreeItem; | |
| 815 | |
| 816 return this.checkEvery_(this.canDropBelow_, overBookmarkNode, overElement); | |
| 807 }, | 817 }, |
| 808 | 818 |
| 809 /** | 819 /** |
| 810 * Helper for canDropBelow that only checks one bookmark node. | 820 * Helper for canDropBelow that only checks one bookmark node. |
| 811 * @private | 821 * @private |
| 812 */ | 822 */ |
| 813 canDropBelow_: function(dragBookmarkNode, overBookmarkNode, overElement) { | 823 canDropBelow_: function(dragNode, overBookmarkNode, overElement) { |
| 814 if (overElement instanceof BookmarkList) | 824 var dragId = dragNode.id; |
| 815 return false; | |
| 816 | |
| 817 // The tree can only hold folders so if we are over a tree item we cannot | |
| 818 // drop a non folder. | |
| 819 if (!bmm.isFolder(dragBookmarkNode) && overElement instanceof TreeItem) | |
| 820 return false; | |
| 821 | |
| 822 // We cannot drop between Bookmarks bar and Other bookmarks | |
| 823 if (overBookmarkNode.parentId == ROOT_ID) | |
| 824 return false; | |
| 825 | 825 |
| 826 // We cannot drop below if the item below is already in the drag source | 826 // We cannot drop below if the item below is already in the drag source |
| 827 var nextElement = overElement.nextElementSibling; | 827 var nextElement = overElement.nextElementSibling; |
| 828 if (nextElement && | 828 if (nextElement && |
| 829 nextElement.bookmarkNode.id == dragBookmarkNode.id) | 829 nextElement.bookmarkId == dragId) |
| 830 return false; | |
| 831 | |
| 832 // Don't allow dropping below an expanded tree item since it is confusing | |
| 833 // to the user anyway. | |
| 834 if (overElement instanceof TreeItem && overElement.expanded) | |
| 835 return false; | 830 return false; |
| 836 | 831 |
| 837 return true; | 832 return true; |
| 838 }, | 833 }, |
| 839 | 834 |
| 840 /** | 835 /** |
| 841 * Whether we can drop the dragged items on the drop target. | 836 * Whether we can drop the dragged items on the drop target. |
| 842 * | 837 * |
| 843 * @param {!Array.<BookmarkTreeNode>} dragBookmarkNodes The bookmarks that are | |
| 844 * currently being dragged. | |
| 845 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are | 838 * @param {!BookmarkTreeNode} overBookmarkNode The bookmark that we are |
| 846 * currently dragging over. | 839 * currently dragging over. |
| 847 * @param {!HTMLElement} overElement The element that we are currently | 840 * @param {!HTMLElement} overElement The element that we are currently |
| 848 * dragging over. | 841 * dragging over. |
| 849 * @return {boolean} Whether we can drop the dragged items on the drop | 842 * @return {boolean} Whether we can drop the dragged items on the drop |
| 850 * target. | 843 * target. |
| 851 */ | 844 */ |
| 852 canDropOn: function(dragBookmarkNodes, overBookmarkNode, overElement) { | 845 canDropOn: function(overBookmarkNode, overElement) { |
| 853 return this.checkEvery_(this.canDropOn_, dragBookmarkNodes, | 846 // We can only drop on a folder. |
| 854 overBookmarkNode, overElement); | 847 if (!bmm.isFolder(overBookmarkNode)) |
| 848 return false; | |
| 849 | |
| 850 if (!this.dragData.sameProfile) | |
| 851 return true; | |
| 852 | |
| 853 return this.checkEvery_(this.canDropOn_, overBookmarkNode, overElement); | |
| 855 }, | 854 }, |
| 856 | 855 |
| 857 /** | 856 /** |
| 858 * Helper for canDropOn that only checks one bookmark node. | 857 * Helper for canDropOn that only checks one bookmark node. |
| 859 * @private | 858 * @private |
| 860 */ | 859 */ |
| 861 canDropOn_: function(dragBookmarkNode, overBookmarkNode, overElement) { | 860 canDropOn_: function(dragNode, overBookmarkNode, overElement) { |
| 862 // We can only drop on a folder... | 861 var dragId = dragNode.id; |
| 863 if (!bmm.isFolder(overBookmarkNode)) | |
| 864 return false; | |
| 865 | 862 |
| 866 if (overElement instanceof BookmarkList) { | 863 if (overElement instanceof BookmarkList) { |
| 867 // We are trying to drop an item after the last item in the list. This | 864 // We are trying to drop an item after the last item in the list. This |
| 868 // is allowed if the item is different from the last item in the list | 865 // is allowed if the item is different from the last item in the list |
| 869 var listItems = list.items; | 866 var listItems = list.items; |
| 870 var len = listItems.length; | 867 var len = listItems.length; |
| 871 if (len == 0 || | 868 if (len == 0 || |
| 872 listItems[len - 1].bookmarkNode.id != dragBookmarkNode.id) { | 869 listItems[len - 1].bookmarkId != dragId) { |
| 873 return true; | 870 return true; |
| 874 } | 871 } |
| 875 } | 872 } |
| 876 | 873 |
| 877 // Cannot drop on current parent | 874 // Cannot drop on current parent. |
| 878 if (overBookmarkNode.id == dragBookmarkNode.parentId) | 875 if (overBookmarkNode.id == dragNode.parentId) |
| 879 return false; | 876 return false; |
| 880 | 877 |
| 881 return true; | 878 return true; |
| 882 }, | 879 }, |
| 883 | 880 |
| 884 /** | 881 /** |
| 885 * Callback for the dragstart event. | 882 * Callback for the dragstart event. |
| 886 * @param {Event} e The dragstart event. | 883 * @param {Event} e The dragstart event. |
| 887 */ | 884 */ |
| 888 handleDragStart: function(e) { | 885 handleDragStart: function(e) { |
| 889 // console.log(e.type); | 886 // console.log(e.type); |
| 890 | 887 |
| 891 // Determine the selected bookmarks. | 888 // Determine the selected bookmarks. |
| 892 var target = e.target; | 889 var target = e.target; |
| 893 var draggedItems = []; | 890 var draggedItems = []; |
| 894 if (target instanceof ListItem) { | 891 if (target instanceof ListItem) { |
| 895 // Use selected items. | 892 // Use selected items. |
| 896 draggedItems = target.parentNode.selectedItems; | 893 draggedItems = target.parentNode.selectedItems; |
| 897 } else if (target instanceof TreeItem) { | 894 } else if (target instanceof TreeItem) { |
| 898 draggedItems.push(target); | 895 draggedItems.push(target); |
| 899 } | 896 } |
| 900 | 897 |
| 901 this.dragBookmarkNodes = draggedItems.map(function(item) { | 898 // We manage starting the drag by using the extension API. |
| 902 return item.bookmarkNode; | 899 e.preventDefault(); |
| 903 }); | |
| 904 | 900 |
| 905 // console.log(draggedItems, this.dragBookmarkNodes) | 901 if (draggedItems.length) { |
| 902 // If we are dragging a single link we can do the *Link* effect, otherwise | |
| 903 // we only allow copy and move. | |
| 904 var effectAllowed; | |
| 905 if (draggedItems.length == 1 && | |
| 906 !bmm.isFolder(draggedItems[0].bookmarkNode)) { | |
| 907 effectAllowed = 'copyMoveLink'; | |
| 908 } else { | |
| 909 effectAllowed = 'copyMove'; | |
| 910 } | |
| 911 e.dataTransfer.effectAllowed = effectAllowed; | |
| 906 | 912 |
| 907 // TODO(arv): Fix this once we expose DnD in the extension API | 913 var ids = draggedItems.map(function(el) { |
| 908 // Mac requires setData to be called | 914 return el.bookmarkId; |
| 909 e.dataTransfer.setData('text/uri-list', 'http://www.google.com/'); | 915 }); |
| 910 e.dataTransfer.effectAllowed = this.DND_EFFECT; | |
| 911 | 916 |
| 912 if (!this.dragBookmarkNodes.length) { | 917 chrome.experimental.bookmarkManager.startDrag(ids); |
| 913 e.preventDefault(); | |
| 914 } | 918 } |
| 915 }, | 919 }, |
| 916 | 920 |
| 917 handleDragEnter: function(e) { | 921 handleDragEnter: function(e) { |
| 918 // console.log(e.type); | 922 // console.log(e.type); |
| 919 | 923 |
| 920 e.preventDefault(); | 924 e.preventDefault(); |
| 921 }, | 925 }, |
| 922 | 926 |
| 923 /** | 927 /** |
| 924 * Calback for the dragover event. | 928 * Calback for the dragover event. |
| 925 * @param {Event} e The dragover event. | 929 * @param {Event} e The dragover event. |
| 926 */ | 930 */ |
| 927 handleDragOver: function(e) { | 931 handleDragOver: function(e) { |
| 928 // console.log(e.type); | 932 // console.log(e.type); |
| 929 | 933 |
| 930 if (!this.dragBookmarkNodes.length) | 934 // The default operation is to allow dropping links etc to do navigation. |
| 935 // We never want to do that for the bookmark manager. | |
| 936 e.preventDefault(); | |
| 937 | |
| 938 if (!this.dragData) | |
| 931 return; | 939 return; |
| 932 | 940 |
| 933 var overElement = this.getBookmarkElement(e.target); | 941 var overElement = this.getBookmarkElement(e.target); |
| 934 if (!overElement && e.target == list) | 942 if (!overElement && e.target == list) |
| 935 overElement = list; | 943 overElement = list; |
| 936 | 944 |
| 937 if (!overElement) | 945 if (!overElement) |
| 938 return; | 946 return; |
| 939 | 947 |
| 940 var dragBookmarkNodes = this.dragBookmarkNodes; | |
| 941 var overBookmarkNode = overElement.bookmarkNode; | 948 var overBookmarkNode = overElement.bookmarkNode; |
| 942 | 949 |
| 943 if (!this.canDrop(dragBookmarkNodes, overBookmarkNode, overElement)) | 950 if (!this.canDrop(overBookmarkNode, overElement)) |
| 944 return; | 951 return; |
| 945 | 952 |
| 946 var bookmarkNode = overElement.bookmarkNode; | 953 var bookmarkNode = overElement.bookmarkNode; |
| 947 | 954 |
| 948 var canDropAbove = this.canDropAbove(dragBookmarkNodes, overBookmarkNode, | 955 var canDropAbove = this.canDropAbove(overBookmarkNode, overElement); |
| 949 overElement); | 956 var canDropOn = this.canDropOn(overBookmarkNode, overElement); |
| 950 var canDropOn = this.canDropOn(dragBookmarkNodes, overBookmarkNode, | 957 var canDropBelow = this.canDropBelow(overBookmarkNode, overElement); |
| 951 overElement); | |
| 952 var canDropBelow = this.canDropBelow(dragBookmarkNodes, overBookmarkNode, | |
| 953 overElement); | |
| 954 | 958 |
| 955 if (!canDropAbove && !canDropOn && !canDropBelow) | 959 if (!canDropAbove && !canDropOn && !canDropBelow) |
| 956 return; | 960 return; |
| 957 | 961 |
| 958 // Now we know that we can drop. Determine if we will drop above, on or | 962 // Now we know that we can drop. Determine if we will drop above, on or |
| 959 // below based on mouse position etc. | 963 // below based on mouse position etc. |
| 960 | 964 |
| 961 var dropPos; | 965 var dropPos; |
| 962 e.preventDefault(); | 966 |
| 963 // TODO(arv): Fix this once we expose DnD in the extension API | 967 e.dataTransfer.dropEffect = this.dragData.sameProfile ? |
| 964 e.dataTransfer.dropEffect = this.DND_EFFECT; | 968 this.DND_EFFECT_MOVE : this.DND_EFFECT_COPY; |
| 965 | 969 |
| 966 var rect; | 970 var rect; |
| 967 if (overElement instanceof TreeItem) { | 971 if (overElement instanceof TreeItem) { |
| 968 // We only want the rect of the row representing the item and not | 972 // We only want the rect of the row representing the item and not |
| 969 // its children | 973 // its children |
| 970 rect = overElement.rowElement.getBoundingClientRect(); | 974 rect = overElement.rowElement.getBoundingClientRect(); |
| 971 } else { | 975 } else { |
| 972 rect = overElement.getBoundingClientRect(); | 976 rect = overElement.getBoundingClientRect(); |
| 973 } | 977 } |
| 974 | 978 |
| 975 if (canDropAbove && !canDropOn && !canDropBelow) { | 979 var dy = e.clientY - rect.top; |
| 980 var yRatio = dy / rect.height; | |
| 981 | |
| 982 // above | |
| 983 if (canDropAbove && | |
| 984 (yRatio <= .25 || yRatio <= .5 && !(canDropBelow && canDropOn))) { | |
| 976 dropPos = 'above'; | 985 dropPos = 'above'; |
| 977 } else if (!canDropAbove && canDropOn && !canDropBelow) { | 986 |
| 987 // below | |
| 988 } else if (canDropBelow && | |
| 989 (yRatio > .75 || yRatio > .5 && !(canDropAbove && canDropOn))) { | |
| 990 dropPos = 'below'; | |
| 991 | |
| 992 // on | |
| 993 } else if (canDropOn) { | |
| 978 dropPos = 'on'; | 994 dropPos = 'on'; |
| 979 } else if (!canDropAbove && !canDropOn && canDropBelow) { | 995 |
| 980 dropPos = 'below'; | 996 // none |
| 981 } else { | 997 } else { |
| 982 // We need to compare the mouse position with the element rect. | 998 // No drop can happen. Exit now. |
| 983 | 999 e.dataTransfer.dropEffect = 'none'; |
| 984 var dy = e.clientY - rect.top; | 1000 return; |
| 985 var yRatio = dy / rect.height; | |
| 986 if (!canDropOn) { | |
| 987 dropPos = yRatio < .5 ? 'above' : 'below'; | |
| 988 } else if (!canDropAbove) { | |
| 989 dropPos = yRatio < .5 ? 'on' : 'below'; | |
| 990 } else if (!canDropBelow) { | |
| 991 dropPos = yRatio < .5 ? 'above' : 'on'; | |
| 992 } else { | |
| 993 dropPos = yRatio < .25 ? 'above' : yRatio > .75 ? 'below' : 'on'; | |
| 994 } | |
| 995 } | 1001 } |
| 996 | 1002 |
| 997 function cloneClientRect(rect) { | 1003 function cloneClientRect(rect) { |
| 998 var newRect = {}; | 1004 var newRect = {}; |
| 999 for (var key in rect) { | 1005 for (var key in rect) { |
| 1000 newRect[key] = rect[key]; | 1006 newRect[key] = rect[key]; |
| 1001 } | 1007 } |
| 1002 return newRect; | 1008 return newRect; |
| 1003 } | 1009 } |
| 1004 | 1010 |
| 1005 // If we are dropping above or below a tree item adjust the width so | 1011 // If we are dropping above or below a tree item adjust the width so |
| 1006 // that it is clearer where the item will be dropped. | 1012 // that it is clearer where the item will be dropped. |
| 1007 if ((dropPos == 'above' || dropPos == 'below' ) && | 1013 if ((dropPos == 'above' || dropPos == 'below') && |
| 1008 overElement instanceof TreeItem) { | 1014 overElement instanceof TreeItem) { |
| 1009 // ClientRect is read only so clone in into a read-write object. | 1015 // ClientRect is read only so clone in into a read-write object. |
| 1010 rect = cloneClientRect(rect); | 1016 rect = cloneClientRect(rect); |
| 1011 var rtl = getComputedStyle(overElement).direction == 'rtl'; | 1017 var rtl = getComputedStyle(overElement).direction == 'rtl'; |
| 1012 var labelElement = overElement.labelElement; | 1018 var labelElement = overElement.labelElement; |
| 1013 var labelRect = labelElement.getBoundingClientRect(); | 1019 var labelRect = labelElement.getBoundingClientRect(); |
| 1014 if (rtl) { | 1020 if (rtl) { |
| 1015 rect.width = labelRect.left + labelRect.width - rect.left; | 1021 rect.width = labelRect.left + labelRect.width - rect.left; |
| 1016 } else { | 1022 } else { |
| 1017 rect.left = labelRect.left; | 1023 rect.left = labelRect.left; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1036 } else { | 1042 } else { |
| 1037 // If there are no items, collapse the height of the rect | 1043 // If there are no items, collapse the height of the rect |
| 1038 rect = cloneClientRect(rect); | 1044 rect = cloneClientRect(rect); |
| 1039 rect.height = 0; | 1045 rect.height = 0; |
| 1040 // We do not use bottom so we don't care to adjust it. | 1046 // We do not use bottom so we don't care to adjust it. |
| 1041 } | 1047 } |
| 1042 } | 1048 } |
| 1043 | 1049 |
| 1044 this.showDropOverlay_(rect, overlayType); | 1050 this.showDropOverlay_(rect, overlayType); |
| 1045 | 1051 |
| 1046 // TODO(arv): Multiple selection DnD. | |
| 1047 this.dropDestination = { | 1052 this.dropDestination = { |
| 1048 dropPos: dropPos, | 1053 dropPos: dropPos, |
| 1049 relatedNode: overElement.bookmarkNode | 1054 relatedNode: overElement.bookmarkNode |
| 1050 }; | 1055 }; |
| 1051 }, | 1056 }, |
| 1052 | 1057 |
| 1053 /** | 1058 /** |
| 1054 * Shows and positions the drop marker overlay. | 1059 * Shows and positions the drop marker overlay. |
| 1055 * @param {ClientRect} targetRect The drop target rect | 1060 * @param {ClientRect} targetRect The drop target rect |
| 1056 * @param {string} overlayType The position relative to the target rect. | 1061 * @param {string} overlayType The position relative to the target rect. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1097 | 1102 |
| 1098 handleDragLeave: function(e) { | 1103 handleDragLeave: function(e) { |
| 1099 // console.log(e.type); | 1104 // console.log(e.type); |
| 1100 | 1105 |
| 1101 this.hideDropOverlay_(); | 1106 this.hideDropOverlay_(); |
| 1102 }, | 1107 }, |
| 1103 | 1108 |
| 1104 handleDrop: function(e) { | 1109 handleDrop: function(e) { |
| 1105 // console.log(e.type); | 1110 // console.log(e.type); |
| 1106 | 1111 |
| 1107 if (this.dropDestination && this.dragBookmarkNodes.length) { | 1112 if (this.dropDestination && this.dragData) { |
| 1108 // console.log('Drop', this.dragBookmarkNodes, this.dropDestination); | |
| 1109 | |
| 1110 var dropPos = this.dropDestination.dropPos; | 1113 var dropPos = this.dropDestination.dropPos; |
| 1111 var relatedNode = this.dropDestination.relatedNode; | 1114 var relatedNode = this.dropDestination.relatedNode; |
| 1112 var parentId = dropPos == 'on' ? relatedNode.id : relatedNode.parentId; | 1115 var parentId = dropPos == 'on' ? relatedNode.id : relatedNode.parentId; |
| 1113 | 1116 |
| 1114 var moveInfo = { | 1117 var index; |
| 1115 parentId: parentId | 1118 if (dropPos == 'above') |
| 1116 }; | 1119 index = relatedNode.index; |
| 1120 else if (dropPos == 'below') | |
| 1121 index = relatedNode.index + 1; | |
| 1117 | 1122 |
| 1118 if (dropPos == 'above') { | 1123 if (index != undefined) |
| 1119 moveInfo.index = relatedNode.index; | 1124 chrome.experimental.bookmarkManager.drop(parentId, index); |
| 1120 } else if (dropPos == 'below') { | 1125 else |
| 1121 moveInfo.index = relatedNode.index + 1; | 1126 chrome.experimental.bookmarkManager.drop(parentId); |
| 1122 } | |
| 1123 | |
| 1124 // TODO(arv): Add support for multiple move in bookmarks API? | |
| 1125 this.dragBookmarkNodes.forEach(function(bookmarkNode) { | |
| 1126 var id = bookmarkNode.id; | |
| 1127 // console.info('Calling move', id, moveInfo.index, bookmarkNode); | |
| 1128 chrome.bookmarks.move(id, moveInfo, | |
| 1129 function(result) { | |
| 1130 // console.log('chrome.bookmarks.move', arguments); | |
| 1131 }); | |
| 1132 moveInfo.index++; | |
| 1133 }); | |
| 1134 | 1127 |
| 1135 // TODO(arv): Select the newly dropped items. | 1128 // TODO(arv): Select the newly dropped items. |
| 1136 } | 1129 } |
| 1137 this.dropDestination = null; | 1130 this.dropDestination = null; |
| 1138 this.hideDropOverlay_(); | 1131 this.hideDropOverlay_(); |
| 1139 }, | 1132 }, |
| 1140 | 1133 |
| 1141 handleDrag: function(e) { | 1134 handleDrag: function(e) { |
| 1142 // console.log(e.type); | 1135 // console.log(e.type); |
| 1143 }, | 1136 }, |
| 1144 | 1137 |
| 1145 handleDragEnd: function(e) { | 1138 handleDragEnd: function(e) { |
| 1146 // console.log(e.type); | 1139 // console.log(e.type); |
| 1147 | 1140 |
| 1148 var self = this; | 1141 var self = this; |
| 1149 // Chromium Win incorrectly fires the dragend event before the drop event. | 1142 // Chromium Win incorrectly fires the dragend event before the drop event. |
| 1150 // http://code.google.com/p/chromium/issues/detail?id=31292 | 1143 // http://code.google.com/p/chromium/issues/detail?id=31292 |
| 1151 window.setTimeout(function() { | 1144 window.setTimeout(function() { |
| 1152 self.dragBookmarkNodes = []; | 1145 self.dragData = null; |
| 1153 self = null; | |
| 1154 }, 1) | 1146 }, 1) |
| 1155 }, | 1147 }, |
| 1156 | 1148 |
| 1149 handleChromeDragEnter: function(dragData) { | |
| 1150 this.dragData = dragData; | |
| 1151 }, | |
| 1152 | |
| 1157 init: function() { | 1153 init: function() { |
| 1158 document.addEventListener('dragstart', cr.bind(this.handleDragStart, this)); | 1154 document.addEventListener('dragstart', cr.bind(this.handleDragStart, this)); |
| 1159 document.addEventListener('dragenter', cr.bind(this.handleDragEnter, this)); | 1155 document.addEventListener('dragenter', cr.bind(this.handleDragEnter, this)); |
| 1160 document.addEventListener('dragover', cr.bind(this.handleDragOver, this)); | 1156 document.addEventListener('dragover', cr.bind(this.handleDragOver, this)); |
| 1161 document.addEventListener('dragleave', cr.bind(this.handleDragLeave, this)); | 1157 document.addEventListener('dragleave', cr.bind(this.handleDragLeave, this)); |
| 1162 document.addEventListener('drop', cr.bind(this.handleDrop, this)); | 1158 document.addEventListener('drop', cr.bind(this.handleDrop, this)); |
| 1163 document.addEventListener('dragend', cr.bind(this.handleDragEnd, this)); | 1159 document.addEventListener('dragend', cr.bind(this.handleDragEnd, this)); |
| 1164 document.addEventListener('drag', cr.bind(this.handleDrag, this)); | 1160 document.addEventListener('drag', cr.bind(this.handleDrag, this)); |
| 1161 | |
| 1162 chrome.experimental.bookmarkManager.onDragEnter.addListener(cr.bind( | |
| 1163 this.handleChromeDragEnter, this)); | |
| 1165 } | 1164 } |
| 1166 | 1165 |
| 1167 }; | 1166 }; |
| 1168 | 1167 |
| 1169 dnd.init(); | 1168 dnd.init(); |
| 1170 | 1169 |
| 1171 | |
| 1172 </script> | 1170 </script> |
| 1173 | 1171 |
| 1174 <!-- Organize menu --> | 1172 <!-- Organize menu --> |
| 1175 <command i18n-values=".label:rename_folder" id="rename-folder-command"></command > | 1173 <command i18n-values=".label:rename_folder" id="rename-folder-command"></command > |
| 1176 <command i18n-values=".label:edit" id="edit-command"></command> | 1174 <command i18n-values=".label:edit" id="edit-command"></command> |
| 1177 <command i18n-values=".label:delete" id="delete-command"></command> | 1175 <command i18n-values=".label:delete" id="delete-command"></command> |
| 1178 <command i18n-values=".label:show_in_folder" id="show-in-folder-command"></comma nd> | 1176 <command i18n-values=".label:show_in_folder" id="show-in-folder-command"></comma nd> |
| 1179 <command i18n-values=".label:cut" id="cut-command"></command> | 1177 <command i18n-values=".label:cut" id="cut-command"></command> |
| 1180 <command i18n-values=".label:copy" id="copy-command"></command> | 1178 <command i18n-values=".label:copy" id="copy-command"></command> |
| 1181 <command i18n-values=".label:paste" id="paste-command"></command> | 1179 <command i18n-values=".label:paste" id="paste-command"></command> |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1764 }; | 1762 }; |
| 1765 setTemplateData(fakeData); | 1763 setTemplateData(fakeData); |
| 1766 } | 1764 } |
| 1767 | 1765 |
| 1768 </script> | 1766 </script> |
| 1769 | 1767 |
| 1770 <div id="drop-overlay"></div> | 1768 <div id="drop-overlay"></div> |
| 1771 | 1769 |
| 1772 </body> | 1770 </body> |
| 1773 </html> | 1771 </html> |
| OLD | NEW |