我正在尝试创建一个文本搜索功能,但是当元素中有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)
它并不漂亮,但最好的方法是以递归方式遍历页面上的每个节点.当您遇到文本节点时,请检查它是否包含您的搜索字符串.如果找到它,请删除原始文本节点并将其替换为匹配前文本的文本节点,带有突出显示匹配的新元素以及匹配后文本节点.
这是一个示例函数:
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/