UNPKG

17.7 kBJavaScriptView Raw
1/*syn@0.14.0#drag*/
2define([
3 'require',
4 'exports',
5 'module',
6 './synthetic'
7], function (require, exports, module) {
8 var syn = require('./synthetic');
9 var elementFromPoint = function (point, win) {
10 var clientX = point.clientX;
11 var clientY = point.clientY;
12 if (point == null) {
13 return null;
14 }
15 if (syn.support.elementFromPage) {
16 var off = syn.helpers.scrollOffset(win);
17 clientX = clientX + off.left;
18 clientY = clientY + off.top;
19 }
20 return win.document.elementFromPoint(Math.round(clientX), Math.round(clientY));
21 };
22 var DragonDrop = {
23 html5drag: false,
24 focusWindow: null,
25 dragAndDrop: function (focusWindow, fromPoint, toPoint, duration, callback) {
26 this.currentDataTransferItem = null;
27 this.focusWindow = focusWindow;
28 this._mouseOver(fromPoint);
29 this._mouseEnter(fromPoint);
30 this._mouseMove(fromPoint);
31 this._mouseDown(fromPoint);
32 this._dragStart(fromPoint);
33 this._drag(fromPoint);
34 this._dragEnter(fromPoint);
35 this._dragOver(fromPoint);
36 DragonDrop.startMove(fromPoint, toPoint, duration, function () {
37 DragonDrop._dragLeave(fromPoint);
38 DragonDrop._dragEnd(fromPoint);
39 DragonDrop._mouseOut(fromPoint);
40 DragonDrop._mouseLeave(fromPoint);
41 DragonDrop._drop(toPoint);
42 DragonDrop._dragEnd(toPoint);
43 DragonDrop._mouseOver(toPoint);
44 DragonDrop._mouseEnter(toPoint);
45 DragonDrop._mouseMove(toPoint);
46 DragonDrop._mouseOut(toPoint);
47 DragonDrop._mouseLeave(toPoint);
48 callback();
49 DragonDrop.cleanup();
50 });
51 },
52 _dragStart: function (node, options) {
53 this.createAndDispatchEvent(node, 'dragstart', options);
54 },
55 _drag: function (node, options) {
56 this.createAndDispatchEvent(node, 'drag', options);
57 },
58 _dragEnter: function (node, options) {
59 this.createAndDispatchEvent(node, 'dragenter', options);
60 },
61 _dragOver: function (node, options) {
62 this.createAndDispatchEvent(node, 'dragover', options);
63 },
64 _dragLeave: function (node, options) {
65 this.createAndDispatchEvent(node, 'dragleave', options);
66 },
67 _drop: function (node, options) {
68 this.createAndDispatchEvent(node, 'drop', options);
69 },
70 _dragEnd: function (node, options) {
71 this.createAndDispatchEvent(node, 'dragend', options);
72 },
73 _mouseDown: function (node, options) {
74 this.createAndDispatchEvent(node, 'mousedown', options);
75 },
76 _mouseMove: function (node, options) {
77 this.createAndDispatchEvent(node, 'mousemove', options);
78 },
79 _mouseEnter: function (node, options) {
80 this.createAndDispatchEvent(node, 'mouseenter', options);
81 },
82 _mouseOver: function (node, options) {
83 this.createAndDispatchEvent(node, 'mouseover', options);
84 },
85 _mouseOut: function (node, options) {
86 this.createAndDispatchEvent(node, 'mouseout', options);
87 },
88 _mouseLeave: function (node, options) {
89 this.createAndDispatchEvent(node, 'mouseleave', options);
90 },
91 createAndDispatchEvent: function (point, eventName, options) {
92 if (point) {
93 var targetElement = elementFromPoint(point, this.focusWindow);
94 syn.trigger(targetElement, eventName, options);
95 }
96 },
97 getDataTransferObject: function () {
98 if (!this.currentDataTransferItem) {
99 return this.currentDataTransferItem = this.createDataTransferObject();
100 } else {
101 return this.currentDataTransferItem;
102 }
103 },
104 cleanup: function () {
105 this.currentDataTransferItem = null;
106 this.focusWindow = null;
107 },
108 createDataTransferObject: function () {
109 var dataTransfer = {
110 dropEffect: 'none',
111 effectAllowed: 'uninitialized',
112 files: [],
113 items: [],
114 types: [],
115 data: [],
116 setData: function (dataFlavor, value) {
117 var tempdata = {};
118 tempdata.dataFlavor = dataFlavor;
119 tempdata.val = value;
120 this.data.push(tempdata);
121 },
122 getData: function (dataFlavor) {
123 for (var i = 0; i < this.data.length; i++) {
124 var tempdata = this.data[i];
125 if (tempdata.dataFlavor === dataFlavor) {
126 return tempdata.val;
127 }
128 }
129 }
130 };
131 return dataTransfer;
132 },
133 startMove: function (start, end, duration, callback) {
134 var startTime = new Date();
135 var distX = end.clientX - start.clientX;
136 var distY = end.clientY - start.clientY;
137 var win = this.focusWindow;
138 var current = start;
139 var cursor = win.document.createElement('div');
140 var calls = 0;
141 var move;
142 move = function onmove() {
143 var now = new Date();
144 var scrollOffset = syn.helpers.scrollOffset(win);
145 var fraction = (calls === 0 ? 0 : now - startTime) / duration;
146 var options = {
147 clientX: distX * fraction + start.clientX,
148 clientY: distY * fraction + start.clientY
149 };
150 calls++;
151 if (fraction < 1) {
152 syn.helpers.extend(cursor.style, {
153 left: options.clientX + scrollOffset.left + 2 + 'px',
154 top: options.clientY + scrollOffset.top + 2 + 'px'
155 });
156 current = DragonDrop.mouseMove(options, current);
157 syn.schedule(onmove, 15);
158 } else {
159 current = DragonDrop.mouseMove(end, current);
160 win.document.body.removeChild(cursor);
161 callback();
162 }
163 };
164 syn.helpers.extend(cursor.style, {
165 height: '5px',
166 width: '5px',
167 backgroundColor: 'red',
168 position: 'absolute',
169 zIndex: 19999,
170 fontSize: '1px'
171 });
172 win.document.body.appendChild(cursor);
173 move();
174 },
175 mouseMove: function (thisPoint, previousPoint) {
176 var thisElement = elementFromPoint(thisPoint, this.focusWindow);
177 var previousElement = elementFromPoint(previousPoint, this.focusWindow);
178 var options = syn.helpers.extend({}, thisPoint);
179 if (thisElement !== previousElement) {
180 options.relatedTarget = thisElement;
181 this._dragLeave(previousPoint, options);
182 options.relatedTarget = previousElement;
183 this._dragEnter(thisPoint, options);
184 }
185 this._dragOver(thisPoint, options);
186 return thisPoint;
187 }
188 };
189 function createDragEvent(eventName, options, element) {
190 var dragEvent = syn.create.mouse.event(eventName, options, element);
191 dragEvent.dataTransfer = DragonDrop.getDataTransferObject();
192 return syn.dispatch(dragEvent, element, eventName, false);
193 }
194 syn.create.dragstart = { event: createDragEvent };
195 syn.create.dragenter = { event: createDragEvent };
196 syn.create.dragover = { event: createDragEvent };
197 syn.create.dragleave = { event: createDragEvent };
198 syn.create.drag = { event: createDragEvent };
199 syn.create.drop = { event: createDragEvent };
200 syn.create.dragend = { event: createDragEvent };
201 (function dragSupport() {
202 if (!document.body) {
203 syn.schedule(dragSupport, 1);
204 return;
205 }
206 var div = document.createElement('div');
207 document.body.appendChild(div);
208 syn.helpers.extend(div.style, {
209 width: '100px',
210 height: '10000px',
211 backgroundColor: 'blue',
212 position: 'absolute',
213 top: '10px',
214 left: '0px',
215 zIndex: 19999
216 });
217 document.body.scrollTop = 11;
218 if (!document.elementFromPoint) {
219 return;
220 }
221 var el = document.elementFromPoint(3, 1);
222 if (el === div) {
223 syn.support.elementFromClient = true;
224 } else {
225 syn.support.elementFromPage = true;
226 }
227 document.body.removeChild(div);
228 document.body.scrollTop = 0;
229 }());
230 var mouseMove = function (point, win, last) {
231 var el = elementFromPoint(point, win);
232 if (last !== el && el && last) {
233 var options = syn.helpers.extend({}, point);
234 options.relatedTarget = el;
235 if (syn.support.pointerEvents) {
236 syn.trigger(last, 'pointerout', options);
237 syn.trigger(last, 'pointerleave', options);
238 }
239 syn.trigger(last, 'mouseout', options);
240 syn.trigger(last, 'mouseleave', options);
241 options.relatedTarget = last;
242 if (syn.support.pointerEvents) {
243 syn.trigger(el, 'pointerover', options);
244 syn.trigger(el, 'pointerenter', options);
245 }
246 syn.trigger(el, 'mouseover', options);
247 syn.trigger(el, 'mouseenter', options);
248 }
249 if (syn.support.pointerEvents) {
250 syn.trigger(el || win, 'pointermove', point);
251 }
252 if (syn.support.touchEvents) {
253 syn.trigger(el || win, 'touchmove', point);
254 }
255 if (DragonDrop.html5drag) {
256 if (!syn.support.pointerEvents) {
257 syn.trigger(el || win, 'mousemove', point);
258 }
259 } else {
260 syn.trigger(el || win, 'mousemove', point);
261 }
262 return el;
263 }, createEventAtPoint = function (event, point, win) {
264 var el = elementFromPoint(point, win);
265 syn.trigger(el || win, event, point);
266 return el;
267 }, startMove = function (win, start, end, duration, callback) {
268 var startTime = new Date(), distX = end.clientX - start.clientX, distY = end.clientY - start.clientY, current = elementFromPoint(start, win), cursor = win.document.createElement('div'), calls = 0, move;
269 move = function onmove() {
270 var now = new Date(), scrollOffset = syn.helpers.scrollOffset(win), fraction = (calls === 0 ? 0 : now - startTime) / duration, options = {
271 clientX: distX * fraction + start.clientX,
272 clientY: distY * fraction + start.clientY
273 };
274 calls++;
275 if (fraction < 1) {
276 syn.helpers.extend(cursor.style, {
277 left: options.clientX + scrollOffset.left + 2 + 'px',
278 top: options.clientY + scrollOffset.top + 2 + 'px'
279 });
280 current = mouseMove(options, win, current);
281 syn.schedule(onmove, 15);
282 } else {
283 current = mouseMove(end, win, current);
284 win.document.body.removeChild(cursor);
285 callback();
286 }
287 };
288 syn.helpers.extend(cursor.style, {
289 height: '5px',
290 width: '5px',
291 backgroundColor: 'red',
292 position: 'absolute',
293 zIndex: 19999,
294 fontSize: '1px'
295 });
296 win.document.body.appendChild(cursor);
297 move();
298 }, startDrag = function (win, fromPoint, toPoint, duration, callback) {
299 if (syn.support.pointerEvents) {
300 createEventAtPoint('pointerover', fromPoint, win);
301 createEventAtPoint('pointerenter', fromPoint, win);
302 }
303 createEventAtPoint('mouseover', fromPoint, win);
304 createEventAtPoint('mouseenter', fromPoint, win);
305 if (syn.support.pointerEvents) {
306 createEventAtPoint('pointermove', fromPoint, win);
307 }
308 createEventAtPoint('mousemove', fromPoint, win);
309 if (syn.support.pointerEvents) {
310 createEventAtPoint('pointerdown', fromPoint, win);
311 }
312 if (syn.support.touchEvents) {
313 createEventAtPoint('touchstart', fromPoint, win);
314 }
315 createEventAtPoint('mousedown', fromPoint, win);
316 startMove(win, fromPoint, toPoint, duration, function () {
317 if (syn.support.pointerEvents) {
318 createEventAtPoint('pointerup', toPoint, win);
319 }
320 if (syn.support.touchEvents) {
321 createEventAtPoint('touchend', toPoint, win);
322 }
323 createEventAtPoint('mouseup', toPoint, win);
324 if (syn.support.pointerEvents) {
325 createEventAtPoint('pointerleave', toPoint, win);
326 }
327 createEventAtPoint('mouseleave', toPoint, win);
328 callback();
329 });
330 }, center = function (el) {
331 var j = syn.jquery()(el), o = j.offset();
332 return {
333 pageX: o.left + j.outerWidth() / 2,
334 pageY: o.top + j.outerHeight() / 2
335 };
336 }, convertOption = function (option, win, from) {
337 var page = /(\d+)[x ](\d+)/, client = /(\d+)X(\d+)/, relative = /([+-]\d+)[xX ]([+-]\d+)/, parts;
338 if (typeof option === 'string' && relative.test(option) && from) {
339 var cent = center(from);
340 parts = option.match(relative);
341 option = {
342 pageX: cent.pageX + parseInt(parts[1]),
343 pageY: cent.pageY + parseInt(parts[2])
344 };
345 }
346 if (typeof option === 'string' && page.test(option)) {
347 parts = option.match(page);
348 option = {
349 pageX: parseInt(parts[1]),
350 pageY: parseInt(parts[2])
351 };
352 }
353 if (typeof option === 'string' && client.test(option)) {
354 parts = option.match(client);
355 option = {
356 clientX: parseInt(parts[1]),
357 clientY: parseInt(parts[2])
358 };
359 }
360 if (typeof option === 'string') {
361 option = syn.jquery()(option, win.document)[0];
362 }
363 if (option.nodeName) {
364 option = center(option);
365 }
366 if (option.pageX != null) {
367 var off = syn.helpers.scrollOffset(win);
368 option = {
369 clientX: option.pageX - off.left,
370 clientY: option.pageY - off.top
371 };
372 }
373 return option;
374 }, adjust = function (from, to, win) {
375 if (from.clientY < 0) {
376 var off = syn.helpers.scrollOffset(win);
377 var top = off.top + from.clientY - 100, diff = top - off.top;
378 if (top > 0) {
379 } else {
380 top = 0;
381 diff = -off.top;
382 }
383 from.clientY = from.clientY - diff;
384 to.clientY = to.clientY - diff;
385 syn.helpers.scrollOffset(win, {
386 top: top,
387 left: off.left
388 });
389 }
390 };
391 syn.helpers.extend(syn.init.prototype, {
392 _move: function (from, options, callback) {
393 var win = syn.helpers.getWindow(from);
394 var sourceCoordinates = convertOption(options.from || from, win, from);
395 var destinationCoordinates = convertOption(options.to || options, win, from);
396 DragonDrop.html5drag = syn.support.pointerEvents;
397 if (options.adjust !== false) {
398 adjust(sourceCoordinates, destinationCoordinates, win);
399 }
400 startMove(win, sourceCoordinates, destinationCoordinates, options.duration || 500, callback);
401 },
402 _drag: function (from, options, callback) {
403 var win = syn.helpers.getWindow(from);
404 var sourceCoordinates = convertOption(options.from || from, win, from);
405 var destinationCoordinates = convertOption(options.to || options, win, from);
406 if (options.adjust !== false) {
407 adjust(sourceCoordinates, destinationCoordinates, win);
408 }
409 DragonDrop.html5drag = from.draggable;
410 if (DragonDrop.html5drag) {
411 DragonDrop.dragAndDrop(win, sourceCoordinates, destinationCoordinates, options.duration || 500, callback);
412 } else {
413 startDrag(win, sourceCoordinates, destinationCoordinates, options.duration || 500, callback);
414 }
415 }
416 });
417});
\No newline at end of file