457 Stimmen

HTML5-Dragleave wird beim Verweilen auf einem untergeordneten Element ausgelöst

Das Problem, das ich habe, ist, dass die dragleave Ereignis eines Elements wird ausgelöst, wenn der Mauszeiger über ein untergeordnetes Element dieses Elements bewegt wird. Auch, dragenter wird nicht ausgelöst, wenn der Mauszeiger wieder zum übergeordneten Element zurückkehrt.

Ich habe eine vereinfachte Fiedel gemacht: http://jsfiddle.net/pimvdb/HU6Mk/1/ .

HTML:

<div id="drag" draggable="true">drag me</div>

<hr>

<div id="drop">
    drop here
    <p>child</p>
    parent
</div>

mit dem folgenden JavaScript:

$('#drop').bind({
                 dragenter: function() {
                     $(this).addClass('red');
                 },

                 dragleave: function() {
                     $(this).removeClass('red');
                 }
                });

$('#drag').bind({
                 dragstart: function(e) {
                     e.allowedEffect = "copy";
                     e.setData("text/plain", "test");
                 }
                });

Es soll den Benutzer benachrichtigen, indem es die Drop div rot, wenn etwas dorthin gezogen wird. Das funktioniert, aber wenn Sie etwas in den Bereich p Kind, das dragleave wird ausgelöst und die div ist nicht mehr rot. Zurück zum Tropfen div macht es auch nicht wieder rot. Es ist notwendig, sich vollständig aus dem Tropfen herauszubewegen div und ziehen Sie es erneut hinein, um es rot zu machen.

Ist es möglich zu verhindern dragleave beim Ziehen in ein untergeordnetes Element nicht ausgelöst wird?

2017 Update: TL;DR, CSS nachschlagen pointer-events: none; wie in der Antwort von @H.D. unten beschrieben, die in modernen Browsern und IE11 funktioniert.

5voto

Chris Kirby Punkte 117

Ich weiß, dies ist eine alte Frage, aber ich wollte meine Präferenz hinzufügen. Ich befasse mich mit diesem durch Hinzufügen von Klasse ausgelöst css :nach Element bei einem höheren z-Index als Ihr Inhalt. Dadurch wird der ganze Müll herausgefiltert.

.droppable{
    position: relative;
    z-index: 500;
}

.droppable.drag-over:after{
    content: "";
    display:block;
    position:absolute;
    left:0;
    right:0;
    top:0;
    bottom:0;
    z-index: 600;
}

Dann fügen Sie einfach die Drag-over-Klasse zu Ihrem ersten Dragenter-Ereignis hinzu und keines der untergeordneten Elemente löst das Ereignis mehr aus.

dragEnter(event){
 dropElement.classList.add('drag-over');
}

dragLeave(event){
 dropElement.classList.remove('drag-over');
}

5voto

Profet Punkte 935

Eine alternative Lösung, die ein wenig einfacher ist.

//Note: Due to a bug with Chrome the 'dragleave' event is fired when hovering the dropzone, then
//      we must check the mouse coordinates to be sure that the event was fired only when 
//      leaving the window.
//Facts:
//  - [Firefox/IE] e.originalEvent.clientX < 0 when the mouse is outside the window
//  - [Firefox/IE] e.originalEvent.clientY < 0 when the mouse is outside the window
//  - [Chrome/Opera] e.originalEvent.clientX == 0 when the mouse is outside the window
//  - [Chrome/Opera] e.originalEvent.clientY == 0 when the mouse is outside the window
//  - [Opera(12.14)] e.originalEvent.clientX and e.originalEvent.clientY never get
//                   zeroed if the mouse leaves the windows too quickly.
if (e.originalEvent.clientX <= 0 || e.originalEvent.clientY <= 0) {

5voto

chrisallick Punkte 1300

Ich bin nicht sicher, ob dies browserübergreifend ist, aber ich habe es in Chrome getestet und es löst mein Problem:

Ich möchte eine Datei über die gesamte Seite ziehen und ablegen, aber mein Dragleave wird ausgelöst, wenn ich über ein untergeordnetes Element ziehe. Meine Lösung war es, auf die x und y der Maus zu schauen:

Ich habe ein Div, das meine gesamte Seite überlagert, wenn die Seite lädt, blende ich es aus.

Wenn Sie über das Dokument ziehen, zeige ich es an, und wenn Sie es auf dem übergeordneten Dokument ablegen, wird es behandelt, und wenn Sie das übergeordnete Dokument verlassen, prüfe ich x und y.

$('#draganddrop-wrapper').hide();

$(document).bind('dragenter', function(event) {
    $('#draganddrop-wrapper').fadeIn(500);
    return false;
});

$("#draganddrop-wrapper").bind('dragover', function(event) {
    return false;
}).bind('dragleave', function(event) {
    if( window.event.pageX == 0 || window.event.pageY == 0 ) {
        $(this).fadeOut(500);
        return false;
    }
}).bind('drop', function(event) {
    handleDrop(event);

    $(this).fadeOut(500);
    return false;
});

5voto

sofarsoghood Punkte 233

Prüfen Sie einfach, ob es sich bei dem gezogenen Element um ein untergeordnetes Element handelt, und wenn ja, dann entfernen Sie die Stilklasse "dragover" nicht. Ziemlich einfach und funktioniert für mich:

 $yourElement.on('dragleave dragend drop', function(e) {
      if(!$yourElement.has(e.target).length){
           $yourElement.removeClass('is-dragover');
      }
  })

4voto

Ben Punkte 660

Ich habe eine kleine Bibliothek geschrieben, die Dragster um genau dieses Problem zu behandeln, funktioniert überall außer stillschweigend nichts in IE (die nicht unterstützt DOM Event Constructors, aber es wäre ziemlich einfach, etwas ähnliches mit jQuery's benutzerdefinierte Ereignisse zu schreiben)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X