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


163

总览

我具有以下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

这是一个可以修补的jsFiddle: http //jsfiddle.net/yYF3S/2/

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

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

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


通过e.stopPropagation();
Blender 2012年

我想我已经...查看更新
Hristo

您可以在jsfiddle.net上的某个地方发布演示吗,人们可以修改它吗?
搅拌器

@Blender ...肯定的事情,请给我几分钟!
赫里斯托(Hristo)

@Blender ...我用小提琴更新了我的问题
Hristo

Answers:


171

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

.child-elements {
  pointer-events: none;
}

4
最好的解决方案!我什至没有想到我可以以如此优雅的方式使用CSS解决问题。非常感谢你!
serg66 2013年

1
哦耶。就是这个!
mcmlxxxiii

23
这种方法的唯一缺点是,它会使子元素上的所有指针事件发生变化(例如,它们不再具有单独的:hover样式或click事件处理程序)。如果您想保留这些事件,这是我一直在使用另一种解决办法:bensmithett.github.io/dragster

2
与css子选择器结合使用,可以到达您的拖放区的所有孩子:.dropzone * {pointer-events: none;}
Philipp F

7
您已经在使用jQuery,因此只需$('.element').addClass('dragging-over')拖动到要拖动的元素以及$('.element').removeClass('dragging-over')何时拖动。然后在CSS中就可以了.element.dragging-over * { pointer-events: none; }。仅当您将鼠标悬停在上面时,才从所有子元素中删除指针事件。
加文2015年

56

我终于找到了我满意的解决方案。实际上,我发现有几种方法可以做自己想做的事,但没有一种方法能像当前解决方案一样成功。在一种解决方案中,由于在边框上添加/删除边框,我经常出现闪烁现象。#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)。


到目前为止,这是最好的解决方案。唯一的问题是,当您添加文件,删除文件并将另一个文件拖到该文件上时,此代码不起作用。仅在提高HoverEnd和再次提高HoverStart之后,此代码才能再次起作用。
MysticEthth,2015年

@MysticEarth,您可以在无法使用时放一个jsFiddle进行演示吗?
赫里斯特

1
谢谢您的回答。这确实很有帮助,因为HTML5拖放界面和事件侦听器确实很痛苦。这是处理疯狂事件的最佳方法,尤其是当您要处理拖放区元素的多个实例时。
Nico O

为什么我们需要调用stopPropagation()preventDefault()并返回false。返回false应该足够。应该是 ?
Dejo 2015年

这是多余的,但调用stopPropagation()preventDefault()优先。我将放弃return false
Peeja

38

这有点难看,但是该死的!!

在您的“ dragenter”处理程序上存储event.target(在闭包内部的变量中,或其他任何东西),然后在您的“ dragleave”处理程序中,仅当event.target ===您存储的代码时才触发您的代码。

如果您不希望触发“ dragoner”(例如,在离开子元素之后进入时),则在鼠标离开父级之前最后一次触发时,它在父级上,因此父级始终是最终的“ dragerer”在预期的“ dragleave”之前。

(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");
        }
    });

}());

稍后再尝试。如果有的话,它看起来比我的解决方案还干净,但是我无法确定它是否与跨浏览器兼容。您在哪里测试过?
赫里斯特

1
仅适用于Chrome,并且只能在子元素与容器之间存在物理间隙的前提下工作。
hacklikecrack 2012年

5
我最喜欢的答案在这里。一点也不觉得丑:)
Matt Way

1
在IE,铬,FF对我的作品
Vicentiu Bacioiu

1
如果在子代上开始拖动,这将不起作用。例如,以某种方式从另一个窗口中的其他窗口中拖动来开始在孩子内部进行拖动。
FINDarkside '19

29

首先,我同意放弃该pointer-events: none方法的人们。但是后来我问自己:

在拖动过程中,您真的需要指针事件来处理子元素吗?

在我的情况下,我的孩子有很多事情要做,例如,悬停以显示按钮以进行其他操作,内联编辑等。但是,拖动过程中这些都不是必需的,甚至甚至是不需要的。

就我而言,我使用类似这样的方法为父容器的所有子节点有选择地关闭指针事件:

  div.drag-target-parent-container.dragging-in-progress * {
    pointer-events: none;
  }

使用您喜欢的方法dragging-in-progressdragEnter/ dragLeave事件处理程序中添加/删除类,就像我在dragStart,等中所做的或做的一样。等


1
此解决方案既最简单,又是完全可靠的(据我所知)。只需在dragstart事件中添加类,然后将其删除dragend
cmann

