如何识别浏览器元素的标签关闭事件[XUL / firefox]

时间:2014-04-18 16:46:53

标签: javascript dom firefox-addon xul xpcom

我在插件上工作,观察所有的http请求并填充与每个标签对应的一些信息。我想清除我关闭的选项卡的数据。但是,我无法以更清洁/更健全的方式获得标识选项。 所以我有contentWindow(LoadContext - > associatedWindow)请求,以及该内容窗口的browser(用于选项卡)。

  1. 我意识到要做browser.addEventListener,我将不得不听DOMNodeRemoved事件 - deprecated as per MDN(而应该使用变异观察者)。此外,当弹出窗口关闭时,我不会收到事件。
  2. 如果我执行contentWindow.addEventListener并查找unload事件,则结果非常难以预测。有时候,我根本没有参加活动。
  3. 如果我从tab获取此gBrowser.tabs元素并收听TabClose事件,我可以获取该标签的所有关闭事件。但话说回来,它不会通知任何弹出窗口关闭(虽然我为弹出窗口获得了tab元素)
  4. 那么知道任何标签/弹出窗口关闭的最简单/最简洁的方法是什么?我不使用插件SDK,顺便说一句。

    编辑:寻找更简单,有效的案例解决方案。即。我收到关闭事件的通知,无论是标签还是弹出窗口(或任何其他类型的窗口,如果它们存在!)。我相信这可能是可能的,因为我持有一个包含DOM窗口的浏览器元素,并在关闭时删除(卸载)DOM。

    EDIT-2:意识到所有问题都是由于一件事:当最后一个标签关闭时(这是窗口关闭),Firefox没有TabClose事件。如果我们收到关闭窗口时关闭的标签的通知,那么生活会容易得多。除了TabClose监听器之外,我还会采用@ Noitidart解决方案的修改版本 - 拥有一个单独的窗口监听器。并找到其中的tab元素并进行清理。叹! 将在此进行更多搜索,并查看是否符合错误/增强的条件。 感谢@Noitidart和@Blargh的建议。

3 个答案:

答案 0 :(得分:2)

我说要保留对标签的引用。这就是我在插件MouseControl和WorkspaceHopper中的表现。

所以请检查:

if (tab.parentNode) {

}

尝试捕获,如果它捕获,那么tab显然不存在。

但是对于tabClos​​e你也可以使用tabclose事件和窗口弹出窗口,使用windowsMediator列表器并听取onWindowClose

var windowListener = {
    //DO NOT EDIT HERE
    onOpenWindow: function (aXULWindow) {
        // Wait for the window to finish loading
        let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        aDOMWindow.addEventListener('load', function () {
            aDOMWindow.removeEventListener('load', arguments.callee, false);
            windowListener.loadIntoWindow(aDOMWindow);
        }, false);
    },
    onCloseWindow: function (aXULWindow) {},
    onWindowTitleChange: function (aXULWindow, aNewTitle) {},
    register: function () {

        // Load into any existing windows
        let DOMWindows = Services.wm.getEnumerator(null);
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.loadIntoWindow(aDOMWindow);
        }
        // Listen to new windows
        Services.wm.addListener(windowListener);
    },
    unregister: function () {
        // Unload from any existing windows
        let DOMWindows = Services.wm.getEnumerator(null);
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.unloadFromWindow(aDOMWindow);
        }

        //Stop listening so future added windows dont get this attached
        Services.wm.removeListener(windowListener);
    },
    //END - DO NOT EDIT HERE
    loadIntoWindow: function (aDOMWindow) {
        if (!aDOMWindow) {
            return;
        }

        //do stuff here

    },
    unloadFromWindow: function (aDOMWindow) {
        if (!aDOMWindow) {
            return;
        }
        //do stuff here
    }
};

答案 1 :(得分:2)

这是@Noitidart答案的修改版本。我在browser上使用expando属性(例如:_myextensionTabId)来索引我的缓存数组。

var WindowListener = {
/* Same as @Noitidart's listener */
  onOpenWindow : function(xulWindow) {
    /* Get DOM window, call other window specific modules init */
    myExtension.initWindow(domWindow);
    myHttpObserver.initWindow(domWindow);
  },
  onCloseWindow: function(xulWindow) {
    /* Get DOM window, call other window specific modules uninit */
    myExtension.uninitWindow(domWindow);
    myHttpObserver.uninitWindow(domWindow);
  },
};

var myHttpObserver = {
    ..  
    initWindow: function(window) {
      window.gBrowser.tabContainer
              .addEventListener('TabClose', tabClosed, false);
    }, 

    uninitWindow: function(window) {
      dump ("Uninit window http observer\n");
      window.gBrowser.tabContainer
                .removeEventListener('TabClose', tabClosed);
      for (var browser of window.gBrowser.browsers) {
        if (browser._myextensionTabId) {
          // Do any cleanup.
        }
      }
    },
  .. 
    /* Other http observer stuff, methods that sets the expando property etc. */
};

function tabClosed(e) {
  var browser = Services.wm.getMostRecentWindow("navigator:browser")
                           .gBrowser.getBrowserForTab(e.target);
  dump("Tab closed. \n");
  if (browser._myextensionTabId) {
    dump("My extension tab id : " + browser._myextensionTabId);
    // Do any cleanup
  }
}

答案 2 :(得分:1)

对于一个解决方案拟合选项卡和窗口,您可以尝试窗口观察者: https://developer.mozilla.org/en-US/docs/Observer_Notifications#Windows

可能想要使用outer-window-destroyed观察者,我认为标签中的每个浏览器元素都是一个外窗口。我不确定。它可能会在每次文档更改时触发,因此您必须QI并获取选项卡并检查其是关闭/关闭还是仍然打开。

尝试一下,与我们分享你学到的东西,我很感兴趣。在收盘时我认为它会被摧毁。