JS - 如何获取节点开头和当前光标位置(文本光标)之间的文本?

4

我需要获取一个带有contenteditable属性的元素中,当前文本光标位置所在节点的文本(或整个内部html)并进行截断。我尝试使用range.setStart()等方法,但是我无法理解...

编辑: 为了澄清,在某些事件发生时,我希望脚本从当前具有焦点的节点的开头提取文本到光标位置(如果可编辑字段具有焦点,则为闪烁垂直线所在位置),并将其存储在变量中。类似于用户按下ctrl+shift+home和ctrl+c时发生的操作。

示例: 给定html:

<span contenteditable=true>Hello, world<br> Good bye, World</span>

假设插入符号在“Good”和“bye”之间,我想要获取以下内容:

"Hello, world<br> Good"

请注意保留HTML标记。

请提供更多细节... - mate64
这大致就是全部内容了。在某些事件发生时,我想从当前具有焦点的节点的开头提取文本到插入符号的位置,并稍后在脚本中使用它。类似于用户按下 Ctrl+Shift+Home 和 Ctrl+C 所发生的操作。 - Kuba Orlik
什么是caret?是哪种节点? - Fresheyeball
通过“插入符号”,我指的是文本光标。它可以是任何节点,我考虑使用带有contenteditable属性的span标签。 - Kuba Orlik
请发布一些HTML代码,告诉我们插入符号将在哪里(在这个例子中),并清楚地告诉我们您希望从函数中检索到什么。 - David Thomas
显示剩余2条评论
4个回答

7
我建议采用以下方法:
  • 创建一个包含所需内容的范围
  • 调用该范围的cloneContents()方法获取表示范围内容的DocumentFragment
  • 创建一个<div><body>元素并将片段附加到其上
  • 获取元素的innerHTML

示例:http://jsfiddle.net/sUSYG/

代码:

function getHtmlPrecedingSelectionIn(container) {
    var html = "";
    if (window.getSelection && document.createRange) {
        var sel = window.getSelection();
        if (sel.rangeCount > 0) {
            var selRange = sel.getRangeAt(0);
            var range = document.createRange();
            range.selectNodeContents(container);
            range.setEnd(selRange.startContainer, selRange.startOffset);

            var frag = range.cloneContents();
            var el = document.createElement("body");
            el.appendChild(frag);
            html = el.innerHTML;
        }
    }
    return html;
}

注意事项:
  • 此方法不适用于IE <= 8,不过使用不同的选择/范围API编写代码或使用像Rangy这样的库并非太难实现。
  • 生成的HTML不能保证是可编辑区域原始HTML的子字符串。

6

你可以使用 RangyjQuery 轻松完成这个操作。

这里有一个 jsFiddle 演示了这种方法。注释中解释了发生了什么。

$("contenteditable-element").click(function () {
    // Get the current selection with Rangy
    var sel = rangy.getSelection()
    // Insert a temporary caret element at the caret position 
    // (which is inside the contenteditable element)
    if (sel.rangeCount) sel.getRangeAt(0).insertNode($("<caret />")[0]);
    // Read the html inside the contenteditable element
    var innerHTML = $("contenteditable-element").html();
    // Clean up, get rid of the caret element
    $("caret").remove();
    // Only keep the text before the first occurrence of the caret element
    innerHTML = innerHTML.substr(0, innerHTML.indexOf('<caret>'));
});

0
也许这会引导你朝正确的方向前进: 获取相对于其父容器的范围起始和结束偏移量 我创建了一个小示例,展示了该函数在您的示例中的工作方式: http://jsfiddle.net/Kn8qr/2/
function getCaret(element) {
var caretOffset = 0;
if (typeof window.getSelection != "undefined") {
    var range = window.getSelection().getRangeAt(0);
    var preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(element);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    caretOffset = preCaretRange.toString().length;
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
    var textRange = document.selection.createRange();
    var preCaretTextRange = document.body.createTextRange();
    preCaretTextRange.moveToElementText(element);
    preCaretTextRange.setEndPoint("EndToEnd", textRange);
    caretOffset = preCaretTextRange.text.length;
}
var elCont=element.innerHTML;

var truncCont=elCont.substr(0,caretOffset);

alert(truncCont);
}

这个功用的作者应该得到赞誉,我只是稍微编辑了一下。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接