【问题标题】:Applying RegEx on all text in element对元素中的所有文本应用正则表达式
【发布时间】:2013-12-22 13:50:53
【问题描述】:

我正在尝试使用 JS 将特定单词动态替换为某个 HTML 元素中的链接。我想我会使用一个简单的正则表达式:

var regEx = new RegExp('\\b'+text+'\\b', 'gi');

在上下文 div 的 innerHTML 属性上应用正则表达式替换的快速'n'nasty 方式:

context.innerHTML = context.innerHTML.replace(regEx, '<a href="#">'+text+"</a>");

这样做的问题是它也适用于图像标题,从而破坏了页面的布局。我希望它仅适用于页面的文本,如果可能的话还排除标题标签,当然还有 HTML 注释等。

所以我尝试了类似的方法,但它似乎根本不起作用:

function replaceText(context, regEx, replace) {
    var childNodes = context.childNodes;
    for (n in childNodes) {
        console.log(childNodes[n].nodeName);
        if (childNodes[n] instanceof Text) {
            childNodes[n].textContent = childNodes[n].textContent.replace(regEx, replace);
        } else if (childNodes[n] instanceof HTMLElement) {
            replaceText(childNodes[n], regEx, replace);
            console.log('Entering '+childNodes[n].nodeName);
        } else {
            console.log('Skipping '+childNodes[n].nodeName);
        }
    }
}

谁能看到我做错了什么,或者想出一个更好的解决方案?谢谢!

更新:

这是context 的内容可能是什么样子的sn-p:

<h4>Newton's Laws of Motion</h4>
<p><span class="inline_title">Law No.1</span>: <span class="caption">An object at rest will remain at rest, and an object in motion will continue to move at constant velocity, unless a net force is applied.</span></p>
<ul>Consequences: <li>Conservation of Momentum in both elastic and inelastic collisions</li>
<li>Conservation of kinetic energy in elastic collisions but not inelastic.</li>
<li>Conservation of angular momentum.</li>
</ul>
<h5>Equations</h5>
<p class="equation">&rho; = mv</p>
<p>where &rho; is the momentum, and m is the mass of an object moving at constant velocity v.</p>

【问题讨论】:

  • 你能展示你的 HTML 吗?
  • 你不应该用 RegEx 做那部分。最好缩小循环中节点的内容,仅缩小其内容,排除其子节点。
  • @PraveenJeganathan 这没什么特别的,只是一个包含一堆

    以及图像和东西的 div...

  • @Allendar 你是什么意思?
  • @Sean context 持有什么?如果你设置一个小提琴,我会容易得多。

标签: javascript html regex replace


【解决方案1】:

你可以用这个:

function replaceText(context, regEx, replace)
{
    var childNodes = context.childNodes;
    for (var i = 0; i<childNodes.length; i++) {
        var childNode = childNodes[i];
        if (childNode.nodeType === 3) // 3 is for text node
            childNode.nodeValue = childNode.nodeValue.replace(regEx, replace);
        else if (childNode.nodeType === 1 && childNode.nodeName != "HEAD")
            replaceText(childNode, regEx, replace); 
    }
}
replaceText(context, /cons/ig, 'GROUIK!');

这个想法是在“上下文”DOM树中找到所有文本节点,这就是我使用递归函数来搜索子节点内的文本节点的原因。

注意:我在函数中测试childNode.nodeName != "HEAD"。这只是避免使用特定标签的示例。在现实生活中,将 body 节点作为参数传递给函数更简单。

【讨论】:

  • 非常感谢!这很好用,但仍然存在一个问题:不能用标签替换字符串,因为它不会被解释......
  • 因为您使用的是nodeValue 属性,它作用于文本节点。这是我一开始没有意识到的问题
【解决方案2】:

据我了解,您正在尝试替换 innerHTML 中但在 tags 内的文本。

首先我尝试使用innerText 而不是innerHTML,但它没有给出预期的结果。后来我找到了@Alan Moore 的answerNegative Lookahead regex 之类的

(?![^<>]*>)

可用于忽略标签&lt;&gt; 中的文本。这是我的方法

var regEx = new RegExp("(?![^<>]*>)" + title, 'gi');
context.innerHTML = context.innerHTML.replace(regEx, '<a href="#">'+text+"</a>");

这是一个示例JSFiddle

【讨论】:

  • 非常感谢您的回答!这非常有效,尽管这种级别的正则表达式远远超出了我的知识范围。
  • 你能想出一种方法来排除特定标签吗?例如。我不想在另一个链接中添加链接...
猜你喜欢
  • 2011-12-18
  • 2017-07-23
  • 2018-03-07
  • 2010-11-16
  • 2011-01-06
  • 2011-04-02
  • 1970-01-01
  • 2019-05-02
  • 2012-10-28
相关资源
最近更新 更多