这是一个很好的解决方案,但并不完美。如果从子元素开始拖动(从另一个窗口拖动),则永远不会触发dragEnter。可能还可以足够快地移动鼠标,以使您移到孩子时不会触发dragEnter,但不能100%地确定。
FINDarkside '19

12

这似乎是Chrome错误。

我唯一想到的解决方法是创建一个透明的覆盖元素来捕获您的事件:http : //jsfiddle.net/yYF3S/10/

JS

$(document).ready(function() {
    var dropzone = $('#overlay');

    dropzone.on('dragenter', function(event) {
        $('#dropzone-highlight').addClass('dnd-hover');
    });

    dropzone.on('dragleave', function(event) {
        $('#dropzone-highlight').removeClass('dnd-hover');
    });

});​

HTML

<div id="dropzone-highlight">
    <div id="overlay"></div>

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

<h2 draggable="true">Drag me</h2>

谢谢你的答案,搅拌器。我已经尝试过了。这种解决方案的问题在于,overlay元素“覆盖”了我需要与之交互的子元素...因此,具有overlay会禁用我与孩子之间的交互性……将其视为文件drag-n拖放框...您可以拖放,也可以单击输入元素以选择文件。
赫里斯托

这是一个示例提琴,您的解决方案无法满足... jsfiddle.net/UnsungHero97/yYF3S/11
Hristo

我很困惑。为什么还需要与子元素进行交互?
Blender 2012年

在我的特定情况下,“ dropzone”的子元素是文件选择按钮...因此,如果我不想拖放文件,则可以使用input元素选择它们。但是有了覆盖...我无法单击输入元素。合理?
赫里斯托(Hristo)2012年

@Blender大多数情况下,我们需要从桌面拖动文件,而不是从页面拖动元素,因此这有点用。
马丁斯Briedis

5

问题在于,拖放区中的元素当然是拖放区的一部分,当您输入子元素时,您将离开父元素。解决这个问题并不容易。您也可以尝试向孩子添加事件,也可以将课程再次添加到父级。

$("#dropzone,#dropzone *").on('dragenter', function(event) {

    // add a class to #dropzone

    event.stopPropagation(); // might not be necessary
    event.preventDefault();
    return false;
});

您的事件仍会多次触发,但没人会看到。

//编辑:使用dragmove事件永久覆盖dragleave事件:

$("#dropzone,#dropzone *").on('dragenter dragover', function(event) {

    // add a class to #dropzone

    event.stopPropagation(); // might not be necessary
    event.preventDefault();
    return false;
});

仅为dropzone定义dragleave事件。


2
但这并不能解决问题。真正的问题是dragleave……当我离开孩子时,我可能仍在父母中,#dropzone但不会dragenter再次触发该事件:(
Hristo

您确定该Dragenter不会再被解雇吗?
奥利弗·

嗯,对了...它再次被触发,但是,在它被触发之后,dragleave将为刚刚剩下的子元素触发该事件,因此再次removeClass执行了该指令
Hristo

我不能dragleave只为#dropzone... 定义,如果可以的话,我不会有这个问题。
赫里斯托(Hristo)2012年

不,我的意思是不要向孩子们添加Dragleave事件。
奥利弗(Oliver)2012年

4

本答案中的benr所述,您可以防止子节点在事件上触发,但是如果您需要绑定某些事件,请执行以下操作:

#dropzone.dragover *{
   pointer-events: none;
}

并将其添加到您的JS代码中:

$("#dropzone").on("dragover", function (event) {
   $("#dropzone").addClass("dragover");
});

$("#dropzone").on("dragleave", function (event) {
   $("#dropzone").removeClass("dragover");
});

2
对我来说,这导致覆盖层不断闪烁。
安德烈·米哈伊洛夫

3

如果您使用的是jQuery,请查看以下内容:https : //github.com/dancork/jquery.event.dragout

真的很棒。

创建特殊事件以处理真正的Dragleave功能。

HTML5 dragleave事件的工作方式类似于mouseout。创建此插件的目的是在拖动时复制mouseleave样式的功能。

用法示例:

