javascript - Chrome-utvidelse hvordan sende data fra innholdsskript til popup.html
Jeg vet at dette har blitt spurt om i mange innlegg, men ærlig talt forstår jeg dem ikke. Jeg er ny på JavaScript, Chrome-utvidelser og alt dette, og jeg har en klasseoppgave. Så jeg må lage en plugin som teller DOM-objekter på hvilken som helst side ved bruk av Cross Domain Requests. Jeg har så langt klart å oppnå dette ved å bruke Chrome Extension API-er. Nå er problemet at jeg må vise dataene på min popup.html-side fra contentScript.js-filen. Jeg vet ikke hvordan jeg skal gjøre det, jeg har prøvd å lese dokumentasjonen, men meldingshåndtering i Chrome skjønner jeg bare ikke hva jeg skal gjøre med.
følgende er koden så langt.
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>
eventSide.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"});
});
});
});
innholdsskript
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
});
All hjelp vil bli satt pris på, og vennligst unngå enhver nybegynnerfeil jeg gjorde :)
Svar #1
Selv om du definitivt er på rett vei (og faktisk ganske nær slutten), er det flere (etter min mening) dårlige praksiser i koden din (f.eks. å injisere et helt bibliotek (jquery) for en så triviell oppgave, deklarere unødvendige tillatelser, gjøre overflødige kall til API-metoder osv).
Jeg har ikke testet koden din selv, men ut fra en rask oversikt tror jeg at å rette opp følgende kunne resultere i en fungerende løsning (selv om den ikke er veldig nær optimal):
- I manifest.json: Endre rekkefølgen på innholdsskriptet, og legg jQuery først. I følge de relevante dokumentene:
"js" [...] Listen over JavaScript-filer som skal injiseres på samsvarende sider. Disse injiseres i den rekkefølgen de vises i dette arrayet.
(utheving mitt)
- I contentscript.js: Flytt chrome.runtime.sendMessage({...})-blokken inn i
onMessage-lytterens tilbakeringingsfunksjon.
Når det er sagt, her er min foreslåtte tilnærming:
Kontrollflyt:
- Et innholdsskript injiseres på hver side som oppfyller visse kriterier.
- Når de er injisert, sender innholdsskriptene en melding til hendelsessiden (også kjent som ikke-persistent bakgrunnsside), og hendelsessiden legger til en sidehandling for fanen.
- Så snart side-handlingspopupen er lastet, sender den en melding til innholdsskriptet, og spør etter informasjonen den trenger.
- Innholdsskriptet behandler forespørselen, og svarer slik at sidehandlingspopupen kan vise informasjonen.
Katalogstruktur:
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((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((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.
const 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', () => {
// ...query for the active tab...
chrome.tabs.query({
active: true,
currentWindow: true
}, 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>
Svar #2
Du kan bruke chrome.storage.local til det. Legg til storage-tillatelse i manifest.json, og du kan lagre alle data i et hash-tabellformat i nettleserminnet og få tilgang til det når som helst.
Først, send data fra innholdsskriptet til bakgrunnssiden, lagre det, og hent det deretter i popup-skriptet. Slik gjør du det gjennom bakgrunnssiden din:
I contentScript.js:
// contentScript.js
chrome.runtime.sendMessage({
total_elements: totalElements // or whatever you want to send
});
På bakgrunnssiden din:
// background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
chrome.storage.local.set({ data: request.total_elements });
}
);
Da kan du få tilgang til den variabelen i popup.js (husk å await):
// popup.js
const totalElements = await chrome.storage.local.get('data');
Kanskje du kan få tilgang til localStorage direkte fra innholdsskriptet i moderne nettlesere. Da trenger du ikke å sende dataene gjennom bakgrunnssiden din. Interessant å lese om localStorage: http://diveintohtml5.info/storage.html.
