Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If possible: Who did the binding of the event? #31

Open
netsi1964 opened this issue Sep 17, 2013 · 10 comments
Open

If possible: Who did the binding of the event? #31

netsi1964 opened this issue Sep 17, 2013 · 10 comments

Comments

@netsi1964
Copy link

This is a feature request.

While debugging events it is so cool the stuff which VisualEvent does in the current version, however to make it even more cool this could be added:

Tracking of the binding process, that is: I could see in VisualEvent which code (where with link) did the binding of the event. "Who is watching?" - so that can backtrack events to the part of the code which has added the event. An example could be:

function clickHandler() {
  // I'm the handler
}

$(function() {
  // Im am binding the handler to elements
 $('li').on('click', clickHandler);
});```

I do not know if that is possible, but hey it would be a great feature! :-)

/Sten
@DataTables
Copy link
Collaborator

Agreed! However, when I looked at this previously, I couldn't find a way to do it - at least not in all browsers. The Function.prototype.toString() in Webkit returns the function as it was originally formatted, including white-space, so what I've done in Webkit browsers is to have it Ajax load, as text, the Javascript source files, and it will then look over those files for the function and attempt to display where it was sourced from.

Firefox, IE etc reflow the function, so its not possible in those browsers. I've also found it isn't 100% reliable in webkit browsers, but haven't looked into why that is yet. I'll leave this bug open to see if I can pin point that.

@ticky
Copy link

ticky commented Sep 17, 2013

I think what @netsi1964 means is that it would be cool if, for the example above, it could show not only the function defined on line 1, but also the binding context of line 7.

@DataTables
Copy link
Collaborator

It will show where in the code it was defined, so you would be able to see the context, but you couldn't be able to "Inspect" it like you can on the console.

@ticky
Copy link

ticky commented Sep 17, 2013

Yes, but it only shows the function definition, not the binding context, which is sometimes different - the definition of ClickHandler could be somewhere else in the file (or in another file altogether), while it is bound by that jQuery on atline 7.

@DataTables
Copy link
Collaborator

My point is that where Visual Event says "Function definition could not be found automatically" (currently - not sure why it can't be found!) it should say, "Function definition in {file} line {#}.". Is that not what you are looking for?

As I say, that should work in Webkit browser (it used to!), but appears to be broken at the moment.

@ticky
Copy link

ticky commented Sep 17, 2013

Yes, but I believe what @netsi1964 is after is in addition to that - which is very useful in itself.

i.e. for the above, it could output both the function definition and where it was bound to the element, like (for example) this;

Click event subscribed by jQuery 2.0 on line 7;

 $('li').on('click', clickHandler);

Handler function definition;

function clickHandler() {
  // I'm the handler
}

@DataTables
Copy link
Collaborator

Ah I see - no that's not possible without evaluating the Javascript. I can say where clickHandler was defined, but not where it was used or bound. I could show the lines around where it defined, but there is no way to say where it was applied.

@ticky
Copy link

ticky commented Sep 18, 2013

It may be possible to combine this technique for retrieving a stack trace with overriding the built-in addEventListener to add this kind of functionality to the browser extension version of Visual Event.

A quick demo, which Works-For-Me™ in Chrome (YMMV), is as follows;

HTMLDocument.prototype._addEventListener = HTMLDocument.prototype.addEventListener;
Element.prototype._addEventListener = Element.prototype.addEventListener;
window._addEventListener = window.addEventListener;
HTMLDocument.prototype.addEventListener = function(a, b, c) {
    HTMLDocument.prototype._addEventListener.call(this, a, b, c);
    try {
        // Forces an error to be thrown
        non.existant.item+=0;
    } catch (e) {
        // Prints out the error (works in Chrome - differs in other browsers)
        console.log(e.stack);
    }
}
Element.prototype.addEventListener = function(a, b, c) {
    Element.prototype._addEventListener.call(this, a, b, c);
    try {
        non.existant.item+=0;
    } catch (e) {
        console.log(e.stack);
    }
}
window.addEventListener = function(a, b, c) {
    window._addEventListener.call(this, a, b, c);
    try {
        non.existant.item+=0;
    } catch (e) {
        console.log(e.stack);
    }
}

This, run before any other JS in the page, will print out the stack trace whenever addEventListener is called (whether from jQuery or other sources), as well as doing the default action.

From this, you get something like this;

ReferenceError: non is not defined
    at HTMLAnchorElement.Element.addEventListener (http://localhost/:22:6)
    at Object.v.event.add (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:34395)
    at HTMLAnchorElement.<anonymous> (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:43530)
    at Function.v.extend.each (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:14543)
    at v.fn.v.each (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:11217)
    at v.fn.extend.on (http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js:2:43506)
    at http://localhost/:79:15 

Which could then be parsed to work out where the event is attached (by looking for the next item in the stack after a jQuery "on", for instance).

This would not be possible from the bookmarklet, as it would have to be injected before any events were bound, so it may be out of scope for this project, but it would be useful context to have alongside VE.

@DataTables
Copy link
Collaborator

overriding the built-in addEventListener

That only works if I can replace the function before it is called. However, VisualEvent is run after the events have been attached. Perhaps VisualEvent could offer a "debug mode" script, which you would pre-load on your page to get extra information about your events, using this method... Not as handy, but might be useful.

@ticky
Copy link

ticky commented Sep 19, 2013

This would not be possible from the bookmarklet, as it would have to be injected before any events were bound, so it may be out of scope for this project, but it would be useful context to have alongside VE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants