这是我解决可编辑元素上的自定义拖动元素问题的方法。最大的问题是当鼠标悬停在可编辑元素上时,无法确定鼠标光标的文本偏移量。我曾尝试假装单击鼠标以将插入符号设置在所需位置,但这不起作用。即使这样做了,在拖动时也不会直观地看到插入符号的位置,而只会看到结果下降。
由于可以将鼠标悬停事件绑定到元素而不是文本节点,因此可以将可编辑元素设置为暂时不可编辑。查找所有元素并将每个文本节点包装在一个跨度中,以免破坏文本流。每个跨度都应该有一个类名,以便我们可以再次找到它们。
包装之后,应该再次找到所有包装的文本节点,并将每个字符与另一个具有类名的跨度包装在一起,以便再次找到它们。
使用事件委托,可以将一个事件添加到主要的可编辑元素,该元素将为每个字符跨度应用一种样式,以显示插入符号,一个闪烁的 GIF 图像作为背景。
同样,使用事件委托,应该为每个字符的鼠标向上事件(放下事件)添加一个事件。现在可以使用字符跨度在其父级(包装的文本节点)中的位置(偏移量)来确定偏移量。现在可以撤消所有包装,保留对计算偏移量的引用,并在撤消包装时保留对适用文本节点的引用。
使用浏览器的范围和选择对象,现在可以使用计算的偏移量设置选择到适用的文本节点,并在新设置的选择(插入符号位置)处注入所需的 HTML,等等!
下面是一个使用 jQuery 的片段,它将找到文本节点,将它们包装起来:
editElement.find("*:not(.text-node)").contents().filter(function(){
return this.nodeType != 1;
}).wrap("<span class=\"text-node\"/>");
要查找每个文本节点并包装每个字符,请使用:
editElement.find(".text-node").each(function()
{
var textnode = $(this), text = textnode.text(), result = [];
for (var i = 0; i < text.length; i++) result.push(text.substr(i, 1));
textnode.html("<span class=\"char\">"
+ result.join("</span><span class=\"char\">") + "</span>");
});
要撤消包装:
editElement.find(".text-node").each(function()
{
this.parentNode.replaceChild(document.createTextNode($(this).text()), this);
});
希望这种方法可以帮助那些有类似挑战的人