选择HTML元素中的一部分文本

时间:2014-06-01 13:44:51

标签: javascript html selection

我想创建一个在HTML元素中选择给定文本的函数。

例如,调用selectText('world')会在world

等标记中选择<span>Hello </span><strong>world</strong>!

关于类似问题的大量答案建议使用rangeselection,但在我的情况下,它们都不起作用(有些会选择所有文字,有些会赢得这样的标记, ...)。

现在这就是我的(它不起作用)

function selectText ( element, textToSelect ) {
    var text  = element.textContent, 
        start = text.indexOf( textToSelect ),
        end   = start + textToSelect.length - 1,
        selection, range;

    element.focus();

    if( window.getSelection && document.createRange ) {
        range = document.createRange();

        range.setStart( element.firstChild, start );
        range.setEnd( element.lastChild, end );

        selection = window.getSelection();

        selection.removeAllRanges();
        selection.addRange( range );
    } else if (document.body.createTextRange) {
        range = document.body.createTextRange();

        range.moveToElementText( element );
        range.moveStart( 'character', start );
        range.collapse( true );
        range.moveEnd( 'character', end );
        range.select();
    }
}

这是一个jsfiddle,你可以看到实际发生的事情:http://jsfiddle.net/H2H2p/

输出错误:

Uncaught IndexSizeError: Failed to execute 'setStart' on 'Range': The offset 11 is larger than or equal to the node's length (5). 

P.S。:请不要jQuery:)

1 个答案:

答案 0 :(得分:1)

您可以结合使用在元素textContentthis function中查找文字的方法。

演示:http://jsfiddle.net/H2H2p/3/

代码:

function selectText(element, textToSelect) {
    var elementText;
    if (typeof element.textContent == "string" && document.createRange && window.getSelection) {
        elementText = element.textContent;
    } else if (document.selection && document.body.createTextRange) {
        var textRange = document.body.createTextRange();
        textRange.moveToElement(element);
        elementText = textRange.text;
    }

    var startIndex = elementText.indexOf(textToSelect);
    setSelectionRange(element, startIndex, startIndex + textToSelect.length);
}

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();
    }
}