使用 .replace() 突出显示页面上的一个词 [英] Highlight a word of text on the page using .replace()

查看:29
本文介绍了使用 .replace() 突出显示页面上的一个词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Google Chrome 扩展程序,它允许您自动将突出显示的 CSS 规则应用于您选择的单词.

I'm developing a Google Chrome extension that allows you to automatically apply a highlighting CSS rule to a word that you choose.

我有以下代码

var elements = document.getElementsByTagName('*');

for (var i=0; i<elements.length; i++) {
    var element = elements[i];

    for (var j=0; j<element.childNodes.length; j++) {
        var node = element.childNodes[j];

        if(node.nodeType === 3) {
            var text = node.nodeValue;

            var fetchedText = text.match(/teste/gi);

            if(fetchedText) {
                var replacedText = element.innerHTML.replace(/(teste)/gi, "<span style="background-color: yellow">$1</span>");

                if (replacedText !== text) {
                    element.innerHTML = replacedText;
                }
            }
        }
    }
}

它打破并冻结了我的 Chrome 标签.但是,如果我从 element.innerHTML = replacementText; 切换到 element.innerHTML = "text"; 这会起作用.

Which breaks and freezes my Chrome tab. However, if I switch from element.innerHTML = replacedText; to element.innerHTML = "text"; this works.

我似乎找不到以下代码有什么问题.

I can't seem to find what's wrong with the following code.

推荐答案

我遇到的错误是由于递归循环,例如,我正在寻找关键字 teste 而我插入内容为 <span style="background-color: #ffff00">teste</span> 的新元素,这将强制脚本尝试替换新关键字 teste 再次等等.

The error I was experiencing was due to a recursive loop because, for instance, I was looking for the keyword teste and I was inserting a new element with the content <span style="background-color: #ffff00">teste</span> which would force the script to try to replace the new keyword teste again and so on.

我想出了这个函数:

function applyReplacementRule(node) {
    // Ignore any node whose tag is banned
    if (!node || $.inArray(node.tagName, hwBannedTags) !== -1) { return; }

    try {
        $(node).contents().each(function (i, v) {
            // Ignore any child node that has been replaced already or doesn't contain text
            if (v.isReplaced || v.nodeType !== Node.TEXT_NODE) { return; }

            // Apply each replacement in order
            hwReplacements.then(function (replacements) {
                replacements.words.forEach(function (replacement) {
                    //if( !replacement.active ) return;
                    var matchedText = v.textContent.match(new RegExp(replacement, "i"));

                    if (matchedText) {
                        // Use `` instead of '' or "" if you want to use ${variable} inside a string
                        // For more information visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
                        var replacedText = node.innerHTML.replace(new RegExp(`(${replacement})`, "i"), "<span style="background-color: #ffff00">$1</span>");

                        node.innerHTML = replacedText;
                    }
                });
            }).catch(function (reason) {
                console.log("Handle rejected promise (" + reason + ") here.");
            });

            v.isReplaced = true;
        });
    } catch (err) {
        // Basically this means that an iframe had a cross-domain source
        if (err.name !== "SecurityError")
        { throw err; }
    }
}

我修改节点属性并告诉"我已经修改了该节点的地方,这样我就不会再次陷入递归无限循环.

Where I modify the node property and "tell" that I've already modify that node so I don't end up on a recursive infinite loop again.

附言如您所见,此解决方案使用 jQuery.我将尝试重写它以仅使用 Vanilla JS.

P.S. As you can see this solution uses jQuery. I'll try to rewrite this to use just Vanilla JS.

这篇关于使用 .replace() 突出显示页面上的一个词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