";
+ row.querySelector("rect").setAttribute("width", 2);
+ }
+ row.querySelector("rect").setAttribute("x", getLeft(stat));
+ tbody.appendChild(row);
+ }
+
+ const browserTiming = document.getElementById("djDebugBrowserTiming");
+ // Determine if the browser timing section has already been rendered.
+ if (browserTiming.classList.contains("djdt-hidden")) {
+ const tbody = document.getElementById("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");
+ addRow(tbody, "requestStart", "responseEnd"); // There is no requestEnd
+ addRow(tbody, "responseStart", "responseEnd");
+ addRow(tbody, "domLoading", "domComplete"); // Spans the events below
+ addRow(tbody, "domInteractive");
+ addRow(tbody, "domContentLoadedEventStart", "domContentLoadedEventEnd");
+ addRow(tbody, "loadEventStart", "loadEventEnd");
+ browserTiming.classList.remove("djdt-hidden");
}
- row.querySelector("rect").setAttribute("x", getLeft(stat));
- tbody.appendChild(row);
}
-const tbody = document.getElementById("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");
-addRow(tbody, "requestStart", "responseEnd"); // There is no requestEnd
-addRow(tbody, "responseStart", "responseEnd");
-addRow(tbody, "domLoading", "domComplete"); // Spans the events below
-addRow(tbody, "domInteractive");
-addRow(tbody, "domContentLoadedEventStart", "domContentLoadedEventEnd");
-addRow(tbody, "loadEventStart", "loadEventEnd");
-document.getElementById("djDebugBrowserTiming").classList.remove("djdt-hidden");
+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();
+$$.onPanelRender(djDebug, "TimerPanel", insertBrowserTiming);
diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.js b/debug_toolbar/static/debug_toolbar/js/toolbar.js
index d739cbdb3..579548d4e 100644
--- a/debug_toolbar/static/debug_toolbar/js/toolbar.js
+++ b/debug_toolbar/static/debug_toolbar/js/toolbar.js
@@ -20,7 +20,8 @@ const djdt = {
if (!this.className) {
return;
}
- const current = document.getElementById(this.className);
+ const panelId = this.className;
+ const current = document.getElementById(panelId);
if ($$.visible(current)) {
djdt.hide_panels();
} else {
@@ -39,13 +40,24 @@ const djdt = {
window.location
);
url.searchParams.append("store_id", store_id);
- url.searchParams.append("panel_id", this.className);
+ url.searchParams.append("panel_id", panelId);
ajax(url).then(function (data) {
inner.previousElementSibling.remove(); // Remove AJAX loader
inner.innerHTML = data.content;
$$.executeScripts(data.scripts);
$$.applyStyles(inner);
+ djDebug.dispatchEvent(
+ new CustomEvent("djdt.panel.render", {
+ detail: { panelId: panelId },
+ })
+ );
});
+ } else {
+ djDebug.dispatchEvent(
+ new CustomEvent("djdt.panel.render", {
+ detail: { panelId: panelId },
+ })
+ );
}
}
}
diff --git a/debug_toolbar/static/debug_toolbar/js/utils.js b/debug_toolbar/static/debug_toolbar/js/utils.js
index 4683b319f..da810aad0 100644
--- a/debug_toolbar/static/debug_toolbar/js/utils.js
+++ b/debug_toolbar/static/debug_toolbar/js/utils.js
@@ -7,6 +7,21 @@ const $$ = {
}
});
},
+ onPanelRender(root, panelId, fn) {
+ /*
+ This is a helper function to attach a handler for a `djdt.panel.render`
+ event of a specific panel.
+
+ root: The container element that the listener should be attached to.
+ panelId: The Id of the panel.
+ fn: A function to execute when the event is triggered.
+ */
+ root.addEventListener("djdt.panel.render", function (event) {
+ if (event.detail.panelId === panelId) {
+ fn.call(event);
+ }
+ });
+ },
show(element) {
element.classList.remove("djdt-hidden");
},
diff --git a/docs/changes.rst b/docs/changes.rst
index bef5d1964..b3da18d49 100644
--- a/docs/changes.rst
+++ b/docs/changes.rst
@@ -9,8 +9,13 @@ Next version
* Added ``PRETTIFY_SQL`` configuration option to support controlling
SQL token grouping. By default it's set to True. When set to False,
a performance improvement can be seen by the SQL panel.
-* Fixed issue with toolbar expecting URL paths to start with `/__debug__/`
- while the documentation indicates it's not required.
+* Added a JavaScript event when a panel loads of the format
+ ``djdt.panel.[PanelId]`` where PanelId is the ``panel_id`` property
+ of the panel's Python class. Listening for this event corrects the bug
+ in the Timer Panel in which it didn't insert the browser timings
+ after switching requests in the History Panel.
+* Fixed issue with the toolbar expecting URL paths to start with
+ ``/__debug__/`` while the documentation indicates it's not required.
3.2 (2020-12-03)
----------------
diff --git a/docs/panels.rst b/docs/panels.rst
index c21e90801..dfa5ec92a 100644
--- a/docs/panels.rst
+++ b/docs/panels.rst
@@ -184,9 +184,9 @@ URL: https://github.com/danyi1212/django-windowsauth
Path: ``windows_auth.panels.LDAPPanel``
-LDAP Operations performed during the request, including timing, request and response messages,
+LDAP Operations performed during the request, including timing, request and response messages,
the entries received, write changes list, stack-tracing and error debugging.
-This panel also shows connection usage metrics when it is collected.
+This panel also shows connection usage metrics when it is collected.
`Check out the docs `_.
Line Profiler
@@ -402,3 +402,32 @@ common methods available.
.. js:function:: djdt.show_toolbar
Shows the toolbar.
+
+Events
+^^^^^^
+
+.. js:attribute:: djdt.panel.render
+
+ This is an event raised when a panel is rendered. It has the property
+ ``detail.panelId`` which identifies which panel has been loaded. This
+ event can be useful when creating custom scripts to process the HTML
+ further.
+
+ An example of this for the ``CustomPanel`` would be:
+
+.. code-block:: javascript
+
+ import { $$ } 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");
+ $$.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
+ // been raised. To account for that, the rendering function should be
+ // called here as well.
+ addCustomMetrics();