How can I use jQuery to style /parts/ of all instances of a specific word?

Unusual situation. I have a client, let's call them "BuyNow." They would like for every instance of their name throughout the copy of their site to be stylized like "BuyNow," where the second half of their name is in bold.

I'd really hate to spend a day adding <strong> tags to all the copy. Is there a good way to do this using jQuery?

I've seen the highlight plugin for jQuery and it's very close, but I need to bold just the second half of that word.

Answers:

Answer

To do it reliably you'd have to iterate over each element in the document looking for text nodes, and searching for text in those. (This is what the plugin noted in the question does.)

Here's a plain JavaScript/DOM one that allows a RegExp pattern to match. jQuery doesn't really give you much help here since selectors can only select elements, and the ‘:contains’ selector is recursive so not too useful to us.

// Find text in descendents of an element, in reverse document order
// pattern must be a regexp with global flag
//
function findText(element, pattern, callback) {
    for (var childi= element.childNodes.length; childi-->0;) {
        var child= element.childNodes[childi];
        if (child.nodeType==1) {
            findText(child, pattern, callback);
        } else if (child.nodeType==3) {
            var matches= [];
            var match;
            while (match= pattern.exec(child.data))
                matches.push(match);
            for (var i= matches.length; i-->0;)
                callback.call(window, child, matches[i]);
        }
    }
}

findText(document.body, /\bBuyNow\b/g, function(node, match) {
    var span= document.createElement('span');
    span.className= 'highlight';
    node.splitText(match.index+6);
    span.appendChild(node.splitText(match.index+3));
    node.parentNode.insertBefore(span, node.nextSibling);
});
Answer

Regular Expressions and replace() spring to mind. Something like

var text = $([selector]).html();
text = text.replace(/Now/g,'<strong>Now<\strong>');
$([selector]).html(text);

A word of caution in using html() to do this. Firstly, there is the potential to replace matched strings in href attributes of <a> elements and other attributes that may cause the page to then incorrectly function. It might be possible to write a better regular expression to overcome some of the potential problems, but performance may suffer (I'm no regular expression guru). Secondly, using html() to replace content will cause non-serializable data such as event handlers bound to elements markup that is replaced, form data, etc. to be lost. Writing a function to target only text nodes may be the better/safer option, it just depends on how complex the pages are.

If you have access to the HMTL files, it would probably be better to do a find and replace on the words they want to change the appearance of in the files if the content is static. NotePad++'s Find in Files option is performant for this job in most cases.

Going with SingleShot's suggestion and using a <span> with a CSS class will afford more flexibility than using a <strong> element.

Answer

I wrote a little plugin to do just that. Take a look at my answer to a similar question.

Instead of downloading the plugin suggested in the accepted answer, I strongly recommend that you use the plugin I've written--it's a lot faster.

Answer
var Run=Run || {};

Run.makestrong= function(hoo, Rx){
 if(hoo.data){
  var X= document.createElement('strong');
  X.style.color= 'red'; // testing only, easier to spot changes
  var pa= hoo.parentNode;
  var res, el, tem;
  var str= hoo.data;
  while(str && (res= Rx.exec(str))!= null){
   var tem= res[1];
   el= X.cloneNode(true);
   el.appendChild(document.createTextNode(tem));
   hoo.replaceData(res.index, tem.length,'');
   hoo= hoo.splitText(res.index);
   str= hoo.data;
   if(str) pa.insertBefore(el, hoo);
   else{
    pa.appendChild(el);
    return;
   }
  }
 }
}

Run.godeep= function(hoo, fun, arg){
 var A= [];
 if(hoo){
  hoo= hoo.firstChild;
  while(hoo!= null){
   if(hoo.nodeType== 3){
    if(hoo.data) A[A.length]= fun(hoo, arg);
   }
   else A= A.concat(arguments.callee(hoo, fun, arg));
   hoo= hoo.nextSibling;
  }
 }
 return A;
}

//test

**Run.godeep(document.body, Run.makestrong,/([Ee]+)/g);**
Answer

This is not a jQuery script but pure javaScript, i believe it can be altered a little. Link.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.