我想要一个Javascript Regex来包装给定的start(<span>)和结束标记(即</span>)中给定的单词列表,但前提是该单词实际上是页面上的"可见文本",而不是在html属性中(例如链接的标题标记或<script></script>块内部.
我已经创建了一个基本设置的JS小提琴:http: //jsfiddle.net/4YCR6/1/
T.J*_*der 38
HTML过于复杂,无法使用正则表达式进行可靠的解析.
如果您希望在客户端执行此操作,则可以创建文档片段和/或断开连接的DOM节点(两者都不显示在任何位置)并使用HTML字符串对其进行初始化,然后遍历生成的DOM树并处理文本节点.(或者使用库来帮助你做到这一点,虽然它实际上非常简单.)
这是一个DOM行走示例.这个例子比你的问题稍微简单一些,因为它只是更新文本,它没有向结构中添加新元素(在spans中包含部分文本涉及更新结构),但它应该让你前进.关于最后需要改变什么的说明.
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");
}
Run Code Online (Sandbox Code Playgroud)
您需要做出的更改将在handleText.具体而言,nodeValue您需要:而不是更新,您需要:
nodeValue字符串中每个单词开头的索引.Node#splitText分割文本节点到最多三个文本节点(您匹配的文本之前的部分,该部分是你匹配的文本,并按照您的匹配文本的部分).document.createElement以创建新的span(这是真的只是span = document.createElement('span')).Node#insertBefore插入新span文本; 这没关系,如果你并不需要创建第三个节点,因为你匹配的文本是在文本节点的结束,只是通过在null作为refChild.Node#appendChild所述第二文本节点(具有匹配的文本)移入span.(无需先将其从父项中删除; appendChild为您做到这一点.)Tim*_*own 10
TJ Crowder的回答是正确的.我已经进一步改进了代码:这是一个完整的示例,适用于所有主流浏览器.我之前已经在Stack Overflow上发布了这些代码的变体(例如这里和这里),并且使它很好并且通用,所以我(或其他任何人)不必更改它以重用它.
jsFiddle示例:http://jsfiddle.net/7Vf5J/38/
码:
// Reusable generic function
function surroundInElement(el, regex, surrounderCreateFunc) {
// script and style elements are left alone
if (!/^(script|style)$/.test(el.tagName)) {
var child = el.lastChild;
while (child) {
if (child.nodeType == 1) {
surroundInElement(child, regex, surrounderCreateFunc);
} else if (child.nodeType == 3) {
surroundMatchingText(child, regex, surrounderCreateFunc);
}
child = child.previousSibling;
}
}
}
// Reusable generic function
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
var parent = textNode.parentNode;
var result, surroundingNode, matchedTextNode, matchLength, matchedText;
while ( textNode && (result = regex.exec(textNode.data)) ) {
matchedTextNode = textNode.splitText(result.index);
matchedText = result[0];
matchLength = matchedText.length;
textNode = (matchedTextNode.length > matchLength) ?
matchedTextNode.splitText(matchLength) : null;
// Ensure searching starts at the beginning of the text node
regex.lastIndex = 0;
surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
parent.insertBefore(surroundingNode, matchedTextNode);
parent.removeChild(matchedTextNode);
}
}
// This function does the surrounding for every matched piece of text
// and can be customized to do what you like
function createSpan(matchedTextNode) {
var el = document.createElement("span");
el.style.color = "red";
el.appendChild(matchedTextNode);
return el;
}
// The main function
function wrapWords(container, words) {
// Replace the words one at a time to ensure "test2" gets matched
for (var i = 0, len = words.length; i < len; ++i) {
surroundInElement(container, new RegExp(words[i]), createSpan);
}
}
wrapWords(document.getElementById("container"), ["test2", "test"]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11970 次 |
| 最近记录: |