Highlight text inside html with jQuery

2020-01-28 08:55发布

I am looking to do something similar to this plugin http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

But the problem I am facing is that the above plugin does not allow you to highlight words within html.

So if you are looking for my text

inside html like

this is <a href="#">my</a> text that needs highlighting

You will not get any highlighting.

Is there a way to highlight text while ignoring any html tags in between?

3条回答
beautiful°
2楼-- · 2020-01-28 09:17

I would like to leave a comment but stack doesn't allow me or I can't seem to find a button for it so have to do it in an answer. There is a problem with the script. for example: Highlighting fox in the following string:

<img src="brown fox.jpg" title="The brown fox" /><p>some text containing fox.</p>

Would break the img tag:

var term = "fox";
term = term.replace(/(\s+)/,"(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("("+term+")", "i");
src_str ='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox.</p>'
src_str = src_str.replace(pattern, "<mark>$1</mark>");
src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/,"$1</mark>$2<mark>$4");
src_str

I was working on a highlight script and solved that problem not realizing the script might have to highlight over multiple tags. Here is how I got it not to destroy tags by trying to highlight content within tags, this script highlights multiple instances within content as well but not over multiple tags:

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox. And onother fox.</p>'
var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
        + "\\b)";
var r = new RegExp(word,"igm")
str.replace(/(>[^<]+)/igm,function(a){
    return a.replace(r,"<span class='hl'>$1</span>");
})

Not sure how to combine these scripts and make a highlight over multiple tags work but will keep my eye on this thread.

查看更多
▲ chillily
3楼-- · 2020-01-28 09:25

I tried the accepted solution and it seems to break on complex pages such as this one (infinite recursion). Also, I don't really see the benefit of relying on jQuery, so I rewrote the code to be independent of jQuery (it's also substantially shorter and doesn't support the fancy options).

It's easy enough to add the options back in and use classes if you like.

function highlight(re, node, depth, maxdepth){
    node = node || document.body;
    depth = depth || 0;
    maxdepth = maxdepth || 10;

    if( node.nodeType === 3 ){
        var match = node.data.match(re);
        if(match){
            var span = document.createElement('span');
            span.style.backgroundColor = '#ffa';
            var wordNode = node.splitText(match.index);
            wordNode.splitText(match[0].length);
            var wordClone = wordNode.cloneNode(true);
            span.appendChild(wordClone);
            wordNode.parentNode.replaceChild(span, wordNode);
            return 1;
        }
    } else if( depth === maxdepth ){
        console.log( 'Reached max recursion depth!', node );
    } else if( (node.nodeType === 1 && node.childNodes) && !/(script|style)/i.test(node.tagName) ) {
        for( var i = 0; i < node.childNodes.length; i++ ){
            i += highlight(re, node.childNodes[i], depth + 1, maxdepth);
        }
    }
    return 0;
}
查看更多
放荡不羁爱自由
4楼-- · 2020-01-28 09:30

I fiddled some RegEx which allows HTML tags at the position of whitespace chars:

<div id="test">this is <a href="#">my</a> text that needs highlighting</div>

JavaScript:

var src_str = $("#test").html();
var term = "my text";
term = term.replace(/(\s+)/,"(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("("+term+")", "i");

src_str = src_str.replace(pattern, "<mark>$1</mark>");
src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/,"$1</mark>$2<mark>$4");

$("#test").html(src_str);

Try it here: http://jsfiddle.net/UPs3V/

查看更多
登录 后发表回答