You know what I liked best about obtrusive javascript? You always knew what it was going to do when you triggered an event.
<a onclick="thisHappens()" />
Now that everybody's drinking the unobtrusive kool-aid it's not so obvious. Calls to bind events can happen on any line of any number of javascript file that get included on your page. This might not be a problem if you're the only developer, or if your team has some kind of convention for binding eventhandlers like always using a certain format of CSS class. In the real world though, it makes it hard to understand your code.
DOM browsers like Firebug seem like they could help, but it's still time consuming to browse all of an element's event handler properties just to find one that executes the code you're looking for. Even then it usually just tells you it's an anonymous function() with no line number.
The technique I've found for discovering what JS code gets executed when events are triggered is to use Safari's Profiling tool which can tell you what JS gets executed in a certain period of time, but that can sometimes be a lot of JS to hunt through.
There's got to be a faster way to find out what's happening when I click an element. Can someone please enlighten me?
To answer your question, try using the Firebug command line. This will let you use JavaScript to quickly grab an element by an ID, and then iterate through its listeners. Often, if used with console.log, you'll even be able to get the function definitions.
Now, to defend the unobtrusive:
The benefit I find in unobtrusive JavaScript is that it is a lot easier for me to see the DOM for what it is. That said, I feel that it is generally bad practice to create anonymous functions (with only few exceptions). (The biggest fault I find with JQuery is actually in their documentation. Anonymous functions can exist in a nether-world where failure does not lead to useful output, yet JQuery has made them standard.) I generally have the policy of only using anonymous functions if I need to use something like bindAsListener from Prototype.
Further, if the JS files are properly divided, they will only be addressing one sub-set of the DOM at a time. I have an "ordered checkbox" library, it is in only one JS file which then gets re-used in other projects. I'll also generally have all of the methods of a given sub-library as member methods of either a JSON object or a class and I have one object/class per js file (just as if I were doing everything in a more formalized language). If I have a question about my "form validation code", I will look at the
formValidation
object in formvalidation.js.At the same time, I'll agree that sometimes things can become obtuse this way, especially when dealing with others. But disorganized code is disorganized code, and it is impossible to avoid unless you are working by yourself and are a good programmer.
In the end, though, I would rather deal with using
/* */
to comment out most of two or three js files to find misbehaving code, then go through the HTML and remove the onclick attributes.One thing: you shouldn't be able to see what will happen in JavaScript by looking at the HTML code. What nuisance is that? HTML is for structure.
If you want to check what events are bound to certain elements, there's a bookmarklet called visual event for now, and firebug 1.6 (IIRC) will have some sort of event inspector.
If you're using jQuery you can take advantage of its advanced event system and inspect the function bodies of event handlers attached:
Or you could implement your own event system.
Check out Visual Event... it's a bookmarklet you can use to expose events on a page.
Calling it "kool-aid" seems unfair. DOM Level 2 events solve specific problems with inline event handling, like the conflicts that always result. I don't look back to writing code to use
window.onload
that has to check whether someone else has assigned it before, and sometimes having it overriden by accident or out of sloppiness. It also ensures a better separation of the structure (HTML) and behaviour (JS) layers. All in all, it's a good thing.Regarding debugging, I don't think there's any way to solve the event handlers being anonymous functions, other than nagging the authors to use named functions where possible. If you can, tell them that it produces more meaningful call stacks and makes the code more maintainable.