将网页文本中的匹配字词更改为按钮

时间:2016-11-13 10:08:20

标签: javascript jquery google-chrome-extension

我正在尝试制作Chrome扩展程序,通过网站解析关键字,然后用按钮替换这些关键字。但是,当我更改文本时,图像路径会损坏。

// This is a content script (isolated environment)
//    It will have partial access to the chrome API
// TODO 
//    Consider adding a "run_at": "document_end" in the manifest... 
//      don't want to run before full load
//      Might also be able to do this via the chrome API 
console.log("Scraper Running");
var keywords = ["sword", "gold", "yellow", "blue", "green", "china", "civil", "state"];

// This will match the keywords with the page textx
// Will also create the necessary buttons
(function() {
  function runScraper() {
    console.log($('body'));
    for(var i = 0; i < keywords.length; i++){
     $("body:not([href]):not(:image)").html($("body:not([href]):not(:image)").html()
         .replace(new RegExp(keywords[i], "ig"),"<button> " + keywords[i] + " </button>"));
     console.log("Ran it " + i);
    }
  }
  function createResourceButton() {
    // Programatically create a button here

    // Really want to return the button
    return null;
  }
  function createActionButton() {
  }
  runScraper();
})();
// TODO create the functions that the buttons will call
//      These will pass data to the chrome extension (see message passing)
//      Or we can consider a hack like this: 
// "Building a Chrome Extension - Inject code in a page using a Content script"
// http://stackoverflow.com/questions/9515704

当前结果的图片:

Wikipedia images will not load

1 个答案:

答案 0 :(得分:4)

您解决此问题的方法是错误的。为此,您需要遍历文档,只更改文本节点,而不是所有节点的HTML。

修改this other answer of mine中的代码,以下完整扩展程序会将页面上所有匹配的字词更改为按钮。

行动中的扩展:

button-izing matching words in Wikipedia page used in image by OP

的manifest.json

{
    "description": "Upon action button click, make all matching words buttons.",
    "manifest_version": 2,
    "name": "Button all matching words",
    "version": "0.1",

    "permissions": [
        "activeTab"
    ],

    "background": {
        "scripts": [
            "background.js"
        ]
    },

    "browser_action": {
        "default_icon": {
            "32": "myIcon.png"
        },
        "default_title": "Make Buttons of specified words"
    }
}

background.js

chrome.browserAction.onClicked.addListener(function(tab) {
    //Inject the script to change the text of all matching words into buttons.
    chrome.tabs.executeScript(tab.id,{file: 'contentScript.js'});
});

contentScript.js

(function(){
    var keywords = ["sword", "gold", "yellow", "blue", "green", "china", "civil", "state"];
    //Build the RegExp once. Doing it for every replace is inefficient.
    //  Build one RegExp that matches all of the words instead of multiple RegExp.
    var regExpText = '\\b(' + keywords.join('|') + ')\\b';
    console.log(regExpText);
    var myRegExp = new RegExp(regExpText ,'mgi');

    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;
        //Clear the regExp search, not doing so may cause issues if matching against
        //  identical strings after the first one.
        myRegExp.lastIndex = 0;
        let newHtml=origText.replace(myRegExp, '<button>$1</button>');
        //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);
        }
    }

    //This assumes that you want all matching words in the document changed, without
    //  limiting it to only certain sub portions of the document (i.e. not 'not(a)').
    let textNodes = [];
    //Create a NodeIterator to get the text node descendants
    let nodeIter = document.createNodeIterator(document.body,NodeFilter.SHOW_TEXT);
    let currentNode;
    //Add text nodes found to list of text nodes to process below.
    while(currentNode = nodeIter.nextNode()) {
        textNodes.push(currentNode);
    }
    //Process each text node
    textNodes.forEach(function(el){
        handleTextNode(el);
    });
})();

myIcon.png

Icojam-Weathy-24-tornado.png

handleTextNode中用于修改文本节点的代码已从another answer of mine中的代码修改。