当前位置: 首页 > 知识库问答 >
问题:

在子元素上拖动时,父元素的“dragleave”激发

戎高爽
2023-03-14

我有以下HTML结构,并将dragenter和dragleave事件附加到

<div id="dropzone">
    <div id="dropzone-content">
        <div id="drag-n-drop">
            <div class="text">this is some text</div>
            <div class="text">this is a container with text and images</div>
        </div>
    </div>
</div>

当我将文件拖过

如果我悬停在

这种行为有两个问题:

>

  • 我只附加了dragenter

    我还在拖

    这里有一个jsFiddle来修补:http://jsfiddle.net/yYF3S/2/

    所以当我在<代码>

    我需要跨浏览器兼容,至少在支持HTML5拖放的浏览器中是这样,所以这个答案是不够的。

    谷歌和Dropbox似乎已经解决了这个问题,但他们的源代码是精简/复杂的,所以我无法从他们的实现中解决这个问题。


  • 共有3个答案

    乐正镜
    2023-03-14

    这有点难看,但它的工作该死的!。。。

    在dragenter处理程序中存储event.target(在闭包中的变量中,或者其他),然后在draglet处理程序中,如果event.target===存储的代码,则只触发代码。

    如果您的“dragenter”在您不希望它启动时启动(即,当它在离开子元素后进入时),那么最后一次在鼠标离开父对象之前启动时,它位于父对象上,因此父对象将始终是预期“dragleave”之前的最终“dragenter”。

    (function () {
    
        var droppable = $('#droppable'),
            lastenter;
    
        droppable.on("dragenter", function (event) {
            lastenter = event.target;
            droppable.addClass("drag-over");            
        });
    
        droppable.on("dragleave", function (event) {
            if (lastenter === event.target) {
                droppable.removeClass("drag-over");
            }
        });
    
    }());
    
    孙修德
    2023-03-14

    我终于找到了一个我满意的解决方案。我实际上找到了几种方法来做我想做的事情,但没有一种方法像当前的解决方案那样成功...在一个解决方案中,由于向#dropzone元素添加/删除边框,我经历了频繁的闪烁...在另一个解决方案中,如果您将鼠标悬停在浏览器之外,边框永远不会被删除。

    无论如何,我最好的黑客解决方案是:

    var dragging = 0;
    
    attachEvent(window, 'dragenter', function(event) {
    
        dragging++;
        $(dropzone).addClass('drag-n-drop-hover');
    
        event.stopPropagation();
        event.preventDefault();
        return false;
    });
    
    attachEvent(window, 'dragover', function(event) {
    
        $(dropzone).addClass('drag-n-drop-hover');
    
        event.stopPropagation();
        event.preventDefault();
        return false;
    });
    
    attachEvent(window, 'dragleave', function(event) {
    
        dragging--;
        if (dragging === 0) {
            $(dropzone).removeClass('drag-n-drop-hover');
        }
    
        event.stopPropagation();
        event.preventDefault();
        return false;
    });
    

    这工作得很好,但是在Firefox中出现了问题,因为Firefox正在双重调用dragenter,所以我的计数器关闭了。但尽管如此,它不是一个非常优雅的解决方案。

    然后我偶然发现了这个问题:当在窗口外拖动时,如何检测Firefox中的dragleave事件

    所以我把答案应用到我的情况中:

    $.fn.dndhover = function(options) {
    
        return this.each(function() {
    
            var self = $(this);
            var collection = $();
    
            self.on('dragenter', function(event) {
                if (collection.size() === 0) {
                    self.trigger('dndHoverStart');
                }
                collection = collection.add(event.target);
            });
    
            self.on('dragleave', function(event) {
                /*
                 * Firefox 3.6 fires the dragleave event on the previous element
                 * before firing dragenter on the next one so we introduce a delay
                 */
                setTimeout(function() {
                    collection = collection.not(event.target);
                    if (collection.size() === 0) {
                        self.trigger('dndHoverEnd');
                    }
                }, 1);
            });
        });
    };
    
    $('#dropzone').dndhover().on({
        'dndHoverStart': function(event) {
    
            $('#dropzone').addClass('drag-n-drop-hover');
    
            event.stopPropagation();
            event.preventDefault();
            return false;
        },
        'dndHoverEnd': function(event) {
    
            $('#dropzone').removeClass('drag-n-drop-hover');
    
            event.stopPropagation();
            event.preventDefault();
            return false;
        }
    });
    

    这是干净和优雅的,似乎在我测试过的每一款浏览器(尚未测试IE)中都能正常工作。

    魏凯捷
    2023-03-14

    如果不需要将事件绑定到子元素,则始终可以使用指针事件属性。

    .child-elements {
      pointer-events: none;
    }
    
     类似资料:
    • 问题内容: 总览 我具有以下HTML结构,并且将和事件附加到了元素上。 问题 当我将文件拖到时,事件将按预期触发。但是,当我将鼠标移到子元素(例如)上时,会为该元素触发该事件,然后为该元素触发该事件。 如果我再次将鼠标悬停在该元素上,则再次触发该事件,这很酷,但是随后为刚刚剩下的子元素触发了该事件,因此执行了该指令,这并不酷。 此行为有问题的原因有两个: 我只附加&,所以我不明白为什么子元素也要附

    • 问题内容: 我有一个( 父 )包含另一个( 子 )。Parent是第一个没有特定CSS样式的元素。当我设定 最终结果是我的孩子的顶部仍然与父母对齐。我的父母没有将孩子向下移动10px,而是将其向下移动10px。 我的设定为。 我在这里想念什么? 编辑1 我的父母需要具有严格定义的尺寸,因为它的背景必须从上到下显示(像素完美)。因此,在其上设置垂直边距是 不可行的 。 编辑2 此行为在FF,IE和C

    • 急求!子元素设置了float:left,为什么是浮动到父元素的父元素(part1)上,而不是浮动到父元素(box1)上?想让这个子元素和学院新闻同行应该怎么办? 这是那个子元素 这是那个子元素 这是整体:

    • 问题内容: 当父元素悬停时如何更改子元素的样式。如果可能的话,我希望使用CSS解决方案。有没有可能通过:hover CSS选择器解决方案。实际上,当面板上悬停时,我需要更改面板内选项栏的颜色。 希望支持所有主流浏览器。 问题答案: 是的,您绝对可以做到这一点。只需使用类似 根据此页面,所有主流浏览器都支持该页面。

    • 问题内容: 首先,我假设对于CSS3来说这太复杂了,但是如果某个地方有解决方案,我很乐意使用它。 HTML非常简单。 子div设置为显示:无;默认情况下,但更改为display:block; 当鼠标悬停在父div上时。问题是此标记出现在我网站上的多个位置,并且我只希望在鼠标悬停在其父项上方时显示该子项,而不是在鼠标悬停在其他任何父项上时都显示该子项(它们都具有相同的类)名称和ID)。 我尝试使用并

    • 我有一个来自服务器的响应,我想把它放到列表中。但是当列表为空时,我需要隐藏这个div容器。例如,如果不在数组中-我想隐藏div。但是我想在ng之后使用bird重复,所以我不能使在上。我可以检查li是否为空,然后隐藏div吗? 普朗克例子 AngularJS ng-重复处理空列表大小写-这是不一样的。如果li是空的,我不想隐藏li,我想在li是空的时候隐藏父元素h1。