【问题标题】:Communication between scripts in Firefox addon sdk - self.port doesn't existFirefox 插件 sdk 中脚本之间的通信 - self.port 不存在
【发布时间】:2013-05-28 20:51:04
【问题描述】:

我正在尝试使用他们的 sdk 制作一个 firefox 插件,但我不知道如何让我的 js 脚本进行通信。目标是制作一个带有表单的面板,其中有 3 个复选框,选中时可以隐藏/显示活动选项卡上的某些元素。

以下是脚本: main.js:

var data = require("sdk/self").data;

var painel1 = require("sdk/panel").Panel({
    width: 215,
    height: 160,
    contentURL: data.url("painelDestroyer.html"),
    contentScriptFile: [data.url("jquery.js"),data.url("panel.js")]
});

require("sdk/widget").Widget({
    id: "open-form-btn",
    label: "Clear",
    contentURL: data.url("mozico.png"),
    panel: painel1
});

// Attach a content script to the current active tab
let worker = require("sdk/tabs").activeTab.attach({
    contentScriptFile: data.url("clear.js")
});


painel1.port.on("show-tag",function(tag){
    worker.port.emit("show-tag", {tag:tag});
    console.log("worker emited");
});

painel1.port.on("hide-tag",function(tag){
    worker.port.emit("clear-tag", {tag:tag});
    console.log("worker emited");
});

painel.js:

$("#imgD").click(function() {
    if ($(this).is(":checked")) {
        panel.port.emit("clear-tag","img");
        console.log("panel emited");
    } else {
       panel.port.emit("show-tag","img");
       console.log("panel emited");
    }
});
$("#aD").click(function() {
    if ($(this).is(":checked")) {
        panel.port.emit("clear-tag","a");
        console.log("panel emited");
    } else {
        panel.port.emit("show-tag","a");
        console.log("panel emited");
    }
});
$("#iframeD").click(function() {
    if ($(this).is(":checked")) {
       panel.port.emit("clear-tag","iframe");
       console.log("panel emited");
    } else {
        panel.port.emit("show-tag","iframe");
        console.log("panel emited");
    }
});

clear.js:

    function tagHide (tag, hide) {
    $(tag).each(function() {
        if (hide === false) {
            $(this).css({
                "visibility": "visible"
            });
        } else {
            $(this).css({
                "visibility": "hidden"
            });
        }
    });
}

self.port.on('show-tag', function(tag) {
    tagHide(tag, false);
});
self.port.on('clear-tag', function(tag) {
    tagHide(tag, true);
});

问题:我该如何进行这项工作,如何在这 3 个脚本之间进行通信?我的猜测是我必须将消息从 painel.js 发送到 main.js,然后再发送到 clean.js,但我该怎么做呢?如何在 clean.js 或 painel.js 中接收消息? 我不断得到 self.port 在 painel.js 中不存在。

【问题讨论】:

    标签: javascript firefox firefox-addon firefox-addon-sdk


    【解决方案1】:

    问题是您试图从模块脚本而不是内容脚本访问和修改页面内容。模块脚本的范围内没有windowdocument,如the documentation 中所述。因此,jQuery 的 $ 在您的附加脚本中没有任何可使用的内容。

    您需要attach 另一个内容脚本到当前选项卡。然后,您可以通过向其工作端口发送消息来显示/隐藏页面上的元素,类似于您在附加模块脚本和面板脚本之间进行通信的方式。

    // Attach a content script to the current active tab
    let worker = require("sdk/tabs").activeTab.attach({
        contentScriptFile: data.url("tabscript.js")
    });
    // Send it a message
    worker.port.emit("show-tag", tag);
    

    然后,您可以将 tagHide 函数移动到活动选项卡的内容脚本中,并在其中放置一些端口侦听器。这样,插件脚本可以发出一些消息并让内容脚本适当地调用tagHide

    注意:您最好使用page-mod,而不是附加到选项卡上。最后,您可能不想在每次用户导航到不同页面时手动附加脚本,因此全局 PageMod (include: "*") 是一个简单的解决方案。尽管如此,您仍需要确保在转发消息时以当前选项卡的工作人员为目标。因此,您需要跟踪所有这些工人和clean them up when the worker is detached(使用worker.on('detach', callback)。最后,您应该遍历所有当前附加的工人并找到附加到当前活动选项卡页面的工人(通过比较每个worker.tabtabs.activeTab)。

    或者,您可以直接将命令作为 JavaScript 注入标签页,如 Attaching Content Scripts to Tabs 所示。我觉得这很丑陋,它不允许您在内容脚本中保留某些状态(页面上的变量跨命令保留),而您可能需要更复杂的脚本。

    更新1:至于您更新的问题,答案是very well documented in the SDK guides。你只需要使用self.port.on绑定一个监听器:

    self.port.on('show-tag', function(tag) {
        tagHide(tag, false);
    });
    self.port.on('clear-tag', function(tag) {
        tagHide(tag);
    });
    

    另一方面,您当前的代码仅在加载项启动时与当前活动的选项卡一起使用。最有可能的是,活动选项卡会发生变化,您需要随着时间的推移将内容脚本注入其他选项卡。请参阅我之前关于如何管理所有这些脚本的工作人员的说明。

    【讨论】:

    • 那么我该如何在“show-tag”和“hide-tag”之间切换,因为它是由面板中的js定义的?我是否必须将 pannel.js 文件中的 port.emiter 添加到附加脚本,然后添加到内容脚本?就像从面板发出“1”或“2”到附加脚本,然后将其重新发送到内容脚本以在页面上采取行动?因为我需要使用面板脚本来决定它是“1”还是“2”(在这种情况下是“显示”或“隐藏”)。
    • 是的,您需要使您的附加脚本“转发”面板内容脚本中的命令到选项卡的内容脚本。例如,在Annotator tutorial 中,来自小部件内容脚本的left-clickmain.js 转发到page-mod 内容脚本上的activate/deactivate 消息。
    • @GiovanniDiToro 是的,self.port.on 应该在内容脚本中“正常工作”(在面板或页面上)。你不需要require 任何东西,self 应该可以作为全局变量使用。
    • 它无法正常工作,它让我知道 self.port 没有定义。
    • self.port.on 似乎已经贬值了。关于现在如何做到这一点的任何想法?我什么都找不到
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多