如何在firefox插件中只运行一个代码实例?

时间:2011-12-08 15:34:17

标签: javascript firefox firefox-addon

我在主窗口上监听onload事件,然后在每个浏览器/选项卡上监听DOMContentLoaded事件(我需要在浏览器中最多运行代码)并标记为{{ 1}}代码是在浏览器上运行的。

controlExecuted

这不起作用。代码运行多次,具体取决于浏览器/标签的数量。

那么如何在firefox插件中只运行一个代码实例?

2 个答案:

答案 0 :(得分:1)

正如您所注意到的,每次打开新的浏览器窗口时,您的代码都会运行。您可能没有意识到的是,一个窗口中的脚本在另一个窗口中完全独立相同的脚本。也就是说,每次都会实例化一组新对象,这意味着一个窗口中的controlExecuted与另一个窗口中的controlExecuted不是同一个对象。

在扩展程序中共享代码有两种方法:

  • 创建XPCOM component。这是在浏览器扩展中共享代码的经典,更难(但非常强大)的方法。

  • 创建JavaScript code module(JSM)。简而言之:

      

    JavaScript代码模块是Gecko 1.9中引入的概念,可以   用于在不同的特权范围之间共享代码。模块   也可用于创建全局JavaScript单例   以前需要使用JavaScript XPCOM对象。

您也可以考虑将此标记设置为用户首选项,您的脚本的每个实例都可以读取该标记。对于这样一个简单的用例,这可能是最简单的方法。

答案 1 :(得分:1)

这是使用JavaScript code modules在firefox插件中仅运行一个代码实例的完整解决方案。

// modules/main.jsm
var EXPORTED_SYMBOLS = ["instancesControl"];

var instancesControl = {
    executed : 0,
    windowExecuting : 0,

    get : function(){
        return ++instancesControl.executed;
    },
    reset : function(){
        instancesControl.executed = 0;
    },
    getWindowExecuting : function(){
        return instancesControl.windowExecuting;
    },
    setWindowExecuting : function(id){
        instancesControl.windowExecuting = id;
    }   
};

主要呼叫代码:

 // load instancesControl module
Components.utils.import("resource://my-own-alias/main.jsm");

// identify window that will execute the one-instance code
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var windowID = util.outerWindowID;

// listen load window event 
window.addEventListener("load", function(){
    var appcontent = document.getElementById("appcontent");
    if (appcontent){
        // listen load content (on every tab)
        appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
            appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
            if (instancesControl.get() == 1){
                instancesControl.setWindowExecuting(windowID);

                // this code will run only once no matter
                // how many tabs or windows user opens.

            }
        }, true);
    }
}, false);

// re-init code if executing windows is closed
window.addEventListener("unload", function(){
    if (instancesControl.getWindowExecuting() == windowID){
        instancesControl.reset();
    }
}, false);

当然可以改进它。如果你这样做,请使用@nomikos进行评论 THX。