ballonizer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/ballonizer_app/config.ru +59 -0
- data/examples/ballonizer_app/index.html +159 -0
- data/examples/ballonizer_js_module/index.html +196 -0
- data/lib/assets/javascripts/ballonizer.js +482 -0
- data/lib/assets/stylesheets/ballonizer.css +78 -0
- data/lib/ballonizer.rb +201 -36
- data/spec/ballonizer_spec.rb +153 -2
- data/spec/javascripts/ballonizer_spec.js +568 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-anchor-in-image.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-ballons.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-without-ballons.html +163 -0
- data/spec/javascripts/fixtures/xkcd.css +191 -0
- data/spec/javascripts/helpers/jasmine-jquery.js +660 -0
- data/spec/javascripts/helpers/jquery.simulate-ext.js +32 -0
- data/spec/javascripts/helpers/jquery.simulate.drag-n-drop.js +583 -0
- data/spec/javascripts/helpers/jquery.simulate.js +328 -0
- data/spec/javascripts/support/jasmine.yml +99 -0
- data/vendor/assets/javascripts/jquery-2.0.1.js +8837 -0
- data/vendor/assets/javascripts/jquery-ui-1.10.3.custom.min.js +6 -0
- data/vendor/assets/javascripts/jquery.json-2.4.min.js +24 -0
- data/vendor/assets/stylesheets/ui-lightness/images/animated-overlay.gif +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/jquery-ui-1.10.3.custom.min.css +5 -0
- metadata +51 -3
@@ -0,0 +1,583 @@
|
|
1
|
+
/*jshint camelcase:true, plusplus:true, forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, devel:true, maxerr:100, white:false, onevar:false */
|
2
|
+
/*jslint white: true vars: true browser: true todo: true */
|
3
|
+
/*global jQuery:true $:true */
|
4
|
+
|
5
|
+
/* jQuery Simulate Drag-n-Drop Plugin 1.1.5
|
6
|
+
* http://github.com/j-ulrich/jquery-simulate-ext
|
7
|
+
*
|
8
|
+
* Copyright (c) 2013 Jochen Ulrich
|
9
|
+
* Licensed under the MIT license (MIT-LICENSE.txt).
|
10
|
+
*/
|
11
|
+
|
12
|
+
;(function($, undefined) {
|
13
|
+
"use strict";
|
14
|
+
|
15
|
+
/* Overwrite the $.fn.simulate function to reduce the jQuery set to the first element for the
|
16
|
+
* drag-n-drop interactions.
|
17
|
+
*/
|
18
|
+
$.fn.simulate = function( type, options ) {
|
19
|
+
switch (type) {
|
20
|
+
case "drag":
|
21
|
+
case "drop":
|
22
|
+
case "drag-n-drop":
|
23
|
+
var ele = this.first();
|
24
|
+
new $.simulate( ele[0], type, options);
|
25
|
+
return ele;
|
26
|
+
default:
|
27
|
+
return this.each(function() {
|
28
|
+
new $.simulate( this, type, options );
|
29
|
+
});
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
var now = Date.now || function() { return new Date().getTime(); };
|
34
|
+
|
35
|
+
var rdocument = /\[object (?:HTML)?Document\]/;
|
36
|
+
/**
|
37
|
+
* Tests whether an object is an (HTML) document object.
|
38
|
+
* @param {DOM Element} elem - the object/element to be tested
|
39
|
+
* @returns {Boolean} <code>true</code> if <i>elem</i> is an (HTML) document object.
|
40
|
+
* @private
|
41
|
+
* @author julrich
|
42
|
+
* @since 1.1
|
43
|
+
*/
|
44
|
+
function isDocument( elem ) {
|
45
|
+
return rdocument.test(Object.prototype.toString.call($(elem)[0]));
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Selects the first match from an array.
|
50
|
+
* @param {Array} array - Array of objects to be be tested
|
51
|
+
* @param {Function} check - Callback function that accepts one argument (which will be one element
|
52
|
+
* from the <i>array</i>) and returns a boolean.
|
53
|
+
* @returns {Boolean|null} the first element in <i>array</i> for which <i>check</i> returns <code>true</code>.
|
54
|
+
* If none of the elements in <i>array</i> passes <i>check</i>, <code>null</code> is returned.
|
55
|
+
* @private
|
56
|
+
* @author julrich
|
57
|
+
* @since 1.1
|
58
|
+
*/
|
59
|
+
function selectFirstMatch(array, check) {
|
60
|
+
var i;
|
61
|
+
if ($.isFunction(check)) {
|
62
|
+
for (i=0; i < array.length; i+=1) {
|
63
|
+
if (check(array[i])) {
|
64
|
+
return array[i];
|
65
|
+
}
|
66
|
+
}
|
67
|
+
return null;
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
for (i=0; i < array.length; i+=1) {
|
71
|
+
if (array[i]) {
|
72
|
+
return array[i];
|
73
|
+
}
|
74
|
+
}
|
75
|
+
return null;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
// Based on the findCenter function from jquery.simulate.js
|
80
|
+
/**
|
81
|
+
* Calculates the position of the center of an DOM element.
|
82
|
+
* @param {DOM Element} elem - the element whose center should be calculated.
|
83
|
+
* @returns {Object} an object with the properties <code>x</code> and <code>y</code>
|
84
|
+
* representing the position of the center of <i>elem</i> in page relative coordinates
|
85
|
+
* (i.e. independent of any scrolling).
|
86
|
+
* @private
|
87
|
+
* @author julrich
|
88
|
+
* @since 1.0
|
89
|
+
*/
|
90
|
+
function findCenter( elem ) {
|
91
|
+
var offset;
|
92
|
+
elem = $( elem );
|
93
|
+
if ( isDocument(elem[0]) ) {
|
94
|
+
offset = {left: 0, top: 0};
|
95
|
+
}
|
96
|
+
else {
|
97
|
+
offset = elem.offset();
|
98
|
+
}
|
99
|
+
|
100
|
+
return {
|
101
|
+
x: offset.left + elem.outerWidth() / 2,
|
102
|
+
y: offset.top + elem.outerHeight() / 2
|
103
|
+
};
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Converts page relative coordinates into client relative coordinates.
|
108
|
+
* @param {Numeric|Object} x - Either the x coordinate of the page relative coordinates or
|
109
|
+
* an object with the properties <code>pageX</code> and <code>pageY</code> representing page
|
110
|
+
* relative coordinates.
|
111
|
+
* @param {Numeric} [y] - If <i>x</i> is numeric (i.e. the x coordinate of page relative coordinates),
|
112
|
+
* then this is the y coordinate. If <i>x</i> is an object, this parameter is skipped.
|
113
|
+
* @param {DOM Document} [docRel] - Optional DOM document object used to calculate the client relative
|
114
|
+
* coordinates. The page relative coordinates are interpreted as being relative to that document and
|
115
|
+
* the scroll position of that document is used to calculate the client relative coordinates.
|
116
|
+
* By default, <code>document</code> is used.
|
117
|
+
* @returns {Object} an object representing the client relative coordinates corresponding to the
|
118
|
+
* given page relative coordinates. The object either provides the properties <code>x</code> and
|
119
|
+
* <code>y</code> when <i>x</i> and <i>y</i> were given as arguments, or <code>clientX</code>
|
120
|
+
* and <code>clientY</code> when the parameter <i>x</i> was given as an object (see above).
|
121
|
+
* @private
|
122
|
+
* @author julrich
|
123
|
+
* @since 1.0
|
124
|
+
*/
|
125
|
+
function pageToClientPos(x, y, docRel) {
|
126
|
+
var jDocument;
|
127
|
+
if ( isDocument(y) ) {
|
128
|
+
jDocument = $(y);
|
129
|
+
} else {
|
130
|
+
jDocument = $(docRel || document);
|
131
|
+
}
|
132
|
+
|
133
|
+
if (typeof x === "number" && typeof y === "number") {
|
134
|
+
return {
|
135
|
+
x: x - jDocument.scrollLeft(),
|
136
|
+
y: y - jDocument.scrollTop()
|
137
|
+
};
|
138
|
+
}
|
139
|
+
else if (typeof x === "object" && x.pageX && x.pageY) {
|
140
|
+
return {
|
141
|
+
clientX: x.pageX - jDocument.scrollLeft(),
|
142
|
+
clientY: x.pageY - jDocument.scrollTop()
|
143
|
+
};
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
/**
|
148
|
+
* Browser-independent implementation of <code>document.elementFromPoint()</code>.
|
149
|
+
*
|
150
|
+
* When run for the first time on a scrolled page, this function performs a check on how
|
151
|
+
* <code>document.elementFromPoint()</code> is implemented in the current browser. It stores
|
152
|
+
* the results in two static variables so that the check can be skipped for successive calls.
|
153
|
+
*
|
154
|
+
* @param {Numeric|Object} x - Either the x coordinate of client relative coordinates or an object
|
155
|
+
* with the properties <code>x</code> and <code>y</code> representing client relative coordinates.
|
156
|
+
* @param {Numeric} [y] - If <i>x</i> is numeric (i.e. the x coordinate of client relative coordinates),
|
157
|
+
* this is the y coordinate. If <i>x</i> is an object, this parameter is skipped.
|
158
|
+
* @param {DOM Document} [docRel] - Optional DOM document object
|
159
|
+
* @returns {DOM Element|Null}
|
160
|
+
* @private
|
161
|
+
* @author Nicolas Zeh (Basic idea), julrich
|
162
|
+
* @see http://www.zehnet.de/2010/11/19/document-elementfrompoint-a-jquery-solution/
|
163
|
+
* @since 1.0
|
164
|
+
*/
|
165
|
+
function elementAtPosition(x, y, docRel) {
|
166
|
+
var doc;
|
167
|
+
if ( isDocument(y) ) {
|
168
|
+
doc = y;
|
169
|
+
} else {
|
170
|
+
doc = docRel || document;
|
171
|
+
}
|
172
|
+
|
173
|
+
if(!doc.elementFromPoint) {
|
174
|
+
return null;
|
175
|
+
}
|
176
|
+
|
177
|
+
var clientX = x, clientY = y;
|
178
|
+
if (typeof x === "object" && (x.clientX || x.clientY)) {
|
179
|
+
clientX = x.clientX || 0 ;
|
180
|
+
clientY = x.clientY || 0;
|
181
|
+
}
|
182
|
+
|
183
|
+
if(elementAtPosition.prototype.check)
|
184
|
+
{
|
185
|
+
var sl, ele;
|
186
|
+
if ((sl = $(doc).scrollTop()) >0)
|
187
|
+
{
|
188
|
+
ele = doc.elementFromPoint(0, sl + $(window).height() -1);
|
189
|
+
if ( ele !== null && ele.tagName.toUpperCase() === 'HTML' ) { ele = null; }
|
190
|
+
elementAtPosition.prototype.nativeUsesRelative = ( ele === null );
|
191
|
+
}
|
192
|
+
else if((sl = $(doc).scrollLeft()) >0)
|
193
|
+
{
|
194
|
+
ele = doc.elementFromPoint(sl + $(window).width() -1, 0);
|
195
|
+
if ( ele !== null && ele.tagName.toUpperCase() === 'HTML' ) { ele = null; }
|
196
|
+
elementAtPosition.prototype.nativeUsesRelative = ( ele === null );
|
197
|
+
}
|
198
|
+
elementAtPosition.prototype.check = (sl<=0); // Check was not meaningful because we were at scroll position 0
|
199
|
+
}
|
200
|
+
|
201
|
+
if(!elementAtPosition.prototype.nativeUsesRelative)
|
202
|
+
{
|
203
|
+
clientX += $(doc).scrollLeft();
|
204
|
+
clientY += $(doc).scrollTop();
|
205
|
+
}
|
206
|
+
|
207
|
+
return doc.elementFromPoint(clientX,clientY);
|
208
|
+
}
|
209
|
+
// Default values for the check variables
|
210
|
+
elementAtPosition.prototype.check = true;
|
211
|
+
elementAtPosition.prototype.nativeUsesRelative = true;
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Informs the rest of the world that the drag is finished.
|
215
|
+
* @param {DOM Element} ele - The element which was dragged.
|
216
|
+
* @param {Object} [options] - The drag options.
|
217
|
+
* @fires simulate-drag
|
218
|
+
* @private
|
219
|
+
* @author julrich
|
220
|
+
* @since 1.0
|
221
|
+
*/
|
222
|
+
function dragFinished(ele, options) {
|
223
|
+
var opts = options || {};
|
224
|
+
$(ele).trigger({type: "simulate-drag"});
|
225
|
+
if ($.isFunction(opts.callback)) {
|
226
|
+
opts.callback.apply(ele);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
/**
|
231
|
+
* Generates a series of <code>mousemove</code> events for a drag.
|
232
|
+
* @param {Object} self - The simulate object.
|
233
|
+
* @param {DOM Element} ele - The element which is dragged.
|
234
|
+
* @param {Object} start - The start coordinates of the drag, represented using the properties
|
235
|
+
* <code>x</code> and <code>y</code>.
|
236
|
+
* @param {Object} drag - The distance to be dragged, represented using the properties <code>dx</code>
|
237
|
+
* and <code>dy</code>.
|
238
|
+
* @param {Object} options - The drag options. Must have the property <code>interpolation</code>
|
239
|
+
* containing the interpolation options (<code>stepWidth</code>, <code>stepCount</code>, etc.).
|
240
|
+
* @requires eventTarget
|
241
|
+
* @requires now()
|
242
|
+
* @private
|
243
|
+
* @author julrich
|
244
|
+
* @since 1.0
|
245
|
+
*/
|
246
|
+
function interpolatedEvents(self, ele, start, drag, options) {
|
247
|
+
var targetDoc = selectFirstMatch([ele, ele.ownerDocument], isDocument) || document,
|
248
|
+
interpolOptions = options.interpolation,
|
249
|
+
dragDistance = Math.sqrt(Math.pow(drag.dx,2) + Math.pow(drag.dy,2)), // sqrt(a^2 + b^2)
|
250
|
+
stepWidth, stepCount, stepVector;
|
251
|
+
|
252
|
+
if (interpolOptions.stepWidth) {
|
253
|
+
stepWidth = parseInt(interpolOptions.stepWidth, 10);
|
254
|
+
stepCount = Math.floor(dragDistance / stepWidth)-1;
|
255
|
+
var stepScale = stepWidth / dragDistance;
|
256
|
+
stepVector = {x: drag.dx*stepScale, y: drag.dy*stepScale };
|
257
|
+
}
|
258
|
+
else {
|
259
|
+
stepCount = parseInt(interpolOptions.stepCount, 10);
|
260
|
+
stepWidth = dragDistance / (stepCount+1);
|
261
|
+
stepVector = {x: drag.dx/(stepCount+1), y: drag.dy/(stepCount+1)};
|
262
|
+
}
|
263
|
+
|
264
|
+
|
265
|
+
var coords = $.extend({},start);
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Calculates the effective coordinates for one <code>mousemove</code> event and fires the event.
|
269
|
+
* @requires eventTarget
|
270
|
+
* @requires targetDoc
|
271
|
+
* @requires coords
|
272
|
+
* @requires stepVector
|
273
|
+
* @requires interpolOptions
|
274
|
+
* @fires mousemove
|
275
|
+
* @inner
|
276
|
+
* @author julrich
|
277
|
+
* @since 1.0
|
278
|
+
*/
|
279
|
+
function interpolationStep() {
|
280
|
+
coords.x += stepVector.x;
|
281
|
+
coords.y += stepVector.y;
|
282
|
+
var effectiveCoords = {pageX: coords.x, pageY: coords.y};
|
283
|
+
if (interpolOptions.shaky && (interpolOptions.shaky === true || !isNaN(parseInt(interpolOptions.shaky,10)) )) {
|
284
|
+
var amplitude = (interpolOptions.shaky === true)? 1 : parseInt(interpolOptions.shaky,10);
|
285
|
+
effectiveCoords.pageX += Math.floor(Math.random()*(2*amplitude+1)-amplitude);
|
286
|
+
effectiveCoords.pageY += Math.floor(Math.random()*(2*amplitude+1)-amplitude);
|
287
|
+
}
|
288
|
+
var clientCoord = pageToClientPos(effectiveCoords, targetDoc),
|
289
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc) || ele;
|
290
|
+
self.simulateEvent( eventTarget, "mousemove", {pageX: Math.round(effectiveCoords.pageX), pageY: Math.round(effectiveCoords.pageY)});
|
291
|
+
}
|
292
|
+
|
293
|
+
|
294
|
+
var lastTime;
|
295
|
+
|
296
|
+
/**
|
297
|
+
* Performs one interpolation step (i.e. cares about firing the event) and then sleeps for
|
298
|
+
* <code>stepDelay</code> milliseconds.
|
299
|
+
* @requires lastTime
|
300
|
+
* @requires stepDelay
|
301
|
+
* @requires step
|
302
|
+
* @requires ele
|
303
|
+
* @requires eventTarget
|
304
|
+
* @reuiqre targetDoc
|
305
|
+
* @requires start
|
306
|
+
* @requires drag
|
307
|
+
* @requires now()
|
308
|
+
* @inner
|
309
|
+
* @author julrich
|
310
|
+
* @since 1.0
|
311
|
+
*/
|
312
|
+
function stepAndSleep() {
|
313
|
+
var timeElapsed = now() - lastTime; // Work-around for Firefox & IE "bug": setTimeout can fire before the timeout
|
314
|
+
if (timeElapsed >= stepDelay) {
|
315
|
+
if (step < stepCount) {
|
316
|
+
interpolationStep();
|
317
|
+
step += 1;
|
318
|
+
lastTime = now();
|
319
|
+
setTimeout(stepAndSleep, stepDelay);
|
320
|
+
}
|
321
|
+
else {
|
322
|
+
var pageCoord = {pageX: Math.round(start.x+drag.dx), pageY: Math.round(start.y+drag.dy)},
|
323
|
+
clientCoord = pageToClientPos(pageCoord, targetDoc),
|
324
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc) || ele;
|
325
|
+
self.simulateEvent( eventTarget, "mousemove", pageCoord);
|
326
|
+
dragFinished(ele, options);
|
327
|
+
}
|
328
|
+
}
|
329
|
+
else {
|
330
|
+
setTimeout(stepAndSleep, stepDelay - timeElapsed);
|
331
|
+
}
|
332
|
+
|
333
|
+
}
|
334
|
+
|
335
|
+
if ( (!interpolOptions.stepDelay && !interpolOptions.duration) || ((interpolOptions.stepDelay <= 0) && (interpolOptions.duration <= 0)) ) {
|
336
|
+
// Trigger as fast as possible
|
337
|
+
for (var i=0; i < stepCount; i+=1) {
|
338
|
+
interpolationStep();
|
339
|
+
}
|
340
|
+
var pageCoord = {pageX: Math.round(start.x+drag.dx), pageY: Math.round(start.y+drag.dy)},
|
341
|
+
clientCoord = pageToClientPos(pageCoord, targetDoc),
|
342
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc) || ele;
|
343
|
+
self.simulateEvent( eventTarget, "mousemove", pageCoord);
|
344
|
+
dragFinished(ele, options);
|
345
|
+
}
|
346
|
+
else {
|
347
|
+
var stepDelay = parseInt(interpolOptions.stepDelay,10) || Math.ceil(parseInt(interpolOptions.duration,10) / (stepCount+1));
|
348
|
+
var step = 0;
|
349
|
+
|
350
|
+
lastTime = now();
|
351
|
+
setTimeout(stepAndSleep, stepDelay);
|
352
|
+
}
|
353
|
+
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* @returns {Object|undefined} an object containing information about the currently active drag
|
358
|
+
* or <code>undefined</code> when there is no active drag.
|
359
|
+
* The returned object contains the following properties:
|
360
|
+
* <ul>
|
361
|
+
* <li><code>dragElement</code>: the dragged element</li>
|
362
|
+
* <li><code>dragStart</code>: object with the properties <code>x</code> and <code>y</code>
|
363
|
+
* representing the page relative start coordinates of the drag</li>
|
364
|
+
* <li><code>dragDistance</code>: object with the properties <code>x</code> and <code>y</code>
|
365
|
+
* representing the distance of the drag in x and y direction</li>
|
366
|
+
* </ul>
|
367
|
+
* @public
|
368
|
+
* @author julrich
|
369
|
+
* @since 1.0
|
370
|
+
*/
|
371
|
+
$.simulate.activeDrag = function() {
|
372
|
+
if (!$.simulate._activeDrag) {
|
373
|
+
return undefined;
|
374
|
+
}
|
375
|
+
return $.extend(true,{},$.simulate._activeDrag);
|
376
|
+
};
|
377
|
+
|
378
|
+
$.extend( $.simulate.prototype,
|
379
|
+
|
380
|
+
/**
|
381
|
+
* @lends $.simulate.prototype
|
382
|
+
*/
|
383
|
+
{
|
384
|
+
|
385
|
+
|
386
|
+
/**
|
387
|
+
* Simulates a drag.
|
388
|
+
*
|
389
|
+
* @see https://github.com/j-ulrich/jquery-simulate-ext/blob/master/doc/drag-n-drop.md
|
390
|
+
* @public
|
391
|
+
* @author julrich
|
392
|
+
* @since 1.0
|
393
|
+
*/
|
394
|
+
simulateDrag: function() {
|
395
|
+
var self = this,
|
396
|
+
ele = self.target,
|
397
|
+
options = $.extend({
|
398
|
+
dx: 0,
|
399
|
+
dy: 0,
|
400
|
+
dragTarget: undefined,
|
401
|
+
clickToDrag: false,
|
402
|
+
interpolation: {
|
403
|
+
stepWidth: 0,
|
404
|
+
stepCount: 0,
|
405
|
+
stepDelay: 0,
|
406
|
+
duration: 0,
|
407
|
+
shaky: false
|
408
|
+
},
|
409
|
+
callback: undefined
|
410
|
+
}, this.options);
|
411
|
+
|
412
|
+
var start,
|
413
|
+
continueDrag = ($.simulate._activeDrag && $.simulate._activeDrag.dragElement === ele);
|
414
|
+
|
415
|
+
if (continueDrag) {
|
416
|
+
start = $.simulate._activeDrag.dragStart;
|
417
|
+
}
|
418
|
+
else {
|
419
|
+
start = findCenter( ele );
|
420
|
+
}
|
421
|
+
|
422
|
+
var x = Math.round( start.x ),
|
423
|
+
y = Math.round( start.y ),
|
424
|
+
coord = { pageX: x, pageY: y },
|
425
|
+
dx,
|
426
|
+
dy;
|
427
|
+
|
428
|
+
if (options.dragTarget) {
|
429
|
+
var end = findCenter(options.dragTarget);
|
430
|
+
dx = Math.round(end.x - start.x);
|
431
|
+
dy = Math.round(end.y - start.y);
|
432
|
+
}
|
433
|
+
else {
|
434
|
+
dx = options.dx || 0;
|
435
|
+
dy = options.dy || 0;
|
436
|
+
}
|
437
|
+
|
438
|
+
if (continueDrag) {
|
439
|
+
// We just continue to move the dragged element
|
440
|
+
$.simulate._activeDrag.dragDistance.x += dx;
|
441
|
+
$.simulate._activeDrag.dragDistance.y += dy;
|
442
|
+
coord = { pageX: Math.round(x + $.simulate._activeDrag.dragDistance.x) , pageY: Math.round(y + $.simulate._activeDrag.dragDistance.y) };
|
443
|
+
}
|
444
|
+
else {
|
445
|
+
if ($.simulate._activeDrag) {
|
446
|
+
// Drop before starting a new drag
|
447
|
+
$($.simulate._activeDrag.dragElement).simulate( "drop" );
|
448
|
+
}
|
449
|
+
|
450
|
+
// We start a new drag
|
451
|
+
self.simulateEvent( ele, "mousedown", coord );
|
452
|
+
if (options.clickToDrag === true) {
|
453
|
+
self.simulateEvent( ele, "mouseup", coord );
|
454
|
+
self.simulateEvent( ele, "click", coord );
|
455
|
+
}
|
456
|
+
$(ele).add(ele.ownerDocument).one('mouseup', function() {
|
457
|
+
$.simulate._activeDrag = undefined;
|
458
|
+
});
|
459
|
+
|
460
|
+
$.extend($.simulate, {
|
461
|
+
_activeDrag: {
|
462
|
+
dragElement: ele,
|
463
|
+
dragStart: { x: x, y: y },
|
464
|
+
dragDistance: { x: dx, y: dy }
|
465
|
+
}
|
466
|
+
});
|
467
|
+
coord = { pageX: Math.round(x + dx), pageY: Math.round(y + dy) };
|
468
|
+
}
|
469
|
+
|
470
|
+
if (dx !== 0 || dy !== 0) {
|
471
|
+
|
472
|
+
if ( options.interpolation && (options.interpolation.stepCount || options.interpolation.stepWidth) ) {
|
473
|
+
interpolatedEvents(self, ele, {x: x, y: y}, {dx: dx, dy: dy}, options);
|
474
|
+
}
|
475
|
+
else {
|
476
|
+
var targetDoc = selectFirstMatch([ele, ele.ownerDocument], isDocument) || document,
|
477
|
+
clientCoord = pageToClientPos(coord, targetDoc),
|
478
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc) || ele;
|
479
|
+
|
480
|
+
self.simulateEvent( eventTarget, "mousemove", coord );
|
481
|
+
dragFinished(ele, options);
|
482
|
+
}
|
483
|
+
}
|
484
|
+
else {
|
485
|
+
dragFinished(ele, options);
|
486
|
+
}
|
487
|
+
},
|
488
|
+
|
489
|
+
/**
|
490
|
+
* Simulates a drop.
|
491
|
+
*
|
492
|
+
* @see https://github.com/j-ulrich/jquery-simulate-ext/blob/master/doc/drag-n-drop.md
|
493
|
+
* @public
|
494
|
+
* @author julrich
|
495
|
+
* @since 1.0
|
496
|
+
*/
|
497
|
+
simulateDrop: function() {
|
498
|
+
var self = this,
|
499
|
+
ele = this.target,
|
500
|
+
activeDrag = $.simulate._activeDrag,
|
501
|
+
options = $.extend({
|
502
|
+
clickToDrop: false,
|
503
|
+
callback: undefined
|
504
|
+
}, self.options),
|
505
|
+
moveBeforeDrop = true,
|
506
|
+
center = findCenter( ele ),
|
507
|
+
x = Math.round( center.x ),
|
508
|
+
y = Math.round( center.y ),
|
509
|
+
coord = { pageX: x, pageY: y },
|
510
|
+
targetDoc = ( (activeDrag)? selectFirstMatch([activeDrag.dragElement, activeDrag.dragElement.ownerDocument], isDocument) : selectFirstMatch([ele, ele.ownerDocument], isDocument) ) || document,
|
511
|
+
clientCoord = pageToClientPos(coord, targetDoc),
|
512
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc);
|
513
|
+
|
514
|
+
if (activeDrag && (activeDrag.dragElement === ele || isDocument(ele))) {
|
515
|
+
// We already moved the mouse during the drag so we just simulate the drop on the end position
|
516
|
+
x = Math.round(activeDrag.dragStart.x + activeDrag.dragDistance.x);
|
517
|
+
y = Math.round(activeDrag.dragStart.y + activeDrag.dragDistance.y);
|
518
|
+
coord = { pageX: x, pageY: y };
|
519
|
+
clientCoord = pageToClientPos(coord, targetDoc);
|
520
|
+
eventTarget = elementAtPosition(clientCoord, targetDoc);
|
521
|
+
moveBeforeDrop = false;
|
522
|
+
}
|
523
|
+
|
524
|
+
if (!eventTarget) {
|
525
|
+
eventTarget = (activeDrag)? activeDrag.dragElement : ele;
|
526
|
+
}
|
527
|
+
|
528
|
+
if (moveBeforeDrop === true) {
|
529
|
+
// Else we assume the drop should happen on target, so we move there
|
530
|
+
self.simulateEvent( eventTarget, "mousemove", coord );
|
531
|
+
}
|
532
|
+
|
533
|
+
if (options.clickToDrop) {
|
534
|
+
self.simulateEvent( eventTarget, "mousedown", coord );
|
535
|
+
}
|
536
|
+
this.simulateEvent( eventTarget, "mouseup", coord );
|
537
|
+
if (options.clickToDrop) {
|
538
|
+
self.simulateEvent( eventTarget, "click", coord );
|
539
|
+
}
|
540
|
+
|
541
|
+
$.simulate._activeDrag = undefined;
|
542
|
+
$(eventTarget).trigger({type: "simulate-drop"});
|
543
|
+
if ($.isFunction(options.callback)) {
|
544
|
+
options.callback.apply(eventTarget);
|
545
|
+
}
|
546
|
+
},
|
547
|
+
|
548
|
+
/**
|
549
|
+
* Simulates a drag followed by drop.
|
550
|
+
*
|
551
|
+
* @see https://github.com/j-ulrich/jquery-simulate-ext/blob/master/doc/drag-n-drop.md
|
552
|
+
* @public
|
553
|
+
* @author julrich
|
554
|
+
* @since 1.0
|
555
|
+
*/
|
556
|
+
simulateDragNDrop: function() {
|
557
|
+
var self = this,
|
558
|
+
ele = this.target,
|
559
|
+
options = $.extend({
|
560
|
+
dragTarget: undefined,
|
561
|
+
dropTarget: undefined
|
562
|
+
}, self.options),
|
563
|
+
// If there is a dragTarget or dx/dy, then we drag there and simulate an independent drop on dropTarget or ele
|
564
|
+
dropEle = ((options.dragTarget || options.dx || options.dy)? options.dropTarget : ele) || ele;
|
565
|
+
/*
|
566
|
+
dx = (options.dropTarget)? 0 : (options.dx || 0),
|
567
|
+
dy = (options.dropTarget)? 0 : (options.dy || 0),
|
568
|
+
dragDistance = { dx: dx, dy: dy };
|
569
|
+
|
570
|
+
$.extend(options, dragDistance);
|
571
|
+
*/
|
572
|
+
$(ele).simulate( "drag", $.extend({},options,{
|
573
|
+
// If there is no dragTarget, no dx and no dy, we drag onto the dropTarget directly
|
574
|
+
dragTarget: options.dragTarget || ((options.dx || options.dy)?undefined:options.dropTarget),
|
575
|
+
callback: function() {
|
576
|
+
$(dropEle).simulate( "drop", options );
|
577
|
+
}
|
578
|
+
}));
|
579
|
+
|
580
|
+
}
|
581
|
+
});
|
582
|
+
|
583
|
+
}(jQuery));
|