]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - resources/lib/jquery.ui/jquery.ui.sortable.js
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / resources / lib / jquery.ui / jquery.ui.sortable.js
similarity index 79%
rename from resources/jquery.ui/jquery.ui.sortable.js
rename to resources/lib/jquery.ui/jquery.ui.sortable.js
index fe9898e066b04490633fde9227907060fa750a52..bd960df3eaf94e221e82d44f7f5c53a16faee92f 100644 (file)
@@ -1,21 +1,24 @@
-/*
- * jQuery UI Sortable 1.8.2
+/*!
+ * jQuery UI Sortable 1.9.2
+ * http://jqueryui.com
  *
- * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
  *
- * http://docs.jquery.com/UI/Sortables
+ * http://api.jqueryui.com/sortable/
  *
  * Depends:
  *     jquery.ui.core.js
  *     jquery.ui.mouse.js
  *     jquery.ui.widget.js
  */
-(function($) {
+(function( $, undefined ) {
 
 $.widget("ui.sortable", $.ui.mouse, {
+       version: "1.9.2",
        widgetEventPrefix: "sort",
+       ready: false,
        options: {
                appendTo: "parent",
                axis: false,
@@ -49,8 +52,8 @@ $.widget("ui.sortable", $.ui.mouse, {
                //Get the items
                this.refresh();
 
-               //Let's determine if the items are floating
-               this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
+               //Let's determine if the items are being displayed horizontally
+               this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
 
                //Let's determine the parent's offset
                this.offset = this.element.offset();
@@ -58,17 +61,18 @@ $.widget("ui.sortable", $.ui.mouse, {
                //Initialize mouse events for interaction
                this._mouseInit();
 
+               //We're ready to go
+               this.ready = true
+
        },
 
-       destroy: function() {
+       _destroy: function() {
                this.element
-                       .removeClass("ui-sortable ui-sortable-disabled")
-                       .removeData("sortable")
-                       .unbind(".sortable");
+                       .removeClass("ui-sortable ui-sortable-disabled");
                this._mouseDestroy();
 
                for ( var i = this.items.length - 1; i >= 0; i-- )
-                       this.items[i].item.removeData("sortable-item");
+                       this.items[i].item.removeData(this.widgetName + "-item");
 
                return this;
        },
@@ -76,9 +80,8 @@ $.widget("ui.sortable", $.ui.mouse, {
        _setOption: function(key, value){
                if ( key === "disabled" ) {
                        this.options[ key ] = value;
-       
-                       this.widget()
-                               [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
+
+                       this.widget().toggleClass( "ui-sortable-disabled", !!value );
                } else {
                        // Don't call widget base _setOption for disable as it adds ui-state-disabled class
                        $.Widget.prototype._setOption.apply(this, arguments);
@@ -86,6 +89,7 @@ $.widget("ui.sortable", $.ui.mouse, {
        },
 
        _mouseCapture: function(event, overrideHandle) {
+               var that = this;
 
                if (this.reverting) {
                        return false;
@@ -97,13 +101,13 @@ $.widget("ui.sortable", $.ui.mouse, {
                this._refreshItems(event);
 
                //Find out if the clicked node (or one of its parents) is a actual item in this.items
-               var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
-                       if($.data(this, 'sortable-item') == self) {
+               var currentItem = null, nodes = $(event.target).parents().each(function() {
+                       if($.data(this, that.widgetName + '-item') == that) {
                                currentItem = $(this);
                                return false;
                        }
                });
-               if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
+               if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);
 
                if(!currentItem) return false;
                if(this.options.handle && !overrideHandle) {
@@ -121,7 +125,7 @@ $.widget("ui.sortable", $.ui.mouse, {
 
        _mouseStart: function(event, overrideHandle, noActivation) {
 
-               var o = this.options, self = this;
+               var o = this.options;
                this.currentContainer = this;
 
                //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
@@ -151,11 +155,6 @@ $.widget("ui.sortable", $.ui.mouse, {
                        left: this.offset.left - this.margins.left
                };
 
-               // Only after we got the offset, we can change the helper's position to absolute
-               // TODO: Still need to figure out a way to make relative sorting possible
-               this.helper.css("position", "absolute");
-               this.cssPosition = this.helper.css("position");
-
                $.extend(this.offset, {
                        click: { //Where the click happened, relative to the element
                                left: event.pageX - this.offset.left,
@@ -165,6 +164,11 @@ $.widget("ui.sortable", $.ui.mouse, {
                        relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
                });
 
+               // Only after we got the offset, we can change the helper's position to absolute
+               // TODO: Still need to figure out a way to make relative sorting possible
+               this.helper.css("position", "absolute");
+               this.cssPosition = this.helper.css("position");
+
                //Generate the original position
                this.originalPosition = this._generatePosition(event);
                this.originalPageX = event.pageX;
@@ -217,7 +221,7 @@ $.widget("ui.sortable", $.ui.mouse, {
 
                //Post 'activate' events to possible containers
                if(!noActivation) {
-                        for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
+                        for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); }
                }
 
                //Prepare possible droppables
@@ -292,10 +296,19 @@ $.widget("ui.sortable", $.ui.mouse, {
                        var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
                        if (!intersection) continue;
 
-                       if(itemElement != this.currentItem[0] //cannot intersect with itself
+                       // Only put the placeholder inside the current Container, skip all
+                       // items form other containers. This works because when moving
+                       // an item from one container to another the
+                       // currentContainer is switched before the placeholder is moved.
+                       //
+                       // Without this moving items in "sub-sortables" can cause the placeholder to jitter
+                       // beetween the outer and inner container.
+                       if (item.instance !== this.currentContainer) continue;
+
+                       if (itemElement != this.currentItem[0] //cannot intersect with itself
                                &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
-                               &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
-                               && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
+                               &&      !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
+                               && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
                                //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
                        ) {
 
@@ -335,16 +348,16 @@ $.widget("ui.sortable", $.ui.mouse, {
                        $.ui.ddmanager.drop(this, event);
 
                if(this.options.revert) {
-                       var self = this;
-                       var cur = self.placeholder.offset();
+                       var that = this;
+                       var cur = this.placeholder.offset();
 
-                       self.reverting = true;
+                       this.reverting = true;
 
                        $(this.helper).animate({
-                               left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
-                               top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
+                               left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
+                               top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
                        }, parseInt(this.options.revert, 10) || 500, function() {
-                               self._clear(event);
+                               that._clear(event);
                        });
                } else {
                        this._clear(event, noPropagation);
@@ -356,11 +369,9 @@ $.widget("ui.sortable", $.ui.mouse, {
 
        cancel: function() {
 
-               var self = this;
-
                if(this.dragging) {
 
-                       this._mouseUp();
+                       this._mouseUp({ target: null });
 
                        if(this.options.helper == "original")
                                this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
@@ -369,30 +380,32 @@ $.widget("ui.sortable", $.ui.mouse, {
 
                        //Post deactivating events to containers
                        for (var i = this.containers.length - 1; i >= 0; i--){
-                               this.containers[i]._trigger("deactivate", null, self._uiHash(this));
+                               this.containers[i]._trigger("deactivate", null, this._uiHash(this));
                                if(this.containers[i].containerCache.over) {
-                                       this.containers[i]._trigger("out", null, self._uiHash(this));
+                                       this.containers[i]._trigger("out", null, this._uiHash(this));
                                        this.containers[i].containerCache.over = 0;
                                }
                        }
 
                }
 
-               //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
-               if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
-               if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
-
-               $.extend(this, {
-                       helper: null,
-                       dragging: false,
-                       reverting: false,
-                       _noFinalSort: null
-               });
+               if (this.placeholder) {
+                       //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+                       if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+                       if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
 
-               if(this.domPosition.prev) {
-                       $(this.domPosition.prev).after(this.currentItem);
-               } else {
-                       $(this.domPosition.parent).prepend(this.currentItem);
+                       $.extend(this, {
+                               helper: null,
+                               dragging: false,
+                               reverting: false,
+                               _noFinalSort: null
+                       });
+
+                       if(this.domPosition.prev) {
+                               $(this.domPosition.prev).after(this.currentItem);
+                       } else {
+                               $(this.domPosition.parent).prepend(this.currentItem);
+                       }
                }
 
                return this;
@@ -409,6 +422,10 @@ $.widget("ui.sortable", $.ui.mouse, {
                        if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
                });
 
+               if(!str.length && o.key) {
+                       str.push(o.key + '=');
+               }
+
                return str.join('&');
 
        },
@@ -458,8 +475,8 @@ $.widget("ui.sortable", $.ui.mouse, {
 
        _intersectsWithPointer: function(item) {
 
-               var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
-                       isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
+               var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+                       isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
                        isOverElement = isOverElementHeight && isOverElementWidth,
                        verticalDirection = this._getDragVerticalDirection(),
                        horizontalDirection = this._getDragHorizontalDirection();
@@ -510,10 +527,9 @@ $.widget("ui.sortable", $.ui.mouse, {
                        ? [options.connectWith]
                        : options.connectWith;
        },
-       
+
        _getItemsAsjQuery: function(connected) {
 
-               var self = this;
                var items = [];
                var queries = [];
                var connectWith = this._connectWith();
@@ -522,7 +538,7 @@ $.widget("ui.sortable", $.ui.mouse, {
                        for (var i = connectWith.length - 1; i >= 0; i--){
                                var cur = $(connectWith[i]);
                                for (var j = cur.length - 1; j >= 0; j--){
-                                       var inst = $.data(cur[j], 'sortable');
+                                       var inst = $.data(cur[j], this.widgetName);
                                        if(inst && inst != this && !inst.options.disabled) {
                                                queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
                                        }
@@ -544,16 +560,15 @@ $.widget("ui.sortable", $.ui.mouse, {
 
        _removeCurrentsFromItems: function() {
 
-               var list = this.currentItem.find(":data(sortable-item)");
-
-               for (var i=0; i < this.items.length; i++) {
+               var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
 
+               this.items = $.grep(this.items, function (item) {
                        for (var j=0; j < list.length; j++) {
-                               if(list[j] == this.items[i].item[0])
-                                       this.items.splice(i,1);
+                               if(list[j] == item.item[0])
+                                       return false;
                        };
-
-               };
+                       return true;
+               });
 
        },
 
@@ -562,15 +577,14 @@ $.widget("ui.sortable", $.ui.mouse, {
                this.items = [];
                this.containers = [this];
                var items = this.items;
-               var self = this;
                var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
                var connectWith = this._connectWith();
 
-               if(connectWith) {
+               if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
                        for (var i = connectWith.length - 1; i >= 0; i--){
                                var cur = $(connectWith[i]);
                                for (var j = cur.length - 1; j >= 0; j--){
-                                       var inst = $.data(cur[j], 'sortable');
+                                       var inst = $.data(cur[j], this.widgetName);
                                        if(inst && inst != this && !inst.options.disabled) {
                                                queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
                                                this.containers.push(inst);
@@ -586,7 +600,7 @@ $.widget("ui.sortable", $.ui.mouse, {
                        for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
                                var item = $(_queries[j]);
 
-                               item.data('sortable-item', targetData); // Data for target checking (mouse manager)
+                               item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
 
                                items.push({
                                        item: item,
@@ -609,6 +623,10 @@ $.widget("ui.sortable", $.ui.mouse, {
                for (var i = this.items.length - 1; i >= 0; i--){
                        var item = this.items[i];
 
+                       //We ignore calculating positions of all connected containers when we're not over them
+                       if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
+                               continue;
+
                        var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
 
                        if (!fast) {
@@ -637,16 +655,16 @@ $.widget("ui.sortable", $.ui.mouse, {
        },
 
        _createPlaceholder: function(that) {
-
-               var self = that || this, o = self.options;
+               that = that || this;
+               var o = that.options;
 
                if(!o.placeholder || o.placeholder.constructor == String) {
                        var className = o.placeholder;
                        o.placeholder = {
                                element: function() {
 
-                                       var el = $(document.createElement(self.currentItem[0].nodeName))
-                                               .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
+                                       var el = $(document.createElement(that.currentItem[0].nodeName))
+                                               .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
                                                .removeClass("ui-sortable-helper")[0];
 
                                        if(!className)
@@ -661,46 +679,46 @@ $.widget("ui.sortable", $.ui.mouse, {
                                        if(className && !o.forcePlaceholderSize) return;
 
                                        //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
-                                       if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
-                                       if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
+                                       if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };
+                                       if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };
                                }
                        };
                }
 
                //Create the placeholder
-               self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
+               that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
 
                //Append it after the actual current item
-               self.currentItem.after(self.placeholder);
+               that.currentItem.after(that.placeholder);
 
                //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
-               o.placeholder.update(self, self.placeholder);
+               o.placeholder.update(that, that.placeholder);
 
        },
 
        _contactContainers: function(event) {
-               
-               // get innermost container that intersects with item 
-               var innermostContainer = null, innermostIndex = null;           
-               
-               
+
+               // get innermost container that intersects with item
+               var innermostContainer = null, innermostIndex = null;
+
+
                for (var i = this.containers.length - 1; i >= 0; i--){
 
-                       // never consider a container that's located within the item itself 
-                       if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
+                       // never consider a container that's located within the item itself
+                       if($.contains(this.currentItem[0], this.containers[i].element[0]))
                                continue;
 
                        if(this._intersectsWith(this.containers[i].containerCache)) {
 
-                               // if we've already found a container and it's more "inner" than this, then continue 
-                               if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
+                               // if we've already found a container and it's more "inner" than this, then continue
+                               if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
                                        continue;
 
-                               innermostContainer = this.containers[i]; 
+                               innermostContainer = this.containers[i];
                                innermostIndex = i;
-                                       
+
                        } else {
-                               // container doesn't intersect. trigger "out" event if necessary 
+                               // container doesn't intersect. trigger "out" event if necessary
                                if(this.containers[i].containerCache.over) {
                                        this.containers[i]._trigger("out", event, this._uiHash(this));
                                        this.containers[i].containerCache.over = 0;
@@ -708,42 +726,53 @@ $.widget("ui.sortable", $.ui.mouse, {
                        }
 
                }
-               
-               // if no intersecting containers found, return 
-               if(!innermostContainer) return; 
+
+               // if no intersecting containers found, return
+               if(!innermostContainer) return;
 
                // move the item into the container if it's not there already
                if(this.containers.length === 1) {
                        this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
                        this.containers[innermostIndex].containerCache.over = 1;
-               } else if(this.currentContainer != this.containers[innermostIndex]) { 
-
-                       //When entering a new container, we will find the item with the least distance and append our item near it 
-                       var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
-                       for (var j = this.items.length - 1; j >= 0; j--) { 
-                               if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
-                               var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
-                               if(Math.abs(cur - base) < dist) { 
-                                       dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
-                               } 
-                       } 
-
-                       if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
-                               return; 
-
-                       this.currentContainer = this.containers[innermostIndex]; 
-                       itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
-                       this._trigger("change", event, this._uiHash()); 
-                       this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
-
-                       //Update the placeholder 
-                       this.options.placeholder.update(this.currentContainer, this.placeholder); 
-               
-                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
+               } else {
+
+                       //When entering a new container, we will find the item with the least distance and append our item near it
+                       var dist = 10000; var itemWithLeastDistance = null;
+                       var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top';
+                       var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height';
+                       var base = this.positionAbs[posProperty] + this.offset.click[posProperty];
+                       for (var j = this.items.length - 1; j >= 0; j--) {
+                               if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
+                               if(this.items[j].item[0] == this.currentItem[0]) continue;
+                               var cur = this.items[j].item.offset()[posProperty];
+                               var nearBottom = false;
+                               if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
+                                       nearBottom = true;
+                                       cur += this.items[j][sizeProperty];
+                               }
+
+                               if(Math.abs(cur - base) < dist) {
+                                       dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+                                       this.direction = nearBottom ? "up": "down";
+                               }
+                       }
+
+                       if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+                               return;
+
+                       this.currentContainer = this.containers[innermostIndex];
+                       itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+                       this._trigger("change", event, this._uiHash());
+                       this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+
+                       //Update the placeholder
+                       this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
                        this.containers[innermostIndex].containerCache.over = 1;
-               } 
-       
-               
+               }
+
+
        },
 
        _createHelper: function(event) {
@@ -796,13 +825,13 @@ $.widget("ui.sortable", $.ui.mouse, {
                // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
                // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
                //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
                        po.left += this.scrollParent.scrollLeft();
                        po.top += this.scrollParent.scrollTop();
                }
 
                if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
-               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
                        po = { top: 0, left: 0 };
 
                return {
@@ -870,20 +899,20 @@ $.widget("ui.sortable", $.ui.mouse, {
 
                if(!pos) pos = this.position;
                var mod = d == "absolute" ? 1 : -1;
-               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);
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
 
                return {
                        top: (
                                pos.top                                                                                                                                 // The absolute mouse position
                                + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+                               - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
                        ),
                        left: (
                                pos.left                                                                                                                                // The absolute mouse position
                                + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+                               - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
                        )
                };
 
@@ -891,7 +920,7 @@ $.widget("ui.sortable", $.ui.mouse, {
 
        _generatePosition: function(event) {
 
-               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);
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
 
                // This is another very weird special case that only happens for relative elements:
                // 1. If the css position is relative
@@ -934,14 +963,14 @@ $.widget("ui.sortable", $.ui.mouse, {
                                - this.offset.click.top                                                                                                 // Click offset (relative to the element)
                                - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+                               + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
                        ),
                        left: (
                                pageX                                                                                                                           // The absolute mouse position
                                - this.offset.click.left                                                                                                // Click offset (relative to the element)
                                - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+                               + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
                        )
                };
 
@@ -957,11 +986,11 @@ $.widget("ui.sortable", $.ui.mouse, {
                // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
                // 4. this lets only the last addition to the timeout stack through
                this.counter = this.counter ? ++this.counter : 1;
-               var self = this, counter = this.counter;
+               var counter = this.counter;
 
-               window.setTimeout(function() {
-                       if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
-               },0);
+               this._delay(function() {
+                       if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
+               });
 
        },
 
@@ -970,11 +999,11 @@ $.widget("ui.sortable", $.ui.mouse, {
                this.reverting = false;
                // We delay all events that have to be triggered to after the point where the placeholder has been removed and
                // everything else normalized again
-               var delayedTriggers = [], self = this;
+               var delayedTriggers = [];
 
                // We first have to update the dom position of the actual currentItem
                // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
-               if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
+               if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
                this._noFinalSort = null;
 
                if(this.helper[0] == this.currentItem[0]) {
@@ -988,15 +1017,17 @@ $.widget("ui.sortable", $.ui.mouse, {
 
                if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
                if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
-               if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
-                       if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
-                       for (var i = this.containers.length - 1; i >= 0; i--){
-                               if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
-                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
-                                       delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
-                               }
-                       };
-               };
+
+               // Check if the items Container has Changed and trigger appropriate
+               // events.
+               if (this !== this.currentContainer) {
+                       if(!noPropagation) {
+                               delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+                               delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
+                               delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
+                       }
+               }
+
 
                //Post events to containers
                for (var i = this.containers.length - 1; i >= 0; i--){
@@ -1019,6 +1050,8 @@ $.widget("ui.sortable", $.ui.mouse, {
                                for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
                                this._trigger("stop", event, this._uiHash());
                        }
+
+                       this.fromOutside = false;
                        return false;
                }
 
@@ -1045,23 +1078,19 @@ $.widget("ui.sortable", $.ui.mouse, {
                }
        },
 
-       _uiHash: function(inst) {
-               var self = inst || this;
+       _uiHash: function(_inst) {
+               var inst = _inst || this;
                return {
-                       helper: self.helper,
-                       placeholder: self.placeholder || $([]),
-                       position: self.position,
-                       originalPosition: self.originalPosition,
-                       offset: self.positionAbs,
-                       item: self.currentItem,
-                       sender: inst ? inst.element : null
+                       helper: inst.helper,
+                       placeholder: inst.placeholder || $([]),
+                       position: inst.position,
+                       originalPosition: inst.originalPosition,
+                       offset: inst.positionAbs,
+                       item: inst.currentItem,
+                       sender: _inst ? _inst.element : null
                };
        }
 
 });
 
-$.extend($.ui.sortable, {
-       version: "1.8.2"
-});
-
 })(jQuery);