当前位置: 首页 > 面试题库 >

拖动子元素时会触发父元素的“ dragleave”

翟博雅
2023-03-14
问题内容

总览

我具有以下HTML结构,并且将dragenterdragleave事件附加到了<div id="dropzone">元素上。

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

问题

当我将文件拖到时<div id="dropzone">dragenter事件将按预期触发。但是,当我将鼠标移到子元素(例如)上时<div id="drag-n-drop">,会dragenter为该<div id="drag-n- drop">元素dragleave触发该事件,然后为该<div id="dropzone">元素触发该事件。

如果我<div id="dropzone">再次将鼠标悬停在该元素上,dragenter则再次触发该事件,这很酷,但是随后dragleave为刚刚剩下的子元素触发了该事件,因此removeClass执行了该指令,这并不酷。

此行为有问题的原因有两个:

  1. 我只附加dragenterdragleave<div id="dropzone">所以我不明白为什么子元素也要附加这些事件。

  2. 我仍将鼠标悬停在<div id="dropzone">元素上,同时将其悬停在其子元素上,因此我不希望dragleave开火!

jsFiddle

所以…我该怎么做,以至于当我在<div id="dropzone">元素上拖动文件时,dragleave即使我在任何子元素上拖动也不会触发…仅当我离开该<div id="dropzone">元素时才触发。在元素边界内的任何位置悬停/拖动都不 应该 触发dragleave事件。

我至少在支持HTML5拖放的浏览器中需要跨浏览器兼容,因此此答案是不够的。

似乎Google和Dropbox已经解决了这一问题,但是它们的源代码是缩小的/复杂的,所以我无法从其实现中解决这一问题。


问题答案:

我终于找到了我满意的解决方案。我实际上找到了几种方法来做自己想做的事,但是没有一种方法能像当前解决方案一样成功。在一种解决方案中,由于在#dropzone元素上添加/删除了边框,我经常出现闪烁现象。如果将鼠标悬停在浏览器之外,则不会删除它。

无论如何,我最好的hacky解决方案是这样的:

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



 类似资料:
  • 我有以下HTML结构,并将dragenter和dragleave事件附加到

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

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

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

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

  • 问题内容: 当显示其父元素时,是否有任何机制可显示子元素:无? 这种情况是隐藏选项卡上的验证错误。我想显示错误消息,即使该字段是隐藏的。 标记: CSS: 我猜这是不可能的,因为孩子没有上下文,但以防万一? 问题答案: 不,这是不可能的。隐藏该元素,因此不会显示任何子元素。 编辑: 这可能是沿着你想要的线,如果你能够从使用切换到。 使用此方法,您可以隐藏父元素的内容,但显示所需的特定内容。唯一需要