web-dev-qa-db-ger.com

'dragleave' des übergeordneten Elements wird beim Ziehen über untergeordnete Elemente ausgelöst

Überblick

Ich habe die folgende HTML-Struktur und habe die dragenter- und dragleave -Ereignisse an das <div id="dropzone">-Element angehängt.

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

Problem

Wenn ich eine Datei über den <div id="dropzone"> ziehen, wird das dragenter-Ereignis erwartungsgemäß ausgelöst. Wenn ich jedoch die Maus über ein untergeordnetes Element bewegen, z. B. <div id="drag-n-drop">, wird das Ereignis dragenter für das Element <div id="drag-n-drop"> ausgelöst, und dann wird das Ereignis dragleave für das Element <div id="dropzone"> ausgelöst.

Wenn ich erneut über das <div id="dropzone">-Element schwebe, wird das dragenter-Ereignis erneut ausgelöst, was cool ist. Das dragleave-Ereignis wird jedoch für das untergeordnete Element ausgelöst, sodass nur die removeClass-Anweisung ausgeführt wird.

Dieses Verhalten ist aus zwei Gründen problematisch:

  1. Ich füge nur dragenter & dragleave an den <div id="dropzone"> an, daher verstehe ich nicht, warum die untergeordneten Elemente diese Ereignisse ebenfalls angefügt haben.

  2. Ich ziehe immer noch über das <div id="dropzone">-Element, während ich über seine Kinder schwebe, so dass ich nicht möchte, dass dragleave ausgelöst wird!

jsFiddle

Hier ist ein jsFiddle zum Basteln: http://jsfiddle.net/yYF3S/2/

Frage

Also ... wie kann ich es so machen, dass dragleave beim Ziehen einer Datei über das <div id="dropzone">-Element nicht ausgelöst wird, auch wenn ich über alle untergeordneten Elemente gezogen bin ... es sollte nur ausgelöst werden, wenn ich den <div id="dropzone"> verlasse element ... Schweben/Ziehen an einer beliebigen Stelle innerhalb der Grenzen des Elements sollte nicht löst das Ereignis dragleave aus.

Ich brauche dies, um Browser-kompatibel zu sein, zumindest in den Browsern, die HTML5-Drag-n-Drop unterstützen, also diese Antwort ist nicht ausreichend.

Es hat den Anschein, als hätten Google und Dropbox dies herausgefunden, aber der Quellcode ist minimal/komplex, so dass ich es bei ihrer Implementierung nicht herausfinden konnte.

146
Hristo

Endlich habe ich eine Lösung gefunden, mit der ich zufrieden bin. Ich habe tatsächlich mehrere Möglichkeiten gefunden, um das zu tun, was ich will, aber keiner war so erfolgreich wie die aktuelle Lösung ... In einer Lösung erlebte ich häufiges Flimmern als Folge des Hinzufügens/Entfernens einer Grenze zum #dropzone-Element ... in einer anderen Lösung Die Grenze wurde nie entfernt, wenn Sie sich vom Browser wegbewegen.

Jedenfalls ist meine beste hacky Lösung diese:

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

Das funktioniert ziemlich gut, aber es kam zu Problemen in Firefox, da Firefox dragenter doppelt aufgerufen hat, also war mein Counter ausgeschaltet. Trotzdem ist es keine sehr elegante Lösung.

Dann bin ich auf diese Frage gestoßen: Wie finde ich das Dragleave-Ereignis in Firefox, wenn Sie aus dem Fenster ziehen

Also nahm ich die Antwort und wendete sie auf meine Situation an:

$.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;
    }
});

Dies ist sauber und elegant und scheint in jedem Browser zu funktionieren, den ich bisher getestet habe (noch nicht getestet IE).

52
Hristo

Wenn Sie keine Ereignisse an die untergeordneten Elemente binden müssen, können Sie immer die Eigenschaft pointer-events verwenden.

.child-elements {
  pointer-events: none;
}
152
Ben Rudolph

Dies ist ein wenig hässlich, aber es funktioniert verdammt noch mal! ...

Speichern Sie in Ihrem 'Dragenter'-Handler das event.target (in einer Variablen innerhalb Ihres Abschlusses oder was auch immer), und in Ihrem' Dragleave'-Handler geben Sie Ihren Code nur dann aus, wenn event.target den von Ihnen gespeicherten Code enthält.

Wenn Ihr 'Dragenter' feuert, wenn Sie es nicht möchten (dh, wenn es nach dem Verlassen von untergeordneten Elementen betreten wird), dann ist es das letzte Mal, wenn es ausgelöst wird, bevor die Maus das übergeordnete Element verlässt, auf dem übergeordneten Element das letzte 'Dragenter' vor dem beabsichtigten '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");
        }
    });

}());
35
hacklikecrack

Zuerst stimmte ich zu, dass die Leute den pointer-events: none-Ansatz verwerfen. Aber dann habe ich mich gefragt:

