Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search body for string and then style

I need to search through a document with jQuery to find a particular word. It's actually a brand name that has to be bold and italic wherever used.

I can do this using :contain but only on an individual element basis. I need to be able to go through anchors, lists divs etc.

$( "a:contains('brand name')" ).html().replace('brand name'.... 

Any ideas would be appreciated.

Update: I have got this far which works and replaces everything on a page but I now need to wrap in a span with a class. So close but stumped on this one. Again an ideas would be appreciated.

    $("body *").contents().each(function() {
  if(this.nodeType==3){
    this.nodeValue = this.nodeValue.replace(/brandname/g, 'colour');

  }
});
like image 335
ShambalaG Avatar asked Nov 19 '15 12:11

ShambalaG


People also ask

What is the search () method of a string?

The search () method searches a string for a value. The search () method returns the index (position) of a match. The search () method returns -1 if no match is found. The search () method is case sensitive. The search value can be a string or a regular expression. Required.

How do you search for a string in JavaScript?

JavaScript String search() Method ... The search() method searches a string for a specified value, and returns the position of the match. The search value can be string or a regular expression. This method returns -1 if no match is found. Read more about regular expressions in our RegExp Tutorial and our RegExp Object Reference.

How to do string search in SQL?

String Search in SQL can be done using the functions available in SQL: PATINDEX, CHARINDEX and LIKE. Full-text is the searching facility that allows the users to search for certain keys that are not even mentioned perfectly and help in retrieving the searched filtered data in a fast and easy way.

Which pattern starts from index 0 in the given text?

Given two strings, text and pattern, of size N and M (N > M)respectively, the task is to print all occurrences of pattern in text . Explanation: The pattern “This” starts from index 0 in the given text.


3 Answers

You can replace the textNodes with a document fragment. This allows you to group text and styled nodes and swap it with the existing textNode.

var x = 0;
$("body *").contents().each(function() {

   if (this.nodeType == 3 && this.parentElement.tagName != "SCRIPT") {

     var text = this.nodeValue;
     var i = 0, lastIndex = 0;
     var search = /brandname/ig;
     var result;
     var parent = this.parentNode;
     var textNode = null;
     var highlight = null;
     var textRange = "";
     var fragment = document.createDocumentFragment();

     // Do search
     while ((result = search.exec(text)) !== null) {
    
       // add plain text before match
       textRange = text.substring(lastIndex, result.index);
       if (textRange != '') {
         textNode = document.createTextNode(textRange);
         fragment.appendChild(textNode);
       }
       
       // add highlight elements
       highlight = document.createElement('span');
       highlight.innerHTML = result[0];
       highlight.className = "hi";
       fragment.appendChild(highlight);
       lastIndex = search.lastIndex;
     }

     // Add trailing text
     textRange = text.substring(lastIndex);
     if (textRange != '') {
       textNode = document.createTextNode(textRange);
       fragment.appendChild(textNode);
     }
     
     // Replace textNode with our text+highlight
     if(fragment.children.length > 0) {
       this.parentNode.replaceChild(fragment, this);
     }
   }

 });
span.hi {
  background-color: #FFCC00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  Hello world this is my brandname. The BrAnDNAMe is regex matched and we can change subelements like "<a href=''>Brandname</a>." It should not replace <b>elements</b> that don't match.
</p>
like image 165
wolfhammer Avatar answered Oct 19 '22 11:10

wolfhammer


$.fn.ignore = function(sel){
  return this.clone().find(sel||">*").remove().end();
};

function rebrand(el, word){
  if (!word.length && !el) return;
  var $el = $(el), html = $el.ignore("script").html(),
      rgx = new RegExp("(?![^<]+>)("+ word +")", "g");
  $el.html( html.replace(rgx, "<span class='brand'>$1</span>") );
}

$(function() { // DOM ready

  // !!!  IMPORTANT: REBRAND FIRST !!!
  rebrand("body", "Brand Name");
  // so the following code will not break on lost events, data bindings etc...

  // Other DOM ready code here like:
  $("button").click(function(){ $(this).css({color:"red"}); });
  
});

// Other JS, jQ code here...
.brand{
    color: rgba(255,0, 100,0.4);
    font: italic normal bold 1em/1 sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <h1>Title with Brand Name!</h1>
  <p>
    Change styles only to Brand Name!<br>
    but don't mess with <a href="#">links to Brand Name are cool</a><br>
    <button>Button with Brand Name works!</button>
  </p>
  <ul>
    <li>Other Brand</li><li>Brand Name</li><li>Brandy</li>
  </ul>
</div>
<div>
  <h2>Subtitle <i>and italic Brand Name</i></h2>
  <p>The HTML will not get messed cause of Brand Nameing<br>
  Paragraph with a &lt;b&gt; tag <b>bold Brand Name actually</b></p>
  <code>This is a code tag with a Brand Name :)</code>
</div>

Kudos to this two answers:
jQuery.ignore Plugin
Highlight Words (Ignoring names of HTML tags)

like image 42
Roko C. Buljan Avatar answered Oct 19 '22 11:10

Roko C. Buljan


if your code works, just add such a similar row of code:

this.nodeValue.wrap( "<span class='new'></span>" );
like image 2
luca3003 Avatar answered Oct 19 '22 09:10

luca3003