具有多个作用域的JQuery UI拖放?

8
我想要几个可拖动的类别,每个类别对应一个可放置的类别。但是,我还想有一个单独的“废纸篓”,所有的可拖动项都可以被丢到里面,直到找到适合它们的可放置项为止。
现在,这可以通过使用 accept 函数轻松实现。然而,我可能会有多达20个类别,每个类别都有30-40个可拖动/可放置的项。因此,如果我为此使用 "accept" 函数,一旦我拿起一个可拖动的项,我的 Chrome 就会冻结,因为它会为屏幕上的每个可放置项运行测试 :(
如果我使用 "scope" 属性,似乎可以解决这个问题,因为它似乎使用了一些不同的方法。然而,当我使用范围时,似乎无法实现 "废纸篓" 概念,因为它只能有一个范围!
是否有办法绕过这个问题?给可拖动的项添加多个作用域,或者给垃圾桶添加多个作用域?或者其他我想不到的解决方案?

1
你好。能否发一些代码让我们看看你已经做了什么? - chrisvillanueva
1个回答

9

当您开始拖动一个 draggable 时,jQuery UI会内部运行以下代码以确定哪些 droppable 可以接收 draggable

var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null; // workaround for #2317
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();

droppablesLoop: for (var i = 0; i < m.length; i++) {

    if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
    for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
    m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                   //If the element is not visible, continue

    if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables

    m[i].offset = m[i].element.offset();
    m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };

}

如你所见,这段代码非常复杂,这也就解释了为什么每次开始拖动都会出现缓慢的表现。
注意,在 droppablesLoop 中检查的第一件事是 droppable 是否已禁用。
因此,为了提高性能,您可以始终手动禁用相应的 droppable 小部件,这将使您快速跳出上面的代码块。可以通过使用 draggable 上的 start 事件来实现这一点,该事件将首先触发。
$('.draggable').draggable({
    start: function() {
        $('.invalid-droppable-elements').droppable('option', 'disabled', true);
    },
    stop: function() {
        $('.invalid-droppable-elements').droppable('option', 'disabled', false);
    }
});

这基本上让你自己实现accept/scope逻辑,并且性能影响取决于你的算法。不过实现起来应该不会太难。插件之所以这么慢,是因为它们必须处理很多不同的情况。
jQuery UI不支持向单个draggable / droppable元素添加多个作用域,但您可以自己开发此功能。
我编写了一个示例,展示在这里-http://jsfiddle.net/tj_vantoll/TgQTP/1/

1
这实际上对性能有很好的影响,但与使用作用域相比仍然非常简洁...我实际上已经禁用了所有可拖动的内容,除了垃圾桶并仅启用我需要的内容。是否没有办法使某些东西属于多个作用域? - Gilthans
1
我编辑了我的回答以回应你的问题。简短的回答是不,jQuery UI不支持多个作用域,但自己实现这个并不难。 - TJ VanToll
这很棒,但对于任何想知道的人来说,.each似乎有一些额外的“复杂性”。除非我错过了什么,否则您可以简单地引用$('.draggable')并将var scope的赋值移动到start - MCB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接