【问题标题】:Rangy + ContentEditable + Set Caret and Replace SelectionRangy + ContentEditable + 设置插入符号和替换选择
【发布时间】:2012-01-19 08:40:49
【问题描述】:

我有以下代码片段将插入符号设置为给定索引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 中的一个位置(就好像它们只是一个字符一样)。

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

非常欢迎所有帮助!

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

http://jsfiddle.net/ee93P/

【问题讨论】:

  • I want to treat these inputs as just one position in the div (as if they were just a single character). 在 Firefox 中对我来说就是这样。
  • 是的,但问题是我想操纵 div 来编辑选择并将插入符号放在我想要的位置。
  • 啊,我明白了。 (你正在研究的东西。:)

标签: jquery html contenteditable rangy


【解决方案1】:

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

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

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

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

如果您想将位置设置为&lt;p&gt; 元素文本内容中的偏移量,则需要进行一些 DOM 遍历。我已经编写了一个基于another answer of mine 的实现。这是一个幼稚的实现:它没有考虑任何可能变得不可见的文本(例如,通过 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;
        }
    }
}

【讨论】:

  • 我怎么能做类似的事情,在同一个 div 中获取选定的范围?
  • @Nico:您可以在此答案中调整 saveSelection() 函数:stackoverflow.com/questions/5595956/…。如果我有时间,我会试着看看它。
  • 你救了我的命。谢谢你,先生,我会给你所有的答案+1:D
猜你喜欢
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多