14

互联网上有许多所见即所得的编辑器,但我还没有找到一个实现某种形式的拖放实现的编辑器。

创建自己的编辑器很容易,但我希望用户能够从可编辑区域外拖动元素(即标记),并让他们将其放置在可编辑区域内他们选择的位置。

在可编辑元素的特定位置注入 html 很容易,但是当用户在可编辑区域中的某个元素上拖动 DIV 时,如何确定插入符号的位置。为了更好地说明我要解释的内容,请参见以下场景。

可编辑区域(处于编辑模式的 IFRAME 或 contentEditable 属性设置为 true 的 DIV)已包含以下文本:

“亲爱的,请注意……”

用户现在将表示元素列表中某个标记的元素拖到可编辑区域上,将光标移动到文本上,直到插入符号出现在文本中的逗号 (,) 之前,如上所示。当用户在该位置释放鼠标按钮时,将注入 HTML,这可能会导致如下所示:

“亲爱的 {UserFirstName},请注意……”。

我不知道是否有人做过类似的事情,或者至少知道如何使用 JavaScript 来做这件事。

任何帮助将不胜感激。

4

3 回答 3

6

这是我解决可编辑元素上的自定义拖动元素问题的方法。最大的问题是当鼠标悬停在可编辑元素上时,无法确定鼠标光标的文本偏移量。我曾尝试假装单击鼠标以将插入符号设置在所需位置,但这不起作用。即使这样做了,在拖动时也不会直观地看到插入符号的位置,而只会看到结果下降。

由于可以将鼠标悬停事件绑定到元素而不是文本节点,因此可以将可编辑元素设置为暂时不可编辑。查找所有元素并将每个文本节点包装在一个跨度中,以免破坏文本流。每个跨度都应该有一个类名,以便我们可以再次找到它们。

包装之后,应该再次找到所有包装的文本节点,并将每个字符与另一个具有类名的跨度包装在一起,以便再次找到它们。

使用事件委托,可以将一个事件添加到主要的可编辑元素,该元素将为每个字符跨度应用一种样式,以显示插入符号,一个闪烁的 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);
});

希望这种方法可以帮助那些有类似挑战的人

于 2011-08-15T07:42:15.193 回答
2

如果我明白你在说什么,那么这只是基本的拖放。下面的解决方案应该接近 FIREFOX 的最佳答案。我敢肯定 IE 有不同的功能。如需更多帮助,请访问 http://www.html5rocks.com/en/tutorials/dnd/basics/ 。

设置要拖动的对象的“可拖动”属性,并将对象的“ondragstart”方法设置为“dragStartHandler”或调用任何您的函数。

// You can set this to 'text/plain' if you don't want to insert HTML content
var internalDNDType = 'text/html';

function dragStartHandler(event) {
  // This is whatever html data you want to insert.
  var textContent = "<b>"+userFirstName+"</b>";

  event.dataTransfer.setData(internalDNDType, textContent);
  event.dataTransfer.effectAllowed = 'copy';
}

function dragEnterHandler(event)
{
  event.preventDefault();
  return false;
}

function dragOverHandler(event)
{
  event.preventDefault();
  return false;
}

function dropHandler(event) {
  event.preventDefault();
  event.stopPropogation();
  return false;
}
于 2012-01-03T19:28:18.453 回答
1

目前正在开发一个 HTML5 API 来执行此操作,但不幸的是 IE 不支持它。编辑:显然 IE 实际上确实支持拖放,但我不太熟悉它是如何工作的。尝试谷歌搜索“IE拖放”。

尝试查看这些网站:

于 2010-06-18T23:48:20.357 回答