Workaround for a Firefox bug

Firefox doesn't trigger dragleave if the mouse leaves the browser
window to another window on top during an active drag. That leaves
OctoPrint stuck with the drag-n-drop overlay.

Adding a timeout for dragover for only Firefox that clears the overlay
solves this issue.

Solves #2166
This commit is contained in:
Gina Häußge 2017-10-23 13:38:18 +02:00
parent cb50646134
commit 4439f5aad0

View file

@ -1004,10 +1004,12 @@ $(function() {
if (enable) {
$(document).bind("dragenter", self._handleDragNDrop);
$(document).bind("dragleave", self._endDragNDrop);
$(document).bind("dragover", self._handleDragOver);
log.debug("Enabled drag-n-drop");
} else {
$(document).unbind("dragenter", self._handleDragNDrop);
$(document).unbind("dragleave", self._endDragNDrop);
$(document).unbind("dragover", self._handleDragOver);
log.debug("Disabled drag-n-drop");
}
};
@ -1081,6 +1083,8 @@ $(function() {
};
self._dragNDropTarget = null;
self._dragNDropFFTimeout = undefined;
self._dragNDropFFTimeoutDelay = 100;
self._forceEndDragNDrop = function () {
self.dropOverlay.removeClass("in");
if (self.dropZoneLocal) self.dropZoneLocalBackground.removeClass("hover");
@ -1094,6 +1098,33 @@ $(function() {
self._forceEndDragNDrop();
};
self._handleDragOver = function(e) {
// Workaround for Firefox
//
// Due to a browser bug (https://bugzilla.mozilla.org/show_bug.cgi?id=656164),
// if you drag a file out of the window no drag leave event will be fired. So on Firefox we check if
// our last dragover event was within a timeout. If not, we assume that's because the mouse
// cursor left the browser window and force a drag stop.
//
// Since Firefox keeps on triggering dragover events even if the mouse is not moved while over the
// browser window, this should work without side effects (e.g. the overlay should stay even if the user
// keeps the mouse perfectly still).
//
// See #2166
if (!OctoPrint.coreui.browser.firefox) return;
if (e.target !== self._dragNDropTarget) return;
if (self._dragNDropFFTimeout !== undefined) {
window.clearTimeout(self._dragNDropFFTimeout);
self._dragNDropFFTimeout = undefined;
}
self._dragNDropFFTimeout = window.setTimeout(function() {
self._forceEndDragNDrop();
self._dragNDropFFTimeout = undefined;
}, self._dragNDropFFTimeoutDelay);
};
self._handleDragNDrop = function (e) {
self.dropOverlay.addClass('in');
@ -1129,6 +1160,7 @@ $(function() {
if (self.dropZoneBackground) self.dropZoneBackground.removeClass("hover");
}
self._dragNDropTarget = e.target;
self._dragNDropLastOver = Date.now();
}
}