diff --git a/debug_toolbar/static/debug_toolbar/css/toolbar.css b/debug_toolbar/static/debug_toolbar/css/toolbar.css index 044e15e5f..13b88f5c2 100644 --- a/debug_toolbar/static/debug_toolbar/css/toolbar.css +++ b/debug_toolbar/static/debug_toolbar/css/toolbar.css @@ -1,5 +1,5 @@ /* Variable definitions */ -:root { +:host { /* Font families are the same as in Django admin/css/base.css */ --djdt-font-family-primary: "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif, @@ -13,7 +13,7 @@ "Noto Color Emoji"; } -:root, +:host, #djDebug[data-theme="light"] { --djdt-font-color: black; --djdt-background-color: white; diff --git a/debug_toolbar/static/debug_toolbar/js/history.js b/debug_toolbar/static/debug_toolbar/js/history.js index c2644eca7..148051330 100644 --- a/debug_toolbar/static/debug_toolbar/js/history.js +++ b/debug_toolbar/static/debug_toolbar/js/history.js @@ -1,6 +1,6 @@ -import { $$, ajaxForm, replaceToolbarState } from "./utils.js"; +import { $$, ajaxForm, getDebugElement, replaceToolbarState } from "./utils.js"; -const djDebug = document.getElementById("djDebug"); +const djDebug = getDebugElement(); function difference(setA, setB) { const _difference = new Set(setA); @@ -19,7 +19,7 @@ function pluckData(nodes, key) { function refreshHistory() { const formTarget = djDebug.querySelector(".refreshHistory"); - const container = document.getElementById("djdtHistoryRequests"); + const container = djDebug.querySelector("#djdtHistoryRequests"); const oldIds = new Set( pluckData( container.querySelectorAll("tr[data-request-id]"), @@ -85,7 +85,7 @@ function switchHistory(newRequestId) { ajaxForm(formTarget).then((data) => { if (Object.keys(data).length === 0) { - const container = document.getElementById("djdtHistoryRequests"); + const container = djDebug.querySelector("#djdtHistoryRequests"); container.querySelector( `button[data-request-id="${newRequestId}"]` ).innerHTML = "Switch [EXPIRED]"; diff --git a/debug_toolbar/static/debug_toolbar/js/timer.js b/debug_toolbar/static/debug_toolbar/js/timer.js index a01dbb2d1..a60e931a9 100644 --- a/debug_toolbar/static/debug_toolbar/js/timer.js +++ b/debug_toolbar/static/debug_toolbar/js/timer.js @@ -1,4 +1,6 @@ -import { $$ } from "./utils.js"; +import { $$, getDebugElement } from "./utils.js"; + +const djDebug = getDebugElement(); function insertBrowserTiming() { const timingOffset = performance.timing.navigationStart; @@ -58,10 +60,10 @@ function insertBrowserTiming() { tbody.appendChild(row); } - const browserTiming = document.getElementById("djDebugBrowserTiming"); + const browserTiming = djDebug.querySelector("#djDebugBrowserTiming"); // Determine if the browser timing section has already been rendered. if (browserTiming.classList.contains("djdt-hidden")) { - const tbody = document.getElementById("djDebugBrowserTimingTableBody"); + const tbody = djDebug.querySelector("#djDebugBrowserTimingTableBody"); // This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param) addRow(tbody, "domainLookupStart", "domainLookupEnd"); addRow(tbody, "connectStart", "connectEnd"); @@ -75,7 +77,6 @@ function insertBrowserTiming() { } } -const djDebug = document.getElementById("djDebug"); // Insert the browser timing now since it's possible for this // script to miss the initial panel load event. insertBrowserTiming(); diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.js b/debug_toolbar/static/debug_toolbar/js/toolbar.js index 609842209..bedf364b6 100644 --- a/debug_toolbar/static/debug_toolbar/js/toolbar.js +++ b/debug_toolbar/static/debug_toolbar/js/toolbar.js @@ -1,4 +1,10 @@ -import { $$, ajax, debounce, replaceToolbarState } from "./utils.js"; +import { + $$, + ajax, + debounce, + getDebugElement, + replaceToolbarState, +} from "./utils.js"; function onKeyDown(event) { if (event.keyCode === 27) { @@ -6,15 +12,6 @@ function onKeyDown(event) { } } -function getDebugElement() { - // Fetch the debug element from the DOM. - // This is used to avoid writing the element's id - // everywhere the element is being selected. A fixed reference - // to the element should be avoided because the entire DOM could - // be reloaded such as via HTMX boosting. - return document.getElementById("djDebug"); -} - const djdt = { handleDragged: false, needUpdateOnFetch: false, @@ -27,7 +24,7 @@ const djdt = { return; } const panelId = this.className; - const current = document.getElementById(panelId); + const current = djDebug.querySelector(`#${panelId}`); if ($$.visible(current)) { djdt.hidePanels(); } else { @@ -103,7 +100,7 @@ const djdt = { } ajax(url, ajaxData).then((data) => { - const win = document.getElementById("djDebugWindow"); + const win = djDebug.querySelector("#djDebugWindow"); win.innerHTML = data.content; $$.show(win); }); @@ -116,7 +113,7 @@ const djdt = { const toggleClose = "-"; const openMe = this.textContent === toggleOpen; const name = this.dataset.toggleName; - const container = document.getElementById(`${name}_${id}`); + const container = djDebug.querySelector(`#${name}_${id}`); for (const el of container.querySelectorAll(".djDebugCollapsed")) { $$.toggle(el, openMe); } @@ -156,7 +153,7 @@ const djdt = { }); let startPageY; let baseY; - const handle = document.getElementById("djDebugToolbarHandle"); + const handle = djDebug.querySelector("#djDebugToolbarHandle"); function onHandleMove(event) { // Chrome can send spurious mousemove events, so don't do anything unless the // cursor really moved. Otherwise, it will be impossible to expand the toolbar @@ -240,16 +237,17 @@ const djdt = { }, hidePanels() { const djDebug = getDebugElement(); - $$.hide(document.getElementById("djDebugWindow")); + $$.hide(djDebug.querySelector("#djDebugWindow")); for (const el of djDebug.querySelectorAll(".djdt-panelContent")) { $$.hide(el); } - for (const el of document.querySelectorAll("#djDebugToolbar li")) { + for (const el of djDebug.querySelectorAll("#djDebugToolbar li")) { el.classList.remove("djdt-active"); } }, ensureHandleVisibility() { - const handle = document.getElementById("djDebugToolbarHandle"); + const djDebug = getDebugElement(); + const handle = djDebug.querySelector("#djDebugToolbarHandle"); // set handle position const handleTop = Math.min( localStorage.getItem("djdt.top") || 265, @@ -258,11 +256,12 @@ const djdt = { handle.style.top = `${handleTop}px`; }, hideToolbar() { + const djDebug = getDebugElement(); djdt.hidePanels(); - $$.hide(document.getElementById("djDebugToolbar")); + $$.hide(djDebug.querySelector("#djDebugToolbar")); - const handle = document.getElementById("djDebugToolbarHandle"); + const handle = djDebug.querySelector("#djDebugToolbarHandle"); $$.show(handle); djdt.ensureHandleVisibility(); window.addEventListener("resize", djdt.ensureHandleVisibility); @@ -271,11 +270,12 @@ const djdt = { localStorage.setItem("djdt.show", "false"); }, hideOneLevel() { - const win = document.getElementById("djDebugWindow"); + const djDebug = getDebugElement(); + const win = djDebug.querySelector("#djDebugWindow"); if ($$.visible(win)) { $$.hide(win); } else { - const toolbar = document.getElementById("djDebugToolbar"); + const toolbar = djDebug.querySelector("#djDebugToolbar"); if (toolbar.querySelector("li.djdt-active")) { djdt.hidePanels(); } else { @@ -284,16 +284,16 @@ const djdt = { } }, showToolbar() { + const djDebug = getDebugElement(); document.addEventListener("keydown", onKeyDown); - $$.show(document.getElementById("djDebug")); - $$.hide(document.getElementById("djDebugToolbarHandle")); - $$.show(document.getElementById("djDebugToolbar")); + $$.show(djDebug); + $$.hide(djDebug.querySelector("#djDebugToolbarHandle")); + $$.show(djDebug.querySelector("#djDebugToolbar")); localStorage.setItem("djdt.show", "true"); window.removeEventListener("resize", djdt.ensureHandleVisibility); }, updateOnAjax() { - const sidebarUrl = - document.getElementById("djDebug").dataset.sidebarUrl; + const sidebarUrl = getDebugElement().dataset.sidebarUrl; const slowjax = debounce(ajax, 200); function handleAjaxResponse(requestId) { diff --git a/debug_toolbar/static/debug_toolbar/js/utils.js b/debug_toolbar/static/debug_toolbar/js/utils.js index 9b34f86f8..6a32db892 100644 --- a/debug_toolbar/static/debug_toolbar/js/utils.js +++ b/debug_toolbar/static/debug_toolbar/js/utils.js @@ -70,6 +70,16 @@ const $$ = { }, }; +function getDebugElement() { + // Fetch the debug element from the DOM. + // This is used to avoid writing the element's id + // everywhere the element is being selected. A fixed reference + // to the element should be avoided because the entire DOM could + // be reloaded such as via HTMX boosting. + const root = document.getElementById("djDebugRoot").shadowRoot; + return root.querySelector("#djDebug"); +} + function ajax(url, init) { return fetch(url, Object.assign({ credentials: "same-origin" }, init)) .then((response) => { @@ -89,7 +99,8 @@ function ajax(url, init) { ); }) .catch((error) => { - const win = document.getElementById("djDebugWindow"); + const djDebug = getDebugElement(); + const win = djDebug.querySelector("#djDebugWindow"); win.innerHTML = `

${error.message}

`; $$.show(win); throw error; @@ -110,14 +121,14 @@ function ajaxForm(element) { } function replaceToolbarState(newRequestId, data) { - const djDebug = document.getElementById("djDebug"); + const djDebug = getDebugElement(); djDebug.setAttribute("data-request-id", newRequestId); // Check if response is empty, it could be due to an expired requestId. for (const panelId of Object.keys(data)) { - const panel = document.getElementById(panelId); + const panel = djDebug.querySelector(`#${panelId}`); if (panel) { panel.outerHTML = data[panelId].content; - document.getElementById(`djdt-${panelId}`).outerHTML = + djDebug.querySelector(`#djdt-${panelId}`).outerHTML = data[panelId].button; } } @@ -141,4 +152,4 @@ function debounce(func, delay) { }; } -export { $$, ajax, ajaxForm, replaceToolbarState, debounce }; +export { $$, getDebugElement, ajax, ajaxForm, replaceToolbarState, debounce }; diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html index b7562ecba..161f794df 100644 --- a/debug_toolbar/templates/debug_toolbar/base.html +++ b/debug_toolbar/templates/debug_toolbar/base.html @@ -1,43 +1,48 @@ {% load i18n static %} -{% block css %} - - -{% endblock css %} -{% block js %} - -{% endblock js %} -
-
-
    -
  • {% translate "Hide" %} »
  • -
  • - - {% translate "Toggle Theme" %} {% include "debug_toolbar/includes/theme_selector.html" %} - -
  • +
    +
    diff --git a/docs/configuration.rst b/docs/configuration.rst index 2ff363888..a7be8934d 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -439,7 +439,7 @@ could add a **debug_toolbar/base.html** template override to your project: {% block css %}{{ block.super }} diff --git a/docs/panels.rst b/docs/panels.rst index 65024e3c8..ac4ee681f 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -444,14 +444,14 @@ Events .. code-block:: javascript - import { $$ } from "./utils.js"; + import { $$, getDebugElement } from "./utils.js"; function addCustomMetrics() { // Logic to process/add custom metrics here. // Be sure to cover the case of this function being called twice // due to file being loaded asynchronously. } - const djDebug = document.getElementById("djDebug"); + const djDebug = getDebugElement(); $$.onPanelRender(djDebug, "CustomPanel", addCustomMetrics); // Since a panel's scripts are loaded asynchronously, it's possible that // the above statement would occur after the djdt.panel.render event has