参见英文答案 >
Highlight search terms (select only leaf nodes)7个
我想要一个Javascript正则表达式在给定的开始(< span>)和结束标签(即< / span>)中包装一个给定的单词列表,但只有当该单词实际上是“可见文本”时页面,而不在html属性内(例如链接的标题标签,或< script>< / script>块内).
我想要一个Javascript正则表达式在给定的开始(< span>)和结束标签(即< / span>)中包装一个给定的单词列表,但只有当该单词实际上是“可见文本”时页面,而不在html属性内(例如链接的标题标签,或< script>< / script>块内).
我创建了一个JS Fiddle与基本设置:http://jsfiddle.net/4YCR6/1/
解决方法
HTML太复杂,无法用正则表达式可靠地解析.
如果你想要做这个客户端,你可以创建一个文档片段和/或断开的DOM节点(这两个都不显示在任何地方),并用HTML字符串初始化,然后遍历所生成的DOM树并处理文本节点. (或者使用图书馆来帮助你,尽管它实际上很简单.)
这是一个DOM行走的例子.这个例子比你的问题稍微简单一点,因为它只是更新文本,它不会向结构添加新的元素(包含文本的部分包括更新结构),但它应该让你走.关于你最终需要改变的内容.
var html = "<p>This is a test.</p>" + "<form><input type='text' value='test value'></form>" + "<p class='testing test'>Testing here too</p>"; 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"); }
您需要做的更改将在handleText中.具体而言,您不需要更新nodeValue,您需要:
>查找nodeValue字符串中每个单词开头的索引.
>使用Node#splitText
将文本节点分割为最多三个文本节点(匹配文本之前的部分,匹配文本的部分以及匹配文本后面的部分).
>使用document.createElement创建新的跨度(这是字面上只是span = document.createElement(‘span’)).
>使用Node#insertBefore
在第三个文本节点前面插入新的范围(包含匹配文本后面的文本);没有必要创建第三个节点,因为匹配的文本位于文本节点的末尾,只传入null作为refChild.
>使用Node#appendChild
将第二个文本节点(具有匹配文本的文本)移动到span中. (不需要先从父进程中删除它; appendChild会为你做)