Firefox插件(JPM) - 如何将消息从面板的脚本传递到内容脚本? [英] Firefox addon(JPM) - How to pass message from panel's script to content script?

查看:355
本文介绍了Firefox插件(JPM) - 如何将消息从面板的脚本传递到内容脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从面板脚本(popup.js)发送一个点击事件到内容脚本(content.js)她的代码,我试过了,所需的输出isnt打印在控制台上。


popup.html




 < button id =start-btnonclick =myFunction()>剪辑< / 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);
$ b $ 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
});


解决方案

=https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/panel =nofollow> sdk / panel 到内容脚本,你必须中继它通过你的后台脚本。所以,通信看起来像面板脚本⟷后台脚本⟷内容脚本。



这很复杂,因为您可能有许多不同的内容脚本。您甚至可以为每个选项卡设置多个内容脚本。因此,你必须跟踪你的内容脚本,因为他们附加,并保持有组织,至少通过制表符。这是因为你可以最终将消息中继到正确的内容脚本。



面板,因为它是一个用户界面,通常会发送消息到活动标签。另一方面,它可能希望将消息发送到特定选项卡或特定选项卡中的特定脚本。您需要确定您的插件所需的粒度级别。



以下脚本将通过PageMod载入一个内容脚本到每个标签根据问题,包含的URL是'*')。每个内容脚本都由选项卡进行跟踪。没有规定每个标签有多个内容脚本。标签事件应该真的被监听,以便使内容脚本列表中的条目无效。但是,这不是在这个例子中完成的。该面板将在点击 ActionButton 时显示。点击面板上的按钮后,面板发送 relay 消息给后台脚本,后台脚本解码 relay 消息并将其发送到相应的内容脚本。



我为 relay 消息添加了格式。这种格式是:

  {
target:{
type:targetType,//目前唯一有效的targetType是'content'。
id:targetId //标签ID或'activeTab'
},
emitType:emitType,//发送消息的类型。
data:message //中继消息的内容。



$ b $ p



< :
$ b

var panels = require( SDK /面板);
var self = require(sdk / self);
var data = require(sdk / self)。data;
var pageMod = require(sdk / page-mod);
var tabs = require(sdk / tabs);

//打开浏览器控制台
var utils = require('sdk / window / utils');
activeWin = utils.getMostRecentBrowserWindow();
activeWin.document.getElementById('menu_browserConsole')。doCommand();

var workers = {};
$ b // PageMod
pageMod.PageMod({
include:*,
contentScriptWhen:'ready',
contentScriptFile:[
//data.url(\"js/jquery-3.1.0.min.js),
data.url(js / content.js)
],
onAttach: attachWorker
});

函数attachWorker(worker){
if(!workers.hasOwnProperty(worker.tab.id)){
//以前没有这个标签
workers [worker.tab.id] = {};
}
//这没有考虑到一次有多个工人
//每个选项卡的可能性。
//记住工作者
console.log('index.js:tab =',worker.tab.id上的附加工作者);
workers [worker.tab.id] .worker = worker;


$ b //面板
var panel = panels.Panel({
contentURL:self.data.url(popup.html) ,
onHide:handleHide
});

panel.port.on('message',receiveMessage);
panel.port.on('relay',receiveRelay);

函数handleHide(){
}

函数receiveMessage(消息){
console.log('index.js:received message:',信息);


function receiveRelay(data){
console.log('index.js:received relay:',data);
让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; (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:收到中继:没有目标工作者可用于ID:'
,targetId);
return;
} // else
emitPort = workers [targetId] .worker.port;
}其他没有定义
console.log('index.js:收到的继电器:目标类型不能理解,类型:'
,data.target.type );
return;

console.log('index.js:received relay:emitType =',data.emitType,':: data ='
,data.data);
emitPort.emit(data.emitType,data.data);


$ b //动作按钮
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:Buttoned clicked。Send the relayed message');
//addon.port.emit('message','hello world');
sendRelay('content','activeTab','message','Button in panel');


函数sendRelay(targetType,targetId,emitType,message){
addon.port.emit('relay',{
target:{
类型:targetType,//当前唯一有效的targetType是'content'
id:targetId //标签ID或者'activeTab'
},
emitType:emitType,/ /将要发送的发送消息的类型
data:message //中继消息的内容
});

data / popup.html

< html>
< head>
< meta charset ='utf-8'>
< script type =text / javascriptsrc =popup.js>< / script>
< / head>
< body>
< button id =start-btnonclick =myFunction()>剪辑< / button>
< / body>
< / html>

package.json

$ b $ title:传递一个消息面板背景内容的演示,
name:$ b

relaymessge,
id:relaymessage @ ex,
version:0.0.1,
description:演示从面板传递消息 - > ;
main:index.js,
author:Makyen,vivek,
engines:{
firefox:> = 38.0a1,
fennec:> = 38.0a1
},
关键字:[


}


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
});

解决方案

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"
    ]
}

这篇关于Firefox插件(JPM) - 如何将消息从面板的脚本传递到内容脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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