2011-06-02 48 views
2

我有一个很长的div列表,我试图用它作为droppable的 - 但我想隐藏所有不接受当前的拖放可拖动元素。jQuery Droppables - 隐藏'不活动'拖放区域时的问题

我已经把一个例子了在http://jsfiddle.net/N3uh3/

基本上,如果我拖“拖一个”元素,将隐藏所有“可放开B”元素,让我落到正确的元素,这工作得很好。

但是,如果我拖动'拖动B'元素,它将隐藏所有'Droppable A'元素,但其余的拖放区域不接受我的可拖动项目。如果我将物品放在“Droppable B”元素的原始位置,则它会正确下落(即使元素的位置已移动)。如果我使用“可见度:隐藏的”而不是“显示:无”,这也适用于元素不移动。

我希望这是有道理的 - 似乎可以将可投放区域设置为元素的原始位置....是否有解决方法?

.lhs { width: 40%; float:left; } 
.rhs { width: 40%; float:right; } 
.lhs div { margin: 4px; } 
.a { background-color: green; } 
.b { background-color: red; } 
.ui-state-highlight { background-color: yellow; } 
.dropZones .ui-droppable { display: none; } 
.dropZones .ui-state-highlight { display: block; } 
.currentDropZone { display: block; } 

<div class="wrapper"> 
    <div class="lhs"> 
     <div class="a">DROP A</div> 
     <div class="a">DROP A</div> 
     <div class="a">DROP A</div> 
     <div class="a">DROP A</div> 
     <div class="a">DROP A</div> 
     <div class="a">DROP A</div> 
     <div class="b">DROP B</div> 
     <div class="b">DROP B</div> 
     <div class="b">DROP B</div> 
     <div class="b">DROP B</div> 
     <div class="b">DROP B</div> 
     <div class="b">DROP B</div> 
    </div> 
    <div class="rhs"> 
     <div class="a">Drag A</div> 
     <br /> 
     <div class="b">Drag B</div> 
    </div> 
</div> 


$(document).ready(function(){ 
    $('.rhs div').draggable({ 
     helper: function (e,ui) { 
      // this sets the clone to be a child of the body - fixing overflow:auto problems on divs! 
      return $(this).clone().appendTo('body').css('zIndex',5).show(); 
     }, 
     revert: 'invalid', 
     cursor: 'move', 
     start: function(){ 
      //$('.lhs').addClass('dropZones'); // immediately hides so doesn't get the ui-state-highlight class' 

      // give a quick period of time then add the class 
      setTimeout(function() { $('.lhs').addClass('dropZones'); }, 250); 
     }, 
     stop: function(){ 
      $('.lhs').removeClass('dropZones'); 
     }, 
    }); 

    $('.lhs div').each(function(){ 
     $(this).droppable({ 
      greedy: true, 
      activeClass: 'ui-state-highlight', 
      accept: '.' + $(this).attr('class'), 
      drop: function(event, ui) { 
       $(this).append($(ui.draggable).clone()); 
      }, 
      activate: function(){ 
       $(this).addClass('currentDropZone'); 
      }, 
      deactivate: function(){ 
       $(this).removeClass('currentDropZone'); 
      } 

     }); 
    }); 
}); 

在此先感谢!

回答

3

问题是隐藏不活动的droppables会改变活动元素的流动和位置。当你的延迟事件触发时,绝对可丢弃的位置已经被jQuery UI缓存了,这就是你放开鼠标按钮时所检查的内容。在原始示例中,如果将其拖动到B下拉列表的旧位置(即正好位于可见列表下方),仍然可以放下B

一个快速而简单的解决方案是告诉jQuery UI重新计算每个鼠标移动的拖放位置,方法是使用拖动表上的refreshPositions: true选项。从documentation

refreshPositions:布尔

如果设置为true,所有可放开 位置计算出每个 鼠标移动。注意:这可以在高动态页面上解决问题 ,但 会显着降低性能。

您更新演示:http://jsfiddle.net/N3uh3/1/

这是速战速决,但我的建议是隐藏在你的项目的时候,而不是依靠setTimeout(),其中隐藏之前增加了一个明显的恼人的滞后,弥补自己的逻辑你的droppables。

由于只显示了可拖动对象,因此我会在jQuery UI之前添加我的隐藏逻辑,甚至有可能建立一个可接受可拖放对象列表,如项目上的mousedown事件。然后,您可以执行自己的自定义代码来隐藏不需要的可拖放对象,因此,当涉及到缓存位置时,它们将是正确的,并且不需要每次移动鼠标时刷新缓存,这可能是一个昂贵的操作,具体取决于可以放弃的东西。

+0

Cheers DarthJDG。现在像魅力一样工作 - 非常感谢! – Gus 2011-06-03 00:32:01

+0

对于任何有兴趣的人 - 我已经使用达斯的建议更新了jsfiddle - 更好! http://jsfiddle.net/N3uh3/ – Gus 2011-06-03 01:20:38