0
|
1 /*
|
|
2 * jQuery UI Draggable 1.8.11
|
|
3 *
|
|
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
|
5 * Dual licensed under the MIT or GPL Version 2 licenses.
|
|
6 * http://jquery.org/license
|
|
7 *
|
|
8 * http://docs.jquery.com/UI/Draggables
|
|
9 *
|
|
10 * Depends:
|
|
11 * jquery.ui.core.js
|
|
12 * jquery.ui.mouse.js
|
|
13 * jquery.ui.widget.js
|
|
14 */
|
|
15 (function( $, undefined ) {
|
|
16
|
|
17 $.widget("ui.draggable", $.ui.mouse, {
|
|
18 widgetEventPrefix: "drag",
|
|
19 options: {
|
|
20 addClasses: true,
|
|
21 appendTo: "parent",
|
|
22 axis: false,
|
|
23 connectToSortable: false,
|
|
24 containment: false,
|
|
25 cursor: "auto",
|
|
26 cursorAt: false,
|
|
27 grid: false,
|
|
28 handle: false,
|
|
29 helper: "original",
|
|
30 iframeFix: false,
|
|
31 opacity: false,
|
|
32 refreshPositions: false,
|
|
33 revert: false,
|
|
34 revertDuration: 500,
|
|
35 scope: "default",
|
|
36 scroll: true,
|
|
37 scrollSensitivity: 20,
|
|
38 scrollSpeed: 20,
|
|
39 snap: false,
|
|
40 snapMode: "both",
|
|
41 snapTolerance: 20,
|
|
42 stack: false,
|
|
43 zIndex: false
|
|
44 },
|
|
45 _create: function() {
|
|
46
|
|
47 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
|
|
48 this.element[0].style.position = 'relative';
|
|
49
|
|
50 (this.options.addClasses && this.element.addClass("ui-draggable"));
|
|
51 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
|
|
52
|
|
53 this._mouseInit();
|
|
54
|
|
55 },
|
|
56
|
|
57 destroy: function() {
|
|
58 if(!this.element.data('draggable')) return;
|
|
59 this.element
|
|
60 .removeData("draggable")
|
|
61 .unbind(".draggable")
|
|
62 .removeClass("ui-draggable"
|
|
63 + " ui-draggable-dragging"
|
|
64 + " ui-draggable-disabled");
|
|
65 this._mouseDestroy();
|
|
66
|
|
67 return this;
|
|
68 },
|
|
69
|
|
70 _mouseCapture: function(event) {
|
|
71
|
|
72 var o = this.options;
|
|
73
|
|
74 // among others, prevent a drag on a resizable-handle
|
|
75 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
|
|
76 return false;
|
|
77
|
|
78 //Quit if we're not on a valid handle
|
|
79 this.handle = this._getHandle(event);
|
|
80 if (!this.handle)
|
|
81 return false;
|
|
82
|
|
83 return true;
|
|
84
|
|
85 },
|
|
86
|
|
87 _mouseStart: function(event) {
|
|
88
|
|
89 var o = this.options;
|
|
90
|
|
91 //Create and append the visible helper
|
|
92 this.helper = this._createHelper(event);
|
|
93
|
|
94 //Cache the helper size
|
|
95 this._cacheHelperProportions();
|
|
96
|
|
97 //If ddmanager is used for droppables, set the global draggable
|
|
98 if($.ui.ddmanager)
|
|
99 $.ui.ddmanager.current = this;
|
|
100
|
|
101 /*
|
|
102 * - Position generation -
|
|
103 * This block generates everything position related - it's the core of draggables.
|
|
104 */
|
|
105
|
|
106 //Cache the margins of the original element
|
|
107 this._cacheMargins();
|
|
108
|
|
109 //Store the helper's css position
|
|
110 this.cssPosition = this.helper.css("position");
|
|
111 this.scrollParent = this.helper.scrollParent();
|
|
112
|
|
113 //The element's absolute position on the page minus margins
|
|
114 this.offset = this.positionAbs = this.element.offset();
|
|
115 this.offset = {
|
|
116 top: this.offset.top - this.margins.top,
|
|
117 left: this.offset.left - this.margins.left
|
|
118 };
|
|
119
|
|
120 $.extend(this.offset, {
|
|
121 click: { //Where the click happened, relative to the element
|
|
122 left: event.pageX - this.offset.left,
|
|
123 top: event.pageY - this.offset.top
|
|
124 },
|
|
125 parent: this._getParentOffset(),
|
|
126 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
|
|
127 });
|
|
128
|
|
129 //Generate the original position
|
|
130 this.originalPosition = this.position = this._generatePosition(event);
|
|
131 this.originalPageX = event.pageX;
|
|
132 this.originalPageY = event.pageY;
|
|
133
|
|
134 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
|
|
135 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
|
|
136
|
|
137 //Set a containment if given in the options
|
|
138 if(o.containment)
|
|
139 this._setContainment();
|
|
140
|
|
141 //Trigger event + callbacks
|
|
142 if(this._trigger("start", event) === false) {
|
|
143 this._clear();
|
|
144 return false;
|
|
145 }
|
|
146
|
|
147 //Recache the helper size
|
|
148 this._cacheHelperProportions();
|
|
149
|
|
150 //Prepare the droppable offsets
|
|
151 if ($.ui.ddmanager && !o.dropBehaviour)
|
|
152 $.ui.ddmanager.prepareOffsets(this, event);
|
|
153
|
|
154 this.helper.addClass("ui-draggable-dragging");
|
|
155 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
|
|
156 return true;
|
|
157 },
|
|
158
|
|
159 _mouseDrag: function(event, noPropagation) {
|
|
160
|
|
161 //Compute the helpers position
|
|
162 this.position = this._generatePosition(event);
|
|
163 this.positionAbs = this._convertPositionTo("absolute");
|
|
164
|
|
165 //Call plugins and callbacks and use the resulting position if something is returned
|
|
166 if (!noPropagation) {
|
|
167 var ui = this._uiHash();
|
|
168 if(this._trigger('drag', event, ui) === false) {
|
|
169 this._mouseUp({});
|
|
170 return false;
|
|
171 }
|
|
172 this.position = ui.position;
|
|
173 }
|
|
174
|
|
175 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
|
|
176 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
|
|
177 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
|
|
178
|
|
179 return false;
|
|
180 },
|
|
181
|
|
182 _mouseStop: function(event) {
|
|
183
|
|
184 //If we are using droppables, inform the manager about the drop
|
|
185 var dropped = false;
|
|
186 if ($.ui.ddmanager && !this.options.dropBehaviour)
|
|
187 dropped = $.ui.ddmanager.drop(this, event);
|
|
188
|
|
189 //if a drop comes from outside (a sortable)
|
|
190 if(this.dropped) {
|
|
191 dropped = this.dropped;
|
|
192 this.dropped = false;
|
|
193 }
|
|
194
|
|
195 //if the original element is removed, don't bother to continue if helper is set to "original"
|
|
196 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
|
|
197 return false;
|
|
198
|
|
199 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
|
|
200 var self = this;
|
|
201 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
|
|
202 if(self._trigger("stop", event) !== false) {
|
|
203 self._clear();
|
|
204 }
|
|
205 });
|
|
206 } else {
|
|
207 if(this._trigger("stop", event) !== false) {
|
|
208 this._clear();
|
|
209 }
|
|
210 }
|
|
211
|
|
212 return false;
|
|
213 },
|
|
214
|
|
215 cancel: function() {
|
|
216
|
|
217 if(this.helper.is(".ui-draggable-dragging")) {
|
|
218 this._mouseUp({});
|
|
219 } else {
|
|
220 this._clear();
|
|
221 }
|
|
222
|
|
223 return this;
|
|
224
|
|
225 },
|
|
226
|
|
227 _getHandle: function(event) {
|
|
228
|
|
229 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
|
|
230 $(this.options.handle, this.element)
|
|
231 .find("*")
|
|
232 .andSelf()
|
|
233 .each(function() {
|
|
234 if(this == event.target) handle = true;
|
|
235 });
|
|
236
|
|
237 return handle;
|
|
238
|
|
239 },
|
|
240
|
|
241 _createHelper: function(event) {
|
|
242
|
|
243 var o = this.options;
|
|
244 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
|
|
245
|
|
246 if(!helper.parents('body').length)
|
|
247 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
|
|
248
|
|
249 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
|
|
250 helper.css("position", "absolute");
|
|
251
|
|
252 return helper;
|
|
253
|
|
254 },
|
|
255
|
|
256 _adjustOffsetFromHelper: function(obj) {
|
|
257 if (typeof obj == 'string') {
|
|
258 obj = obj.split(' ');
|
|
259 }
|
|
260 if ($.isArray(obj)) {
|
|
261 obj = {left: +obj[0], top: +obj[1] || 0};
|
|
262 }
|
|
263 if ('left' in obj) {
|
|
264 this.offset.click.left = obj.left + this.margins.left;
|
|
265 }
|
|
266 if ('right' in obj) {
|
|
267 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
|
|
268 }
|
|
269 if ('top' in obj) {
|
|
270 this.offset.click.top = obj.top + this.margins.top;
|
|
271 }
|
|
272 if ('bottom' in obj) {
|
|
273 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
|
|
274 }
|
|
275 },
|
|
276
|
|
277 _getParentOffset: function() {
|
|
278
|
|
279 //Get the offsetParent and cache its position
|
|
280 this.offsetParent = this.helper.offsetParent();
|
|
281 var po = this.offsetParent.offset();
|
|
282
|
|
283 // This is a special case where we need to modify a offset calculated on start, since the following happened:
|
|
284 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
|
|
285 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
|
|
286 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
|
|
287 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
|
|
288 po.left += this.scrollParent.scrollLeft();
|
|
289 po.top += this.scrollParent.scrollTop();
|
|
290 }
|
|
291
|
|
292 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
|
|
293 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
|
|
294 po = { top: 0, left: 0 };
|
|
295
|
|
296 return {
|
|
297 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
|
|
298 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
|
|
299 };
|
|
300
|
|
301 },
|
|
302
|
|
303 _getRelativeOffset: function() {
|
|
304
|
|
305 if(this.cssPosition == "relative") {
|
|
306 var p = this.element.position();
|
|
307 return {
|
|
308 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
|
|
309 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
|
|
310 };
|
|
311 } else {
|
|
312 return { top: 0, left: 0 };
|
|
313 }
|
|
314
|
|
315 },
|
|
316
|
|
317 _cacheMargins: function() {
|
|
318 this.margins = {
|
|
319 left: (parseInt(this.element.css("marginLeft"),10) || 0),
|
|
320 top: (parseInt(this.element.css("marginTop"),10) || 0),
|
|
321 right: (parseInt(this.element.css("marginRight"),10) || 0),
|
|
322 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
|
|
323 };
|
|
324 },
|
|
325
|
|
326 _cacheHelperProportions: function() {
|
|
327 this.helperProportions = {
|
|
328 width: this.helper.outerWidth(),
|
|
329 height: this.helper.outerHeight()
|
|
330 };
|
|
331 },
|
|
332
|
|
333 _setContainment: function() {
|
|
334
|
|
335 var o = this.options;
|
|
336 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
|
|
337 if(o.containment == 'document' || o.containment == 'window') this.containment = [
|
|
338 (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
|
|
339 (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
|
|
340 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
|
|
341 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
|
|
342 ];
|
|
343
|
|
344 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
|
|
345 var ce = $(o.containment)[0]; if(!ce) return;
|
|
346 var co = $(o.containment).offset();
|
|
347 var over = ($(ce).css("overflow") != 'hidden');
|
|
348
|
|
349 this.containment = [
|
|
350 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
|
|
351 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
|
|
352 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
|
|
353 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
|
|
354 ];
|
|
355 } else if(o.containment.constructor == Array) {
|
|
356 this.containment = o.containment;
|
|
357 }
|
|
358
|
|
359 },
|
|
360
|
|
361 _convertPositionTo: function(d, pos) {
|
|
362
|
|
363 if(!pos) pos = this.position;
|
|
364 var mod = d == "absolute" ? 1 : -1;
|
|
365 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
|
|
366
|
|
367 return {
|
|
368 top: (
|
|
369 pos.top // The absolute mouse position
|
|
370 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
|
|
371 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
|
|
372 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
|
|
373 ),
|
|
374 left: (
|
|
375 pos.left // The absolute mouse position
|
|
376 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
|
|
377 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
|
|
378 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
|
|
379 )
|
|
380 };
|
|
381
|
|
382 },
|
|
383
|
|
384 _generatePosition: function(event) {
|
|
385
|
|
386 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
|
|
387 var pageX = event.pageX;
|
|
388 var pageY = event.pageY;
|
|
389
|
|
390 /*
|
|
391 * - Position constraining -
|
|
392 * Constrain the position to a mix of grid, containment.
|
|
393 */
|
|
394
|
|
395 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
|
|
396
|
|
397 if(this.containment) {
|
|
398 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
|
|
399 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
|
|
400 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
|
|
401 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
|
|
402 }
|
|
403
|
|
404 if(o.grid) {
|
|
405 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
|
|
406 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
|
|
407
|
|
408 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
|
|
409 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
|
|
410 }
|
|
411
|
|
412 }
|
|
413
|
|
414 return {
|
|
415 top: (
|
|
416 pageY // The absolute mouse position
|
|
417 - this.offset.click.top // Click offset (relative to the element)
|
|
418 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
|
|
419 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
|
|
420 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
|
|
421 ),
|
|
422 left: (
|
|
423 pageX // The absolute mouse position
|
|
424 - this.offset.click.left // Click offset (relative to the element)
|
|
425 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
|
|
426 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
|
|
427 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
|
|
428 )
|
|
429 };
|
|
430
|
|
431 },
|
|
432
|
|
433 _clear: function() {
|
|
434 this.helper.removeClass("ui-draggable-dragging");
|
|
435 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
|
|
436 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
|
|
437 this.helper = null;
|
|
438 this.cancelHelperRemoval = false;
|
|
439 },
|
|
440
|
|
441 // From now on bulk stuff - mainly helpers
|
|
442
|
|
443 _trigger: function(type, event, ui) {
|
|
444 ui = ui || this._uiHash();
|
|
445 $.ui.plugin.call(this, type, [event, ui]);
|
|
446 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
|
|
447 return $.Widget.prototype._trigger.call(this, type, event, ui);
|
|
448 },
|
|
449
|
|
450 plugins: {},
|
|
451
|
|
452 _uiHash: function(event) {
|
|
453 return {
|
|
454 helper: this.helper,
|
|
455 position: this.position,
|
|
456 originalPosition: this.originalPosition,
|
|
457 offset: this.positionAbs
|
|
458 };
|
|
459 }
|
|
460
|
|
461 });
|
|
462
|
|
463 $.extend($.ui.draggable, {
|
|
464 version: "1.8.11"
|
|
465 });
|
|
466
|
|
467 $.ui.plugin.add("draggable", "connectToSortable", {
|
|
468 start: function(event, ui) {
|
|
469
|
|
470 var inst = $(this).data("draggable"), o = inst.options,
|
|
471 uiSortable = $.extend({}, ui, { item: inst.element });
|
|
472 inst.sortables = [];
|
|
473 $(o.connectToSortable).each(function() {
|
|
474 var sortable = $.data(this, 'sortable');
|
|
475 if (sortable && !sortable.options.disabled) {
|
|
476 inst.sortables.push({
|
|
477 instance: sortable,
|
|
478 shouldRevert: sortable.options.revert
|
|
479 });
|
|
480 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
|
|
481 sortable._trigger("activate", event, uiSortable);
|
|
482 }
|
|
483 });
|
|
484
|
|
485 },
|
|
486 stop: function(event, ui) {
|
|
487
|
|
488 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
|
|
489 var inst = $(this).data("draggable"),
|
|
490 uiSortable = $.extend({}, ui, { item: inst.element });
|
|
491
|
|
492 $.each(inst.sortables, function() {
|
|
493 if(this.instance.isOver) {
|
|
494
|
|
495 this.instance.isOver = 0;
|
|
496
|
|
497 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
|
|
498 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
|
|
499
|
|
500 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
|
|
501 if(this.shouldRevert) this.instance.options.revert = true;
|
|
502
|
|
503 //Trigger the stop of the sortable
|
|
504 this.instance._mouseStop(event);
|
|
505
|
|
506 this.instance.options.helper = this.instance.options._helper;
|
|
507
|
|
508 //If the helper has been the original item, restore properties in the sortable
|
|
509 if(inst.options.helper == 'original')
|
|
510 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
|
|
511
|
|
512 } else {
|
|
513 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
|
|
514 this.instance._trigger("deactivate", event, uiSortable);
|
|
515 }
|
|
516
|
|
517 });
|
|
518
|
|
519 },
|
|
520 drag: function(event, ui) {
|
|
521
|
|
522 var inst = $(this).data("draggable"), self = this;
|
|
523
|
|
524 var checkPos = function(o) {
|
|
525 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
|
|
526 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
|
|
527 var itemHeight = o.height, itemWidth = o.width;
|
|
528 var itemTop = o.top, itemLeft = o.left;
|
|
529
|
|
530 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
|
|
531 };
|
|
532
|
|
533 $.each(inst.sortables, function(i) {
|
|
534
|
|
535 //Copy over some variables to allow calling the sortable's native _intersectsWith
|
|
536 this.instance.positionAbs = inst.positionAbs;
|
|
537 this.instance.helperProportions = inst.helperProportions;
|
|
538 this.instance.offset.click = inst.offset.click;
|
|
539
|
|
540 if(this.instance._intersectsWith(this.instance.containerCache)) {
|
|
541
|
|
542 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
|
|
543 if(!this.instance.isOver) {
|
|
544
|
|
545 this.instance.isOver = 1;
|
|
546 //Now we fake the start of dragging for the sortable instance,
|
|
547 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
|
|
548 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
|
|
549 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
|
|
550 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
|
|
551 this.instance.options.helper = function() { return ui.helper[0]; };
|
|
552
|
|
553 event.target = this.instance.currentItem[0];
|
|
554 this.instance._mouseCapture(event, true);
|
|
555 this.instance._mouseStart(event, true, true);
|
|
556
|
|
557 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
|
|
558 this.instance.offset.click.top = inst.offset.click.top;
|
|
559 this.instance.offset.click.left = inst.offset.click.left;
|
|
560 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
|
|
561 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
|
|
562
|
|
563 inst._trigger("toSortable", event);
|
|
564 inst.dropped = this.instance.element; //draggable revert needs that
|
|
565 //hack so receive/update callbacks work (mostly)
|
|
566 inst.currentItem = inst.element;
|
|
567 this.instance.fromOutside = inst;
|
|
568
|
|
569 }
|
|
570
|
|
571 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
|
|
572 if(this.instance.currentItem) this.instance._mouseDrag(event);
|
|
573
|
|
574 } else {
|
|
575
|
|
576 //If it doesn't intersect with the sortable, and it intersected before,
|
|
577 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
|
|
578 if(this.instance.isOver) {
|
|
579
|
|
580 this.instance.isOver = 0;
|
|
581 this.instance.cancelHelperRemoval = true;
|
|
582
|
|
583 //Prevent reverting on this forced stop
|
|
584 this.instance.options.revert = false;
|
|
585
|
|
586 // The out event needs to be triggered independently
|
|
587 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
|
|
588
|
|
589 this.instance._mouseStop(event, true);
|
|
590 this.instance.options.helper = this.instance.options._helper;
|
|
591
|
|
592 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
|
|
593 this.instance.currentItem.remove();
|
|
594 if(this.instance.placeholder) this.instance.placeholder.remove();
|
|
595
|
|
596 inst._trigger("fromSortable", event);
|
|
597 inst.dropped = false; //draggable revert needs that
|
|
598 }
|
|
599
|
|
600 };
|
|
601
|
|
602 });
|
|
603
|
|
604 }
|
|
605 });
|
|
606
|
|
607 $.ui.plugin.add("draggable", "cursor", {
|
|
608 start: function(event, ui) {
|
|
609 var t = $('body'), o = $(this).data('draggable').options;
|
|
610 if (t.css("cursor")) o._cursor = t.css("cursor");
|
|
611 t.css("cursor", o.cursor);
|
|
612 },
|
|
613 stop: function(event, ui) {
|
|
614 var o = $(this).data('draggable').options;
|
|
615 if (o._cursor) $('body').css("cursor", o._cursor);
|
|
616 }
|
|
617 });
|
|
618
|
|
619 $.ui.plugin.add("draggable", "iframeFix", {
|
|
620 start: function(event, ui) {
|
|
621 var o = $(this).data('draggable').options;
|
|
622 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
|
|
623 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
|
|
624 .css({
|
|
625 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
|
|
626 position: "absolute", opacity: "0.001", zIndex: 1000
|
|
627 })
|
|
628 .css($(this).offset())
|
|
629 .appendTo("body");
|
|
630 });
|
|
631 },
|
|
632 stop: function(event, ui) {
|
|
633 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
|
|
634 }
|
|
635 });
|
|
636
|
|
637 $.ui.plugin.add("draggable", "opacity", {
|
|
638 start: function(event, ui) {
|
|
639 var t = $(ui.helper), o = $(this).data('draggable').options;
|
|
640 if(t.css("opacity")) o._opacity = t.css("opacity");
|
|
641 t.css('opacity', o.opacity);
|
|
642 },
|
|
643 stop: function(event, ui) {
|
|
644 var o = $(this).data('draggable').options;
|
|
645 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
|
|
646 }
|
|
647 });
|
|
648
|
|
649 $.ui.plugin.add("draggable", "scroll", {
|
|
650 start: function(event, ui) {
|
|
651 var i = $(this).data("draggable");
|
|
652 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
|
|
653 },
|
|
654 drag: function(event, ui) {
|
|
655
|
|
656 var i = $(this).data("draggable"), o = i.options, scrolled = false;
|
|
657
|
|
658 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
|
|
659
|
|
660 if(!o.axis || o.axis != 'x') {
|
|
661 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
|
662 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
|
|
663 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
|
|
664 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
|
|
665 }
|
|
666
|
|
667 if(!o.axis || o.axis != 'y') {
|
|
668 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
|
669 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
|
|
670 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
|
|
671 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
|
|
672 }
|
|
673
|
|
674 } else {
|
|
675
|
|
676 if(!o.axis || o.axis != 'x') {
|
|
677 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
|
|
678 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
|
|
679 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
|
|
680 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
|
|
681 }
|
|
682
|
|
683 if(!o.axis || o.axis != 'y') {
|
|
684 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
|
|
685 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
|
|
686 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
|
|
687 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
|
|
688 }
|
|
689
|
|
690 }
|
|
691
|
|
692 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
|
|
693 $.ui.ddmanager.prepareOffsets(i, event);
|
|
694
|
|
695 }
|
|
696 });
|
|
697
|
|
698 $.ui.plugin.add("draggable", "snap", {
|
|
699 start: function(event, ui) {
|
|
700
|
|
701 var i = $(this).data("draggable"), o = i.options;
|
|
702 i.snapElements = [];
|
|
703
|
|
704 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
|
|
705 var $t = $(this); var $o = $t.offset();
|
|
706 if(this != i.element[0]) i.snapElements.push({
|
|
707 item: this,
|
|
708 width: $t.outerWidth(), height: $t.outerHeight(),
|
|
709 top: $o.top, left: $o.left
|
|
710 });
|
|
711 });
|
|
712
|
|
713 },
|
|
714 drag: function(event, ui) {
|
|
715
|
|
716 var inst = $(this).data("draggable"), o = inst.options;
|
|
717 var d = o.snapTolerance;
|
|
718
|
|
719 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
|
|
720 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
|
|
721
|
|
722 for (var i = inst.snapElements.length - 1; i >= 0; i--){
|
|
723
|
|
724 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
|
|
725 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
|
|
726
|
|
727 //Yes, I know, this is insane ;)
|
|
728 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
|
|
729 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
|
|
730 inst.snapElements[i].snapping = false;
|
|
731 continue;
|
|
732 }
|
|
733
|
|
734 if(o.snapMode != 'inner') {
|
|
735 var ts = Math.abs(t - y2) <= d;
|
|
736 var bs = Math.abs(b - y1) <= d;
|
|
737 var ls = Math.abs(l - x2) <= d;
|
|
738 var rs = Math.abs(r - x1) <= d;
|
|
739 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
|
|
740 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
|
|
741 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
|
|
742 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
|
|
743 }
|
|
744
|
|
745 var first = (ts || bs || ls || rs);
|
|
746
|
|
747 if(o.snapMode != 'outer') {
|
|
748 var ts = Math.abs(t - y1) <= d;
|
|
749 var bs = Math.abs(b - y2) <= d;
|
|
750 var ls = Math.abs(l - x1) <= d;
|
|
751 var rs = Math.abs(r - x2) <= d;
|
|
752 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
|
|
753 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
|
|
754 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
|
|
755 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
|
|
756 }
|
|
757
|
|
758 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
|
|
759 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
|
|
760 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
|
|
761
|
|
762 };
|
|
763
|
|
764 }
|
|
765 });
|
|
766
|
|
767 $.ui.plugin.add("draggable", "stack", {
|
|
768 start: function(event, ui) {
|
|
769
|
|
770 var o = $(this).data("draggable").options;
|
|
771
|
|
772 var group = $.makeArray($(o.stack)).sort(function(a,b) {
|
|
773 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
|
|
774 });
|
|
775 if (!group.length) { return; }
|
|
776
|
|
777 var min = parseInt(group[0].style.zIndex) || 0;
|
|
778 $(group).each(function(i) {
|
|
779 this.style.zIndex = min + i;
|
|
780 });
|
|
781
|
|
782 this[0].style.zIndex = min + group.length;
|
|
783
|
|
784 }
|
|
785 });
|
|
786
|
|
787 $.ui.plugin.add("draggable", "zIndex", {
|
|
788 start: function(event, ui) {
|
|
789 var t = $(ui.helper), o = $(this).data("draggable").options;
|
|
790 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
|
|
791 t.css('zIndex', o.zIndex);
|
|
792 },
|
|
793 stop: function(event, ui) {
|
|
794 var o = $(this).data("draggable").options;
|
|
795 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
|
|
796 }
|
|
797 });
|
|
798
|
|
799 })(jQuery);
|