Search and Highlight in jQuery
Asked Answered
C

5

24

I would like to search and highlight text using jQuery/Java Script.

sample HTML 1:

<div id="div1"><b>Good</b> <b>Morning</b> </div>
<div id="div2">Good Evening</div> 
<div id="div3">Good Morning</div>Searched String = "Good Morning"

When i search for String "Good Morning", Both the contents in div1 and div3 should get highlighted. ie. the output html should be

<div id="div1"><span class="highlight"><b>Good</b> <b>Morning</b> </span></div>
<div id="div2">Good Evening</div> 
<div id="div3"><span class="highlight">Good Morning</span></div>

I have used the plugin https://raw.github.com/bartaz/sandbox.js/master/jquery.highlight.js to enclose searched content inside span. But only div3 is highlighted. Please help.

Clercq answered 1/11, 2013 at 4:50 Comment(1)
How do you know what to wrap if you have other tags? You'd have to first unwrap the words then highlight them, or modify the plugin to your needs.Teel
K
45

http://jsfiddle.net/UPs3V/291/

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

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 this one it may help you

Kinata answered 1/11, 2013 at 4:58 Comment(10)
Thanks @sarath this works like charm. But it is case sensitive. Can u pls let me know how to make this as case insensitive.Clercq
added i while creating reg exp to make case insensitive , var pattern = new RegExp("("+term+")", "gi");Clercq
pls help. getting error when the searched term contains special Characters.My searched word is: "software (" and Error is Invalid regular expression: /(software(<[^>]+>)* (<[^>]+>)*()/: Unterminated groupClercq
Why not use jQuery's $('#test').text() to get the text?Hound
This will destroy events within #test, as it uses innerHTML in the backgroundScope
@sarath How to ignore html content In DIVMisdemeanor
excellent solution. Can you help me on how can ignore diacriitics in regex pattern and ignore Case? thank youHydric
its modified the url . hyperlink become no longer valid step of reproduce add this in div google.com highlight googleInsanitary
This works fine but. tyring it to 1 or 2 letter will broke the html format. 2 letter must be minimum valid letter to execute this. is there away to solve it also ?Thanksgiving
worked well, but for some reason javascript freezes when these conditions 1. search by two words 2. a lot of nodes to search forStalinsk
A
17

demo

script

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 });
};

jQuery.fn.removeHighlight = function() {
 function newNormalize(node) {
    for (var i = 0, children = node.childNodes, nodeCount = children.length; i < nodeCount; i++) {
        var child = children[i];
        if (child.nodeType == 1) {
            newNormalize(child);
            continue;
        }
        if (child.nodeType != 3) { continue; }
        var next = child.nextSibling;
        if (next == null || next.nodeType != 3) { continue; }
        var combined_text = child.nodeValue + next.nodeValue;
        let new_node = node.ownerDocument.createTextNode(combined_text);
        node.insertBefore(new_node, child);
        node.removeChild(child);
        node.removeChild(next);
        i--;
        nodeCount--;
    }
 }

 return this.find("span.highlight").each(function() {
    var thisParent = this.parentNode;
    thisParent.replaceChild(this.firstChild, this);
    newNormalize(thisParent);
 }).end();
};

HTML

Search: <input type="text" id="text-search" />

<p><b>Demo </b> he new edition of KnowlEdge K12 enables your school with flexibility by wholly automating their administrative and academic processes. With IncTech’s solution for K12 schools, you can. We give you an internal infrastructure so you can share school and student information. </p>

<script type="text/javascript">
$(function() {
    $('#text-search').bind('keyup change', function(ev) {
        // pull in the new value
        var searchTerm = $(this).val();

        // remove any old highlighted terms
        $('body').removeHighlight();

        // disable highlighting if empty
        if ( searchTerm ) {
            // highlight the new term
            $('body').highlight( searchTerm );
        }
    });
});
</script>
Agrapha answered 1/11, 2013 at 5:2 Comment(6)
Thanks ashish. If my search word is "Demo he", it is not highlighted since there is a tag between them.Clercq
because they r separated by some tag..u have to locate all elements in 1 tag like <p> or <span> or <div>..so script will search result from it..Agrapha
You have copied the code from Johann Burkard. You should provide credits.Scope
Hi, I am using this code, its working but reall slow.Stier
IMPORTANT: Johann Burkard included a mining script into the source provided on his website!!!!!!Pageboy
Original Source: johannburkard.de/blog/programming/javascript/…Ginetteginevra
B
7

Try this out:- http://jsfiddle.net/adiioo7/H7CqV/

You need to remove the b tags from div1 and in order to apply bold property you can use css property font-weight:bold.

HTML:-

<div id="div1" style="font-weight:bold">Good Morning</div>
<div id="div2">Good Evening</div> 
<div id="div3">Good Morning</div>

or

<div id="div1"><b>Good Morning</b></div>
<div id="div2">Good Evening</div> 
<div id="div3">Good Morning</div>

JS:-

$("body").highlight("Good Morning");

Edit: highlight is a 3rd party jquery lib, more info here: http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

Borreri answered 1/11, 2013 at 5:11 Comment(2)
Thanks @wiz kid, but my input HTML files are like that. I should not change it.Clercq
what is highlight ! I never seen it @AdityaAdalbert
R
3

Try this in all above answer search with HTML tag.

SHORT AND SWEET

This answer help full to you for perfect search text which I implemented in my project

<script type="text/javascript">
   var term = "my text";
   $('#test').html(function () {
     return $(this).html().replace(new RegExp(term + "(?=[^>]*<)","ig"), "<mark>$&</mark>");
   });
</script>
Rexferd answered 18/11, 2020 at 6:57 Comment(2)
had to add this $('mark').contents().unwrap(); to proper rehighlight and also take care of events attachedStalinsk
<script src="ajax.googleapis.com/ajax/libs/jquery/3.5.1/…> <script type="text/javascript" src="getbootstrap.com/docs/4.3/dist/js/…> @stack('script')Rexferd
T
0

Thanks to previous answers, i made one function to add/remove highlight, i hope it helps.

Note: elements is jquery selector, each node must contain text, not HTML

function HighlightText(elements, txt) {
    $.each(elements, function () {
        var node = $(this);
        var src_str = node.text();
        txt = txt.replace(/(\s+)/, "(<[^>]+>)*$1(<[^>]+>)*");
        var pattern = new RegExp("(" + txt + ")", "gi");
        if (txt != "") {
            src_str = src_str.replace(pattern, "<mark>$1</mark>");
            src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/, "$1</mark>$2<mark>$4");
            node.html(src_str);
        } else {
            src_str = src_str.replace("<mark>$1</mark>", pattern);
            node.html(src_str);
        }
    });
}

To use it:

HighlightText($(".report span"), 'BSNSWORLD.com');
Topflight answered 25/3, 2023 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.