Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A jQuery plugin for tracking HTML "coverage" of jQuery selectors - it helps you figure out which selectors aren't actually selecting any elements, which may signify dead code.
/*
Include using
<script type="text/javascript" src="https://cdn.rawgit.com/drmercer/7da5b9dbe1a3e0b3ccc43c7fff8a1ec5/raw/86dba4b108a0ac3f1889f06c9db9454d88f770b1/jQuery-coverage.js"></script>
Be sure to include it after you've loaded jQuery.
*/
window.jqcoverage = (function ($) {
"use strict";
function log(...args) {
console.log("%c[jQuery-coverage]", "color:aqua", ...args);
}
// Configuration stuff (stores settings in localStorage)
const KEY_SELECTORS = "jQuery-coverage-badSelectors";
const badSelectors = JSON.parse(localStorage.getItem(KEY_SELECTORS)) || [];
const KEY_BLACKLIST = "jQuery-coverage-blacklist";
const blacklistedSelectors = JSON.parse(localStorage.getItem(KEY_BLACKLIST)) || [];
function saveBlacklist() {
localStorage.setItem(KEY_BLACKLIST, JSON.stringify(blacklistedSelectors));
}
const KEY_LOG_ENABLED = "jQuery-coverage-logEnabled";
var logBadSelectors = JSON.parse(localStorage.getItem(KEY_LOG_ENABLED) || "true");
function saveLogEnabledSetting() {
localStorage.setItem(KEY_LOG_ENABLED, JSON.stringify(logBadSelectors));
}
if (badSelectors.length) {
log("Loaded " + badSelectors.length + " bad selectors from a previous run");
if (!logBadSelectors) {
log("(Logging disabled. Call jqcoverage.enableBadSelectorLogging() to enable)");
}
}
// This object is made global, so you can use it from the dev console. More functions below.
const jqcoverage = {
disableBadSelectorLogging: function () {
logBadSelectors = false;
saveLogEnabledSetting();
log("Bad selector logging disabled");
},
enableBadSelectorLogging: function () {
logBadSelectors = true;
saveLogEnabledSetting();
log("Bad selector logging enabled");
},
};
// Create proxy jQuery function:
const coverageMap = {};
const new$ = function (...args) {
const $res = $(...args);
const key = args.join();
const prevCount = coverageMap[key] || 0;
const newCount = Math.max($res.length, prevCount);
coverageMap[key] = newCount;
// Warn when bad selectors are used again, to give the dev a stack trace
if (logBadSelectors &&
newCount === 0 &&
badSelectors.includes(key) &&
!blacklistedSelectors.includes(key)) {
console.warn("Bad selector used: ", ...args);
}
return $res;
};
$.extend(new$, $);
window.jQuery = new$;
if (window.$ === $) {
window.$ = new$;
}
//==============================================
// Coverage report tools
// Call this to get a coverage report
jqcoverage.getCoverage = function () {
const summary = {};
$.each(coverageMap, function (key, val) {
summary[val] || (summary[val] = []);
summary[val].push(key);
});
return summary;
};
jqcoverage.getCoverageOf = function(selector) {
selector = "" + selector;
var useCount = coverageMap[selector] || 0;
return selector + " selected at most " + useCount + " element(s)";
};
// Call this to save the list of bad selectors to localStorage
jqcoverage.saveBadSelectors = function () {
const badSelectors = jqcoverage.getCoverage()[0] || [];
localStorage.setItem(KEY_SELECTORS, JSON.stringify(badSelectors));
const badSelectorCount = badSelectors.length;
log("Saved " + badSelectorCount + " bad selectors to analyze on a later run");
};
// Call this to clear the list of bad selectors inlocalStorage and memory
jqcoverage.clearBadSelectors = function () {
localStorage.removeItem(KEY_SELECTORS);
badSelectors.splice(0);
};
//==============================================
// Key blacklisting tools
jqcoverage.blacklistSelector = function (selector) {
if (typeof selector !== "string") {
throw new Error("Selector must be a string");
}
if (!blacklistedSelectors.includes(selector)) {
blacklistedSelectors.push(selector);
}
saveBlacklist();
};
jqcoverage.unblacklistSelector = function (selector) {
var idx = blacklistedSelectors.indexOf(selector);
if (idx !== -1) {
blacklistedSelectors.splice(idx, 1);
return "Selector removed from blacklist";
} else {
return "Selector not found in blacklist";
}
saveBlacklist();
};
log("jQuery-coverage loaded");
return jqcoverage;
}(window.jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment