Itβs not clear what kind of "HTML" you are working on. If this is HTML code, possibly something from an Ajax request, then you can use a regex; matching both the link and the template, and then figure out what to do in the callback:
var html = document.body.innerHTML; html = html.replace(/(<a\s.*?>.*?<\/a>)|(\?\?\?([a-z0-9.]*)\?\?\?)/g, function ( a, b, c, d ) { return ( a[0] == '<' ) ? a : '<a href="#">' + d + '</a>'; }); context.innerHTML = html;
Conveniently, replace() can use the callback function as a replaceable generator, rather than a simple string.
If you are working on a live DOM tree, you might want to respect events on the nodes, not just reset innerHTML . To do this, you will need a more primitive approach:
// returns all childnodes of type text that do not have A as parent function walker ( node ) { var nodes = []; for (var c, i = 0; c = node.childNodes[i]; i++) { if ( c.nodeType === 1 && c.tagName !== 'A' ) { nodes = nodes.concat( arguments.callee( c ) ); } else if ( c.nodeType === 3 ) { nodes.push( c ); } } return nodes; } var textNodes = walker( document.body ); for (var i = 0; i < textNodes.length; i++) { // create an array of strings separating the pattern var m = textNodes[i].nodeValue.split( /(\?\?\?([a-z0-9.]*)\?\?\?)/ ); if ( m.length > 1 ) { for (var j=0; j<m.length; j++) { var t, parent = textNodes[i].parentNode; // create a link for any occurence of the pattern if ( /^\?\?\?([a-z0-9.]*)\?\?\?$/.test( m[j] ) ) { var a = document.createElement( 'a' ); a.href = "#"; a.innerHTML = RegExp.$1; // m[j] if you don't want to crop the ???'s parent.insertBefore( a, textNodes[i] ); t = document.createTextNode( ' ' ); // whitespace padding } else { t = document.createTextNode( m[j] ); } parent.insertBefore( t, textNodes[i] ); } // remove original text node parent.removeChild( textNodes[i] ); } }
This method applies only to text fields, and then only those that match the pattern.
source share