$('#myelement')。on('dragout',function(event){//您的代码});

编辑:实际上,我不认为它依赖于jQuery,即使没有它,您也可能只使用代码。


哇!dragleave即使我尚未离开父级放置区,但Dragout还是适用于我的布局的一件事,它触发了许多子元素。
马克·卡森

在解决了最后一个小时的问题之后,这dragout是唯一对我有用的解决方案。
詹森·黑兹

2

@hristo我有一个更优雅的解决方案。检查是否可以使用。

毕竟您的努力并没有浪费。一开始我设法使用您的,但是在FF,Chrome中遇到了不同的问题。花了很多小时后,我才完全按照预期工作了。

这是实现的方式。我还利用视觉提示来正确地指导用户有关放置区域的信息。

$(document).on('dragstart dragenter dragover', function(event) {    
    // Only file drag-n-drops allowed, http://jsfiddle.net/guYWx/16/
    if ($.inArray('Files', event.originalEvent.dataTransfer.types) > -1) {
        // Needed to allow effectAllowed, dropEffect to take effect
        event.stopPropagation();
        // Needed to allow effectAllowed, dropEffect to take effect
        event.preventDefault();

        $('.dropzone').addClass('dropzone-hilight').show();     // Hilight the drop zone
        dropZoneVisible= true;

        // http://www.html5rocks.com/en/tutorials/dnd/basics/
        // http://api.jquery.com/category/events/event-object/
        event.originalEvent.dataTransfer.effectAllowed= 'none';
        event.originalEvent.dataTransfer.dropEffect= 'none';

         // .dropzone .message
        if($(event.target).hasClass('dropzone') || $(event.target).hasClass('message')) {
            event.originalEvent.dataTransfer.effectAllowed= 'copyMove';
            event.originalEvent.dataTransfer.dropEffect= 'move';
        } 
    }
}).on('drop dragleave dragend', function (event) {  
    dropZoneVisible= false;

    clearTimeout(dropZoneTimer);
    dropZoneTimer= setTimeout( function(){
        if( !dropZoneVisible ) {
            $('.dropzone').hide().removeClass('dropzone-hilight'); 
        }
    }, dropZoneHideDelay); // dropZoneHideDelay= 70, but anything above 50 is better
});

您可能似乎缺少某些超出范围的变量的定义,我认为var dropZoneHideDelay=70, dropZoneVisible=true;
Timo Huovinen 2014年

@TimoHuovinen是的,正确。无论dropZoneHideDelay, dropZoneVisible是分布于两个需要'on'在我的执行文件的事件。
2014年

2

我的两分钱:在您的拖放区上隐藏一个图层,然后在拖动时显示该图层,然后将其作为目标。

演示: https //jsfiddle.net/t6q4shat/

的HTML

<div class="drop-zone">
  <h2 class="drop-here">Drop here</h2>
  <h2 class="drop-now">Drop now!</h2>
  <p>Or <a href="#">browse a file</a></p>
  <div class="drop-layer"></div>
</div>

的CSS

.drop-zone{
  padding:50px;
  border:2px dashed #999;
  text-align:center;
  position:relative;
}
.drop-layer{
  display:none;
  position:absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
  z-index:5;
}
.drop-now{
  display:none;
}

JS

$('.drop-zone').on('dragenter', function(e){
    $('.drop-here').css('display','none');
    $('.drop-now').css('display','block');
    $(this).find('.drop-layer').css('display','block');
    return false;
});

$('.drop-layer').on('dragleave', function(e){
    $('.drop-here').css('display','block');
    $('.drop-now').css('display','none');
    $(this).css('display','none');
    return false;
});

简单有效!我沿着stopPropagation()路线行驶,我不喜欢将事件处理程序应用于所有子级。看起来很杂乱,但这很好用并且易于实现。好主意。
乔恩·卡特穆尔

1

所以对我来说,这种方法pointer-events: none;效果不太好...所以这是我的替代解决方案:

    #dropzone {
        position: relative;
    }

    #dropzone(.active)::after {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        content: '';
    }

这样dragleave,父项(在子项上)或dragover子项元素是不可能的。希望这可以帮助 :)

*当我dragenter或时添加的“ .active”类dragleave。但是,如果您在没有这些的情况下工作,那就别上课了。


1
我在EmberJS D&D组件中尝试了此操作,并且以编程方式添加“活动”类的速度太慢,大约是鼠标进入父级div(ember-view)时间的40%。不知道为什么。但是,不用理会它,效果很好,因此感谢您提供此简单的解决方案。在Mac上测试了最新版本(截至今天)的Safari,Chrome,Firefox。
rmcsharry16年

1

超级简单的快速修复程序,尚未经过全面测试,但现在可在Chrome中使用。

请原谅咖啡。

  dragEndTimer = no

  document.addEventListener 'dragover', (event) ->
    clearTimeout dragEndTimer
    $('body').addClass 'dragging'
    event.preventDefault()
    return no

  document.addEventListener 'dragenter', (event) ->
    $('section').scrollTop(0)
    clearTimeout dragEndTimer
    $('body').addClass 'dragging'

  document.addEventListener 'dragleave', (event) ->
    dragEndTimer = setTimeout ->
      $('body').removeClass 'dragging'
    , 50

