]> source.dussan.org Git - jquery-ui.git/commitdiff
sortable: fixed issues with nested containers (fixes #4703,#4611, thanks kae!)
authorPaul Bakaus <paul.bakaus@googlemail.com>
Tue, 28 Jul 2009 05:50:23 +0000 (05:50 +0000)
committerPaul Bakaus <paul.bakaus@googlemail.com>
Tue, 28 Jul 2009 05:50:23 +0000 (05:50 +0000)
ui/ui.sortable.js

index f2d5dc4ed8f35ff49e2eb5d4f85faa7a0d744796..36e13ae75a69610eb33e4c1ddd2c42732f06804e 100644 (file)
@@ -258,6 +258,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
                                &&      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 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
        },
 
        _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--){
 
-                       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];
-                                                       }
-                                               }
+                       // never consider a container that's located within the item itself 
+                       if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
+                               continue;
 
-                                               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));
+                       if(this._intersectsWith(this.containers[i].containerCache)) {
 
-                                               //Update the placeholder
-                                               this.options.placeholder.update(this.currentContainer, this.placeholder);
+                               // 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;
 
-                                       }
-
-                                       this.containers[i]._trigger("over", event, this._uiHash(this));
-                                       this.containers[i].containerCache.over = 1;
-                               }
+                               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) {