使用JavaScript突出显示文本范围

Vin*_*ent 38 javascript selection textrange

我想强调(应用css)某个文本范围,由其开始和结束位置表示.这比看起来更难以实现,因为文本中可能还有其他标记需要忽略.

例:

<div>abcd<em>efg</em>hij</div>
Run Code Online (Sandbox Code Playgroud)

highlight(2, 6)需要突出显示"cdef"不删除标签.

我已经尝试过使用TextRange对象,但没有成功.

提前致谢!

Tim*_*own 57

下面是一个功能,用于将选择设置为特定元素中的一对字符偏移.这是天真的实现:它没有考虑任何可能被隐藏的文本(例如,通过CSS或通过在一个<script><style>元素内部),并且可能有浏览器差异(IE与其他所有内容)有换行符,并且需要没有折叠空格的帐户(例如2个或更多连续的空格字符折叠到页面上的一个可见空间).但是,它适用于所有主流浏览器中的示例.

对于另一部分,突出显示,我建议使用document.execCommand()它.您可以使用下面的功能设置选择,然后调用document.execCommand().您需要在非IE浏览器中临时编辑文档才能使命令正常工作.有关代码,请参阅我的答案:跨多个标签的getSelection和surroundContents

这是一个jsFiddle示例,展示了整个事情,在所有主流浏览器中工作:http://jsfiddle.net/8mdX4/1211/

选择设置代码:

function getTextNodesIn(node) {
    var textNodes = [];
    if (node.nodeType == 3) {
        textNodes.push(node);
    } else {
        var children = node.childNodes;
        for (var i = 0, len = children.length; i < len; ++i) {
            textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
        }
    }
    return textNodes;
}

function setSelectionRange(el, start, end) {
    if (document.createRange && window.getSelection) {
        var range = document.createRange();
        range.selectNodeContents(el);
        var textNodes = getTextNodesIn(el);
        var foundStart = false;
        var charCount = 0, endCharCount;

        for (var i = 0, textNode; textNode = textNodes[i++]; ) {
            endCharCount = charCount + textNode.length;
            if (!foundStart && start >= charCount
                    && (start < endCharCount ||
                    (start == endCharCount && i <= textNodes.length))) {
                range.setStart(textNode, start - charCount);
                foundStart = true;
            }
            if (foundStart && end <= endCharCount) {
                range.setEnd(textNode, end - charCount);
                break;
            }
            charCount = endCharCount;
        }

        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.selection && document.body.createTextRange) {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(true);
        textRange.moveEnd("character", end);
        textRange.moveStart("character", start);
        textRange.select();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 精彩的解决方案@ tim-down!您的代码适用于合并嵌套的HTML格式文本.http://stackoverflow.com/questions/16226671/consolidate-stacked-dom-formatting-elements-contenteditable-div (2认同)