javascript - 将网页段落中的每个单词替换为包含该文本的按钮

标签 javascript jquery html dom google-chrome-extension

我正在开发一个 Google Chrome 扩展程序,它获取所有段落(p 标签内容)并将其中的每个单词放入一个按钮中。这是我正在开发的一个更大项目的一部分。我在 JSFiddle 上有该应用程序部分的工作副本.

现在,我正在尝试将该代码移植到 Chrome 扩展程序中。但是,我在从后台脚本访问 DOM 时遇到了问题,因此我可以用我的代码(在我的函数 FormatText() 中)操作它。我什至还没有调用该函数,因为我不知道应该如何在 background.js 中编辑 DOM。

这是我的代码:

ma​​nifest.json

{
  "manifest_version": 2,
  "name": "Test Extension",
  "version": "1",
  "background": {
    "persistent": false,
    "scripts": ["background.js","jquery-3.0.0.min.js","TextSplitter.js"]
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content.js"]
  }],
  "browser_action": {
    "default_title": "Test Extension"
  },
  "permissions": ["activeTab","tabs"]
}

content.js

// Listen for messages
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
    // If the received message has the expected format...
    if (msg.text === 'report_back') {
        // Call the specified callback, passing
        // the web-page's DOM content as argument
        sendResponse(document);
    }
});

背景.js

// A function to use as callback
function doStuffWithDom(domContent) {
    console.log('I received the following DOM content:\n');
    console.log(JSON.stringify(domContent));
    var domAccess = $(domContent);
    var myText = $(domAccess).find("p").text();
    console.log("THIS IS MY TEXT: " + myText);
}

chrome.tabs.onUpdated.addListener(function (tabID, info, tab) {
    console.log("Status: " + info.status);
    if (info.status == "complete") {
        chrome.tabs.sendMessage(tab.id, { text: 'report_back' }, doStuffWithDom);
    }
});

TextSplitter.js

function FormatText(domObject) {
    var pElements = []; // Holds the split paragraphs for each p tag
    var pElementIndex = 0;

    //Loop through each p tag in web page
    $("p").each(function (webPElementIndex, webPElement) {
        var jQObjWebPElement = $(webPElement);// Convert p element to jQuery Obj
        // split current paragraph element text into an array of seperate words
        pElements[webPElementIndex] = jQObjWebPElement.text().split(" ");
    });

    //Clear text out of all p elements
    $("p").empty();

    //Loop through p elements in the webpage to add back text with spans around each word
    $("p").each(function (webPElementIndex, webPElement) {
        // convert current web page element to jQuery Obj
        var jQObjWebPElement = $(webPElement);
        // Loop through each word stored in each stored paragraph element
        $.each(pElements[pElementIndex], function (pElementWordIndex, pElementWord) {
            var jQObjPElementWord = $(pElementWord); // convert element to jQuery object
            jQObjWebPElement.append($("<button>")
                            .text(pElements[pElementIndex][pElementWordIndex]));
        });
        pElementIndex = pElementIndex + 1;
    });
}

请原谅我的无知,因为我对使用 DOM 非常陌生,尤其是在 Chrome 扩展中。

最佳答案

您的代码在某些方面显得过于复杂。特别是,DOM 只能通过内容脚本进行操作。正如 wOxxOm 在评论中提到的,您最好阅读 Chrome extension architecture overview 。它具有整体架构信息,可以帮助您了解事物通常是如何完成/组织的。

以下完整扩展(在 Chrome 和 Firefox 上测试)将空白字符(或行/段落的开头或结尾)包围的所有非空白字符更改为 <button> 内。 。当 actionButton 时,它会执行此操作。在浏览器用户界面中单击。

actionButton单击后,将注入(inject) contentScript.js 文件。内容脚本进行更改并退出。对于此功能,不需要在页面中等待获取消息来执行简单功能的内容脚本。您实际上所做的可能比用代码描述/显示的要多,但是对于问题中提到的功能,请使用 tabs.executeScript() 注入(inject)脚本。是一个更好、更简单、更高效的选择。

我选择不使用 jQuery。 jQuery 有很多好处。在这种情况下,我不喜欢加载 90 KiB 代码来节省几个字符,而不是使用普通 JavaScript 来完成同样的事情。

我没有仔细查看您用来执行按钮化的代码。我已经在 another answer 中有代码它可以很容易地适应执行此任务。鉴于您的问题是关于如何操作 DOM,而不是关于按钮化代码的功能,我选择使用我已经熟悉的代码。

正在运行的扩展:

button-izing example.com

manifest.json

{
    "description": "Inject content script to make all words in <p> elements buttons",
    "manifest_version": 2,
    "name": "Button all words in <p>",
    "version": "0.1",

    "permissions": [
        "activeTab"
    ],

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

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

background.js:

chrome.browserAction.onClicked.addListener(function(tab) {
    //Inject the script to change the text in <p> to buttons
    chrome.tabs.executeScript(tab.id,{file: 'contentScript.js'});
});

contentScript.js:

(function(){
    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(/(^|\s)(\S+)(?=\s|$)/mg, '$1<button>$2</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);
        }
    }

    //Find all text node descendants of <p> elements:
    let allP = document.querySelectorAll('p');  // Get all <p>
    let textNodes = [];
    for (let p of allP) {
        //Create a NodeIterator to get the text nodes descendants of each <p>
        let nodeIter = document.createNodeIterator(p,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 中的代码修改的.

关于javascript - 将网页段落中的每个单词替换为包含该文本的按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40542280/

相关文章:

jquery - 根据具有选定属性的选择输入更改文本框值

javascript - CSS Transform Skew 和 Scale 在 Microsoft Edge 中无法正常工作

html - 在 VSCode 中以与 Visual Studio 相同的方式格式化 HTML

javascript - 我不明白为什么我处理格式参数失败; Python 再次 'list'

javascript - 循环遍历json并获取nodejs中的特定值

javascript - 根据下拉选择将文本加载到文本区域

javascript防止复制/粘贴超出文本区域中的字符限制

javascript - 为什么后续点击 jstree 的子级不起作用

javascript - 垂直向下滑动加载页面

javascript - 我正在尝试使用复选框作为条件