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

时间:2013-05-19 12:43:09

标签: javascript jquery range selection

我需要获取节点的文本(或整个内部html),在contenteditable设置为true的元素中的当前插入符(文本光标)位置上截断。我已经尝试过使用range.setStart()等,但我无法做出正面和反面...

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

时会发生的动作

实施例: 鉴于html:

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

假设插入符号位于“Good”和“bye”之间,我想要检索

"Hello, world<br> Good"

4 个答案:

答案 0 :(得分: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>'));
});

答案 1 :(得分:5)

我建议采用以下方法:

  • 创建包含所需内容的范围
  • 调用范围的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&lt; = 8中不起作用,虽然它不是很难做到(通过使用其不同的选择/范围API或使用诸如Rangy之类的库来编写代码)
  • 生成的HTML不保证是可编辑范围的原始HTML的子字符串。

答案 2 :(得分:0)

也许这会让你朝着正确的方向前进: Get a range's start and end offset's relative to its parent container

我构建了一个小提琴,它显示了与您的示例一起使用的功能: 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);
}

归功于该函数的作者,我刚刚将其编辑为abit。

答案 3 :(得分:0)

看看这个答案:https://stackoverflow.com/a/16575647/1532004我认为他正在做类似的事情。 Perhapes他在月球上射击,但他得到了一个有效的解决方案:)