jQuery Droppables - 隐藏“非活动”放置区时的问题

时间:2011-06-02 16:00:25

标签: jquery css jquery-ui html jquery-ui-droppable

我有一个相当长的div列表,我试图将其用作droppable - 但我想隐藏所有不接受当前可拖动元素的droppable。

我在http://jsfiddle.net/N3uh3/

举了一个例子

基本上,如果我拖动'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');
            }

        });
    });
});

提前致谢!

1 个答案:

答案 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上的缓存,这可能是一个昂贵的操作,取决于数量你有可放置的。