Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>HTML is too complex to reliably parse with a regular expression.</p> <p>If you're looking to do this client-side, you can create a document fragment and/or disconnected DOM node (neither of which is displayed anywhere) and initialize it with your HTML string, then walk through the resulting DOM tree and process the text nodes. (Or use a library to help you do that, although it's actually quite simple.)</p> <p>Here's a DOM walking example. This example is <em>slightly</em> simpler than your problem because it just updates the text, it doesn't add new elements to the structure (wrapping parts of the text in <code>span</code>s involves updating the structure), but it should get you going. Notes on what you'll need to change at the end.</p> <pre><code>var html = "&lt;p&gt;This is a test.&lt;/p&gt;" + "&lt;form&gt;&lt;input type='text' value='test value'&gt;&lt;/form&gt;" + "&lt;p class='testing test'&gt;Testing here too&lt;/p&gt;"; var frag = document.createDocumentFragment(); var body = document.createElement('body'); var node, next; // Turn the HTML string into a DOM tree body.innerHTML = html; // Walk the dom looking for the given text in text nodes walk(body); // Insert the result into the current document via a fragment node = body.firstChild; while (node) { next = node.nextSibling; frag.appendChild(node); node = next; } document.body.appendChild(frag); // Our walker function function walk(node) { var child, next; switch (node.nodeType) { case 1: // Element case 9: // Document case 11: // Document fragment child = node.firstChild; while (child) { next = child.nextSibling; walk(child); child = next; } break; case 3: // Text node handleText(node); break; } } function handleText(textNode) { textNode.nodeValue = textNode.nodeValue.replace(/test/gi, "TEST"); } </code></pre> <p><a href="http://jsbin.com/unuli5" rel="noreferrer">Live example</a></p> <p>The changes you'll need to make will be in <code>handleText</code>. Specifically, rather than updating <code>nodeValue</code>, you'll need to:</p> <ul> <li>Find the index of the beginning of each word within the <code>nodeValue</code> string.</li> <li>Use <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-38853C1D" rel="noreferrer"><code>Node#splitText</code></a> to split the text node into up to three text nodes (the part before your matching text, the part that <em>is</em> your matching text, and the part following your matching text).</li> <li>Use <code>document.createElement</code> to create the new <code>span</code> (this is literally just <code>span = document.createElement('span')</code>).</li> <li>Use <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-952280727" rel="noreferrer"><code>Node#insertBefore</code></a> to insert the new <code>span</code> in front of the third text node (the one containing the text following your matched text); it's okay if you didn't need to create a third node because your matched text was at the end of the text node, just pass in <code>null</code> as the <code>refChild</code>.</li> <li>Use <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-184E7107" rel="noreferrer"><code>Node#appendChild</code></a> to move the second text node (the one with the matching text) into the <code>span</code>. (No need to remove it from its parent first; <code>appendChild</code> does that for you.)</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload