r2999 commited - sortable: fixed issues with nested containers (fixes #4703,#4611, than...

r2999 commited - sortable: fixed issues with nested containers (fixes #4703,#4611, than...


Revision: 2999
Author: paul.bakaus
Date: Mon Jul 27 22:50:23 2009
Log: sortable: fixed issues with nested containers (fixes #4703,#4611,
thanks kae!)
http://code.google.com/p/jquery-ui/source/detail?r=2999
Modified:
/trunk/ui/ui.sortable.js
=======================================
--- /trunk/ui/ui.sortable.js    Tue Jul 7 03:41:42 2009
+++ /trunk/ui/ui.sortable.js    Mon Jul 27 22:50:23 2009
@@ -258,6 +258,7 @@
                &&    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)
+                //&& itemElement.parentNode == this.placeholder[0].parentNode // only
rearrange items within the same container
            ) {
                this.direction = intersection == 1 ? "down" : "up";
@@ -640,47 +641,68 @@
    },
    _contactContainers: function(event) {
+
+        // 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]))
+                continue;
+
            if(this._intersectsWith(this.containers[i].containerCache)) {
-                if(!this.containers[i].containerCache.over) {
-
-                    if(this.currentContainer != this.containers[i]) {
-
-                        //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[i].floating ? 'left' : 'top'];
-                        for (var j = this.items.length - 1; j >= 0; j--) {
-                            if(!$.ui.contains(this.containers[i].element[0],
this.items[j].item[0])) continue;
-                            var cur =
this.items[j][this.containers[i].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
-                            continue;
-
-                        this.currentContainer = this.containers[i];
-                        itemWithLeastDistance ? this._rearrange(event,
itemWithLeastDistance, null, true) : this._rearrange(event, null,
this.containers[i].element, true);
-                        this._trigger("change", event, this._uiHash());
-                        this.containers[i]._trigger("change", event, this._uiHash(this));
-
-                        //Update the placeholder
-                        this.options.placeholder.update(this.currentContainer,
this.placeholder);
-
-                    }
-
-                    this.containers[i]._trigger("over", event, this._uiHash(this));
-                    this.containers[i].containerCache.over = 1;
-                }
+
+                // 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]))
+                    continue;
+
+                innermostContainer = this.containers[i];
+                innermostIndex = i;
+
            } else {
+                // 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;
                }
            }
-        };
+        }
+
+        // if no intersecting containers found, return
+        if(!innermostContainer) return;
+
+        // move the item into the container if it's not there already
+        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));
+        this.containers[innermostIndex].containerCache.over = 1;
+
    },
    _createHelper: function(event) {