这可以修复Chrome闪烁错误,或者至少可以解决引起我问题的排列错误。


1

这个答案可以在这里找到:

悬停子元素时触发HTML5 dragleave

var counter = 0;

$('#drop').bind({
    dragenter: function(ev) {
        ev.preventDefault(); // needed for IE
        counter++;
        $(this).addClass('red');
    },

    dragleave: function() {
        counter--;
        if (counter === 0) { 
            $(this).removeClass('red');
        }
    }
});

1

我的版本:

$(".dropzone").bind("dragover", function(e){
    console.log('dragover');
});

$(".dropzone").bind("dragleave", function(e) {
  var stopDrag = false;
  if (!e.relatedTarget) stopDrag = true;
  else {
    var parentDrop = $(e.relatedTarget).parents('.dropzone');
    if (e.relatedTarget != this && !parentDrop.length) stopDrag = true;
  }

  if (stopDrag) {
    console.log('dragleave');
  }
});

使用此布局:

<div class="dropzone">
  <div class="inner-zone">Inner-zone</div>
</div>

我做了元素类的转储e.targete.currentTargete.relatedTarget两个dragoverdragleave事件。

它向我显示,离开父块(.dropzonee.relatedTarget并不是该块的子对象,所以我知道我已经离开了dropzone。


0

在这里,最简单的解决方案之一

看看这个小提琴 <-尝试在框中拖动一些文件

您可以执行以下操作:

var dropZone= document.getElementById('box');
var dropMask = document.getElementById('drop-mask');


dropZone.addEventListener('dragover', drag_over, false);
dropMask.addEventListener('dragleave', drag_leave, false);
dropMask.addEventListener('drop', drag_drop, false);

这样一来,您应该已经知道这里发生了什么。
看看小提琴吧。


0

我遇到了类似的问题,并通过以下方式解决了问题:

问题:当用户将元素放置在“放置区域”(ul元素)中时,会触发功能drop(ev),但是不幸的是,当该元素被放置在其子元素之一(li元素)中时,也会触发该功能。

解决方法:

function drop(ev) { 
ev.preventDefault(); 
data=ev.dataTransfer.getData('Text'); 
if(ev.target=="[object HTMLLIElement]")  
{ev.target.parentNode.appendChild(document.getElementById(data));}
else{ev.target.appendChild(document.getElementById(data));} 
} 

0

我正在尝试自己为文件上传框实现此功能,当用户将文件拖到该空间时,框颜色会更改。

我找到了一个将Javascript和CSS完美结合的解决方案。假设您有一个divID 为的可投放区域#drop。将此添加到您的JavaScript:

$('#drop').on('dragenter', function() {
    $(this).addClass('dragover');
    $(this).children().addClass('inactive');
});

$('#drop').on('dragleave', function() {
    $(this).removeClass('dragover');
    $(this).children().removeClass('inactive');
});

然后,将其添加到您的CSS中,以停用所有将class的孩子.inactive

#drop *.inactive {
    pointer-events: none;
}

因此,只要用户将元素拖动到框上,子元素就不会处于活动状态。


0

我对这里介绍的任何解决方法都不满意,因为我不想失去对child元素的控制。

因此,我使用了另一种逻辑方法,将其转换为一个名为jquery-draghandler的jQuery插件。它绝对不会操纵DOM,从而保证了高性能。它的用法很简单:

$(document).ready(function() {

    $(selector).draghandler({
        onDragEnter: function() {
            // $(this).doSomething();
        },
        onDragLeave: function() {
            // $(this).doSomethingElse();
        }
    });

});

它可以完美地处理该问题,而不会损害任何DOM功能。

在其Git存储库中下载,详细信息和说明。


如何在您的插件中获取拖动输入事件?
伍迪2015年

我尚未真正测试过您的指令,但如果父元素(A)并未真正包围要检查的元素(B),则我认为它不起作用。例如,如果在B的底部边缘和A的底部边缘之间没有填充,那么Dragenter将永远不会触发元素A,对吗?
marcelj

@marcelj元素A可以是主体文档本身,因此,您实际上不需要最少的填充量(主体可以完成工作)。后来我发现这种方法的局限性是,如果您使用frames并且您的元素位于其边界。在那种情况下,我不建议采用这种方法。
卡·法乔利

0

