我正在使用插件 SDK。我有一个小部件,点击小部件后,我想对网站做一些事情(无论是修改页面还是阅读深层 DOM)。

所以我读完 https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/page-mod#Communicating_With_Content_Scripts 后的想法是:

  • pagemod 在匹配的 url 上激活(在本例中为 ANY)
  • 单击满足 left-click 事件的小部件。然后它发出 widget-click
  • Pagemod 接收 widget-click 事件并触发一个名为 from-pagemod 的事件。
  • from-pagemod 对网页做一些事情。

  • 我在标准输出中看到以下输出:
    console.log: project: about to emit widget-click
    console.log: project: after emitting widget-click
    

    所以 pagemod 没有收到该事件,或者它从未设置过。我不确定这个简单的测试用例缺少什么。任何帮助表示赞赏。

    这是 lib/main.js
    var widgets = require('sdk/widget');
    var pageMod = require("sdk/page-mod");
    var data = require("sdk/self").data;
    var tabs = require("sdk/tabs");
    
    exports.main = function() {
        var widget = widgets.Widget({
            label: "widget label",
            id: "widget-id",
            contentURL: data.url("off.png"),
            contentScriptFile: [data.url("widget.js"), data.url("page.js")]
        });
    
        widget.port.on("left-click", function() {
            console.log("about to emit widget-click");
            widget.port.emit("widget-click", "foo");
            console.log("after emitting widget-click");
        });
    
    
        var page = pageMod.PageMod({
            include: "*",
            contentScriptWhen: "end",
            contentScriptFile: data.url("page.js"),
            onAttach: function(worker) {
                worker.port.on("widget-click", function(msg) {
                    console.log("on widget-click, ready to emit from-pagemod event");
                    worker.port.emit("from-pagemod", "foo");
                });
            }
        });
    };
    

    这是 page.js
    self.port.on("from-pagemod", function(msg) {
        console.log("inside from-pagemod listener");
        // read DOM or modify the DOM
    });
    

    这是 widget.js
    this.addEventListener('click', function(event) {
      if(event.button == 0 && event.shiftKey == false)
        self.port.emit('left-click');
    }, true);
    

    最佳答案

    编辑2,回答实际问题:

    如果您想在内容脚本已附加时在小部件单击时对页面执行某些操作,请在您有权访问 widget 的地方注册您的 page-worker 监听器。您可以通过将 widget.port.on 代码放在 pageModonAttach() 中来做到这一点,但它仅适用于最近附加的页面。使其发挥作用的最佳方法是存储所有工作人员,然后在单击小部件时检查当前选项卡是否有工作人员,如下所示:

    main.js 部分

    var workers = [];
    
    widget.port.on("left-click", function() {
      console.log("about to emit widget-click");
      var worker = getWorker(tabs.activeTab);
      if (worker) {
        worker.port.emit("widget-click", "foo");
        console.log("after emitting widget-click");
      }
    });
    
    var page = pageMod.PageMod({
      include: "*", // TODO: make more specific
      contentScriptWhen: "end",
      contentScriptFile: data.url("page.js"),
      onAttach: function(worker) {
        workers.push(worker);
        worker.on('detach', function() {
          detachWorker(worker);
        });
        // could be written as
        // worker.on('detach', detachWorker.bind(null, worker);
      }
    });
    
    function detachWorker(worker) {
      var index = workers.indexOf(worker);
      if(index!==-1) workerArray.splice(index, 1);
    }
    
    function getWorker(workers, tab) {
      for (var i = workers.length - 1; i >= 0; i--) {
        if (workers[i].tab===tab) return worker;
      }
    }
    

    page.js
    self.port.on("widget-click", function(msg) {
      console.log("inside widget-click listener");
      // read DOM or modify the DOM
    });
    

    您的解决方案不起作用的原因是您假设事件以某种方式链接到文件而不是对象。

    旧答案:你让它变得太复杂了。

    只需在点击时附加内容脚本(而不是将内容脚本添加到每个页面,除非它收到事件,否则什么都不做)

    主文件
    var widgets = require('sdk/widget');
    var data = require("sdk/self").data;
    var tabs = require("sdk/tabs");
    
    exports.main = function() {
        var widget = widgets.Widget({
            label: "widget label",
            id: "widget-id",
            contentURL: data.url("off.png"),
            contentScriptFile: data.url("widget.js")
        });
    
        widget.port.on("left-click", function() {
            console.log("about to attach script");
            var worker = tabs.activeTab.attach({
                contentScriptFile: data.url("page.js");
            });
            worker.port.on('message from content script', function(someVariable){
                //Now I can do something with someVariable in main.js
            });
        });
    };
    

    页面.js
    // read DOM or modify the DOM
    //I'm done, I'll send info back to the main script. This is optional
    self.port.emit('message from content script', someVariable);
    

    编辑:阅读 Modifying the Page Hosted by a Tab 了解更多信息。此外,Tutorials 页面是您尝试使用 SDK 执行之前未曾做过的事情时的良好起点。这是退后一步思考尝试实现目标的替代方法的好方法。

    关于firefox - 如何在 pagemod 和小部件之间发出和监听事件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22009187/

    10-11 06:12