Jon | 2 Apr 2008 16:48

Finding events on a page added using addEventListener

Hi,

I'm building a Javascript crawler using XULRunner as part of a
University project. Its easy to pull out all the element.on* events by
traversing the dom tree, however I'm having difficulties with the
addEventListener events. I can't find any interfaces that expose these
events, so I'm guessing the best way forward is to overwrite the
addEventListener function and redirect the arguments to an array
something like this:

Node.prototype.addEventListenerOld = Node.prototype.addEventListener;
Node.prototype.addEventListener = function(type, func, capture) {
  events.push({this, type, func, capture});
  return this.addEventListenerOld(type, func, capture);
}

This doesn't work however I can overide a single elements
eventlistener like so:

var z = browser.contentDocument.wrappedJSObject.getElementById("z");
z.addEventListenerOld = z.addEventListener;
z.addEventListener = function(type, func, capture) {
  events.push({this, type, func, capture});
  return z.addEventListenerOld(type, func, capture);
}

browser points to an <xul:browser>.

So my question is what would I need to overide to get this working for
all objects in my <xul:browser> element? Alternatively is there a
(Continue reading)

Boris Zbarsky | 2 Apr 2008 20:10
Picon
Favicon

Re: Finding events on a page added using addEventListener

Jon wrote:
> I can't find any interfaces that expose these events

There isn't one.

> Node.prototype.addEventListenerOld = Node.prototype.addEventListener;

Does it work if you do it on, say, HTMLBodyElement instead of Node and then try 
calling addEventListener() on the body?

Note that there is some magic involving trusted/untrusted events which might 
mean that the property lives on objects directly, not on the prototype chain...

-Boris
Jon | 3 Apr 2008 14:47

Re: Finding events on a page added using addEventListener

I'm using google groups as I don't have a newsgroups account and I
just realised I clicked reply to author instead of reply. So I think I
sent my response to your e-mail address.
Boris Zbarsky | 3 Apr 2008 17:22
Picon
Favicon

Re: Finding events on a page added using addEventListener

Jon wrote:
> I'm using google groups as I don't have a newsgroups account and I
> just realised I clicked reply to author instead of reply. So I think I
> sent my response to your e-mail address.

Yeah, sounds like the addEventListener magic with trusted events is biting you. 
  I'm pretty sure this has come up before; I'd search bugzilla and the list 
archives here.  But I think the answer is that you need to set it on each node 
individually...

-Boris
Jon | 3 Apr 2008 18:54

Re: Finding events on a page added using addEventListener

Thanks for your help ;) I came up with this solution:

function catcher(x) {
    x.addEventListenerOld = x.addEventListener;
    x.addEventListener = function(event, func, capture) {
        alert(
            "element: " + this +
            "\nevent: " + event +
            "\nfunc: " + func +
            "\ncapture: " + capture
        );
        return this.addEventListenerOld(event, func, capture);
    }
}

document.addEventListener(
    "DOMNodeInserted",
    function(e) { catcher(e.target); },
    false
);

document.addEventListener(
    "DOMContentLoaded",
    function() {
        nodes = document.getElementsByTagName("*");
        for (i = 0; i < nodes.length; i++) {
            catcher(nodes.item(i));
        }
    },
    false
(Continue reading)

Boris Zbarsky | 3 Apr 2008 19:00
Picon
Favicon

Re: Finding events on a page added using addEventListener

Jon wrote:
> document.addEventListener(
>     "DOMNodeInserted",
>     function(e) { catcher(e.target); },
>     false
> );

Don't you also need to do this with the descendants of e.target?

> I think its triggered if an element is moved around the DOM so that means
> catcher() will be called multiple times on a node and so
> addEventListenerOld will recursively call itself when an event is
> added.

Yes.  You need to handle that.

-Boris
Jon | 3 Apr 2008 19:41

Re: Finding events on a page added using addEventListener

On Apr 3, 6:00 pm, Boris Zbarsky <bzbar... <at> mit.edu> wrote:
> Jon wrote:
> > document.addEventListener(
> >     "DOMNodeInserted",
> >     function(e) { catcher(e.target); },
> >     false
> > );
>
> Don't you also need to do this with the descendants of e.target?

I thought that but when I tested it, it appeared to work. Maybe its
not implemented correctly in gecko?

This is what the specs say.

http://www.w3.org/TR/DOM-Level-3-Events/events.html#event-DOMNodeInserted
http://www.w3.org/TR/DOM-Level-3-Events/events.html#event-DOMNodeInsertedIntoDocument

Jon
Boris Zbarsky | 3 Apr 2008 20:06
Picon
Favicon

Re: Finding events on a page added using addEventListener

Jon wrote:
>> Don't you also need to do this with the descendants of e.target?
> 
> I thought that but when I tested it, it appeared to work. Maybe its
> not implemented correctly in gecko?

It was last I checked.

-Boris
Jon | 4 Apr 2008 13:23

Re: Finding events on a page added using addEventListener

You are the expert! So I'm sure you are right. Thanks for all your
help.
fchen8@gmail.com | 11 Apr 2008 05:29
Picon

Is it possible to extend nsIDOMNode and alike?

I have Mozilla embedded in my application through Java-xpcom. I want
to attach certain reference (to Java object) to each of the nodes in
the DOM tree. In another word, once I get a nsIDOMNode from Mozilla, I
would like to call methods on its attached reference. I can certainly
build a map and store the references in it. But it won't scale well
and constantly adding/removing from a big map is kind of expensive.
Since nsIDOMNode is an interface, I am thinking if I can wrap
Mozilla's implementation in my own class and somehow provide that
class back to Mozilla DOM then I should be able to achieve what I
need. The problem now lies in how to provide the class back to
Mozilla. nsIDOMDOMImplementation looks like a potential entry point
but is read-only on nsIDOMDocument. Is the route I am taking even
possible in xpcom? Are there any other solutions that you can suggest?
Thanks in advance for your help.

Feng

Gmane