6

考虑以下内容可编辑的 div。

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

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

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

$( '#EDITABLE' ).focus();

var selection = window.getSelection();

var range = document.createRange();

var div = $('#div2').get(0);

range.setStartBefore(div);
range.collapse(true);

selection.removeAllRanges();
selection.addRange(range);

// cursor should now be between div1 and div2

range = window.getSelection().getRangeAt(0);

console.log("range object returned is: ", range);

// type something into the content editable div. why is it coming
// up bold since the cursor should be between the divs? it's 
// positioning the cursor at the end of the previous div. I want to
// target the spot between the divs. how?
div.content {
  display: inline-block;
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div contenteditable="true" id="EDITABLE">
  <div class="content" id="div1">Content for div1</div>
  <div class="content" id="div2">content for div 2</div>
</div>

原jsfiddle:http: //jsfiddle.net/9ZZpX/3/

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

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

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

我疯狂地搜索,找不到任何说明这应该如何工作的参考资料。显然有些东西我不明白,而且这方面的文档确实很缺乏。

(我也想做的是检测光标何时要进入这些 div 之一并跳过它。如果两个 div 彼此相邻,则光标会跳入其中一个 div 并且它搞砸了作品。)

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

4

3 回答 3

8

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

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

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

于 2012-12-31T17:02:28.850 回答
4

我的回答只是对蒂姆回答的补充,它是全面的。

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

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

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

于 2013-01-01T16:02:06.210 回答
0

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

于 2015-03-19T11:48:18.020 回答