在节点innerText中搜索匹配的字符串并将匹配项包装在innerHTML维护标记中

jay*_*jay 5 html javascript jquery

我正在寻找一种在节点的 insideText 中搜索匹配字符串的方法。然后将匹配的文本包装在<span>.

要求:

1 > 该节点可能包含 html 标签,我希望在匹配的文本选择中保留这些标签。

2 > 我还希望匹配文本区分大小写。

前任:

This is my <strong>content</strong> to search.
Run Code Online (Sandbox Code Playgroud)

我想找到“我要搜索的内容”

匹配并包裹"my <strong>content</strong> to search"在一个跨度中,结果是:

This is <span>my <strong>content</strong> to search</span>.
Run Code Online (Sandbox Code Playgroud)

此代码仅搜索节点内的精确匹配,如果存在 html 标记则不匹配(因为这些是附加子节点):

/* Prompt for search */
    var text = prompt("Search for:", "");
    if (text == null || text.length == 0) return;

    /* Remove highlighted results */
    var spans = document.getElementsByClassName("labnol");

    if (spans) {
        for (var i = 0; i < spans.length; i++) {
            spans[i].style.backgroundColor = "transparent";
        }
    }

    function searchWithinNode(node, te, len) {
        var pos, skip, spannode, middlebit, endbit, middleclone;

        skip = 0;
        if (node.nodeType == 3) {
            pos = node.data.indexOf(te);

            if (pos >= 0) {
                spannode = document.createElement("span");
                spannode.setAttribute("class", "labnol");
                spannode.style.backgroundColor = "yellow";
                middlebit = node.splitText(pos);
                endbit = middlebit.splitText(len);
                middleclone = middlebit.cloneNode(true);
                spannode.appendChild(middleclone);
                middlebit.parentNode.replaceChild(spannode, middlebit);
                skip = 1;
            }
        } else if (node.nodeType == 1 && node.childNodes && node.tagName.toUpperCase() != "SCRIPT" && node.tagName.toUpperCase != "STYLE") {
            for (var child = 0; child < node.childNodes.length; ++child) {
                child = child + searchWithinNode(node.childNodes[child], te, len);
            }
        }
        return skip;
    }
    searchWithinNode(document.body, text, text.length);
Run Code Online (Sandbox Code Playgroud)

Rom*_*iuk 1

我必须为类似的目的编写代码 - 为选定的文本着色。我不知道如何通过节点执行此操作,因此我执行此任务作为 HTML 的替换(当然,如果所选文本中有特殊功能,例如鼠标悬停等,它将丢失)。

您可以根据自己的目的更改 searchInHtml() 函数:

function colorizeSelection(color) {
    var selectedText = getSelectionText();
    if (selectedText == '') {
        console.log('Nothing is selected.');
        return;
    }

    var q = window.getSelection();

    var selectionObject;
    if (q.anchorNode.innerHTML) {
        selectionObject = q.anchorNode;
    }
    else {
        selectionObject = q.anchorNode.parentNode;
    }

    if (color != undefined) {
        var tmp = selectionObject.innerHTML;
        tmp = tmp.replace(
            new RegExp('(' + selectedText.replace(/\(/g,'\\(').replace(/\)/g,'\\)').replace(/\//g,'\\/').replace(/\:/g,'\\:') + ')'),
            '<span class="colorized" style="background-color: ' + color +'">$1</span>'
        );
       
        if (tmp.length != selectionObject.innerHTML.length) {
            selectionObject.innerHTML = tmp;
        }
        else {
            console.log('Possible tags in the selection.');
            var matchingStr = searchInHtml(selectionObject.innerHTML, selectedText);
            selectionObject.innerHTML = selectionObject.innerHTML.replace(matchingStr,
                '<span class="colorized" style="background-color: ' + color +'">' + matchingStr + '</span>');
        }
    }
    else {
        // selectionObject.parentNode.innerHTML = selectionObject.parentNode.innerHTML.replace(
        //     new RegExp('<span class="colorized" style="background-color: .*?">(.*?)</span>'),
        //     '$1'
        // );
        q.baseNode.parentNode.style.backgroundColor = null;
    }

    function searchInHtml(html, text) {
        var splitted = splitHtml(html);
        var resultStr = '';

        var textOnly = '';
        for (var i = 0; i < splitted.length; i++) {
            if (!splitted[i].startsWith('<')) {
                textOnly += splitted[i];
            }
        }

        var start = textOnly.indexOf(text);

        if (start >= 0) {
            var startTmp = 0;
            var length = 0;

            for (var i = 0; i < splitted.length; i++) {
                if (splitted[i].startsWith('<')) {
                    if (resultStr == '') {
                        continue;
                    }
                    else {
                        resultStr += splitted[i];
                    }
                }
                else {
                    if (resultStr.length == 0) {
                        startTmp += splitted[i].length;
                        if (start >= startTmp) {
                            continue;
                        }
                        var substrLength = Math.min(startTmp - start, text.length);
                        resultStr = text.substr(0, substrLength);
                        length = substrLength;
                    }
                    else {                    
                        var substrLength = Math.min(splitted[i].length, text.length - length);
                        resultStr += splitted[i].substr(0, substrLength);
                        length += substrLength;
                    }
                }

                if (length == text.length) {
                    break;
                }
            }
        }

        return resultStr;

        function splitHtml(html) {
            var splitted = [];

            while (html.length > 0) {
                var toPosition = 0;
                if (html[0] == '<') {
                    toPosition = html.indexOf('>');
                }
                else {
                    toPosition = html.indexOf('<') - 1;
                }

                if (toPosition <= -1) {
                    toPosition = html.length;
                }

                splitted.push(html.substring(0, toPosition + 1));
                html = html.substr(toPosition + 1);
            }

            return splitted;
        }
    }

    function getSelectionText() {
        var text = "";
        if (window.getSelection) {
            text = window.getSelection().toString();
        } else if (document.selection && document.selection.type != "Control") {
            text = document.selection.createRange().text;
        }
        return text;
    }
}
Run Code Online (Sandbox Code Playgroud)