Changing the contents of a page is generally not as simple as replacing html() markup with regex. All such attempts will fail if there is consistent text in the markup itself, it may fail when the browser decides to serialize its DOM in a way that does not meet your expectations, and in the best case, when it works, it still forces you to serialize and repeatedly analyze all the searched text that is slow and destroys all non-serializable information, such as form field values, JavaScript links, and event handlers. You can avoid this for simple low-level elements, but against a container like <body> would be awful.
Better: instead of hacking an HTML string, stick to live DOM nodes, look for Text nodes matching your requirements, and replace the direct text data with a node. Here is some simple JS code for this (I think you could put it in a plugin if you want.)
// Utility function to find matches in an element descendant Text nodes, // calling back a function with (node, match) arguments. The `pattern` can // be a string, for direct string matching, or a RegExp object (which must // be a `g`lobal regex. // function findText(element, pattern, callback) { for (var childi= element.childNodes.length; childi-->0;) { var child= element.childNodes[childi]; if (child.nodeType==1) { var tag= child.tagName.toLowerCase(); if (tag!=='script' && tag!=='style' && tag!=='textarea') findText(child, pattern, callback); } else if (child.nodeType==3) { var matches= []; if (typeof pattern==='string') { var ix= 0; while (true) { ix= child.data.indexOf(pattern, ix); if (ix===-1) break; matches.push({index: ix, '0': pattern}); } } else { var match; while (match= pattern.exec(child.data)) matches.push(match); } for (var i= matches.length; i-->0;) callback.call(window, child, matches[i]); } } }
Usage example with a regular search term:
// Replace "World to" string in element text with <i>-wrapped version // var element= $('#construct_version')[0]; findText(element, 'World to', function(node, match) { var wrap= document.createElement('i'); node.splitText(match.index+match[0].length); wrap.appendChild(node.splitText(match.index)); node.parentNode.insertBefore(span, node.nextSibling); });
source share