如何在两个div之间的contenteditable div中设置插入符/光标位置。

时间:2012-12-31 06:30:48

标签: javascript dom cursor range contenteditable

考虑以下可疑的div。

<div contenteditable="true">
<div>bold text</div><div>bold text</div>
</div>

如果我将光标放在两个div之间并开始输入,则文本将以粗体显示,而不是在两个div之间插入新的文本节点。如果你回到家并尝试在第一个div前面输入一些东西,也会发生同样的情况。它成为第一个div的一部分。

如果我检查从选择中返回的范围的startContainer,我会得到其中一个div的内容而不是我期望的空文本节点。

请参阅此http://jsfiddle.net/9ZZpX/3/

问题是为什么会发生这种情况?如何选择div之间的位置,以便在输入内容时不会加粗? (显然我可以添加一个空间,这可以解决问题,但这很难看。)

如果您在状态更新框中输入@mention并按HOME,则可以在Facebook上看到此功能正常工作。如果键入,文本将不会突出显示。

我唯一能想到的就是拦截按键并以编程方式插入文本节点,但这看起来很难看。

我疯狂地搜索,找不到任何记录如何真正起作用的参考文献。显然有一些我不理解的东西,而且这方面的文档确实缺乏。

(我希望能够做的是检测光标即将进入其中一个div并跳过它。如果两个div正好相邻,则光标会跳转到其中一个divs和它破坏了作品。)

有关我正在尝试做的更多信息:http://a-software-guy.com/2012/12/the-horrors-of-cursor-positioning-in-contenteditable-divs/

3 个答案:

答案 0 :(得分:8)

浏览器与此不一致。 Firefox将允许您将插入符放置在比大多数浏览器更多的位置,但WebKit和IE都有关于有效插入符位置的明确想法,并将修改您添加到选择中的范围以符合最接近的有效位置。这确实有意义:具有不同的文档位置并因此对于相同的视觉插入位置的行为使用户感到困惑。但是,这是以开发人员缺乏灵活性为代价的。

这在任何地方都没有记录。 current Selection spec对此一无所知,主要是因为当浏览器实现其选择API时没有规范,并且当前规范没有统一的行为来记录。

一种选择是按照您的建议截取keypress事件,但是当用户使用编辑或上下文菜单粘贴内容时,这将无济于事。另一种方法是使用鼠标和键事件跟踪选择,创建元素,例如,零宽度空格字符,以便放置插入符号,并在必要时将插入符号放在一个元素中。如你所说,丑陋。

答案 1 :(得分:4)

我的答案只是Tim的一个补充,这是一个全面的。

AFAIK Facebook不使用可编辑的内容。状态框由一个简单的textarea和div层组成,在它下面为它们呈现蓝色。

虽然,即使他们这样做,但这将是一个不同的情况,因为nick将是一个内联元素,幸运的是内联元素的情况更简单:)。

关于在难以接近的地方放置插入符号 - 在CKEditor我们遇到了同样的问题。有很多地方用户无法移动插入符号。我们决定使用名为Magic-line的插件解决此问题。正如您在演示中看到的那样,我们完全绕过了选择问题,我认为这是解决此问题的最佳方法。它非常实用,在CKEditor 4.0.1中,它(并且已经在master上)也可以通过击键完全访问。

答案 2 :(得分:0)

您可以做的另一件事是使用Mutation Observer来捕获突变,然后在事后修复它们。在我的用例中,我很幸运,因为每个元素都有预定义的文本。当变异观察者触发时,我只是根据需要将更改的文本移动到元素之前或之后的新文本节点。这似乎比其他选项容易得多,因为观察者会触发对字符数据的所有更改,并且它还具有所有更改的正确记录,这与keypress事件不同。