4
votes

For kicks and giggles, I'm trying to write a Firefox extension. Just a really simple one. I've gone through the tutorials I've found, and I've gotten the basic "Hello, World" app working.

What I'd like to do, is add an event listener to an existing element in the browser's Firefox Application DOM (i.e. tabs). So far, all the resources I've been able to find show how to add a new element to the application and then add an action to it using Javascript. I've tried several ways of going about adding a Javascript function (which I know works, as I've successfully added elements with the function) to existing elements.

My latest attempt at this is structured as follows:

<?xml version="1.0"?>
<!-- in myExtension.xul -->

<overlay  id="myExtension"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript">
    var tabs = document.getElementsByTagName("tabbrowser-tab")
    var len = tabs.length;
    for (var i = 0; i < len; i++) {
      tabs[i].ondblclick = function() {
        alert('bam!');
      }
    };
  </script>

</overlay>

None of this stuff works. Like I said, I'm totally new to this stuff, and I just got a little inspired for a weekend project. Maybe there's some way of making sure I'm accessing the chrome document rather than the page document? Although when I try to get page elements (i.e. "p") using this technique, that doesn't work either, so that's probably a dead end.

[edit] To attempt to clear up some confusion:

What I mean by "the browser's DOM" is elements that are part of the chrome interface, not webpage elements. I'm talking about putting an event listener specifically on an element that already exists as part of the Firefox application UI, such as a tab (not the content of the tab, but the tab itself), or say, the Home button. I want to redefine behavior of parts of the Firefox Application GUI.

Say, for instance, that I wanted to add an alert every time someone clicked the "New Tab" button, or the "Close Tab" button. Or if I wanted to redefine the "Reload" button to redirect to the root of the domain of the current tab rather than just reloading the page. These are all existing parts of Firefox, and I want to redefine them/overwrite them through an extension, specifically by adding a javascript action to them.

[/edit]

[sidenote]Is embedded javascript allowed in an xul? Or does it need to be in a separate file?[/sidenote]

Anyone have any advice on this?

2
Doesn't document.getElementsByTagName("tabbrowser-tab") return a NodeList? Have you tried to get the first tab and register a listener to it? Could you post your extension somewhere? - speedball2001
I actually noticed that problem a while ago, and have since modified my code attempt. Updated to latest attempt. - Josh Kovach

2 Answers

4
votes

The javascript code in the overlay code doesn't work because it runs earlier than gbrowser contains any tabs.

In Firefox (or Thunderbird) extensions you usually start your extension in a load event listener:

window.addEventListener("load",
                         pinfresh.init,
                         false);

The init function then needs to register event listeners for various tab events:

  pub.init = function() {
    var container = gBrowser.tabContainer;

    container.addEventListener("TabOpen", tabOpened, false);
    container.addEventListener("TabClose", tabRemoved, false);
  };

When a new tab is opened we register another listener which will trigger the tab reload when the user double clicks on the tab:

  tabOpened = function(e) {
    var tab = e.target;
    tab.addEventListener("dblclick", tabDoubleClicked, false);
  }

  tabDoubleClicked = function(e) {
    gBrowser.reloadTab(e.target);
  }

The complete code looks like this:

<overlay  id="pinfresh"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript">
    pinfresh = function() {
      var pub = {};

      tabOpened = function(e) {
        var tab = e.target;
        tab.addEventListener("dblclick", tabDoubleClicked, false);
      }

      tabRemoved = function(e) {
        var tab = e.target;

        tab.removeEventListener("dblclick", tabDoubleClicked, false);
      }

      tabDoubleClicked = function(e) {
        gBrowser.reloadTab(e.target);
      }

      pub.init = function() {
        var container = gBrowser.tabContainer;

        container.addEventListener("TabOpen", tabOpened, false);
        container.addEventListener("TabClose", tabRemoved, false);
      };

      return pub;
    }();

    window.addEventListener("load",
                            pinfresh.init,
                            false);

  </script>
</overlay>

For code snippets to work with tabs I recommend the Tab Browser page at the Mozilla Development Center.

I recommend putting the Javascript code in its own file instead of including it in the XUL file. Errors in external Javascript files show up in Firefox's error console which makes debugging a lot easier.

3
votes

In order to get a page element of the current viewed tab you first need to get the document itself with gBrowser.selectedBrowser.contentDocument

So basically if you had a <p id='test'>blah</p> element and u want to manipulate it you could do var p = gBrowser.selectedBrowser.contentDocument.getElementById('test'); and then do with it whatever you want.

Regarding "adding an event listener to an existing element in the browser's DOM (i.e. tabs)", I'm sorry but I fail to understand what you want, do you want to manipulate the browser GUI (i.e. adding a button to the navigation bar) or do you want to manipulate the DOM content of the tab (i.e. the viewed site)? (basically "browser" can mean lot's of things :)).