条件替换页面中的文本

时间:2013-09-03 12:12:54

标签: javascript jquery regex string replace

我正在使用一个简单的浏览器插件来替换另一个单词,但添加了一个小工具提示/弹出的锚点。我已经实际使用了这个,但我的问题是,如果要替换的单词已经在锚点内,那么我的</a>会关闭已经打开的<a>

所以我需要一些帮助,如何只替换一个单词,只要它不在一个开放的锚标签内。对此进行跟进也是为了确保目标词不在<input>或其他不适当的标签中。

我的代码是:

var regex = new RegExp("\\b" + nativeWord + "\\b", "igm");
var body = $('body');

body.each(function() {
    $(this).html(
        $(this).html().replace(regex, function() {
            counter++;
            if(counter > wordSwapLimit) {
                return nativeWord;
            } else {
                return "<a class=\"tooltip\" href=\"#\">" + studyWord + "<span class=\"classic\">" + nativeWord + "</span></a>";            
            }
        })
    );
});

我怀疑我可能需要编写一个更复杂的RegExp,但这是我第一次参加,所以任何建议都会非常感激!

更新 所以我有一个测试页面,我可以看看我的代码是如何工作的。 这是页面中原始HTML的一部分:

<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>

但是使用上面显示的代码并将'chicken'换成'kip',这会改为:

<p id="changeArea"> I <a href="http://www.&lt;a class=" tooltip"="">kip<span class="classic">chicken</span></a>.com"&gt;love <a class="tooltip" href="#">kip<span class="classic">chicken</span></a> but I hate beef. </p>

如果我在交换的内容周围没有任何锚点,那么它的工作原理非常好,我会得到一个很好的翻转工具提示。

再次感谢您的帮助!

更新2 根据要求,这里是'未经处理'的例子,我的插件可能在交换'kip'的'chicken'时遇到:

<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>
<p id="changeArea2"> Chickenpie? pie-chicken. </p>

我希望的是以下内容:

<p id="changeArea"> I <a href="http://www.chicken.com">love chicken but I hate</a> beef. </p>
<p id="changeArea2"> Chickenpie? pie-<a class="tooltip" href="#">kip<span class="classic">chicken</span></a>. </p>

正如你在第一行中看到的那样,html代码是单独存在的,就像单词的文本一样,因为它在URL中,因此如果放入我的工具提示锚,它会破坏它。 第二行忽略了'chickenpie',因为根据我现有的正则表达式,我只想要整个单词交换。 “馅饼鸡”确实会被换掉。使用现有代码正确处理此行。

我真的只是想在我现有的代码中添加额外的规则,这些规则说'不要替换代码,如果在锚开放标记内,则不要替换。

1 个答案:

答案 0 :(得分:0)

由于您使用的是JavaScript,因此您已经可以访问DOM。你为什么要试试using Regexes ???

只需遍历文本节点,忽略现有链接:

(function(elem) {
    var recurse = arguments.callee, nodes = elem.childNodes, l = nodes.length, i, t,
        getLink = function() {
            var a = document.createElement('a'), s = document.createElement('span');
            a.href = "#";
            a.className = "tooltip";
            a.appendChild(document.createTextNode(studyWord));
            s.className = "classic";
            s.appendChild(document.createTextNode(nativeWord));
            a.appendChild(s);
            return a;
        };
    for( i=0; i<l; i++) {
        switch(nodes[i].nodeType) {
        case 1:
            // element - recurse, but not if already a link
            if( nodes[i].nodeName != "A") recurse(nodes[i]);
            break;
        case 3:
            // text node, look for keyword
            t = nodes[i].nodeValue.search(new RegExp("\\b"+nativeWord+"\\b","i"));
            if( t > -1) {
                // found it! now to hack around...
                t = nodes[i].splitText(t);
                t.splitText(nativeWord.length);
                t.parentNode.replaceChild(t,getLink());
            }
            break;
        }
    }
})(document.body);

请注意:此方法使用Vanilla JS。您可以确保在加载页面后运行。这可以通过以下方式完成:

  • defer属性添加到脚本中(如果它是外部的)
  • 将脚本放在</body>之前(或至少在您希望影响的所有内容之后)
  • 将它包装在window.onload处理程序中,甚至包含$(function() {...}),因为您已经在使用jQuery。