Benötigen Sie wirklich Zeigerereignisse, um an den untergeordneten Elementen zu arbeiten, während das Ziehen ausgeführt wird

In meinem Fall habe ich viel mit den Kindern zu tun, z. hover, um Schaltflächen für zusätzliche Aktionen, Inline-Bearbeitung usw. anzuzeigen. Allerdings ist none davon notwendig oder sogar gewünscht während des Ziehens.

In meinem Fall verwende ich so etwas, um Zeigerereignisse für alle untergeordneten Knoten des übergeordneten Containers selektiv zu deaktivieren:

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

Verwenden Sie Ihren bevorzugten Ansatz, um die Klasse dragging-in-progress in den dragEnter/dragLeave-Ereignishandlern hinzuzufügen/zu entfernen, wie ich es in dragStart et. al.

21
bargar

Dies scheint ein Chrome-Bug zu sein.

Die einzige Problemlösung, an die ich denken konnte, war das Erstellen eines transparenten Overlay-Elements zum Erfassen Ihrer Ereignisse: 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>
​
12
Blender

Das Problem ist, dass Ihre Elemente in den DropZones natürlich Teil der Dropzone sind und wenn Sie die Kinder betreten, verlassen Sie das übergeordnete Element. Das zu lösen ist nicht einfach. Sie können auch versuchen, den untergeordneten Ereignissen Ereignisse hinzuzufügen und Ihre Klasse erneut dem übergeordneten Element hinzuzufügen.

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

    // add a class to #dropzone

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

Ihre Events werden immer noch mehrfach ausgelöst, aber niemand wird es sehen.

// Bearbeiten: Verwenden Sie das Dragmove-Ereignis, um das Dragleave-Ereignis dauerhaft zu überschreiben:

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

    // add a class to #dropzone

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

Definieren Sie das Dragleave-Ereignis nur für die Dropzone.

5
Oliver

Wie in benr in dieser Antwort erwähnt, können Sie verhindern, dass untergeordnete Knoten bei Ereignissen ausgelöst werden. Wenn Sie jedoch Ereignisse binden möchten, gehen Sie folgendermaßen vor:

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

Und fügen Sie dieses zu Ihrem JS-Code hinzu:

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

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

Wenn Sie jQuery verwenden, überprüfen Sie Folgendes: https://github.com/dancork/jquery.event.dragout

Es ist wirklich großartig.

Ein spezielles Ereignis, das für die Verarbeitung der echten Dragleave-Funktionalität erstellt wurde.

Das HTML5-Dragleave-Ereignis funktioniert eher wie ein Mouseout. Dieses Plugin war erstellt, um die Funktionalität des Mauszeils zu replizieren, während ziehen.

Verwendungsbeispiel:

$ ('# myelement'). on ('dragout', function (event) { // IHR CODE });

BEARBEITEN: Eigentlich glaube ich nicht, dass es von jQuery abhängt. Sie können den Code wahrscheinlich auch ohne verwenden.

3
nkkollaw

@hristo Ich habe eine viel elegantere Lösung. Überprüfen Sie, ob dies etwas ist, das Sie verwenden könnten.

Ihre Anstrengung war doch nicht verschwendet. Ich habe es zuerst geschafft, Ihre zu verwenden, hatte aber unterschiedliche Probleme in FF, Chrome. Nachdem ich so viele Stunden damit verbracht hatte, bekam ich diesen Vorschlag genau wie beabsichtigt.

So sieht die Implementierung aus. Ich habe auch visuelle Hinweise genutzt, um Benutzer korrekt über die Drop-Zone zu leiten.

$(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
});
2
visitsb

Meine zwei Cents: Blenden Sie eine Ebene über Ihrer Dropzone aus, zeigen Sie sie an, wenn Sie sie ziehen, und legen Sie den Dragleave darauf. 

Demo: 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;
});
2
jeremie.b

Super einfache, schnelle Lösung für dieses Problem, nicht umfassend getestet, funktioniert aber jetzt in Chrome.

Entschuldigen Sie das Coffeescript.

  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

Dies behebt den Chrome-Flicker-Fehler oder zumindest die Permutation davon, die Probleme verursacht hat.

1
Dom Vinyard

Der Ansatz pointer-events: none; hat für mich nicht so gut funktioniert ... Hier ist meine alternative Lösung:

    #dropzone {
        position: relative;
    }

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

Auf diese Weise ist es nicht möglich, dragleave das übergeordnete Element (für ein untergeordnetes Element) oder dragover ein untergeordnetes Element zu verwenden. hoffe das hilft :)

* Die '.active'-Klasse füge ich bei dragenter oder dragleave hinzu. Aber wenn Sie ohne arbeiten, lassen Sie die Klasse einfach weg.

1
MMachinegun

Ich habe versucht, dies selbst für eine Datei-Upload-Box zu implementieren, in der sich die Box-Farbe ändern würde, wenn Benutzer eine Datei in den Bereich ziehen.

Ich habe eine Lösung gefunden, die eine schöne Mischung aus Javascript und CSS ist. Angenommen, Sie haben eine abwanderbare Zone mit div mit der ID #drop. Fügen Sie dies Ihrem Javascript hinzu:

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

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

Dann fügen Sie dies zu Ihrem CSS hinzu, um zu deaktivieren, dass alle untergeordneten Klassen .inactive:

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

Daher sind die untergeordneten Elemente inaktiv, solange der Benutzer das Element über die Box zieht.

0
David A

Ich hatte ein ähnliches Problem und habe es so behoben:

Das Problem: .__ Die Funktion drop (ev) wird ausgelöst, wenn der Benutzer ein Element in der "drop zone" (Element ul) ablegt, aber leider auch, wenn das Element in einem seiner untergeordneten Elemente (li-Elemente) abgelegt wird. .

Die Reparatur:

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
Pao

Diese Antwort finden Sie hier:

HTML5-Dragleave wird ausgelöst, wenn ein untergeordnetes Element bewegt wird

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');
        }
    }
});
0
zeros-and-ones

Mir gefällt eigentlich, was ich unter https://github.com/lolmaus/jquery.dragbetter/ sehe, aber ich wollte eine mögliche Alternative mit Ihnen teilen .. Meine allgemeine Strategie bestand darin, einen Hintergrundstil auf die Dropzone anzuwenden (nicht seine Kinder), wenn Sie ihn oder ein Kind davon (per Bubbling) ziehen. Dann entferne ich den Stil beim Ziehen der Drop-Zone. Die Idee war, zu einem Kind zu wechseln, selbst wenn ich den Stil aus der Dropzone entferne (wenn der Dragleave ausgelöst wird), würde ich den Stil einfach auf die übergeordnete Dropzone anwenden, wenn ich ein Kind drückte. Das Problem ist natürlich, dass beim Ziehen von der Dropzone zu einem Kind der Dropzone das Dragenter vor dem Dragleave auf das Kind abgefeuert wird, so dass meine Stile nicht in der richtigen Reihenfolge angewendet wurden. Die Lösung bestand für mich darin, einen Zeitgeber zu verwenden, um das Dragenter-Ereignis zurück in die Nachrichtenwarteschlange zu zwingen, so dass ich es NACH dem Dragieren bearbeiten kann. Ich habe eine Schließung verwendet, um auf das Ereignis im Timer-Rückruf zuzugreifen.

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

Dies scheint in Chrom, dh Firefox, zu funktionieren und funktioniert unabhängig von der Anzahl der Kinder in der Dropzone. Ich bin etwas unruhig wegen der Zeitüberschreitung, die die Neuberechnung von Ereignissen garantiert, aber es scheint ziemlich gut für meinen Anwendungsfall zu funktionieren.

0
mefopolis

Ich war mit keiner der hier vorgestellten Problemumgehungen zufrieden, da ich die Kontrolle über die Kinderelemente nicht verlieren möchte.

Ich habe also einen anderen Logikansatz verwendet und ihn in ein jQuery-Plugin übersetzt, das als jquery-draghandler bezeichnet wird. Es manipuliert absolut nicht das DOM und garantiert hohe Leistungen. Die Verwendung ist einfach:

$(document).ready(function() {

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

});

Das Problem wird einwandfrei gelöst, ohne dass die DOM-Funktionalität beeinträchtigt wird.

Download, Details und Erklärungen zu seinem Git-Repository .

0
Black Shell

Hier eine der einfachsten Lösungen ● ︿ ●

Werfen Sie einen Blick auf diese Fiddle <- Versuchen Sie, eine Datei in die Box zu ziehen

Sie können so etwas tun:

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

Damit sollten Sie bereits wissen, was hier passiert.
Schauen Sie sich einfach die Geige an, wissen Sie.

0

Ich habe versucht, dies selbst zu implementieren, und ich wollte weder Jquery noch irgendein Plugin. 

Ich wollte den Datei-Upload so behandeln, wie es mir am besten erschien:

Dateistruktur: 

---/uploads {uploads-Verzeichnis}

--- /js/slyupload.js {Javascript-Datei.}

--- index.php

--- upload.php

--- styles.css {nur ein bisschen styling ..}

HTML Quelltext:

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

Dann ist dies die angehängte Javascript-Datei :: '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
Andaeiii

Meine Version:

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

Mit diesem Layout:

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

Ich habe einen Dump von Elementklassen für e.target, e.currentTarget, e.relatedTarget für dragover und dragleave Ereignisse erstellt.

Es zeigte mir, dass beim Verlassen des übergeordneten Blocks (.dropzone) e.relatedTarget kein untergeordnetes Element dieses Blocks ist, und ich weiß, dass ich mich außerhalb der Dropzone befinde.

0
mortalis