使用包含html的文本替换元素内的文本,而不删除已存在的html

Met*_*lis 6 javascript jquery

我正在尝试创建一个文本搜索功能,但是当元素中有html时,我很难让它工作.这是一些简单的HTML来演示我的问题.

<b>
    <input type="checkbox" value="" />
    I need replaced
</b>
Run Code Online (Sandbox Code Playgroud)

这是我目前在javascript的地方.假设里面没有html,它的效果很好.

$("*", search_container).each(function() {
    var replaceTxt = $(this).text().replace(new RegExp("(" + search_term + ")", 'i'), '<span style="color: #0095DA;" class="textSearchFound">$1</span>');
    $(this).text().replaceWith(replaceTxt);
}); 
Run Code Online (Sandbox Code Playgroud)

当用户输入时,我需要用span替换文本.所以内容应该像他/她键入的那样.

<b>
    <input type="checkbox" value="" />
    <span style="color: #0095DA" class="textSearchFound">I need</span> replaced
</b>
Run Code Online (Sandbox Code Playgroud)

UPDATE

在查看被投票重复的问题之后,我想出了这个.虽然可能很接近,但它将html作为我不想要的文本插入DOM.请投票重新打开.

$("*", search_container).each(function() {
    var node = $(this).get(0);
    var childs = node.childNodes;
    for(var inc = 0; inc < childs.length; inc++) {
        //Text node
        if(childs[inc].nodeType == 3){ 
            if(childs[inc].textContent) {
                childs[inc].textContent = childs[inc].textContent.replace(new RegExp("(" + search_term + ")", 'i'), '<span style="color: #0095DA;" class="textSearchFound">$1</span>');
             } 
             //IE
             else {
                 childs[inc].nodeValue = childs[inc].nodeValue.replace(new RegExp("(" + search_term + ")", 'i'), '<span style="color: #0095DA;" class="textSearchFound">$1</span>');
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

nde*_*ore 6

它并不漂亮,但最好的方法是以递归方式遍历页面上的每个节点.当您遇到文本节点时,请检查它是否包含您的搜索字符串.如果找到它,请删除原始文本节点并将其替换为匹配前文本的文本节点,带有突出显示匹配的新元素以及匹配后文本节点.

这是一个示例函数:

var highlightSomeText = function(needle, node){
    node = node || document.body; // initialize the first node, start at the body

    if(node.nodeName == 'SCRIPT') return; // don't mess with script tags 

    if(node.nodeType == 3){ // if node type is text, search for our needle
        var parts = node.nodeValue.split(needle); // split text by our needle
        if(parts.length > 1){ // if we found our needle
            var parent = node.parentNode
            for(var i = 0, l = parts.length; i < l;){
                var newText = document.createTextNode(parts[i++]); // create a new text node, increment i
                parent.insertBefore(newText, node);
                if(i != l){ // if we're not on the last part, insert a new span element for our highlighted text
                    var newSpan = document.createElement('span');
                    newSpan.className = 'textSearchFound';
                    newSpan.style.color = '#0095DA';
                    newSpan.innerHTML = needle;
                    parent.insertBefore(newSpan, node);
                }
            }
            parent.removeChild(node); // delete the original text node
        }
    }

    for(var i = node.childNodes.length; i--;) // loop through all child nodes
        highlightSomeText(needle, node.childNodes[i]);
};

highlightSomeText('I need');
Run Code Online (Sandbox Code Playgroud)

关于jsfiddle的演示:http://jsfiddle.net/8Mpqe/


编辑:这是一个更新的方法,它使用Regexp不区分大小写: http: //jsfiddle.net/RPuRG/

更新的行:

var parts = node.nodeValue.split(new RegExp('(' + needle + ')','i'));
Run Code Online (Sandbox Code Playgroud)

使用包含在捕获组中()的正则表达式,捕获的结果将拼接到部件数组中.

newSpan.innerHTML = parts[i++];
Run Code Online (Sandbox Code Playgroud)

新span元素的文本将是我们数组中的下一部分.

编辑2:由于在某些文本字段的每个键盘事件上都会调用此函数,因此提问者希望在每次运行之前删除突出显示的span标记.为此,需要打开每个突出显示的元素,然后调用normalize父节点将相邻的文本节点重新合并在一起.这是一个jQuery示例:

$('.textSearchFound').each(function(i, el){
    $(el).contents().unwrap().
    parent()[0].normalize();
});
Run Code Online (Sandbox Code Playgroud)

这是完成的工作演示:http://jsfiddle.net/xrL3F/