1 |
|
2 | define([
|
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 |