Chrome扩展程序如何将数据从内容脚本发送到popup.html [英] Chrome Extension how to send data from content script to popup.html

查看:92
本文介绍了Chrome扩展程序如何将数据从内容脚本发送到popup.html的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题在很多帖子中都有提到,但老实说我没有得到它们。我不熟悉JavaScript,Chrome扩展和一切,我有这个课程作业。
所以我需要制作一个插件,使用跨域请求来计算任何给定页面上的DOM对象。
使用Chrome浏览器扩展程序API,我已经能够实现这一目标。
现在问题是我需要在contentScript.js文件的popup.html页面上显示数据。
我不知道该怎么做,我试过阅读文档,但使用chrome进行消息传递,我无法理解要做什么。

以下是目前的代码。

manifest.json

  {
manifest_version :2,

name:Dom Reader,
description:Counts Dom Objects,
version:1.0,

page_action:{
default_icon:icon.png,
default_title:Dom阅读器,
default_popup:popup.html
$ bbackground:{
scripts:[eventPage.js],
persistent:false
},

content_scripts:[
{
matches:[http://pluralsight.com/training/Courses/*,http://pluralsight.com / training / Authors / Details / *,https://www.youtube.com/user/*,https://sites.google.com/site/*,http://127.0.0.1 :3667 / popup.html],
js:[domReader_cs.js,jquery-1.10.2.js]
//\"css\":[\"pluralsight_cs.css ]
}
],

权限:[
标签,
http://pluralsight.com/*,
http://youtube.com/*,
https://网站.google.com / *,
http://127.0.0.1:3667/*
]

popup.html

 <!doctype html> 
< html>

< title> Dom阅读器< / title>
< script src =jquery-1.10.2.jstype =text / javascript>< / script>
< script src =popup.jstype =text / javascript>< / script>

< body>
< H1> Dom阅读器< / H1>
< input type =submitid =readDomvalue =Read DOM Objects/>

< div id =domInfo>

< / div>
< / body>
< / html>

eventPage.js

  var value1,value2,value3; 

chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){
if(request.action ==show){
chrome.tabs.query ({active:true,currentWindow:true},function(tabs){
chrome.pageAction.show(tabs [0] .id);
});
}

value1 = request.tElements;
});



popup.js

  $(function(){
$('#readDom')。click(function(){
chrome.tabs.query({active:true,currentWindow:true},函数(标签){
chrome.tabs.sendMessage(tabs [0] .id,{action:readDom});

});
});
});

contentScript

  var totalElements; 
var inputFields;
var buttonElement;

chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){
if(request.action ==readDom){

totalElements = $(*)。length;
inputFields = $(input)。length;
buttonElement = $(button)。length;





chrome.runtime.sendMessage({
action:show,
tElements:totalElements,
Ifields:inputFields,
bElements:buttonElement

});

任何帮助将不胜感激,请避免任何noobness我做:)

$ b $虽然你肯定是在正确的方向(实际上非​​常接近尾声),但是在你的代码中有几个(imo)不好的做法(例如注入一个完整的库(jquery)用于这样一个简单的任务,声明不必要的权限,对API方法进行superflous调用等)。
我没有自己测试你的代码,但是从快速概述我相信纠正以下可能会导致一个工作解决方案(尽管不是非常接近最佳):


  1. manifest.json strong>:更改内容脚本的顺序,首先放置jquery。根据 相关文档


    js[...]要注入匹配页面的JavaScript文件列表。这些按照它们出现的顺序在 中注入

    (强调我的)

  2. contentscript.js :将 chrome.runtime.sendMessage({...})移动到 onMessage 侦听器回调。






这就是我提出的方法:

>

控制流:




  1. 内容脚本被注入符合某些条件的每个页面。 / li>
  2. 注入内容后,内容脚本会将消息发送到事件页面(非持久性背景页面),并且事件页面将页面操作附加到该标签。

  3. 加载页面操作弹出窗口后,它会向内容脚本发送一条消息,询问它需要的信息。 内容脚本处理请求,响应,以便页面操作弹出窗口可以显示信息。 目录结构: / h3>

     根目录/ 
    | _____ img
    | _____ icon19.png
    | _____ icon38.png
    | _____ manifest.json
    | _____ background.js
    | _____ content.js
    | _____ popup.js
    | _____ popup.html






    清单。 json:



      {
    manifest_version:2,
    name:Test Extension,
    version:0.0,
    offline_enabled:true,

    background:{
    persistent:false,
    脚本:[background.js]
    },

    content_scripts:[{
    matches:[*://*.stackoverflow.com/ *],
    js:[content.js],
    run_at:document_idle,
    all_frames:false
    }],
    $ b $page_action:{
    default_title:Test Extension,
    //default_icon:{
    //19:img / icon19。 png,
    //38:img / icon38.png
    //},
    default_popup:popup.html
    }

    //无需特殊权限...
    //permissions:[]
    }






    background.js:



      chrome。 runti me.onMessage.addListener(函数(msg,sender){
    //首先验证消息的结构
    if((msg.from ==='content')&& (msg.subject ==='showPageAction')){
    //为请求标签启用页面操作
    chrome.pageAction.show(sender.tab.id);
    }
    });






    content.js:



      //通知后台页面
    //此页面应该有一个页面操作
    chrome.runtime.sendMessage({
    from:'content',
    subject:'showPageAction'
    });

    //监听弹出消息
    chrome.runtime.onMessage.addListener(函数(msg,sender,response){
    //首先验证消息的结构
    if((msg.from ==='popup')&&(msg.subject ==='DOMInfo')){
    //收集必要的数据
    //(对于你的具体需求,document.querySelectorAll(...)`
    //应该等价于jquery的`$(...)`)
    var domInfo = {
    total:document。 querySelectorAll('*')。length,
    inputs:document.querySelectorAll('input')。length,
    buttons:document.querySelectorAll('button')。length
    };

    //通过指定的回调* /
    响应(domInfo);
    }
    })直接响应发件人(弹出),
    //;






    popup.js:



      //用新数据
    函数更新相关字段setDOMInfo(info){
    document.getElementById('total') .textContent = info.total;
    document.getElementById('inputs')。textContent = info.inputs;
    document.getElementById('buttons')。textContent = info.buttons;
    }

    //一旦DOM准备就绪...
    window.addEventListener('DOMContentLoaded',function(){
    // ...查询活动标签...
    chrome.tabs.query({
    active:true,
    currentWindow:true
    },function(tabs){
    //。 ...并发送一个DOM信息请求...
    chrome.tabs.sendMessage(
    tabs [0] .id,
    {from:'popup',subject:'DOMInfo' },
    // ...还指定一个回调被称为
    //从接收端(内容脚本)
    setDOMInfo);
    });
    });






    popup.html:



     <!DOCTYPE html> 
    < html>
    < head>
    < script type =text / javascriptsrc =popup.js>< / script>
    < / head>
    < body>
    < h3 style =font-weight:bold; text-align:center;> DOM Info< / h3>
    < table border =1cellpadding =3style =border-collapse:collapse;>
    < tr>
    < td nowrap>元素总数:< / td>
    < td align =right>< span id =total> N / A< / span>< / td>
    < / tr>
    < tr>
    < td nowrap>输入元素的数量:< / td>
    < td align =right>< span id =inputs> N / A< / span>< / td>
    < / tr>
    < tr>
    < td nowrap>按钮元素的数量:< / td>
    < td align =right>< span id =buttons> N / A< / span>< / td>
    < / tr>
    < / table>
    < / body>
    < / html>


    I know this this has been asked in numerous posts but honestly I don't get them. I am new to JavaScript, Chrome Extensions and everything and I have this class assignment. So I need to make a plugin that would count DOM objects on any given page using Cross Domain Requests. I've been able to achieve this so far using Chrome Extension API's. Now the problem is I need to show the data on my popup.html page from the contentScript.js file. I don't know how to do that I've tried reading the documentation but messaging in chrome I just can't understand what to do.

    following is the code so far.

    manifest.json

    {
    "manifest_version":2,
    
    "name":"Dom Reader",
    "description":"Counts Dom Objects",
    "version":"1.0",
    
    "page_action": {
        "default_icon":"icon.png",
        "default_title":"Dom Reader",
        "default_popup":"popup.html"
    },
    
    "background":{
        "scripts":["eventPage.js"],
        "persistent":false
    },
    
    "content_scripts":[
        {
            "matches":["http://pluralsight.com/training/Courses/*", "http://pluralsight.com/training/Authors/Details/*",                                          "https://www.youtube.com/user/*", "https://sites.google.com/site/*", "http://127.0.0.1:3667/popup.html"],
            "js":["domReader_cs.js","jquery-1.10.2.js"]
            //"css":["pluralsight_cs.css"]
        }
    ],
    
    "permissions":[
        "tabs",
        "http://pluralsight.com/*",
        "http://youtube.com/*",
        "https://sites.google.com/*",
        "http://127.0.0.1:3667/*"
    ]
    

    popup.html

    <!doctype html>
    <html>
    
        <title> Dom Reader </title>    
        <script src="jquery-1.10.2.js" type="text/javascript"></script>
        <script src="popup.js" type="text/javascript"></script>
    
    <body>
        <H1> Dom Reader </H1>
        <input type="submit" id="readDom" value="Read DOM Objects" />
    
       <div id="domInfo">
    
        </div>
    </body>
    </html>
    

    eventPage.js

    var value1,value2,value3;
    
    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.action == "show") {
        chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
            chrome.pageAction.show(tabs[0].id);
        });
    }
    
    value1 = request.tElements;
    });
    

    popup.js

    $(function (){
    $('#readDom').click(function(){
    chrome.tabs.query({active: true, currentWindow: true}, function (tabs){
        chrome.tabs.sendMessage(tabs[0].id, {action: "readDom"});
    
     });
    });
    });
    

    contentScript

    var totalElements;
    var inputFields;
    var buttonElement;
    
    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){
    if(request.action == "readDom"){
    
        totalElements = $("*").length;
        inputFields = $("input").length;
        buttonElement = $("button").length;
    
    
    }
    })
    
    chrome.runtime.sendMessage({ 
    action: "show", 
    tElements: totalElements, 
    Ifields: inputFields, 
    bElements: buttonElement 
    
    });
    

    Any help would be appreciated and please avoid any noobness I did :)

    解决方案

    Although you are definitely in the right direction (and actually pretty close to the end), there are several (imo) bad practises in your code (e.g. injecting a whole library (jquery) for such a trivial task, declaring unnecessary permissions, making superflous calls to API methods etc).
    I did not test your code myself, but from a quick overview I believe that correcting the following could result in a working solution (although not very close to optimal):

    1. In manifest.json: Change the order of the content scripts, putting jquery first. According to the relevant docs:

      "js" [...] The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.

      (emphasis mine)

    2. In contentscript.js: Move the chrome.runtime.sendMessage({...}) block inside the onMessage listener callback.


    That said, here is my proposed approach:

    Control flow:

    1. A content script is injected into each page matching some criteria.
    2. Once injected, the content scripts send a message to the event page (non-persistent background page) and the event page attaches a page=action to the tab.
    3. As soon as the page-action popup is loaded, it sends a message to the content script, asking for the info it needs.
    4. The content script processes the request, and responds so the page-action popup can display the info.


    Directory structure:

              root-directory/
               |_____img
                     |_____icon19.png
                     |_____icon38.png
               |_____manifest.json
               |_____background.js
               |_____content.js
               |_____popup.js
               |_____popup.html
    


    manifest.json:

    {
      "manifest_version": 2,
      "name":    "Test Extension",
      "version": "0.0",
      "offline_enabled": true,
    
      "background": {
        "persistent": false,
        "scripts": ["background.js"]
      },
    
      "content_scripts": [{
        "matches":    ["*://*.stackoverflow.com/*"],
        "js":         ["content.js"],
        "run_at":     "document_idle",
        "all_frames": false
      }],
    
      "page_action": {
        "default_title": "Test Extension",
        //"default_icon": {
        //    "19": "img/icon19.png",
        //    "38": "img/icon38.png"
        //},
        "default_popup": "popup.html"
      }
    
      // No special permissions required...
      //"permissions": []
    }
    


    background.js:

    chrome.runtime.onMessage.addListener(function (msg, sender) {
      // First, validate the message's structure
      if ((msg.from === 'content') && (msg.subject === 'showPageAction')) {
        // Enable the page-action for the requesting tab
        chrome.pageAction.show(sender.tab.id);
      }
    });
    


    content.js:

    // Inform the background page that 
    // this tab should have a page-action
    chrome.runtime.sendMessage({
      from:    'content',
      subject: 'showPageAction'
    });
    
    // Listen for messages from the popup
    chrome.runtime.onMessage.addListener(function (msg, sender, response) {
      // First, validate the message's structure
      if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
        // Collect the necessary data 
        // (For your specific requirements `document.querySelectorAll(...)`
        //  should be equivalent to jquery's `$(...)`)
        var domInfo = {
          total:   document.querySelectorAll('*').length,
          inputs:  document.querySelectorAll('input').length,
          buttons: document.querySelectorAll('button').length
        };
    
        // Directly respond to the sender (popup), 
        // through the specified callback */
        response(domInfo);
      }
    });
    


    popup.js:

    // Update the relevant fields with the new data
    function setDOMInfo(info) {
      document.getElementById('total').textContent   = info.total;
      document.getElementById('inputs').textContent  = info.inputs;
      document.getElementById('buttons').textContent = info.buttons;
    }
    
    // Once the DOM is ready...
    window.addEventListener('DOMContentLoaded', function () {
      // ...query for the active tab...
      chrome.tabs.query({
        active: true,
        currentWindow: true
      }, function (tabs) {
        // ...and send a request for the DOM info...
        chrome.tabs.sendMessage(
            tabs[0].id,
            {from: 'popup', subject: 'DOMInfo'},
            // ...also specifying a callback to be called 
            //    from the receiving end (content script)
            setDOMInfo);
      });
    });
    


    popup.html:

    <!DOCTYPE html>
    <html>
      <head>
        <script type="text/javascript" src="popup.js"></script>
      </head>
      <body>
        <h3 style="font-weight:bold; text-align:center;">DOM Info</h3>
        <table border="1" cellpadding="3" style="border-collapse:collapse;">
          <tr>
            <td nowrap>Total number of elements:</td>
            <td align="right"><span id="total">N/A</span></td>
          </tr>
          <tr>
            <td nowrap>Number of input elements:</td>
            <td align="right"><span id="inputs">N/A</span></td>
          </tr>
          <tr>
            <td nowrap>Number of button elements:</td>
            <td align="right"><span id="buttons">N/A</span></td>
          </tr>
        </table>
      </body>
    </html>
    

    这篇关于Chrome扩展程序如何将数据从内容脚本发送到popup.html的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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