我真的很喜欢我看到的 https://github.com/lolmaus/jquery.dragbetter/上但想分享一个可能的选择。我的总体策略是在拖曳它或它的任何子对象(通过冒泡)时,将背景样式应用于该放置区(而不是其子对象)。然后,在拖动拖放区时删除样式。想法是移到一个孩子时,即使我在离开样式时从拖放区中删除了样式(拖动拖动),我也会在拖动任何孩子时将样式重新应用于父拖放区。问题当然是,当从放置区移动到放置区的子项时,在拖动器之前,拖动器会在子项上触发,因此我的样式会乱序应用。对我来说,解决方案是使用计时器将Dragenter事件强制返回到消息队列,使我可以在Dragleave之后对其进行处理。我使用了闭包来访问计时器回调上的事件。

$('.dropzone').on('dragenter', function(event) {
  (function (event) {
    setTimeout(function () {
      $(event.target).closest('.dropzone').addClass('highlight');
    }, 0);
  }) (event.originalEvent); 
});

这似乎可以在chrome(即Firefox)中使用,并且无论在dropzone中有多少子代都可以使用。我对保证事件重排序的超时感到有些不安,但是对于我的用例来说,它似乎工作得很好。


0

我试图自己实现它,我也不想要Jquery或任何插件。

我想按照最适合我的方式处理文件上传:

文件结构:

--- / uploads {上传目录}

--- /js/slyupload.js {javascript文件。}

--- index.php

--- upload.php

--- styles.css {只是一些样式。

HTML代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>my Dzone Upload...</title>
<link rel="stylesheet" href="styles.css" />
</head>

<body>
    <div id="uploads"></div>        
    <div class="dropzone" id="dropzone">Drop files here to upload</div>     
    <script type="text/javascript" src="js/slyupload.js"></script>      
</body>
</html>

然后,这是附加的Javascript文件::'js / slyupload.js'

<!-- begin snippet:  -->

<!-- language: lang-js -->

    // JavaScript Document

    //ondragover, ondragleave...


    (function(){        

        var dropzone = document.getElementById('dropzone');
        var intv;

        function displayUploads(data){
            //console.log(data, data.length);
            var uploads = document.getElementById('uploads'),anchor,x;

            for(x=0; x < data.length; x++){

                //alert(data[x].file);
                anchor = document.createElement('a');
                anchor.href = data[x].file;
                anchor.innerText = data[x].name;

                uploads.appendChild(anchor);
            }               
        }

        function upload(files){
            //console.log(files);
            var formData = new FormData(), 
                xhr      = new XMLHttpRequest(),    //for ajax calls...
                x;                                  //for the loop..

                for(x=0;x<files.length; x++){
                    formData.append('file[]', files[x]);

                    /*//do this for every file...
                    xhr = new XMLHttpRequest();

                    //open... and send individually..
                    xhr.open('post', 'upload.php');
                    xhr.send(formData);*/
                }

                xhr.onload = function(){
                    var data = JSON.parse(this.responseText);   //whatever comes from our php..
                    //console.log(data);
                    displayUploads(data);

                    //clear the interval when upload completes... 
                    clearInterval(intv);
                }                   

                xhr.onerror = function(){
                    console.log(xhr.status);
                }

                //use this to send all together.. and disable the xhr sending above...

                //open... and send individually..
                intv = setInterval(updateProgress, 50);
                xhr.open('post', 'upload.php');
                xhr.send(formData);

                //update progress... 
                 /* */                   
        }

        function updateProgress(){
            console.log('hello');
         }          

        dropzone.ondrop = function(e){
            e.preventDefault(); //prevent the default behaviour.. of displaying images when dropped...
            this.className = 'dropzone';
            //we can now call the uploading... 
            upload(e.dataTransfer.files); //the event has a data transfer object...
        }

        dropzone.ondragover = function(){
            //console.log('hello');
            this.className = 'dropzone dragover';
            return false;
        }

        dropzone.ondragleave = function(){
            this.className = 'dropzone';
            return false;
        }           
    }(window));

CSS:

body{
	font-family:Arial, Helvetica, sans-serif; 
	font-size:12px;
}

.dropzone{
	width:300px; 
	height:300px;
	border:2px dashed #ccc;
	color:#ccc;
	line-height:300px;
	text-align:center;
}

.dropzone.dragover{
	border-color:#000;
	color:#000;
}


0

抱歉,它是JavaScript而不是jquery,但对我来说,这是解决该问题的最合乎逻辑的方法。浏览器应在dropenter(新元素之前)之前调用(上一个元素的)dropleave,因为某些东西在离开最重要的东西之前不能输入其他东西,我不明白他们为什么这么做!所以您只需要延迟de dropleave像这样:

function mydropleave(e)
{
    e.preventDefault();
    e.stopPropagation();

    setTimeout(function(e){ //the things you want to do },1);
}

而dropenter将在dropleave之后发生,仅此而已!


-1

greedy : true用作子项的函数droppable。然后在第一层单击仅启动事件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.