2012-10-03 25 views
1

我在容器內部有幾個jQuery排序列表,可以垂直滾動。在這些容器之間拖動時,可以通過拖動容器將其添加到可排序的項目中。考慮下面的html:我該如何防止掉入jQuery的不可見部分sortable

<style> 
     .constrainer { 
      height: 160px; 
      overflow-y: auto; 
      width:280px; 
      border: 1px solid orange; 
     } 
     .sortitem { 
      border: 1px solid #807eba; 
      width: 160px 
      display:inline-block; 
      padding: 10px; 
      margin: 10px; 
      background-color: white; 
     } 
    </style> 

    <div class="constrainer" style="float:left"> 
     <ul class="sortme"> 
      <li class="sortitem">item 1</li> 
      <li class="sortitem">item 2</li> 
      <li class="sortitem">item 3</li> 
      <li class="sortitem">item 4</li> 
      <li class="sortitem">item 5</li> 
      <li class="sortitem">item 6</li> 
     </ul> 
    </div> 
    <div class="constrainer" style="float:right"> 
     <ul class="sortme"> 
      <li class="sortitem">item 1</li> 
      <li class="sortitem">item 2</li> 
      <li class="sortitem">item 3</li> 
      <li class="sortitem">item 4</li> 
      <li class="sortitem">item 5</li> 
      <li class="sortitem">item 6</li> 
     </ul> 
    </div> 

而且下面的腳本:

$('.sortme').sortable({connectWith: '.sortme'}); 

注意,您可以從列表到另一個列表中的一個通過點擊下面的列表中隨意拖動的項目。

我想防止拖到一個被切斷的列表。在我的實際應用中,有一個更爲複雜的DOM結構,所以實際的解決方案需要查找在視圖中可排序的實際區域,並且只允許在該區域中刪除。對於重新排序單個可排序項目也是如此。

這裏是上面的代碼的的jsfiddle: http://jsfiddle.net/PFSsJ/

編輯:澄清

要清楚,我還是想拖項目是可見列表的一部分,只是沒有部分的名單是不可見的。爲了更有趣,將列表垂直排列,這樣jquery ui無法決定將其放在哪一個上,並且像這樣來回閃爍:http://jsfiddle.net/PFSsJ/1/

+0

我相信這是一個錯誤排序將被固定在2.0 – veblock

+0

我可能不理解的問題非常好,但你在想是這樣的:http://jsfiddle.net/W8xHh/1/ –

+0

@ RyanOlds不幸的是,你的編輯不允許項目被丟棄。 –

回答

0

我花了大約兩週的時間處理這個問題的各種解決方案。下面的代碼在我正在構建的應用程序中爲我工作。請注意,它只處理垂直堆疊和垂直滾動的可排序項目。它可能會被修改來處理橫向排序,但是我沒有嘗試,因爲它不適合我的用例。

您可以像使用可排序的那樣使用它,只需$('。ulClass')。boundedSortable();

(function($) { 
$.widget("ui.boundedSortable", $.ui.sortable, { 
    widgetEventPrefix: "sort", 
    _init: function() { 
     this.element.data("sortable", this.element.data("boundedSortable")); 
     return $.ui.sortable.prototype._init.apply(this, arguments); 
    }, 
    _create:function() { 
     var ret = $.ui.sortable.prototype._create.apply(this, arguments); 
     this.containerCache.sortable = this; 
     return ret; 
    }, 
    refreshPositions:function(fast){ 
     $.ui.sortable.prototype.refreshPositions.apply(this, arguments); 
     _.each(this.items, function(item){ 
      var element = item.item[0]; 
      var offset = item.item.offset(); 
      var points = [[offset.left + 1, offset.top + 1], 
          [offset.left + (item.width/2), offset.top + (item.height/2)], 
          [offset.left + item.width - 1, offset.top + 1], 
          [offset.left + item.width - 1, offset.top + item.height - 1]]; 
      item.visible = _.any(points, function(point){ 
       var visibleElement = $.elementFromPoint(point[0], point[1]); 
       if(element === visibleElement || (visibleElement && $.contains(element, visibleElement))){ 
        return true; 
       } 
       return false; 
      }); 
     }, this); 

     _.each(this.containers, function(container){ 
      var parent = container.element; 
      var cache = container.containerCache; 
      while((parent = parent.parent()) && parent.length){ 
       parent = $(parent); 
       var offset = parent.offset(); 
       var parentHeight = parent.height(); 
       if(cache.height > parentHeight){ 
        cache.height = Math.round(parentHeight); 
       } 
       if(offset && cache.top < offset.top){ 
        cache.top = offset.top; 
       } 
      } 
     }, this); 
     return this; 
    }, 
    _intersectsWithPointer: function (item) { 
     var ret = $.ui.sortable.prototype._intersectsWithPointer.apply(this, arguments); 
     if(ret){ 
      if(!item.visible){ 
       return false; 
      } 
     } 
     return ret; 
    }, 
    _clear: function(){ 
     if(!(this.placeholder && this.placeholder[0].parentNode)){ 
      this.placeholder = [{parentNode:{removeChild:function(){}}}]; 
      this.placeholder.before = function(){}; 
     } 
     return $.ui.sortable.prototype._clear.apply(this, arguments); 
    }, 
    _contactContainers: function(event) { 

     /** directly from jQuery source **/ 

     // 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 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; 
       } 
      } 

     } 

     /** end direct copy from jQuery source*/ 

     if(!innermostContainer){ 
      if (this.placeholder) { 
       if(this.placeholder[0].parentNode) { 
        this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 
       } 
      } 
      this.currentContainer = null; 
      return; 
     } 
     return $.ui.sortable.prototype._contactContainers.apply(this, arguments); 
    } 
}); 
})(jQuery); 

(function ($){ 
    var check=false, isRelative=true; 
    $.elementFromPoint = function(x,y) 
    { 
     var elemFromPtFunc = null; 
     if(document.getElementFromPoint){ 
      elemFromPtFunc = _.bind(document.getElementFromPoint, document); 
     }else if(document.elementFromPoint){ 
      elemFromPtFunc = _.bind(document.elementFromPoint, document); 
     } 

     if(!elemFromPtFunc) { 
      console.error('no element from point?'); 
      return null; 
     } 
     var scrollTop = $(document).scrollTop(); 
     var scrollLeft = $(document).scrollLeft(); 
     return elemFromPtFunc(x - scrollLeft,y - scrollTop); 
    }; 
})(jQuery); 
+0

請注意,我在這段代碼中使用了下劃線的一些功能。如果你不使用下劃線js(爲什麼不呢?),那麼你可能需要在幾個地方改變它。 –

相關問題