jQuery拖放/放置范围问题

jas*_*own 3 javascript jquery jquery-ui

请参阅jsbin上的代码.我基本上试图创建一系列开关.每个填充的红色方块都可以上下拖动.底部的红色轮廓是掉落区域.当一个正方形被拖过一个有资格接受它的放置区时,放置区应该变成粉红色.

这段代码有两个问题.一个是当肘节的运动被约束到y轴时,它们仍然可以掉落在任何下落区域上.单击并拖动一个切换按钮并在底行周围滑动,即使切换保持原位,您也会看到拖放区变为粉红色.

这导致了第二个问题.为了解决这个问题,我尝试使用范围选项,该选项对拖放进行分组.拖动只能放在具有相同范围的放置区域上.在上面的示例中,添加范围的行已注释掉.每次拖放的范围都是"默认".

如果取消注释这两行(如果您是jsbin的新用户,请单击右上角的选项卡,然后在更改后单击预览)您将看到不是将每个拖动限制为一个放置区域,而是将它们放下任何掉落区.回调函数永远不会触发.

为方便起见,这里是示例的javascript部分:

$(document).ready( function() {
    var draggables = $('div.dragMe'),
    droppables = $('div.dropMe');

    draggables.draggable(
    {
        axis: 'y',
        containment: 'parent'
    });

    droppables.droppable(
    {
        hoverClass: 'dropped',
        drop: dropCallBack
    });

    draggables.each(function(index) {
        //$(this).draggable('option', 'scope', ''+index);
        //droppables.eq(index).droppable('option', 'scope', ''+index);

        $(this).text( $(this).draggable('option', 'scope') )
        droppables.eq(index).text( droppables.eq(index).droppable('option', 'scope') );
    });

    function dropCallBack(e, ui) {
        alert('Dropped!');
    }
});
Run Code Online (Sandbox Code Playgroud)

Sim*_*olt 9

scope通过选项功能设置droppable的选项时,jQuery中存在一个错误.jQuery维护一个包含所有已注册sortables的数组(S现在让我们调用它),其中每个键都是一个特定的范围.将可拖动元素放入droppable时,jQuery会检查draggable的scope属性,并检查是否存在您尝试拖入的droppable S[scope].如果不是,则意味着您要投入的可投放的范围与可拖动的范围不同.

问题是,当您通过执行更改范围选项时.droppable('option', 'scope', ...),S不会更新该数组.其他所有内容(据我所知)都正确更新(实际jQuery对象的选项属性等),导致在获取范围选项时返回"正确"结果.droppable('option', 'scope').

我发现其他几个人有同样的问题并且没有解决方案出现,当我搜索解决方案("jquery droppable scope option")时出现了这个问题,所以我认为在修复之前提供临时解决方案可能很有用.我做了一个扩展函数,关于可能与其他选项冲突的测试不是很好,但至少它是一个开始.$.ui.ddmanager.droppables是我S之前调用的数组.

jQuery.fn.extend({

    setDroppableScope: function(scope) {
        return this.each(function() {
            var currentScope = $(this).droppable("option","scope");
            if (typeof currentScope == "object" && currentScope[0] == this) return true; //continue if this is not droppable

            //Remove from current scope and add to new scope
            var i, droppableArrayObject;
            for(i = 0; i < $.ui.ddmanager.droppables[currentScope].length; i++) {
                var ui_element = $.ui.ddmanager.droppables[currentScope][i].element[0];

                if (this == ui_element) {
                    //Remove from old scope position in jQuery's internal array
                    droppableArrayObject = $.ui.ddmanager.droppables[currentScope].splice(i,1)[0];
                    //Add to new scope
                    $.ui.ddmanager.droppables[scope] = $.ui.ddmanager.droppables[scope] || [];
                    $.ui.ddmanager.droppables[scope].push(droppableArrayObject);
                    //Update the original way via jQuery
                    $(this).droppable("option","scope",scope);
                    break;
                }
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

那么你的例子就像

draggables.each(function(index) {
    $(this).draggable('option', 'scope', ''+index);
    droppables.eq(index).setDroppableScope(''+index);

    $(this).text( $(this).draggable('option', 'scope') )
    droppables.eq(index).text( droppables.eq(index).droppable('option', 'scope') );
});
Run Code Online (Sandbox Code Playgroud)

这是更新的jsbin