jQuery Audit
Chrome Web Store.
Install it from thejQuery Audit
is a Chrome Developer Tools extension for debugging auditing jQuery — it creates a sidebar in the Elements panel
containing jQuery delegated events, internal data, and more, as live DOM nodes
, functions
, and objects
.
DOM nodes
, functions
, and objects
Live - Variables in the
jQuery Audit
sidebar behave like objects in theSources panel
→Scope Variables
sidebar. You can right-click on afunction
and goto "Show Function Definition", or hover over aDOM node
to highlight it in the document, as well as right-clicking it to "Reveal in Elements Panel".
document
and window
objects
Direct access to the - The
document
and thewindow
objects don't have representations in theElements panel
but can nonetheless be event targets and/or have associated jQuery data.jQuery Audit
adds two comment nodes above the<!DOCTYPE>
to represent them. The<!--@(document)-->
as a stand-in for thedocument
object, and the<!--@(window)-->
as a stand-in for thewindow
object. Select either to audit the represented object in thejQuery Audit
sidebar.
Requirements: jQuery Audit
does a typeof window.jQuery === 'function'
whenever a node
is selected. If it can't find a jQuery
function in the global scope, the sidebar will display Error: "@(window.jQuery is missing)"
.
Tip: Text wrapped in @(...)
are "messages" from jQuery Audit
. This was the compromise made to get live objects in the sidebar and be able to show informative messages.
Sidebar sections
@(this element)
- The element currently selected.
Data
- Data contains the would-be result of invoking
$(element).data()
.jQuery Audit
doesn't invoke.data()
because calling it creates a data object in jQuery's internal store if one doesn't already exist for that element. Instead,jQuery Audit
directly looks in the internal store for the data object and returns it. If there isn't one, you'll see@(none)
, or if it's an empty object you'll see@(empty Object)
.
Events([number_of_events])
- These are the events that the element would react to. That means any delegated events, or any directly bound events that don't delegate. (Directly bound events are under
Internal Data
→events
). For each event name, there is a corresponding jQuery event object associated with it, that has:- a
delegator
: The ancestor element that delegates the event, or@(this element)
when the event is directly bound to the element and there is no delegation. - a
handler
: The function that handles the event. More often than not, thehandler
is a bound function and not directly the function that does the "work". The section below on Finding bound handlers shows you where common binder functions store the bound function. - And more.
- a
Internal Data
- The internal data jQuery keeps on the element - it is the result of calling
$._data(element)
. This is not the same as the data object from$(element).data()
, though the data object is kept here in the internal store.
dataset
- The value of
HTMLElement.dataset
. This is not the same as Data above, but closely related to it.HTMLElement.dataset
contains the rawdata-*
attributes. While Data is the parsed content of anydata-*
attributes jQuery found on the element along with any other arbitrary information. (jQuery convertsBoolean
,Number
andJSON
indata-*
attributes when you call.data()
).
own HTML
- The result of removing the
innerHTML
from theouterHTML
of an element. This helps debug character encoding issues, since what theElements panel
shows is a decoded "pretty" version of the HTML and not the actual HTML.
Finding bound handlers
Often event handlers
are bound functions. In these cases, the function under Events
→ event_name
→ handler
is the binder
function and not the bindee
. Depending on the binder
used, the bindee
function is usually near by.
_.bind
from Lo-Dash
-
Expand the
handler
function followed by the__bindData__
property. In this array, the first element is thebindee
function, the other elements contain thethis
context and any parameters to be partially applied. Older versions of Lo-Dash might not have this structure.
_.bind
from Underscore and native Function.prototype.bind
-
Underscore uses to the native
bind
function. A clear sign that thebinder
is the nativebind
function isfunction () { [native code] }
for ahandler
. Expand thehandler
to locate thebindee
function is under[[TargetFunction]]
. Thethis
context is found in[[BoundThis]]
and any parameters to be partially applied are in[[BoundArgs]]
.
$.proxy
from jQuery
-
With
$.proxy
thebindee
can't be found as a property on thebinder
but rather in aClosure
. Expand thehandler
, followed by<function scope>
and then the inner-mostClosure
. One of the variables in this scope contains thebindee
- the name of the variable that contains thebindee
will likely vary because of minification.
FAQ
- Does
jQuery Audit
work with<iframe>'s
?
Yes, if the
<iframe>
has a jQuery function (regardless of the parent having jQuery or not) and it's not restricted by the same-origin policy.
- How do I remove
<!--@(document)-->
and<!--@(window)-->
?
Run
jQueryAudit()
in the console. When you close the developer tools the twocomment nodes
are removed and thejQueryAudit
object is removed.
- Why exactly the
@(...)
?
The content of a
SidebarPane
can be an HTML page, a JSON object, or "the result of an expression". An HTML page, nor a JSON object, have the ability to display "live" objects. The reason for making this extension was so that I could find a delegated event and be able to use "Show Function Definition" on the handler. For that effect, the contents of the sidebar is actually "the result of an expression" with a lot of trickery to make it look not-so-ugly. So, to differentiate between actual object data and informational messages I went with@(...)
so it wouldn't be easily confused with string data.
- Why the name Audit?
I am a lawyer. Yes, really. Went to law school, passed the bar, and I'm a fully admitted member of the New York State Bar Association. So, yeah, that's why Audit came to mind when I was thinking of a name.
Disclaimer: I am not related to the jQuery project.