4

我有以下代码片段将插入符号设置为给定索引index

var el = $("#subjectMessage"), index = 9 ;
var range = rangy.createRange();
range.setStart(el[0].childNodes[0], index);
range.collapse(true);
var sel = rangy.getSelection();
sel.setSingleRange(range);

当我将输入元素添加到 contentEditable 时会出现问题div,我无法再将插入符号始终设置在所需位置。

我想将这些输入视为 div 中的一个位置(好像它们只是一个字符)。

除此之外,我还需要类似的代码来用div我自己的一些文本替换此 contentEditable 中的选择,而且我对 rangy 并不十分熟悉(完全)以了解如何使这项工作......

非常欢迎所有帮助!

这是一个你可以玩弄的小提琴:

http://jsfiddle.net/ee93P/

4

1 回答 1

7

Rangy 的 Selection 和 Range API 是标准 DOM Selection 和 Range API 的超集,因此来自 MDN(RangeSelection)等地方的文档适用。

您遇到的问题是范围边界表示为包含 DOM 节点内的偏移量。例如,在下面的 HTML 中,插入符号表示为管道字符:

<p>Foo<br>b|ar</p>

...插入符号范围的开始和结束边界是相同的,并且在文本节点“bar”中设置为偏移量 1。

如果要将位置设置为<p>元素文本内容中的偏移量,则需要进行一些 DOM 遍历。我已经根据我的另一个答案编写了一个实现。这是一个幼稚的实现:它没有考虑任何可能变得不可见的文本(例如,通过 CSS 或通过在 a or 元素内)并且可能存在浏览器差异(IE 与其他所有内容)和换行符,并采取不考虑折叠的空白(例如 2 个或更多连续的空格字符折叠到页面上的一个可见空间)。这是一件很难做到的事情,这就是我通常不推荐它的原因。我打算为 Rangy 编写一个基于文本的模块来处理所有这些,但我还没有开始。

http://jsfiddle.net/ee93P/2/

代码:

function setCaretCharIndex(containerEl, index) {
    var charIndex = 0, stop = {};

    function traverseNodes(node) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (index >= charIndex && index <= nextCharIndex) {
                rangy.getSelection().collapse(node, index - charIndex);
                throw stop;
            }
            charIndex = nextCharIndex;
        }
        // Count an empty element as a single character. The list below may not be exhaustive.
        else if (node.nodeType == 1
                 && /^(input|br|img|col|area|link|meta|link|param|base)$/i.test(node.nodeName)) {
            charIndex += 1;
        } else {
            var child = node.firstChild;
            while (child) {
                traverseNodes(child);
                child = child.nextSibling;
            }
        }
    }

    try {
        traverseNodes(containerEl);
    } catch (ex) {
        if (ex != stop) {
            throw ex;
        }
    }
}
于 2011-12-13T15:22:51.337 回答