上传文件时检测到已取消的拖放操作

Detecting a cancelled drag and drop action when uploading files

本文关键字:取消 拖放 操作 文件 检测      更新时间:2023-09-26

这是我想要的行为:

  1. 用户开始从文件资源管理器拖动文件
  2. 当文件悬停在浏览器窗口上时,将显示 3 个放置区
  3. 当用户取消拖放或拖放文件时,拖放区域将消失。

我遇到的问题是#3。
document上使用dragenter时,放置区看起来很好,但我无法让它们再次消失。

我尝试绑定永不触发的dragenddragleave每次拖动离开后代时都会触发,因此拖动区域会闪烁。

哪个事件是正确的收听?

我还没有完全测试它,但似乎你可以利用 dragenterdragleave 的烦人行为,它会在每个元素上触发。

var counter = 0;
$(document).on('dragenter', function () { 
  if (counter++ === 0) {
    console.log('entered the page');
  }
});
$(document).on('dragleave', function () {
  if (--counter === 0) {
    console.log('left the page');
  }
});

如果通过按 esc 取消拖动,似乎也可以工作。

http://jsbin.com/atodem/2/

document上,你想同时收听dragleavedragover,以分别隐藏和显示区域。

好吧,dragstartdragend 事件似乎仅在将某些内容从浏览器拖动浏览器时才触发,这在您的情况下几乎没有用。 我似乎无法阻止闪烁,但是如果您为dragenterdragleave事件添加超时,则可以最大程度地减少闪烁:

window.onload=function(){
    var drag = new (function(){
        var timeout;
        this.detected = function(){
            return !(timeout === undefined)
        }
        this.start = function(){
            clearTimeout(timeout);
        }
        function endDrag(){
            for (var i=0;i<3;i++) //no longer dragging, remove drop zones
                document.getElementsByClassName("dropZone")[i].style.display="none";
        }
        this.end = function(){
            timeout = setTimeout((function(){timeout=undefined;endDrag();}),1500)
        }
    })()
    document.body.ondragenter = function(){
        drag.start();
        for (var i=0;i<3;i++) //drag started, show drop zones
            document.getElementsByClassName("dropZone")[i].style.display="block";
    }
    document.body.ondragleave = function(event){
        event = event||window.event
        if ((event.source||event.target)==document.body)
            drag.end();
    }
}

希望这有帮助,如果它不完美,对不起。 :-(

您可以通过检查在 dragend 之前是否调用了 drop 来验证它。

     var dragConfirmed;
     document.addEventListener("drop", function( event ) {
          // prevent default action (open as link for some elements)
          event.preventDefault();
          dragConfirmed = true;
      }, false);

      document.addEventListener("dragend", function( event ) {
        if (dragConfirmed != true)
        {
             // Escape has been pressed
        }
      }, false);

拖拽对我不起作用。我使用了超时:

function stopDrag(){
   console.log('bye drag!');
}
var timeoutHandle;
document.addEventListener('dragover', function(){
    console.log('you are dragging');
    window.clearTimeout(timeoutHandle);
    timeoutHandle = window.setTimeout(stopDrag, 200);
}, false);

其他答案都不适合我。就我而言,我需要在拖动开始时将拖放目标 z 索引提高到其他元素上方,并在拖动结束后将其降低。我发现,当拖动启动时,mousemove事件停止触发。我使用该行为来检测拖动何时实际停止。

注意:仅使用火狐 v104 进行测试

let dragging = false;
function dragInit(event) {
    // add drag-init class to all drop targets, raising their z-index 
    if (dragging) return // prevent duplicate calls
    dragging = true
    for (const dt of document.querySelectorAll('.droptarget')) dt.classList.add('drag-init')
    // bind mousemove to body element; mouse move events are stopped while dragging 
    document.body.addEventListener('mousemove', dragEnd)
}
function dragEnd(event) {
    // when the dragging ends, the mousemove events are generated, remove the drag-init class to lower the 
    // droptargets back below the other elements 
    dragging = false
    // remove the listener, no longer needed
    document.body.removeEventListener('mousemove', dragEnd)
    for (const dt of document.querySelectorAll('.droptarget')) dt.classList.remove('drag-init')
}
// initialize drag and drop
document.body.addEventListener('dragenter', dragInit)

.CSS

.droptarget {
    // start the drop target below other elements
    z-index: -1;
}
.droptarget.drag-init {
// user is currently dragging, raise the drop target above other elements 
    z-index: 100;
}