我有一个相当长的div列表,我试图将其用作droppable - 但我想隐藏所有不接受当前可拖动元素的droppable。
举了一个例子基本上,如果我拖动'Drag A'元素,它将隐藏所有'Droppable B'元素,并允许我放到正确的元素上,这很有效。
但是,如果我拖动'Drag B'元素,它将隐藏所有'Droppable A'元素,但剩余的拖放区域不接受我的可拖动项目。如果我将项目放在'Droppable B'元素的原始位置,则它会正确地下降(即使元素的位置已移动)。如果我使用“visibility:hidden;”而不是“display:none”,这也可以在元素不移动时起作用。
我希望这是有道理的 - 似乎可放置区域设置为元素的原始位置....有什么方法可以解决这个问题吗?
.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');
}
});
});
});
提前致谢!
答案 0 :(得分:3)
问题在于隐藏不活动的droppable会更改元素流和活动的元素位置。当您的延迟事件触发时,jQuery UI已经缓存了绝对可放置的位置,这就是当您按下鼠标按钮时所检查的位置。在原始示例中,如果您将B
拖放到B
下拉区域的旧位置,您仍然可以放弃refreshPositions: true
。
快速简便的解决方案是告诉jQuery UI使用draggable上的setTimeout()
选项重新计算每个mousemove上的droppable位置。来自documentation:
refreshPositions :布尔值
如果设置为true,则全部可放置 每个人都计算职位 鼠标移动。注意:这解决了问题 在高度动态的页面上,但是 大大降低了性能。
您更新了演示:http://jsfiddle.net/N3uh3/1/
这是一个快速修复,但我的建议是在隐藏项目时构建自己的逻辑,而不是依赖mousedown
,这会在隐藏您的droppable之前增加一个明显的烦人延迟。
由于只显示了droppables,我会在jQuery UI之前添加我的隐藏逻辑,甚至有可能建立一个接受droppables的列表,比如项目上的{{1}}事件。然后你可以做自己的自定义代码来隐藏不需要的droppables,所以当谈到缓存位置时,它们是正确的,并且不需要刷新每个mousemove上的缓存,这可能是一个昂贵的操作,取决于数量你有可放置的。