Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: chrome/browser/resources/bookmark_manager/main.html

Issue 646076: Bookmark manager drag and drop frontend (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698