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.

16voto

Owen M Punkte 2425

Eine sehr einfache Lösung:

parent.addEventListener('dragleave', function(evt) {
    if (!parent.contains(evt.relatedTarget)) {
        // Here it is only dragleave on the parent
    }
}

8voto

rasmusx Punkte 877

Ich hatte das gleiche Problem und habe versucht, die Lösung von pk7 zu verwenden. Es funktionierte, aber es könnte ein wenig besser gemacht werden, ohne zusätzliche Dom-Elemente.

Im Grunde ist die Idee die gleiche - fügen Sie eine zusätzliche unsichtbare Overlay über droppable Bereich. Nur lässt dies ohne zusätzliche Dom-Elemente zu tun. Hier ist der Teil, wo CSS Pseudo-Elemente ins Spiel kommen.

Javascript

var dragOver = function (e) {
    e.preventDefault();
    this.classList.add('overlay');
};

var dragLeave = function (e) {
    this.classList.remove('overlay');
};

var dragDrop = function (e) {
    this.classList.remove('overlay');
    window.alert('Dropped');
};

var dropArea = document.getElementById('box');

dropArea.addEventListener('dragover', dragOver, false);
dropArea.addEventListener('dragleave', dragLeave, false);
dropArea.addEventListener('drop', dragDrop, false);

CSS

Mit dieser Nachregel wird ein vollständig abgedeckter Overlay für den abwerfbaren Bereich erstellt.

#box.overlay:after {
    content:'';
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1;
}

Hier ist die vollständige Lösung: http://jsfiddle.net/F6GDq/8/

Ich hoffe, es hilft allen, die das gleiche Problem haben.

7voto

marcelj Punkte 589

Hier ist eine weitere Lösung mit document.elementFromPoint:

 dragleave: function(event) {
   var event = event.originalEvent || event;
   var newElement = document.elementFromPoint(event.pageX, event.pageY);
   if (!this.contains(newElement)) {
     $(this).removeClass('red');
   }
}

Hoffentlich funktioniert das, hier ist ein fiddle .

7voto

robertc Punkte 72049

Sie können das Problem in Firefox mit ein wenig Inspiration durch die jQuery-Quellcode :

dragleave: function(e) {
    var related = e.relatedTarget,
        inside = false;

    if (related !== this) {

        if (related) {
            inside = jQuery.contains(this, related);
        }

        if (!inside) {

            $(this).removeClass('red');
        }
    }

}

Leider funktioniert es in Chrome nicht, weil relatedTarget scheint nicht zu existieren auf dragleave Ereignisse, und ich nehme an, dass Sie mit Chrome arbeiten, da Ihr Beispiel in Firefox nicht funktioniert hat. Hier ist eine Version mit dem obigen Code implementiert.

7voto

Aldekein Punkte 3219

Und hier ist sie, eine Lösung für Chrome:

.bind('dragleave', function(event) {
                    var rect = this.getBoundingClientRect();
                    var getXY = function getCursorPosition(event) {
                        var x, y;

                        if (typeof event.clientX === 'undefined') {
                            // try touch screen
                            x = event.pageX + document.documentElement.scrollLeft;
                            y = event.pageY + document.documentElement.scrollTop;
                        } else {
                            x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
                            y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
                        }

                        return { x: x, y : y };
                    };

                    var e = getXY(event.originalEvent);

                    // Check the mouseEvent coordinates are outside of the rectangle
                    if (e.x > rect.left + rect.width - 1 || e.x < rect.left || e.y > rect.top + rect.height - 1 || e.y < rect.top) {
                        console.log('Drag is really out of area!');
                    }
                })

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