├── .gitignore ├── icon128.png ├── devtoolsBackground.html ├── options.js ├── manifest.json ├── options.html ├── LICENSE.md ├── eventPage.js ├── README.md └── devtoolsBackground.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zertosh/jquery-audit/HEAD/icon128.png -------------------------------------------------------------------------------- /devtoolsBackground.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var displayHelpersEl = document.querySelector('#display-helpers'); 4 | var displayHelpersSelectionSelector = 'option[value="' + getDisplayHelpers() + '"]'; 5 | function getDisplayHelpers() { 6 | return localStorage.displayHelpers; 7 | } 8 | function setDisplayHelpers(val) { 9 | return (localStorage.displayHelpers = val); 10 | } 11 | 12 | displayHelpersEl.addEventListener('change', function(e) { 13 | setDisplayHelpers(e.target.value); 14 | }); 15 | 16 | var displayHelpersSelection = displayHelpersEl.querySelector(displayHelpersSelectionSelector); 17 | if (displayHelpersSelection) { 18 | displayHelpersSelection.selected = true; 19 | } 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "jQuery Audit", 4 | "short_name": "jQuery Audit", 5 | "version": "1.1.1", 6 | 7 | "description": "Audit jQuery's delegated events, internal data, and more.", 8 | 9 | "icons": { 10 | "128": "icon128.png" 11 | }, 12 | 13 | "author": "Andres Suarez ", 14 | "homepage_url": "https://github.com/zertosh/jquery-audit", 15 | 16 | "devtools_page": "devtoolsBackground.html", 17 | 18 | "background": { 19 | "scripts": [ "eventPage.js" ], 20 | "persistent": false 21 | }, 22 | 23 | "options_page": "options.html", 24 | 25 | "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", 26 | 27 | "permissions": [ "tabs", "http://*/*", "https://*/*" ] 28 | } 29 | -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | jQuery Audit options 4 | 17 | 18 | 19 | 20 |
21 | Display the 22 | <!-- @window --> 23 | and 24 | <!-- @document --> 25 | helpers? 26 | 30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Andres Suarez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /eventPage.js: -------------------------------------------------------------------------------- 1 | /* global chrome, jQueryAudit */ 2 | 3 | // The DevTools page is the only one that can "eval" code within 4 | // the context of the inspected page. But, it has no way of knowing 5 | // that the panel was closed. So, we need this trickery to clean up 6 | // after the DevTools are closed. 7 | 8 | var cleanup = serializeAsIIFE(function(imports) { 9 | var script = document.createElement('script'); 10 | script.innerHTML = imports.remove; 11 | document.head.appendChild(script); 12 | setTimeout(function() { 13 | document.head.removeChild(script); 14 | }); 15 | }, { 16 | remove: serializeAsIIFE(function() { 17 | if (!window.jQueryAudit) return; 18 | jQueryAudit.cleanup(); 19 | delete window.jQueryAudit; 20 | }) 21 | }); 22 | 23 | chrome.runtime.onConnect.addListener(function(port) { 24 | if (port.name !== 'devtools-jqueryaudit') return; 25 | 26 | var tabId; 27 | var tabIdListener = function(message/*, sender, sendResponse*/) { 28 | if (!message.tabId) return; 29 | tabId = message.tabId; 30 | port.onMessage.removeListener(tabIdListener); 31 | }; 32 | port.onMessage.addListener(tabIdListener); 33 | 34 | port.onDisconnect.addListener(function() { 35 | if (tabId == null || !chrome.tabs) return; 36 | chrome.tabs.executeScript(tabId, { 37 | code: cleanup 38 | }); 39 | }); 40 | 41 | }); 42 | 43 | function serializeAsIIFE(fn) { 44 | var params = Array.prototype.slice 45 | .call(arguments, 1) 46 | .map(function(arg) { 47 | return JSON.stringify(arg); 48 | }).join(','); 49 | return [ '(', fn.toString(), ')(', params, ')' ].join(''); 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery Audit 2 | ------------ 3 | 4 | #### **Install it from the [Chrome Web Store](https://chrome.google.com/webstore/detail/jquery-audit/dhhnpbajdcgdmbbcoakfhmfgmemlncjg/).** 5 | 6 | `jQuery 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`**. 7 | 8 | ![jQuery Audit panel](http://static.tumblr.com/p2zjhet/WbZmwfqaq/jquery-audit-panel.png) 9 | 10 | 11 | ##### Live `DOM nodes`, `functions`, and `objects` 12 | * Variables in the `jQuery Audit` sidebar behave like objects in the `Sources panel` → `Scope Variables` sidebar. You can right-click on a `function` and goto **"Show Function Definition"**, or hover over a `DOM node` to highlight it in the document, as well as right-clicking it to **"Reveal in Elements Panel"**. 13 | 14 | ![show function definition](http://static.tumblr.com/p2zjhet/pnimwfrwl/show-function-definition-highlight.png) 15 | 16 | 17 | ##### Direct access to the `document` and `window` objects 18 | * The `document` and the `window` objects don't have representations in the `Elements panel` but can nonetheless be event targets and/or have associated jQuery data. `jQuery Audit` adds two comment nodes above the `` to represent them. The `` as a stand-in for the `document` object, and the `` as a stand-in for the `window` object. Select either to audit the represented object in the `jQuery Audit` sidebar. 19 | 20 | ![document & window](http://static.tumblr.com/p2zjhet/UZlmwfyd4/document-window-highlight.png) 21 | 22 | **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)"`. 23 | 24 | **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. 25 | 26 | *** 27 | 28 | ### Sidebar sections 29 | 30 | ##### `@(this element)` 31 | * The element currently selected. 32 | 33 | ##### `Data` 34 | * _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)`. 35 | 36 | ##### `Events([number_of_events])` 37 | * 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: 38 | * 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. 39 | * a `handler`: The function that handles the event. More often than not, the `handler` is a _bound_ function and not directly the function that does the "work". The section below on [Finding bound handlers](#finding-bound-handlers) shows you where common _binder_ functions store the _bound_ function. 40 | * And more. 41 | 42 | ##### `Internal Data` 43 | * 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. 44 | 45 | ##### `dataset` 46 | * The value of `HTMLElement.dataset`. This is not the same as _Data_ above, but closely related to it. `HTMLElement.dataset` contains the raw `data-*` attributes. While _Data_ is the parsed content of any `data-*` attributes jQuery found on the element along with any other arbitrary information. (jQuery converts `Boolean`, `Number` and `JSON` in `data-*` attributes when you call `.data()`). 47 | 48 | ##### `own HTML` 49 | * The result of removing the `innerHTML` from the `outerHTML` of an element. This helps debug character encoding issues, since what the `Elements panel` shows is a decoded "pretty" version of the HTML and not the actual HTML. 50 | 51 | ### Finding bound handlers 52 | 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. 53 | 54 | ##### `_.bind` from [Lo-Dash](http://lodash.com/) 55 | * Expand the `handler` function followed by the `__bindData__` property. In this array, the first element is the `bindee` function, the other elements contain the `this` context and any parameters to be partially applied. Older versions of Lo-Dash might not have this structure. 56 | 57 | ![Lo-Dash bind](http://static.tumblr.com/p2zjhet/O7mmwfq08/lodash-bind-highlight.png) 58 | 59 | ##### `_.bind` from [Underscore](http://underscorejs.org/) and native `Function.prototype.bind` 60 | * Underscore uses to the native `bind` function. A clear sign that the `binder` is the native `bind` function is `function () { [native code] }` for a `handler`. Expand the `handler` to locate the `bindee` function is under `[[TargetFunction]]`. The `this` context is found in `[[BoundThis]]` and any parameters to be partially applied are in `[[BoundArgs]]`. 61 | 62 | ![Native bind](http://static.tumblr.com/p2zjhet/okVmwfq2u/native-bind-highlight.png) 63 | 64 | ##### `$.proxy` from [jQuery](http://jquery.com/) 65 | * With `$.proxy` the `bindee` can't be found as a property on the `binder` but rather in a `Closure`. Expand the `handler`, followed by `` and then the inner-most `Closure`. One of the variables in this scope contains the `bindee` - the name of the variable that contains the `bindee` will likely vary because of minification. 66 | 67 | ![jQuery proxy](http://static.tumblr.com/p2zjhet/jLfmwfq44/jquery-proxy-highlight.png) 68 | 69 | *** 70 | 71 | ### FAQ 72 | * Does `jQuery Audit` work with `