OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
Aaron Boodman
2011/01/22 23:42:57
Seems like this file should be called drag_drop_co
jstritar
2011/01/24 01:00:42
Done.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // The delegate interface: | |
6 // dragContainer --> | |
7 // element containing the draggable items | |
8 // | |
9 // transitionsDuration --> | |
10 // length of time of transitions in ms | |
11 // | |
12 // dragItem --> | |
13 // get / set property containing the item being dragged | |
14 // | |
15 // dimensions --> | |
16 // property that specifies the dimensions of the items | |
17 // The object should contain the following properties: | |
18 // itemHeight, itemWidth, marginWidth, marginHeight, borderWidth | |
Aaron Boodman
2011/01/22 23:42:57
Why does this class care about marginWidth/height
jstritar
2011/01/24 01:00:42
I removed the dependency on the dimensions.
| |
19 // | |
20 // getItem(e) --> | |
21 // get's the item that is under the mouse event |e| | |
22 // | |
23 // canDropOn(position) --> | |
24 // returns true if the position index is a valid place to drop an item | |
25 // | |
26 // setDragPlaceholder(position) --> | |
27 // tells the delegate that the dragged item is currently above | |
28 // |position| | |
29 // | |
30 // saveDrag() --> | |
31 // tells the delegate that the drag is done. move the item to the | |
32 // position last specified by setDragPlaceholder. (e.g., commit changes) | |
33 // | |
34 | |
35 function DragAndDropController(delegate) { | |
36 this.delegate = delegate; | |
Aaron Boodman
2011/01/22 23:42:57
this.delegate_ ?
jstritar
2011/01/24 01:00:42
Done.
| |
37 | |
38 this.installHandlers_(); | |
39 } | |
40 | |
41 DragAndDropController.prototype = { | |
42 startX_: 0, | |
43 startY_: 0, | |
44 startScreenX_: 0, | |
45 startScreenY_: 0, | |
46 | |
47 installHandlers_: function() { | |
48 var el = this.delegate.dragContainer; | |
49 el.addEventListener('dragstart', this.handleDragStart_.bind(this)); | |
50 el.addEventListener('dragenter', this.handleDragEnter_.bind(this)); | |
51 el.addEventListener('dragover', this.handleDragOver_.bind(this)); | |
52 el.addEventListener('dragleave', this.handleDragLeave_.bind(this)); | |
53 el.addEventListener('drop', this.handleDrop_.bind(this)); | |
54 el.addEventListener('dragend', this.handleDragEnd_.bind(this)); | |
55 el.addEventListener('drag', this.handleDrag_.bind(this)); | |
56 el.addEventListener('mousedown', this.handleMouseDown_.bind(this)); | |
57 }, | |
58 | |
59 isDragging: function() { | |
60 return !!this.delegate.dragItem; | |
Aaron Boodman
2011/01/22 23:42:57
Nit: prefer Boolean(this.delegate.dragItem) or thi
jstritar
2011/01/24 01:00:42
I realized I wasn't using this method, so I yanked
| |
61 }, | |
62 | |
63 getIndexAt_: function(e) { | |
Aaron Boodman
2011/01/22 23:42:57
Design nit: I think that knowledge of layout shoul
jstritar
2011/01/24 01:00:42
Great idea-- I think that's what felt off about th
| |
64 var del = this.delegate; | |
Aaron Boodman
2011/01/22 23:42:57
Careful with your abbreviations again. Since deleg
jstritar
2011/01/24 01:00:42
Done. Cleaned this up throughout the class.
| |
65 var el = del.dragContainer; | |
Aaron Boodman
2011/01/22 23:42:57
This variable is only used once, might as well jus
jstritar
2011/01/24 01:00:42
Done.
| |
66 var rect = el.getBoundingClientRect(); | |
67 var d = del.dimensions; | |
68 var availableWidth = el.offsetWidth; | |
69 | |
70 var clientX = e.clientX + window.scrollX - rect.left; | |
71 var clientY = e.clientY + window.scrollY - rect.top; | |
72 | |
73 var w = d.itemWidth + 2 * d.borderWidth + 2 * d.marginWidth; | |
74 var h = d.itemHeight + 2 * d.borderWidth + 2 * d.marginHeight; | |
75 | |
76 var rtl = isRtl(); | |
77 if (rtl) | |
78 clientX = availableWidth - clientX; | |
79 | |
80 var row = Math.floor(clientY / h); | |
81 var col = Math.floor(clientX / w); | |
82 var index = Math.floor(availableWidth / w) * row + col; | |
83 | |
84 return index; | |
85 }, | |
86 | |
87 // Listen to mousedown to get the relative position of the cursor when | |
88 // starting drag and drop. | |
89 handleMouseDown_: function(e) { | |
90 var item = this.delegate.getItem(e); | |
91 if (item) { | |
Aaron Boodman
2011/01/22 23:42:57
Invert check and return early. Multiple places in
jstritar
2011/01/24 01:00:42
Done.
| |
92 this.startX_ = item.offsetLeft; | |
93 this.startY_ = item.offsetTop; | |
94 this.startScreenX_ = e.screenX; | |
95 this.startScreenY_ = e.screenY; | |
96 | |
97 // We don't want to focus the item on mousedown. However, to prevent | |
98 // focus one has to call preventDefault but this also prevents the drag | |
99 // and drop (sigh) so we only prevent it when the user is not doing a | |
100 // left mouse button drag. | |
101 if (e.button != 0) // LEFT | |
102 e.preventDefault(); | |
103 } | |
104 }, | |
105 | |
106 handleDragStart_: function(e) { | |
107 var item = this.delegate.getItem(e); | |
108 if (item) { | |
109 // Don't set data since HTML5 does not allow setting the name for | |
110 // url-list. Instead, we just rely on the dragging of link behavior. | |
111 this.delegate.dragItem = item; | |
112 item.classList.add('dragging'); | |
113 item.style.zIndex = 2; | |
114 | |
115 e.dataTransfer.effectAllowed = 'copyLinkMove'; | |
116 } | |
117 }, | |
118 | |
119 handleDragEnter_: function(e) { | |
120 if (this.delegate.canDropOn(this.getIndexAt_(e))) | |
121 e.preventDefault(); | |
122 }, | |
123 | |
124 handleDragOver_: function(e) { | |
125 var del = this.delegate; | |
126 var position = this.getIndexAt_(e); | |
127 if (del.canDropOn(position)) { | |
128 del.setDragPlaceholder(position); | |
129 e.preventDefault(); | |
130 e.dataTransfer.dropEffect = 'move'; | |
131 } | |
132 }, | |
133 | |
134 handleDragLeave_: function(e) { | |
135 if (this.delegate.canDropOn(this.getIndexAt_(e))) | |
136 e.preventDefault(); | |
137 }, | |
138 | |
139 handleDrop_: function(e) { | |
140 var del = this.delegate; | |
141 var dragItem = del.dragItem; | |
142 if (dragItem) { | |
143 dragItem.classList.remove('dragging'); | |
144 del.dragItem = null; | |
145 del.invalidate(); | |
Aaron Boodman
2011/01/22 23:42:57
Seems like these two methods should be del.saveDra
jstritar
2011/01/24 01:00:42
Done.
| |
146 del.layout(); | |
147 | |
148 setTimeout(function() { | |
149 dragItem.style.pointerEvents = ''; | |
150 dragItem.style.zIndex = ''; | |
151 }, this.delegate.transitionsDuration + 10); | |
152 } | |
153 }, | |
154 | |
155 handleDragEnd_: function(e) { | |
156 return this.handleDrop_(e); | |
157 }, | |
158 | |
159 handleDrag_: function(e) { | |
160 // Moves the drag item making sure that it is not displayed outside the | |
161 // browser viewport. | |
162 var del = this.delegate; | |
163 var dragItem = del.dragItem; | |
164 var rect = del.dragContainer.getBoundingClientRect(); | |
165 | |
166 var x = this.startX_ + e.screenX - this.startScreenX_; | |
167 var y = this.startY_ + e.screenY - this.startScreenY_; | |
168 | |
169 // The position of the item is relative to #apps so we need to | |
170 // subtract that when calculating the allowed position. | |
171 x = Math.max(x, -rect.left); | |
172 x = Math.min(x, document.body.clientWidth - rect.left - | |
173 dragItem.offsetWidth - 2); | |
174 | |
175 // The shadow is 2px | |
176 y = Math.max(-rect.top, y); | |
177 y = Math.min(y, document.body.clientHeight - rect.top - | |
178 dragItem.offsetHeight - 2); | |
179 | |
180 // Override right in case of RTL. | |
181 dragItem.style.right = 'auto'; | |
Aaron Boodman
2011/01/22 23:42:57
Don't think this line is needed.
jstritar
2011/01/24 01:00:42
Done.
| |
182 dragItem.style.left = x + 'px'; | |
183 dragItem.style.top = y + 'px'; | |
184 dragItem.style.zIndex = 2; | |
185 } | |
186 }; | |
OLD | NEW |