【问题标题】:Tab independent jQuery on Firefox extensionFirefox 扩展上的独立于标签的 jQuery
【发布时间】:2014-05-20 22:29:29
【问题描述】:

我正在开发一个基于 jQuery 的 Firefox,如Answer here 中所述。

在实现答案中提供的示例后,一切正常,但问题是 Firefox 选项卡之间的代码以某种方式链接,example.doc 总是指最后打开的选项卡。

  • 打开的 tab1:plugin-example 已添加到当前页面。
  • this.doc 指的是tab1。
  • 已打开 tab2:plugin-example 已添加到当前页面 (tab2)。
  • this.doc 现在指的是 tab2
  • 返回查看 tab1:this.doc 仍然指的是 tab1。
  • 点击 tab1 上的 plugin-example 将作用于 tab2 中的 plugin-example

如何使我的代码在选项卡之间独立?

以下是代码摘录:

(function() {
    jQuery.noConflict();
    $ = function(selector,context) { 
        return new jQuery.fn.init(selector,context||example.doc); 
    };
    $.fn = $.prototype = jQuery.fn;

    example = new function(){};

    example.run = function(doc,aEvent) {
        if (doc.getElementById("plugin-example")) return;
        this.doc = doc;
        this.main = main = $('<div id="plugin-example">').appendTo(doc.body).html('Example Loaded!');
        this.main.click(function() { //<--- added this function
                example.main.html(example.doc.location.href);
        });
        main.css({ 
            background:'#FFF',color:'#000',position:'absolute',top:0,left:0,padding:8
        });
    };
    // Bind Plugin
    var delay = function(aEvent) { 
        var doc = aEvent.originalTarget; setTimeout(function() { 
            example.run(doc,aEvent); 
        }, 1); 
     };
    var load = function() { 
        gBrowser.addEventListener("DOMContentLoaded", delay, true); 
    };
    window.addEventListener("pageshow", load, false);

})();

【问题讨论】:

    标签: javascript jquery firefox firefox-addon


    【解决方案1】:

    您的代码(覆盖脚本)将仅在每个窗口中运行一次,而不是在每个选项卡中运行一次。所以每个窗口只有一个example 实例。因此example.doc 将设置为最后发送的DOMContentLoaded

    您的函数应正确关闭文档并避免全局状态。 这就是我要写它的人(再一次,我会像瘟疫一样避免使用 jquery(在附加组件中)......)

    // Use strict mode in particular to avoid implicitly var declarations
    (function() {
      "use strict";
    
      // Main runner function for each content window.
      // Similar to SDK page-mod, but without the security boundaries.
      function run(window, document) {
        // jquery setup. per https://stackoverflow.com/a/496970/484441
        $ = function(selector,context) {
          return new jq.fn.init(selector,context || document); 
        };
        $.fn = $.prototype = jq.fn;
    
        if (document.getElementById("my-example-addon-container"))  {
          return;
        }
        let main = $('<div id="my-example-addon-container">');
        main.appendTo(document.body).text('Example Loaded!');
        main.click(function() { //<--- added this function
          main.text(document.location.href);
        });
        main.css({
          background:'#FFF',color:'#000',position:'absolute',top:0,left:0,padding:8
        });
      };
    
      const log = Components.utils.reportError.bind(Components.utils);
    
      // Do not conflict with other add-ons using jquery.
      const jq = jQuery.noConflict(true);
    
      gBrowser.addEventListener("DOMContentLoaded", function load(evt) {
        try {
          // Call run with this == window ;)
          let doc = evt.target.ownerDocument || evt.target;
          if (!doc.location.href.startsWith("http")) {
            // Do not even attempt to interact with non-http(s)? sites.
            return;
          }
          run.call(doc.defaultView, doc.defaultView, doc);
        }
        catch (ex) {
          log(ex);
        }
      }, true);
    })();
    

    这里是a complete add-on as a gist。只需放入 jquery 的副本,就可以了。

    PS: 转发至jquery in extensions question

    【讨论】:

    • 检查目标文档是否为instanceof HTMLDocument会更健壮吗?检查是否已通过http(s) 提供服务也将捕获其他类型的文档(例如图像、SVG)。当然,在某些情况下这可能是可取的,但很可能不是。
    • @paa 好吧,可能还有chrome://HTMLDocuments(可能是特权),所以至少我会过滤协议。在选项卡中加载的“平面”图像也有一个 HTML 容器 FWIW,IIRC 也有一些其他的东西......此外,DOMContentLoaded 应该只在实际存在某种 DOM 时触发。但最终是的,instanceof HTMLDocument 可能是一个很好的附加检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    相关资源
    最近更新 更多