// ==UserScript== // @name Elements with ID lister // @namespace blankie-scripts // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_getResourceURL // @require https://cdn.jsdelivr.net/npm/dialog-polyfill@0.5.6/dist/dialog-polyfill.min.js#sha256-cec1a2e320aab77e28bad4ad6bc5e532a6ef5757345c19bb5158aa880b7162a6 // @resource dialogPolyfillCSS https://cdn.jsdelivr.net/npm/dialog-polyfill@0.5.6/dist/dialog-polyfill.min.css#sha256-4dcb3ab62e545f30bf06a4824c253641ee889ca85ca28d5447590557922496ab // @version 1.0.2 // @author blankie // @description A userscript that adds a "Show elements popup" option to the Monkey Menu which lists all elements with an ID // @inject-into content // ==/UserScript== "use strict"; const DIALOG_WRAPPER_ID = "element_lister-dialog_wrapper"; const ACCENT_COLOR = "#962AC3"; const BRIGHT_ACCENT_COLOR = "#DE6DE6"; const CSS = ` dialog { position: fixed; min-width: 25em; font-size: 11pt; color: white; background-color: black; } dialog.polyfilled { top: 50%; left: 50%; transform: translate(-50%, -50%); } dialog::backdrop, dialog + .backdrop { background-color: rgba(0, 0, 0, .5); } .align-right { text-align: right; } a { color: ${ACCENT_COLOR}; text-decoration: none; } a:hover { color: ${BRIGHT_ACCENT_COLOR}; text-decoration: underline; } `; function showElementList() { if (document.getElementById(DIALOG_WRAPPER_ID)) { return; } let dialogWrapper = document.createElement("div"); dialogWrapper.id = DIALOG_WRAPPER_ID; let shadowRoot = dialogWrapper.attachShadow({mode: "closed"}); let link = document.createElement("link"); link.rel = "stylesheet"; link.href = GM_getResourceURL("dialogPolyfillCSS"); shadowRoot.append(link); let style = document.createElement("style"); style.textContent = CSS; shadowRoot.append(style); let dialog = document.createElement("dialog"); if (!dialog.showModal) { dialog.classList.add("polyfilled"); } dialogPolyfill.registerDialog(dialog); dialog.addEventListener("close", hideElementList, {once: true, passive: true}); dialog.addEventListener("click", function(e) { let rect = dialog.getBoundingClientRect(); if (rect.top <= e.clientY && rect.left <= e.clientX && rect.bottom >= e.clientY && rect.right >= e.clientX) { return; } hideElementList(); }, {passive: true}); let buttonWrapper = document.createElement("div"); buttonWrapper.classList.add("align-right"); let button = document.createElement("button"); button.textContent = "Close"; button.addEventListener("click", hideElementList, {once: true, passive: true}); buttonWrapper.append(button); dialog.append(buttonWrapper); let hr = document.createElement("hr"); dialog.append(hr); let elements = getElementList(); if (elements.length) { let ul = document.createElement("ul"); for (let i of getElementList()) { ul.append(i); } dialog.append(ul); } else { dialog.append("There are no elements with an ID."); } shadowRoot.append(dialog); document.body.append(dialogWrapper); dialog.showModal(); } function hideElementList() { let dialogWrapper = document.getElementById(DIALOG_WRAPPER_ID); if (!dialogWrapper) { return; } dialogWrapper.remove(); } function getElementList() { let elements = []; for (let element of document.querySelectorAll("[id]")) { let rect = element.getBoundingClientRect(); if (rect.x === 0 && rect.y === 0 && rect.right === 0 && rect.bottom === 0 && rect.width === 0 && rect.height === 0) { continue; } elements.push(getElementListItem(element)); } return elements; } function getElementListItem(element) { let li = document.createElement("li"); let a = document.createElement("a"); a.href = a.innerText = "#" + element.id; a.addEventListener("click", hideElementList, {once: true, passive: true}); li.append(a); let description = getElementDescription(element); if (description) { li.append(" (", description, ")"); } return li; } function getElementDescription(element) { let addEilipses = false; let text = (element.innerText || "").trim(); let newlineIndex = text.indexOf("\n"); if (newlineIndex !== -1) { text = text.substring(0, newlineIndex); addEilipses = true; } if (text.length > 50) { text = text.substring(0, 50); addEilipses = true; } if (addEilipses) { text += "..."; } return text; } GM_registerMenuCommand("Show elements popup", function() { if (!document.getElementById(DIALOG_WRAPPER_ID)) { showElementList(); } else { hideElementList(); } })