Correcting type of DatabaseSqlite::insertId()
[mediawiki.git] / resources / jquery.ui / jquery.ui.draggable.js
blob4141ff780905bd3317412fb4887eff9d5ffb9e95
1 /*
2  * jQuery UI Draggable 1.8.18
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 ) {
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() {
47                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
48                         this.element[0].style.position = 'relative';
50                 (this.options.addClasses && this.element.addClass("ui-draggable"));
51                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
53                 this._mouseInit();
55         },
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();
67                 return this;
68         },
70         _mouseCapture: function(event) {
72                 var o = this.options;
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;
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                 }
95                 return true;
97         },
99         _mouseStart: function(event) {
101                 var o = this.options;
103                 //Create and append the visible helper
104                 this.helper = this._createHelper(event);
106                 //Cache the helper size
107                 this._cacheHelperProportions();
109                 //If ddmanager is used for droppables, set the global draggable
110                 if($.ui.ddmanager)
111                         $.ui.ddmanager.current = this;
113                 /*
114                  * - Position generation -
115                  * This block generates everything position related - it's the core of draggables.
116                  */
118                 //Cache the margins of the original element
119                 this._cacheMargins();
121                 //Store the helper's css position
122                 this.cssPosition = this.helper.css("position");
123                 this.scrollParent = this.helper.scrollParent();
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                 };
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                 });
141                 //Generate the original position
142                 this.originalPosition = this.position = this._generatePosition(event);
143                 this.originalPageX = event.pageX;
144                 this.originalPageY = event.pageY;
146                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
147                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
149                 //Set a containment if given in the options
150                 if(o.containment)
151                         this._setContainment();
153                 //Trigger event + callbacks
154                 if(this._trigger("start", event) === false) {
155                         this._clear();
156                         return false;
157                 }
159                 //Recache the helper size
160                 this._cacheHelperProportions();
162                 //Prepare the droppable offsets
163                 if ($.ui.ddmanager && !o.dropBehaviour)
164                         $.ui.ddmanager.prepareOffsets(this, event);
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         },
175         _mouseDrag: function(event, noPropagation) {
177                 //Compute the helpers position
178                 this.position = this._generatePosition(event);
179                 this.positionAbs = this._convertPositionTo("absolute");
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                 }
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);
195                 return false;
196         },
198         _mouseStop: function(event) {
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);
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;
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                 }
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         },
256         _getHandle: function(event) {
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                         });
266                 return handle;
268         },
270         _createHelper: function(event) {
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);
275                 if(!helper.parents('body').length)
276                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
278                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
279                         helper.css("position", "absolute");
281                 return helper;
283         },
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         },
306         _getParentOffset: function() {
308                 //Get the offsetParent and cache its position
309                 this.offsetParent = this.helper.offsetParent();
310                 var po = this.offsetParent.offset();
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                 }
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 };
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                 };
330         },
332         _getRelativeOffset: function() {
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                 }
344         },
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         },
355         _cacheHelperProportions: function() {
356                 this.helperProportions = {
357                         width: this.helper.outerWidth(),
358                         height: this.helper.outerHeight()
359                 };
360         },
362         _setContainment: function() {
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                 ];
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');
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;
387                 } else if(o.containment.constructor == Array) {
388                         this.containment = o.containment;
389                 }
391         },
393         _convertPositionTo: function(d, pos) {
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);
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                 };
414         },
416         _generatePosition: function(event) {
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;
422                 /*
423                  * - Position constraining -
424                  * Constrain the position to a mix of grid, containment.
425                  */
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                                  }
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                         }
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;
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                         }
456                 }
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                 };
475         },
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         },
485         // From now on bulk stuff - mainly helpers
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         },
494         plugins: {},
496         _uiHash: function(event) {
497                 return {
498                         helper: this.helper,
499                         position: this.position,
500                         originalPosition: this.originalPosition,
501                         offset: this.positionAbs
502                 };
503         }
507 $.extend($.ui.draggable, {
508         version: "1.8.18"
511 $.ui.plugin.add("draggable", "connectToSortable", {
512         start: function(event, ui) {
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                 });
529         },
530         stop: function(event, ui) {
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 });
536                 $.each(inst.sortables, function() {
537                         if(this.instance.isOver) {
539                                 this.instance.isOver = 0;
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)
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;
547                                 //Trigger the stop of the sortable
548                                 this.instance._mouseStop(event);
550                                 this.instance.options.helper = this.instance.options._helper;
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' });
556                         } else {
557                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
558                                 this.instance._trigger("deactivate", event, uiSortable);
559                         }
561                 });
563         },
564         drag: function(event, ui) {
566                 var inst = $(this).data("draggable"), self = this;
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;
574                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
575                 };
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)) {
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) {
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]; };
597                                         event.target = this.instance.currentItem[0];
598                                         this.instance._mouseCapture(event, true);
599                                         this.instance._mouseStart(event, true, true);
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;
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;
613                                 }
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);
618                         } else {
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) {
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;
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();
640                                         inst._trigger("fromSortable", event);
641                                         inst.dropped = false; //draggable revert needs that
642                                 }
644                         };
646                 });
648         }
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         }
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         }
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) {
682                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
684                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
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                         }
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                         }
700                 } else {
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                         }
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                         }
716                 }
718                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
719                         $.ui.ddmanager.prepareOffsets(i, event);
721         }
724 $.ui.plugin.add("draggable", "snap", {
725         start: function(event, ui) {
727                 var i = $(this).data("draggable"), o = i.options;
728                 i.snapElements = [];
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                 });
739         },
740         drag: function(event, ui) {
742                 var inst = $(this).data("draggable"), o = inst.options;
743                 var d = o.snapTolerance;
745                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
746                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
748                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
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;
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                         }
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                         }
771                         var first = (ts || bs || ls || rs);
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                         }
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);
788                 };
790         }
793 $.ui.plugin.add("draggable", "stack", {
794         start: function(event, ui) {
796                 var o = $(this).data("draggable").options;
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                 });
808                 this[0].style.zIndex = min + group.length;
810         }
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         }
825 })(jQuery);