Chrome扩展程序如何将数据从内容脚本发送到popup.html [英] Chrome Extension how to send data from content script to 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;
});
$(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调用等)。我没有自己测试你的代码,但是从快速概述我相信纠正以下可能会导致一个工作解决方案(尽管不是非常接近最佳):
-
在 manifest.json
js[...]要注入匹配页面的JavaScript文件列表。这些按照它们出现的顺序在 中注入。
(强调我的) contentscript.js :将 chrome.runtime.sendMessage({...})块移动到 这就是我提出的方法: onMessage
侦听器回调。
控制流:
- 内容脚本被注入符合某些条件的每个页面。 / li>
- 注入内容后,内容脚本会将消息发送到事件页面(非持久性背景页面),并且事件页面将页面操作附加到该标签。
- 加载页面操作弹出窗口后,它会向内容脚本发送一条消息,询问它需要的信息。 内容脚本处理请求,响应,以便页面操作弹出窗口可以显示信息。 目录结构: / 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):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)
In contentscript.js: Move the chrome.runtime.sendMessage({...}) block inside the
onMessage
listener callback.
That said, here is my proposed approach:
Control flow:
- A content script is injected into each page matching some criteria.
- 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.
- As soon as the page-action popup is loaded, it sends a message to the content script, asking for the info it needs.
- 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屋!