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