2

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

我在http://jsfiddle.net/N3uh3/上举了一个例子

基本上,如果我拖动“Drag A”元素,它将隐藏所有“Droppable B”元素并允许我拖放到正确的元素上,这很好用。

但是,如果我拖动“拖动 B”元素,它将隐藏所有“可放置 A”元素,但其余放置区域不接受我的可拖动项目。如果我将项目放置在“可放置 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');
            }

        });
    });
});

提前致谢!

4

1 回答 1

3

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

一个快速简单的解决方案是告诉 jQuery UI 通过使用refreshPositions: true可拖动选项上的选项来重新计算每次鼠标移动时的可放置​​位置。从文档中:

refreshPositions : 布尔值

如果设置为 true,则每次鼠标移动都会计算所有可放置位置。警告:这解决了高度动态页面上的问题,但会显着降低性能。

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

这是一个快速修复,但我的建议是在隐藏您的项目而不是依赖 时制定您自己的逻辑setTimeout(),这会在隐藏您的 droppables 之前增加一个明显的恼人延迟。

由于仅显示了可放置对象被激活,我会在 jQuery UI 甚至有机会建立一个接受可放置对象的列表之前添加我的隐藏逻辑,例如mousedown项目上的事件。然后你可以做你自己的自定义代码来隐藏不需要的droppables,所以在缓存位置时,它们是正确的,并且不需要在每次mousemove时刷新缓存,这可能是一项昂贵的操作,具体取决于你有的droppables。

于 2011-06-02T17:16:24.470 回答