7

我正在尝试创建多个彼此相邻的 jquery droppables,其中某些部分可能重叠,在这些情况下,我希望顶部的那个(z-index 明智)是贪婪的。

我尝试greedy: true在 droppable 中设置选项,但这似乎没有帮助。我也尝试过return falsedrop 事件并使用event.stopPropagation();.

这是一个基于jquery演示页面的jsfiddle

如果有另一个 droppable 触发它,是否有任何方法可以阻止 drop 事件传播,最好是具有最高 z-index 的那个?

4

5 回答 5

7

用于document.elementFromPoint检查光标正下方的元素。如果它不是你的 droppable,请不要做任何事情。将以下内容添加到处理程序的顶部drop:

var droppable = $(this);
ui.helper.css({pointerEvents: 'none'});
var onto = document.elementFromPoint(event.clientX, event.clientY);
ui.helper.css({pointerEvents: ''});
if(!droppable.is(onto) && droppable.has(onto).length === 0) {
    return;
}

禁用助手上的指针事件对于document.elementFromPoint忽略您拖动的内容并仅在下方检查是必要的。我已经更新了您的 jsFiddle 以进行快速演示。请注意,突出显示仍然会影响这两个元素。您应该能够通过不让 jQuery UI 进行突出显示来改变这一点,而是自己在 draggablesdrag:事件中编写它。然而,我发现这在实践中是不可用的,因为这个检查(和禁用指针事件)非常慢并且还可能导致闪烁。

于 2013-02-06T12:01:48.410 回答
2

您需要一个函数来检查元素是否是最高可见元素。某些东西是最高可见的,当

  1. 该项目在 dom 列表中的后面
  2. 它具有更高的 z-index 集

下面的函数可用于查看当前元素(在可放置设置中的 over 方法或 drop 方法中)是否实际上是最高可见元素。

function isHighestVisible(cEl) {
    cEl = $(this); //use this if you want to use it in the over method for draggable, else just pass it to the method

    //get all active droppable elements, based on the classes you provided
    var $list = $('.ui-widget-header.ui-state-active');
    var listCount = $list.length;
    var HighestEl = null;
    var HighestZI = -1;


    //one element is always highest.
    if (listCount<=1) {
        console.log(cEl.attr('id'));
        return true;
    }

    //check each element
    $list.each(function(i) {
        var $el = $(this);

        var id = $el.attr('id');

        //try to parse the z-index. If its 'auto', return 0.

        var zi = isNaN(parseInt($el.css('z-index'))) ? 0 : parseInt($el.css('z-index'));

        if (zi>0) {
            //z-index is set, use it.
            //I add the listCount to prevent errors when a low z-index is used (eg z-index=1) and there are multiple elements.
            //Adding the listCount assures that elements with a z-index are always later in the list then elements without it.
            zi = zi + listCount;
        } else {
            //z-index is not set, check for z-index on parents
            $el.parents().each(function() {
                $par = $(this);
                var ziParent = isNaN(parseInt($par.css('z-index'))) ? 0 : parseInt($par.css('z-index'));
                if (ziParent>0) {
                    zi = ziParent;
                    return false;
                }
            });
        }

        //add the current index of the element to the zi
        zi += i;

        //if the calculated z-index is highest, change the highest element.
        if (HighestEl==null || HighestZI<zi) {
            HighestEl=$el;
            HighestZI = zi;
        }
    });

    //if the highest found active element, return true;
    if (HighestEl.attr('id')==cEl.attr('id')) {
        console.log(cEl.attr('id'));
        return true;
    }

    //if all else fails, return false
    return false;
}
于 2012-11-27T15:59:22.743 回答
0

如果我有这个问题,我会使用 jQuery 的 .addclass

.droppablewidgetforce {
z-index: 1000 !important; 
}

制作一个这样的类,以便无论如何该层都保持在顶部..这应该可以解决问题。

于 2012-10-04T09:41:30.753 回答
0

贪婪选项仅适用于具有可放置父级的嵌套元素。

在您的代码中,2 个可放置元素是兄弟元素,因此贪婪选项将不起作用:

<div id="droppable3" class="ui-widget-header">
    <p>Outer droppable</p>
</div>
<div id="droppable3-inner" class="ui-widget-header">
    <p>Inner droppable (greedy)</p>
</div>

如果您仍然想使用兄弟姐妹而不是父母和孩子,这是一个混乱的解决方法。

实时代码示例

function normalDraggedOver() {
    $( this ).addClass( "ui-state-highlight" )
             .find( "> p" )
             .html( "Droppeeeed!" );
}

var options = {
    activeClass: "ui-state-hover",
    hoverClass: "ui-state-active",
    greedy: true,
    drop: normalDraggedOver
};

var options2 = {
    activeClass: "ui-state-hover",
    hoverClass: "ui-state-active",
    disabledClass: "ui-state-disabled",
    hoverStateClass: "ui-state-hover",
    greedy: true,
    greedyWithSibligs: true,
    drop: normalDraggedOver,
    over: function () {
    /* if we have previous siblings of the inner element we handle them as parents */
        if(options2.greedyWithSibligs && $(this).prev().length > 0) {       
            $(this).siblings().slice(0, $(this).index())
            .removeClass(options2.hoverClass)
            .droppable('disable')
            .removeClass(options2.disabledClass)
            .removeClass(options2.hoverStateClass);
        }
    },
    out: function () {
    /* all the siblings of the inner element that were handled as parents act as one*/
        if(options2.greedyWithSibligs && $(this).prev().length > 0) {
            $(this).siblings().slice(0, $(this).index())
            .droppable('enable')
            .addClass(options2.hoverClass);
            console.log($(this).attr('id'));
        }
    }
};
于 2012-11-26T23:52:59.537 回答
0

如果只是希望它看起来相同,您可以将 #droppable3 设置为 position: relative 并将子 #droppable3-inner 设置为 position: absolute。

HTML:

<div id="droppable3" class="ui-widget-header">
    <p>Outer droppable</p>
</div>
<div id="droppable3-inner" class="ui-widget-header">
    <p>Inner droppable (greedy)</p>
</div>

这是现场示例

于 2012-11-27T06:23:15.333 回答