views:

360

answers:

1

I'm writing a firefox extension that adds event listeners to all the anchor tags on a page. Essentially I have:

window.addEventListener("load", function() { myExtension.init(); }, false);

var myExtension = {

    init: function() {
    var appcontent = document.getElementById("appcontent");  
    if(appcontent)
        appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);  
    },

    onPageLoad: function(event) {
        var doc = event.originalTarget;
        var anchors = doc.getElementsByTagName("a");
        //attach event listeners
    }
}

This works for most of the tags on the page. The problem is that tags added with javascript don't get the event listener attached. I've tried redefining createElement:

//in the onPageLoadFunction
var originalCreateElement = doc.createElement;
doc.createElement = function(tag) {
    if (tag != "a"){
        return originalCreateElement(tag);
    }
    var anchor = originalCreateElement("a");
    anchor.addEventListener("mouseover", myInterestingFunction, false);
    return anchor;
}

and I've tried adding a DOM insertion listener

//in the onPageLoadFunction
function nodeInserted(event){;
    addToChildren(event.originalTarget);
}

function addToChildren(node){
    if (node.hasChildNodes()){
        var nodes = node.childNodes;
        for (var i = 0; i < nodes.length; i++){
            addToChildren(nodes[i]);
        }
    }
    if (node.nodeName == "a"){
        anchorEvent(node); //adds event listeners to node
    }
}

doc.addEventListener("DOMNodeInserted", nodeInserted, false);

but neither work. How can I get references to these anchor objects so I can add listeners to them?

Thanks

+1  A: 

Adding "event listeners to all the anchor tags on a page" dynamically is hard to do efficiently. You have two choices:

  1. Periodically poll the page for anchor tags (like jQuery.live() does)
  2. Use DOM mutation events (DOMNodeInserted, etc.)

The former has an obvious performance impact. Using mutation events has a hidden performance cost: if any mutation events are added for a document, Gecko takes a slower path in its DOM code, so all DOM manipulation works slower.

Why not use addEventListener to set up a listener on some top-level element (or even the whole window) and check if the target is an anchor? You could use a capturing listener to make your listener be called before the default action occurs.

Nickolay
I've tried the DOM mutation event as I noted above, and it didn't seem to work. Periodically polling the page gets to be a problem for an extension because users may have many tabs open at once, and all would be polling at some interval. It slows down alot.
josiahdecker
So I don't know why mutation listener doesn't work for you; I'd need to construct a testcase to play with it to find out. Are you sure the listener doesn't fire? Maybe try registering it on some element deeper in the DOM tree? /// In any case I think the last solution I suggested is better, did you try it?
Nickolay
I tried polling the page 1.5 secs after it loads, and that does work to get most of the links. I also tried it polling the page every three seconds, but that slowed things down too much. So the polling does work, thanks. I was just hoping for a more elegant solution.
josiahdecker
Can you read what I write? :) Try the last suggestion in the main reply and if that doesn't suit your needs, do try to debug the mutation listeners problem, it should work.
Nickolay