Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript正则表达式来替换不在html属性中的文本_Javascript_Regex - Fatal编程技术网

Javascript正则表达式来替换不在html属性中的文本

Javascript正则表达式来替换不在html属性中的文本,javascript,regex,Javascript,Regex,我希望Javascript正则表达式将给定的单词列表包装在给定的开始()和结束标记(即)中,但前提是单词实际上是页面上的“可见文本”,而不是在html属性内(例如链接的标题标记或块内) 我用基本设置创建了一个JS FIDLE:HTML太复杂,无法用正则表达式可靠地解析 如果您希望在客户端执行此操作,则可以创建文档片段和/或断开连接的DOM节点(两者都不显示在任何位置),并使用HTML字符串对其进行初始化,然后遍历生成的DOM树并处理文本节点。(或者使用库来帮助您完成此操作,尽管实际上非常简单。)

我希望Javascript正则表达式将给定的单词列表包装在给定的开始(
)和结束标记(即
)中,但前提是单词实际上是页面上的“可见文本”,而不是在html属性内(例如链接的标题标记或
块内)


我用基本设置创建了一个JS FIDLE:

HTML太复杂,无法用正则表达式可靠地解析

如果您希望在客户端执行此操作,则可以创建文档片段和/或断开连接的DOM节点(两者都不显示在任何位置),并使用HTML字符串对其进行初始化,然后遍历生成的DOM树并处理文本节点。(或者使用库来帮助您完成此操作,尽管实际上非常简单。)

下面是一个DOM漫游示例。这个示例比您的问题稍微简单一些,因为它只更新文本,不向结构中添加新元素(将部分文本包装在
span
s中涉及到更新结构),但应该可以让您继续。最后请注意需要更改的内容

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");
}
var-html=
“这是一个测试。

”+ "" + “

这里也有测试”

”; var frag=document.createDocumentFragment(); var body=document.createElement('body'); var节点,下一步; //将HTML字符串转换为DOM树 body.innerHTML=html; //遍历dom,在文本节点中查找给定的文本 步行(身体); //通过片段将结果插入当前文档 node=body.firstChild; while(节点){ 下一步=node.nextSibling; frag.appendChild(节点); 节点=下一个; } 文件.正文.附件(frag); //我们的步行功能 功能行走(节点){ var child,下一个; 开关(node.nodeType){ 案例1://要素 案例9://文件 案例11://文件片段 child=node.firstChild; while(儿童){ 下一步=child.nextSibling; 步行(儿童); 孩子=下一个; } 打破 案例3://文本节点 handleText(节点); 打破 } } 函数handleText(textNode){ textNode.nodeValue=textNode.nodeValue.replace(/test/gi,“test”); }

您需要在
handleText
中进行更改。具体而言,您需要执行以下操作,而不是更新
nodeValue

  • nodeValue
    字符串中查找每个单词开头的索引
  • 用于将文本节点拆分为最多三个文本节点(匹配文本前的部分、匹配文本的部分以及匹配文本后的部分)
  • 使用
    document.createElement
    创建新的
    span
    (这实际上就是
    span=document.createElement('span')
  • 用于将新的
    span
    插入第三个文本节点(包含匹配文本后面的文本的节点)前面;如果您不需要创建第三个节点,因为匹配文本位于文本节点的末尾,则可以将
    null
    作为
    refChild
    传入
  • 用于将第二个文本节点(具有匹配文本的文本节点)移动到
    span
    (无需先将其从其父节点中删除;
    appendChild
    会为您执行此操作。)
是正确的。我在代码方面做了进一步的改进:这里有一个在所有主流浏览器中都可以使用的完整格式示例。我以前(例如)在Stack Overflow上发布过这段代码的变体,并将其变得很好、通用,因此我(或其他任何人)不必对其进行太多更改即可重用

JSFIDLE示例:

代码:

//可重用泛型函数
函数surroundInElement(el、正则表达式、surrounderCreateFunc){
//脚本和样式元素是单独存在的
if(!/^(脚本|样式)$/.test(el.tagName)){
var child=el.lastChild;
while(儿童){
if(child.nodeType==1){
surroundInElement(child、regex、surrounderCreateFunc);
}else if(child.nodeType==3){
surroundMatchingText(子级、正则表达式、surrounderCreateFunc);
}
child=child.previousSibling;
}
}
}
//可重用泛型函数
函数surroundMatchingText(textNode、regex、surrounderCreateFunc){
var parent=textNode.parentNode;
var结果,环绕节点,匹配文本节点,匹配长度,匹配文本;
while(textNode&(result=regex.exec(textNode.data))){
matchedTextNode=textNode.splitText(结果.索引);
matchedText=结果[0];
MatchedLength=matchedText.length;
textNode=(matchedTextNode.length>matchelength)?
matchedTextNode.splitText(matchLength):空;
//确保搜索从文本节点的开头开始
regex.lastIndex=0;
surroundingNode=surrounderCreateFunc(matchedTextNode.cloneNode(true));
parent.insertBefore(surroundingNode,matchedTextNode);
parent.removeChild(matchedTextNode);
}
}
//此函数用于为每个匹配的文本片段创建环境
//并且可以根据您的喜好进行定制
函数createSpan(matchedTextNode){
var el=document.createElement(“span”);
el.style.color=“红色”;
el.appendChild(matchedTextNode);
返回el;
}
//主要功能
函数包装词(容器、词){
//一次替换一个单词,以确保“test2”匹配
for(变量i=0,len=words.length;i
这正是我想要的,但我怎么能让它完全忽略大小写呢?@MikeMellor:Change
newregexp(words[i],“g”)
改为
newregexp(words[i],“gi”)
。天哪,这很简单,我真的应该学习正则表达式。谢谢Tim@MikeMellor:每个人都应该学习正则表达式:)@TimDown:
// 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"]);