使用 HTML5 拖放防止拖动事件干扰 Firefox 中的输入元素

Posted

技术标签:

【中文标题】使用 HTML5 拖放防止拖动事件干扰 Firefox 中的输入元素【英文标题】:Prevent drag event to interfere with input elements in Firefox using HTML5 drag/drop 【发布时间】:2014-03-07 23:17:39 【问题描述】:

似乎输入元素在放入具有可拖动=“真”的元素时失去了很多功能。这似乎只发生在 Firefox 中。

查看我的 jsfiddle: http://jsfiddle.net/WC9Fe/3/

html

<div id="drag" draggable="true">
    Drag this div <br />
    <input id="message" type="text" />
</div>
<div id="drop">
    Drop area
</div>

JS:

$('#drag').on('dragstart', function(e)
    e.originalEvent.dataTransfer.setData('Text', $('#message').val());
    e.originalEvent.dataTransfer.effectAllowed = 'move';
);

var drop = $('#drop');
drop.on('dragover', function(e)
    e.preventDefault();
);
drop.on('dragenter', function(e)
    e.preventDefault();
);
drop.on('drop', function(e)
    alert('Target succesfully dropped: ' + e.originalEvent.dataTransfer.getData('Text'));
    e.preventDefault();
);

现在尝试使用 firefox 在输入中选择文本。似乎不可能。在 IE/Chrome 中尝试相同的操作。似乎工作得很好。

【问题讨论】:

在 IE 中也观察到此问题...确切地说是 IE 11.0.9600.. 【参考方案1】:

据我所知,这是 FF 中的一个已知错误。一个快速(和“dirty”的解决方法)是删除文本输入 focus 事件上的 draggable 属性,在文本输入 blur 事件上再次添加它,并在 # 上禁用文本选择拖动 div 以在您单击焦点输入外部时启用拖动(直接单击#div)。

更新了小提琴here。

示例代码:

JS:

$('#message')
    .on('focus', function(e) 
        $(this).closest('#drag').attr("draggable", false);
    )
    .on('blur', function(e) 
        $(this).closest('#drag').attr("draggable", true);
    );

CSS:

.disable-selection 
    /* event if these are not necessary, let's just add them */
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;

    /* this will add drag availability once you clicked the 
       #drag div while you're focusing #message div */
    -moz-user-select: none;

希望对你有帮助。

【讨论】:

谢谢!确实是一个肮脏的解决方法......至于现在:我从可拖动区域中删除了输入元素,因为我没有在所有浏览器中达到预期的效果(IE8仍然是一个问题)。你会建议不要使用 html5 拖放,而是使用 JQuery UI 拖放吗? 您可以通过以下方式找到更多信息:advantages of html5 drag and drop over jquery ui drag and drop 和 html5 vs jquery ui drag and drop。如果您需要针对各种浏览器(也包括旧版浏览器),如果您不想头疼并且时间紧迫,我建议您使用 jQuery UI 拖放。【参考方案2】:

见火狐defect。

作为替代方法,在输入焦点事件上设置 draggable="false" 并在输入模糊事件上替换回 draggable="true"。

请参阅jsfiddle 了解没有任何框架的示例。

HTML:

<div draggable="true" id="draggableDiv">
    <textarea onfocus="onFocus();" onblur="onBlur();">Inside draggable (FIXED)</textarea>
</div>

JS:

onFocus= function(e) 
    document.getElementById("draggableDiv").setAttribute("draggable", "false");

onBlur= function(e) 
    document.getElementById("draggableDiv").setAttribute("draggable", "true");

【讨论】:

【参考方案3】:

我在 textarea 上使用了 onMouseEnter 和 onMouseLeave 函数来设置只有当鼠标在 textarea 之外时 div 才可拖动。

我这样做是因为我需要焦点保持在编辑字段中,而拖动和拖动本身不会触发焦点事件。

【讨论】:

【参考方案4】:

我还发现使用 onmouseenter 和 onmouseleave 来切换可拖动属性效果更好,因为它将光标放在您实际单击的输入框中。使用 onfocus/onblur 时,即使单击中间,光标也会始终移动到文本的开头或结尾。

【讨论】:

【参考方案5】:

如果你和我一样遇到这个问题,并且正在使用 Sortable.js,你可以使用filter 选项来指定不会触发拖动的元素,从而让输入正常运行。

JQuery:

$('#my-sortable').sortable(
    filter: ".my-text-input",   // Or whatever class you specify
    preventOnFilter: false      // Allow the input to operate normally
);

您还可以从此处的 Sortable.js 选项列表中找到此信息: https://github.com/SortableJS/sortablejs

【讨论】:

以上是关于使用 HTML5 拖放防止拖动事件干扰 Firefox 中的输入元素的主要内容,如果未能解决你的问题,请参考以下文章

javascript中ondragover是啥事件

HTML5 使用 Hammer.js 拖动事件在 div 上拖放元素

H5拖动事件复习

HTML5 拖放:防止浏览器和浏览器窗口之间的 D&D

HTML5拖放期间没有关键事件

HTML5拖放(Drag和Drop)元素使用详解