jQueryUI droppable,停止传播到重叠的兄弟

Posted

技术标签:

【中文标题】jQueryUI droppable,停止传播到重叠的兄弟【英文标题】:jQueryUI droppable, stop propagation to overlapped sibling 【发布时间】:2012-08-13 09:16:18 【问题描述】:

如您所见:http://jsfiddle.net/rA4CB/6/

当我在重叠区域中放置它时,它会在两个 droppables 中接收,当项目是兄弟时,贪婪不起作用。有什么办法可以阻止接收 zIndex 较低的 droppables 吗?

顺便说一句,mouseOver 不会为可放置元素触发,因为鼠标实际上是在可拖动元素上方。

相关JS:

$(function() 
    $( "#draggable" ).draggable();
    $( "#droppable" ).droppable(
        tolerance:'pointer',
        drop: function( event, ui ) 
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        
    );
    $( "#droppable2" ).droppable(
        tolerance:'pointer',
        greedy:true,
        drop: function( event, ui ) 
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        
    );
);

【问题讨论】:

【参考方案1】:

好的,所以我花了一个小时试图弄清楚,然后我一问就找到答案

http://jsfiddle.net/rA4CB/7/

将JS修改为:

$(function() 
    $( "#draggable" ).draggable();
    $( "#droppable" ).droppable(
        tolerance:'pointer',
        drop: function( event, ui ) 
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        
    );
    $( "#droppable2" ).droppable(
        tolerance:'pointer',
        greedy:true,
        drop: function( event, ui ) 
            $( this )
                .addClass( "ui-state-highlight" )
                .find( "p" )
                    .html( "Dropped!" );
        ,
        over: function(event, ui)
            $( "#droppable" ).droppable( "disable" )
        ,
        out: function(event, ui)
            $( "#droppable" ).droppable( "enable" )
        
    );
);

【讨论】:

聪明 - 花了我一段时间看看你在那里做了什么:-)。过度/禁用和退出/启用是赢家。谢谢 不错的技巧,但不适用于兄弟姐妹的数量。所以请参阅我上面对这个问题的回答。 您知道如何使重叠区域不可删除吗? 如果drop 被调用,则out 不会被调用,因此在删除后#droppable 将保持禁用状态。我已将 drop 更改为以与 out 相同的方式重新启用,并且在 1.8 中有效,但在 1.11 中它会导致传播再次发生。 好吧,上面的评论并不完全正确......它大部分时间都有效,但在某些特殊情况下,我无法完全弄清楚它不再有效。在这些情况下,第二个“drop”处理程序在第一次重新启用然后完成时被调用。【参考方案2】:
$( "#droppable" ).droppable(
    greedy: true,
    drop: function( event, ui ) 
       if(ui.helper.is(".dropped")) 
           return false;
       
       ui.helper.addClass(".dropped");
    
);

只需在可拖动的 ui.helper 上设置一个 css 类。如果draggable 被接受过一次,它将被所有其他droppables 拒绝(也可以使用droppable "accept" 参数来完成,例如accept : ":not(.dropped)" 和添加到ui.draggable 的类)。

【讨论】:

这应该是被接受的答案。唯一的问题是您需要从 addClass 调用中删除句点: addClass("dropped");我使用类名“接受”。唯一有效的东西。 删除activate 中的dropped 类也将允许再次拖动它。 如果您在可拖动对象上使用helper: "clone",这将非常有用,但如果它是默认设置(即"original"),那么可拖动对象将始终被标记为“已丢弃”并且不会起作用更多。 这项技术很可靠,但我没有使用类,而是向event.originalEvent 添加了一个属性,然后对其进行了测试。无论helper 设置如何,这都将起作用。不幸的是,调用的 order drop 方法与 z-index 无关,因此如果首先调用它很重要,即使该解决方案也可能不够。【参考方案3】:

如果您在容器区域中有 可放置的数量,那是什么????

你必须重新考虑这个问题。 贪婪仅适用于父子关系,不适用于兄弟姐妹。所以你必须编辑 droppable js 或者为它添加你自己的逻辑。

因此,如果您有多个可放置对象,那么您必须编写一些额外的代码来处理完美可放置对象的放置,就像在本示例中一样 A number of siblings droppables

