如何在 Firefox 插件中仅运行一个代码实例?

发布于 2024-12-20 00:40:58 字数 774 浏览 1 评论 0原文

我在主窗口上监听 onload 事件,然后在每个浏览器/选项卡上监听 DOMContentLoaded 事件(我最多需要在浏览器内运行代码)并标记controlExecuted 表示代码在浏览器上运行。

window.addEventListener("load", function(){
    try{
        var controlExecuted = 0;
        var appcontent = document.getElementById("appcontent"); // browser
        if (appcontent && controlExecuted == 0)
            appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
                appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
                alert('run code')
                controlExecuted = 1;
            }, true);
    }catch(e){
        // log!
    }
}, false);

这是行不通的。根据浏览器/选项卡的数量,代码会运行多次。

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

I listen for a onload event on a main window, then for a DOMContentLoaded event on each browser/tab (I need run the code inside a browser at the most) and flag with controlExecuted that the code was run on a browser.

window.addEventListener("load", function(){
    try{
        var controlExecuted = 0;
        var appcontent = document.getElementById("appcontent"); // browser
        if (appcontent && controlExecuted == 0)
            appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
                appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
                alert('run code')
                controlExecuted = 1;
            }, true);
    }catch(e){
        // log!
    }
}, false);

This not works. The code run several times depending of the number of browsers/tabs.

So how to run only one instance of code in a firefox addon?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

<逆流佳人身旁 2024-12-27 00:40:58

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

在扩展中共享代码有两种主要方法:

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

  • 创建一个 JavaScript 代码模块 (JSM)。简而言之:

    <块引用>

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

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

As you've noticed, your code runs each time a new browser window is opened. What you might not have realized is that a script in one window is completely independent of the same script in another window. That is, a new set of objects is instantiated each time, which means that controlExecuted in one window is not the same object as controlExecuted in another window.

There are two broad ways to share code in an extension:

  • Create an XPCOM component. This is the classic, more difficult (but very powerful) method of sharing code in a browser extension.

  • Create a JavaScript code module (JSM). In short:

    JavaScript code modules are a concept introduced in Gecko 1.9 and can
    be used for sharing code between different privileged scopes. Modules
    can also be used to create global JavaScript singletons that
    previously required using JavaScript XPCOM objects.

You might also consider setting this flag as a user preference, which each instance of your script can read. This might be the easiest approach for such a simple use case.

吃→可爱长大的 2024-12-27 00:40:58

这里是使用 JavaScript 代码模块 在 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 发表评论。
谢谢。

Here the complete solution to run only one instance of code in a firefox addon using JavaScript code modules.

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

The main calling code:

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

Sure that you can improve it. Comment using @nomikos if you do.
THX.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文