问题
Im trying to send a click event from panels script(popup.js) to content script(content.js) hers the code that i've tried.and the desired output isnt printing on the console.
popup.html
<button id="start-btn" onclick="myFunction()">Clip</button>
popup.js
function myFunction() {
addon.port.emit('message', 'hello world');
}
content.js
self.port.on("message", function(text) {
console.log(text);
});
index.js(main)
var panels = require("sdk/panel");
var self = require("sdk/self");
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
contentScriptWhen: 'ready',
contentScriptFile:
[data.url("js/jquery-3.1.0.min.js"),
data.url("js/content.js")]
});
var panel = panels.Panel({
contentURL: self.data.url("popup.html"),
onHide: handleHide
});
回答1:
In order to pass a message from an sdk/panel to a content script, you have to relay it through your background script. So, the communication looks like panel script ⟷ background script ⟷ content script.
This is complicated by the fact that you, potentially, have many different content scripts. You could even have multiple content scripts per tab. Thus, you have to track your content scripts as they attach and keep them organized, at least by tab. This is so you can end up relaying the message to the correct content script.
The panel, because it is a user interface, will normally want to send a message to the active tab. On the other hand, it might want to send a message to a specific tab, or a specific script within a specific tab. You will need to determine what level of granularity you need for your add-on.
The following script will load, via Page-Mod, a content script into every tab (as per the question the included URLs is '*'
). Each content script is tracked by tab. No provision is made for having multiple content scripts per tab. Tab events should really be listened to in order to invalidate entries in the list of content scripts. However, that is not done in this example. The panel will be displayed upon clicking an ActionButton. When the button in the panel is clicked a relay
message is sent by the panel to the background script which then decodes the relay
message and emits it to the appropriate content script.
I have imposed a format for the relay
messages. That format is:
{
target: {
type:targetType, //Currently, the only valid targetType is 'content'.
id:targetId //A tab ID, or 'activeTab'
},
emitType:emitType, //The type of emit message that will be sent.
data:message //The contents of the relayed message.
}
The code:
index.js:
var panels = require("sdk/panel");
var self = require("sdk/self");
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
var tabs = require("sdk/tabs");
//Open the Browser Console
var utils = require('sdk/window/utils');
activeWin = utils.getMostRecentBrowserWindow();
activeWin.document.getElementById('menu_browserConsole').doCommand();
var workers={};
//PageMod
pageMod.PageMod({
include: "*",
contentScriptWhen: 'ready',
contentScriptFile: [
//data.url("js/jquery-3.1.0.min.js"),
data.url("js/content.js")
],
onAttach: attachWorker
});
function attachWorker(worker){
if(!workers.hasOwnProperty(worker.tab.id)){
//Have not previously had this tab
workers[worker.tab.id]={};
}
//This does not account for the possibility of having multiple workers
// per tab at one time.
//Remember the worker
console.log('index.js: Attached worker on tab=',worker.tab.id);
workers[worker.tab.id].worker = worker;
}
//Panel
var panel = panels.Panel({
contentURL: self.data.url("popup.html"),
onHide: handleHide
});
panel.port.on('message',receiveMessage);
panel.port.on('relay',receiveRelay);
function handleHide(){
}
function receiveMessage(message){
console.log('index.js: received message:',message);
}
function receiveRelay(data){
console.log('index.js: received relay:',data);
let emitPort;
let targetId;
if(typeof data !== 'object'){
console.log('index.js: received relay: data was not an object');
return;
}//else
if(!data.hasOwnProperty('target')){
console.log('index.js: received relay: No target specified');
return;
}//else
if(data.target.type === 'content'){
if(data.target.id && data.target.id === 'activeTab'){
targetId = tabs.activeTab.id;
}else{
targetId = data.target.id;
}
console.log('index.js: received relay: target ID: ', targetId);
if(!workers.hasOwnProperty(targetId) || !workers[targetId].worker){
console.log('index.js: received relay: No target worker available for ID: '
, targetId);
return;
}//else
emitPort = workers[targetId].worker.port;
}else{
//None yet defined
console.log('index.js: received relay: Target type not understood. Type: '
, data.target.type);
return;
}
console.log('index.js: received relay: emitType=', data.emitType, ' ::data='
, data.data);
emitPort.emit(data.emitType,data.data);
}
//Action button
var ui = require("sdk/ui");
var action_button = ui.ActionButton({
id: "panel-show-button",
label: "Show panel",
icon: "./icon.png",
onClick: function(state) {
panel.show();
}
});
data/js/content.js:
console.log('In content.js');
self.port.on("message", function(text) {
console.log('content.js: received message:',text);
});
data/popup.js:
function myFunction() {
console.log('popup.js: Button clicked. Sending relayed message');
//addon.port.emit('message', 'hello world');
sendRelay('content','activeTab','message','Button clicked in panel');
}
function sendRelay(targetType,targetId,emitType,message) {
addon.port.emit('relay', {
target: {
type:targetType, //Currently, the only valid targetType is 'content'.
id:targetId //A tab ID, or 'activeTab'
},
emitType:emitType, //The type of emit message that will be sent.
data:message //The contents of the relayed message.
});
}
data/popup.html:
<html>
<head>
<meta charset='utf-8'>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<button id="start-btn" onclick="myFunction()">Clip</button>
</body>
</html>
package.json:
{
"title": "Demo passing a message panel-background-content",
"name": "relaymessge",
"id": "relaymessage@ex",
"version": "0.0.1",
"description": "Demonstrate passing a message from a panel -> background script -> content script.",
"main": "index.js",
"author": "Makyen, vivek",
"engines": {
"firefox": ">=38.0a1",
"fennec": ">=38.0a1"
},
"keywords": [
"jetpack"
]
}
来源:https://stackoverflow.com/questions/39241698/firefox-addonjpm-how-to-pass-message-from-panels-script-to-content-script