contenteditable div 中的 HTML5 可拖动元素 - 第一次放置后停止工作 - 为啥?
Posted
技术标签:
【中文标题】contenteditable div 中的 HTML5 可拖动元素 - 第一次放置后停止工作 - 为啥?【英文标题】:HTML5 draggable elements within contenteditable div - stops working after first drop - why?contenteditable div 中的 HTML5 可拖动元素 - 第一次放置后停止工作 - 为什么? 【发布时间】:2013-05-29 19:09:31 【问题描述】:我正在尝试创建一些可以在 contenteditable div 内拖动的可拖动元素(标记)。似乎一切正常,除了......在我拖动一个元素并将其放下后,我无法再次拖动它。看来我无法再次绑定到它的 dragstart 事件了。
知道为什么会发生这种情况,我该如何解决?
这是我的小提琴的链接:http://jsfiddle.net/gXScu/1/
html:
<div id="editor" contenteditable="true">
Testime siinkohal seda, et kuidas<br />
on võimalik asja testida.
<span class="draggable" draggable="true" contenteditable="false">Token</span>
</div>
<span class="draggable" draggable="true" contenteditable="false">Token 2</span>
javascript (jQuery)
var bindDraggables = function()
console.log('binding draggables', $('.draggable').length);
$('.draggable').off('dragstart').on('dragstart', function(e)
if (!e.target.id)
e.target.id = (new Date()).getTime();
e.originalEvent.dataTransfer.setData('text/html', e.target.outerHTML);
console.log('started dragging');
$(e.target).addClass('dragged');
).on('click', function()
console.log('there was a click');
);
$('#editor').on('dragover', function (e)
e.preventDefault();
return false;
);
$('#editor').on('drop', function(e)
e.preventDefault();
var e = e.originalEvent;
var content = e.dataTransfer.getData('text/html');
var range = null;
if (document.caretRangeFromPoint) // Chrome
range = document.caretRangeFromPoint(e.clientX, e.clientY);
else if (e.rangeParent) // Firefox
range = document.createRange();
range.setStart(e.rangeParent, e.rangeOffset);
console.log('range', range)
var sel = window.getSelection();
sel.removeAllRanges(); sel.addRange(range);
$('#editor').get(0).focus(); // essential
document.execCommand('insertHTML',false, content);
//$('#editor').append(content);
sel.removeAllRanges();
bindDraggables();
console.log($('[dragged="dragged"]').length);
$('.dragged').remove();
);
bindDraggables();
CSS:
#editor
border: 2px solid red;
padding: 5px;
.draggable
display: inline-block;
padding: 3px;
background: yellow;
cursor: move !important;
【问题讨论】:
它在 Firefox 上运行良好,因此很可能是 Chrome 的错误。并且仅当您使用insertHTML
命令时才会发生。当我用$('#editor').append(content)
替换它时,一切正常......
【参考方案1】:
我也尝试了一些技巧,但它们似乎都不起作用。我正在检查 HTML,发现在您的示例中,新插入的 content 没有分配任何 contenteditable 属性,当我手动分配给它时,它开始正常工作。
这是我的代码http://jsfiddle.net/gXScu/8/
我刚刚添加了这一行
$('.draggable').attr("contenteditable", false);
在bindDraggables
方法中。
我同意 Reinmar 对 contenteditable 的解释。
【讨论】:
@Reinmar: :-)。因此,如果我们通过“document.execCommand”执行“insertHTML”,那么 Chrome 会默默地删除“contenteditable”属性:-)。 Firefox 和 Chrome 都可能使用 'document.execCommand('insertHTML',false, content);' 给出不一致的结果。要解决此问题,请将其更改为“pasteHtmlAtCaret(content)”。功能可以在这里找到:***.com/questions/6690752/…【参考方案2】:显然 Chrome 有一个错误(不足为奇 - contenteditable
是所有浏览器中错误最多的功能)。您的代码在 Firefox 上运行良好,但由于某种原因,使用 insertHTML
命令插入可编辑的元素无法再拖动。
我尝试了一些技巧,但只有一个有效 - 插入其他元素然后替换它。
所以改为:
document.execCommand('insertHTML', false, content);
使用这样的东西:
var spanId = 'temp-' + (new Date()).getTime();
// Insert span with zero-width space (so it isn't visible and it isn't empty).
document.execCommand('insertHTML', false, '<span id="' + spanId + '">\u200b</span>');
// Replace that span with our dragged content.
$('#' + spanId).replaceWith(content);
您可以在这里尝试:http://jsfiddle.net/gXScu/5/。我还纠正了这个错误的顺序:
$('.dragged').remove();
bindDraggables();
【讨论】:
这是一个完全有效的答案和一个很好的解释,谢谢!我选择了 Imran 的答案,因为它更简单,不需要创建额外的元素。 恕我直言,唯一缺少的是插入符号指示器,用于显示鼠标向上后项目将被放置的位置。这有可能吗?以上是关于contenteditable div 中的 HTML5 可拖动元素 - 第一次放置后停止工作 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章
更改 innerHTML 后更改 contenteditable div 中的光标位置
jqueryui 将图像拖入 contentEditable div 并将其放在文本中的该位置
垂直对齐 td 中 contenteditable div 中的文本,其中 div 与 td 大小相同
在 contenteditable div 中的特定位置设置插入符号位置