Я пытался сделать это неправильно. Вот решение, которое я создал, и, кажется, отлично работает. Он использует две рекурсивные функции + обход DOM + регулярные выражения для создания правильных узлов текста и span.
function replaceText(element, pattern, syn_text) {
for (var childi = 0; childi < element.childNodes.length;childi++) {
var child= element2.childNodes[childi];
if (child.nodeType==1 && child.className!=syn_text){ //make sure we don't call function on newly created node
replaceText(child, pattern, syn_text); //call function on child
}
else if (child.nodeType==3){ //this is a text node, being processing with our regular expression
var str = child.data;
str = str.replace(pattern,function(s, p1,p2,p3) {
var parentNode = child.parentNode;
do_replace(s, p1,p2,p3,parentNode,pattern,syn_text);
parentNode.removeChild(child); //delete old child from parent node. we've replaced it with new nodes at this point
});
}
}}
function do_replace(s, p1,p2,p3,parentNode,pattern,syn_text) {
if(p1.length>0){ //this might not be necessary
//create textnode
var text_node = document.createTextNode(p1);
parentNode.appendChild(text_node);
}
if(p2.length > 0){ //create a span + next_node for the highlighting code
spanTag = document.createElement("span");
spanTag.id = "SString" + id++;
spanTag.className = syn_text;
spanTag.innerHTML = p2;
parentNode.appendChild(spanTag);
}
if(p3.length > 0){
//test to see if p3 contains another instance of our string.
if(pattern.test(p3)){ //if there is a instance of our text string in the third part of the string, call function again
p3.replace(pattern,function(s, p1,p2,p3) {
//debugger;
do_replace(s, p1,p2,p3,parentNode,pattern);
return;
});
}
else{ //otherwise, it's just a plain textnode, so just reinsert it.
var text_nodep3 = document.createTextNode(p3);
parentNode.appendChild(text_nodep3);
return;
}
}
else{ //does this do anything?
return;
}
return}
Эта функция вызывается следующим образом:
syn_highlight = "highlight_me"; //class to signify highlighting
pattern = new RegExp('([\\w\\W]*?)\\b('+ searchTerm + '[\\w]*)\\b([\\w\\W]*)',"ig");
replaceText($('#BodyContent')[0],pattern,syn_highlight);