用chrome扩展的链接代替文本



我试图用链接替换网页上的文本。当我尝试这样做时,它只是用标签代替文本,而不是链接。例如,下面的代码将把river替换为:

<a href="http://www.cnn.com">asdf</a>

这是我目前为止写的:

function handleText(textNode)
{
    var v = textNode.nodeValue;
    v = v.replace(/briverb/g, '<a href="http://www.cnn.com">asdf</a>');
    textNode.nodeValue = v;
}

如果您只想将文本更改为其他纯文本,那么您可以直接更改文本节点的内容。然而,您想要添加一个<a>元素。对于您想要添加的每个<a>元素,您实际上想要添加一个子元素。文本节点不能有子节点。因此,要做到这一点,您必须用更复杂的结构实际替换文本节点。在这样做的过程中,您希望对DOM的影响尽可能小,以免干扰依赖于当前DOM结构的其他脚本。产生小影响的最简单方法是将文本节点替换为包含新文本节点的<span>(文本将在新的<a>周围分裂)和任何新的<a>元素。

下面的代码应该做你想做的。它将textNode替换为包含新文本节点和创建的<a>元素的<span>。它只在需要插入一个或多个<a>元素时才进行替换。

function handleTextNode(textNode) {
    if(textNode.nodeName !== '#text'
        || textNode.parentNode.nodeName === 'SCRIPT' 
        || textNode.parentNode.nodeName === 'STYLE'
    ) {
        //Don't do anything except on text nodes, which are not children 
        //  of <script> or <style>.
        return;
    }
    let origText = textNode.textContent;
    let newHtml=origText.replace(/briverb/g,'<a href="http://www.cnn.com">asdf</a>');
    //Only change the DOM if we actually made a replacement in the text.
    //Compare the strings, as it should be faster than a second RegExp operation and
    //  lets us use the RegExp in only one place for maintainability.
    if( newHtml !== origText) {
        let newSpan = document.createElement('span');
        newSpan.innerHTML = newHtml;
        textNode.parentNode.replaceChild(newSpan,textNode);
    }
}
//Testing: Walk the DOM of the <body> handling all non-empty text nodes
function processDocument() {
    //Create the TreeWalker
    let treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT,{
        acceptNode: function(node) { 
            if(node.textContent.length === 0) {
                //Alternately, could filter out the <script> and <style> text nodes here.
                return NodeFilter.FILTER_SKIP; //Skip empty text nodes
            } //else
            return NodeFilter.FILTER_ACCEPT;
        }
    }, false );
    //Make a list of the text nodes prior to modifying the DOM. Once the DOM is 
    //  modified the TreeWalker will become invalid (i.e. the TreeWalker will stop
    //  traversing the DOM after the first modification).
    let nodeList=[];
    while(treeWalker.nextNode()){
        nodeList.push(treeWalker.currentNode);
    }
    //Iterate over all text nodes, calling handleTextNode on each node in the list.
    nodeList.forEach(function(el){
        handleTextNode(el);
    });
} 
document.getElementById('clickTo').addEventListener('click',processDocument,false);
<input type="button" id="clickTo" value="Click to process"/>
<div id="testDiv">This text should change to a link -->river<--.</div>

TreeWalker代码摘自我的回答

最新更新