为了制作完美的 siblings droppable 修改你的 droppbale 如下

        var topElement = undefined;
        var topElementArray = Array();

        $( "#draggable" ).draggable();
        $( ".droppableBox" ).droppable(
            activeClass: "active-droppable",
            tolerance:'pointer',
            over: function( event, ui )  
                // This is for only show a message that z-index must be required for proppable
                // you can remove it after testing or after development
                if ($(this).css("z-index") == 'auto') 
                    alert("Please provide z-index for every droppable.");
                    return;
                
                //

                topElement = undefined;
                topElementArray = Array();
                // Change it as you want to write in your code
                // For Container id or for your specific class for droppable or for both
                $('#demo > .droppableBox').each(function()                     
                    _left = $(this).offset().left, _right = $(this).offset().left + $(this).width();
                    _top = $(this).offset().top, _bottom = $(this).offset().top + $(this).height();
                    if (event.pageX >= _left && event.pageX <= _right && event.pageY >= _top && event.pageY <= _bottom)    
                          topElementArray.push($(this).attr('id'));
                    
                );
            ,
            drop: function( event, ui ) 
                if (!topElement) 
                    topElement = determineTopElement(topElementArray);
                                   
                if ($(this).attr('id') == $(topElement).attr('id')) 
                    $( this ).addClass( "ui-state-highlight" ).find( "p" ).html( "Dropped!" );
                  // Your code after successful dropped element on specific siblings
                  // Start writing code for dropped element & perfect droppable
                

            
        );

        determineTopElement = function(_array) 
            var topElement;
            var zIndexHighest = 0;
            for (i = 0; i < _array.length; i++)
               var element = $("#"+ _array[i]);
               var z_index = $(element).css("z-index");
               if( z_index > zIndexHighest)
                   zIndexHighest = z_index;
                   topElement = element;
               
            
            return topElement;       
        

【讨论】:

您知道如何使重叠区域不可删除吗?【参考方案4】:

在某些情况下:

myjQuery.droppable(
  over:function(evt,ui)
    ui.draggable.attr('drg_time', this.drg_time = evt.timeStamp)
  ,
  accept:function(draggeds)
    if(draggeds.attr('drg_time'))
    
      return draggeds.attr('drg_time') == this.drg_time
    
    return draggeds.hasClass('acceptable_classes_here')
  ,
  out:function(evt,ui)
    // useless but cleaner
    ui.draggable.removeAttr('drg_time')
  
  drop:...,
)

【讨论】:

【参考方案5】:

我遇到了同样的问题,做了一个小插件:)

检查一下:

https://***.com/a/16720944/1308461

【讨论】:

【参考方案6】:

我发现使用#invertedSpear 的方法会导致UI 状态发生变化,这在某些情况下是不可取的。这是代码。

var lastOpertion = new Date().getTime();

drop: function (event, ui) 
        if (new Date().getTime() - lastOpertion < 100) return;
        lastOpertion = new Date().getTime();
        ....

【讨论】:

【参考方案7】:

所以,当我试图找到简单的解决方案时,我想出了这个(它对我有用):

            window.overNowOnThis = "";
            window.olderOnes = [];
            $obj.droppable(
                accept: ".draggable_imgs",
                drop: function(e, ui) 
                    if(window.overNowOnThis == this)
                        // Do whatever
                    
                ,
                over: function(event, ui)
                    window.olderOnes.push(window.overNowOnThis);
                    window.overNowOnThis = this;
                ,
                out: function()
                    var lastElem = window.olderOnes.pop();
                    window.overNowOnThis = lastElem;
                
            );

顶部元素会被选中,因为它“over”会触发最后一个元素。此外 - 如果有两个以上的兄弟姐妹 - 那么当移出元素时,我们将最后一个设置为当前。例如,使用全局“窗口”。更好的选择是使用类,因为它可以安全地保存数据。

【讨论】:

【参考方案8】:

这与倒矛回答非常相似。我不得不稍微改变一下,因为在“over”/“out”内部启用/禁用对我不起作用。我必须在下面做

$("#droppable2").droppable(
    greedy: true,
    drop: function (event, ui) 
        $("droppable").droppable("disable");
    

当我需要它时,我必须显式启用“droppable” div。例如,在启动拖动事件时启用它。例如

$("#drageMe").draggable(
 start:function(event,ui)
   $("droppable").droppable("enable");  

)

【讨论】:

【参考方案9】:

在 ui dropable 中尝试贪婪选项。请参阅下面的小提琴链接进行演示:

http://jsfiddle.net/creators_guru/3vT5C/embedded/result/

$( ".circles" ).droppable(
    greedy: true,
    drop: function( event, ui ) 
        $_data  =   ('drgged class = ' + ui.draggable.attr('class'));
        $_data1 =   ('droped id = #' + $(this).attr('id'));
        $('#data').html($_data + '<br/>'+$_data1);
        return false;
    
);

【讨论】:

在我的问题中,我指出“当项目是兄弟姐妹时,贪婪不起作用”

以上是关于jQueryUI droppable,停止传播到重叠的兄弟的主要内容,如果未能解决你的问题,请参考以下文章

JQueryUI droppable drop 事件在恢复之前触发

jQuery/jQueryUI Droppable 采用 Draggable 的形式

jQueryUI droppable:一遍又一遍的回调按顺序触发

在使用 FancyTree (JS) 和 jqueryUI droppable 的上下文中获取源对象

jQuery UI (Droppable):如果 droppable 具有相对/绝对的 css 位置,则可拖动元素不会放置在鼠标指针处

检查 droppable 是不是已经包含另一个可拖动元素(jQuery UI)