1

我正在开发一个简单的浏览器插件,用另一个单词替换 1 个单词,但添加了一个用于小工具提示/弹出窗口的锚点。我已经有这个实际工作了,但我的问题是,如果要替换的单词已经在锚点内,那么我会</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>";            
            }
        })
    );
});

我怀疑我可能需要编写一个更复杂的正则表达式,但这是我第一次使用它,所以任何建议都将不胜感激!

更新 所以我有一个测试页面来查看我的代码是如何工作的。这是页面中原始 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 根据要求,以下是我的插件在将 'chicken' 替换为 'kip' 时可能遇到的“未处理”示例:

<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”,因为根据我现有的正则表达式,我只想要整个单词交换。'pie-chicken' 确实被交换了。此行已使用现有代码正确处理。

我实际上只是想在我现有的代码中添加额外的规则,上面写着“不要替换代码并且不要替换如果在锚打开标记内。

4

1 回答 1

0

由于您使用的是 JavaScript,因此您已经可以访问 DOM。你为什么要尝试使用正则表达式???

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

(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。
于 2013-09-04T15:04:46.107 回答