创建多个可放置的兄弟姐妹,它们位于彼此的顶部

时间:2012-10-04 09:36:57

标签: javascript jquery jquery-ui jquery-droppable

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

我已尝试在droppable中设置greedy: true选项,但这似乎没有帮助。我还尝试在drop事件上return false并使用了event.stopPropagation();

以下是基于jquery的jsfiddledemo page

有没有办法阻止drop事件传播,如果有另一个droppable触发它,最好是具有最高z-index的那个?

5 个答案:

答案 0 :(得分:7)

使用document.elementFromPoint直接检查光标下的元素。如果不是你的辍学,不要做任何事情。 将以下内容添加到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忽略拖动的东西,只检查下面的内容。我已updated你的jsFiddle进行快速演示。请注意,突出显示仍会影响这两个元素。您应该能够通过不让jQuery UI进行突出显示来改变它,而是在draggables drag:事件上自己编写。但是,我发现这在实践中无法使用,因为此检查(和禁用指针事件)非常慢并且还可能导致闪烁。

答案 1 :(得分:2)

您需要一个函数来检查元素是否是最高的可见元素。

时可以看到最高的东西
  1. 该项目稍后在dom列表中
  2. 它具有更高的z-index集
  3. 以下函数可用于查看当前元素(在droppable设置中的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;
    }
    

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

在你的代码中,2个droppable元素是兄弟姐妹,所以贪婪的选项不起作用:

<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>

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

实时代码example

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'));
        }
    }
};

答案 4 :(得分:0)

如果只是希望它看起来一样,你可以将#droppable3设置为position:relative并将child#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>

这是实时example