ballonizer 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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));
|