无法触发 drop 事件(是的,我在 dragover 中阻止了 Default()ed)

Posted

技术标签:

【中文标题】无法触发 drop 事件(是的,我在 dragover 中阻止了 Default()ed)【英文标题】:Can't get drop event to fire (and yes, I preventDefault()ed in dragover) 【发布时间】:2014-01-22 01:51:25 【问题描述】:

我正在实现可拖动的 html5 列表,但遇到了麻烦。

基本上,每当我拖动一个元素时,我都会在我刚输入的元素之前或之后插入我正在拖动的元素。这意味着当您四处移动鼠标时,元素会不断移动到鼠标下方的位置。 (我在元素上设置了visibility: hidden,所以它显示为一个空格。)当你放下元素时,我会向服务器发送一个 AJAX 调用,描述元素的位置以在服务器上执行移动。

问题是,无论出于何种原因,drop 事件永远不会触发(我的处理程序中的断点永远不会被命中),并且拖动图像会捕捉到它开始的位置。 (当然,元素 在页面上移动了,所以它会重新出现在新位置,但由于 drop 永远不会触发,因此服务器永远不会收到更改通知。)有人知道发生了什么吗?通常的答案是“你需要在 dragenter/dragover 中调用 preventDefault()”,但我已经这样做了。

我使用的是 jQuery 1.10.2,我在 Safari 7.0.1 和 Firefox 26.0 中都看到了这种行为。对于它的价值,Rails 4.0.2 是我的这个项目的框架,我正在使用 jquery_ujs 和 turbolinks。

相关代码:

var draggingLI;

$('ol[data-passage-id]').find('li > a').attr('draggable', 'true')
.on('dragstart', function (ev) 
    draggingLI = $(ev.target).closest("li")[0];

    ev.originalEvent.dataTransfer.effectAllowed = 'move';
    ev.originalEvent.dataTransfer.setData('text/plain', ev.target.href);
    ev.originalEvent.dataTransfer.setData('text/uri-list', ev.target.href);
)
.on('dragenter', function (ev) 
    ev.originalEvent.dataTransfer.dropEffect = 'move'; 
    $(draggingLI).css('visibility', 'hidden');

    if(canDropIn(ev.target)) 
        var droppingLI = $(ev.target).closest("li")[0];

        if(draggingLI == droppingLI) 
            // do nothing
        
        if(draggingLI.nextElementSibling == droppingLI) 
            // We want to move the dragging element below this element.
            $(droppingLI).after(draggingLI);
        
        else 
            // We want to move the dragging element above this element.
            $(droppingLI).before(draggingLI);
        

        ev.preventDefault();
        ev.stopPropagation();
        return false;
    
)
.on('dragover', function (ev) 
    if(canDropIn(ev.target)) 
        ev.preventDefault();
        ev.stopPropagation();
        return false;
    
)
.on('drop', function (ev) 
    sendMovedItem(draggingLI);
    ev.preventDefault();
    ev.stopPropagation();
    return false;
)
.on('dragend', function (ev) 
    $(draggingLI).css('visibility', '');
);

canDropIn() 当前是一个始终返回 true 的存根。 sendMovedItem() 是执行 AJAX 调用的函数。控制台上没有错误。

【问题讨论】:

【参考方案1】:

问题似乎是由我移动拖动元素本身的策略引起的;我不确定这是因为在拖动元素时移动元素会导致浏览器出现问题,还是因为不允许放置在原始元素上。我通过完全隐藏原始元素然后插入一个可以移动的占位符元素来解决它。 (您必须将 dragenter/dragover/drop 处理程序附加到占位符,因为所有成功的放置都在占位符上结束。)

不过,如果有人有想法,我仍然更喜欢不需要占位符的解决方案!

【讨论】:

以上是关于无法触发 drop 事件(是的,我在 dragover 中阻止了 Default()ed)的主要内容,如果未能解决你的问题,请参考以下文章

原生 drag drop HTML5

dragenter/dragleave 防止 drop 发射

HTML5拖拽/拖放(drag & drop)详解

jQuery.on("drop") 没有触发

HTML5拖放的dragover vs dragenter事件

如何从dragover事件中获取源节点