A fixed-position developer panel that lives at the bottom of the screen during development. The markup is rendered server-side (PHP outputs the panel and its data); this JavaScript module wires the tab switching, collapse toggle, AJAX log clearing, and localStorage state persistence. Activate any
[data-wf-debug]
element automatically on
DOMContentLoaded
, or call
new
WojoDebug(el).init()
manually.
The panel is fully server-rendered. JavaScript only adds behaviour – tab switching, toggle animation, and AJAX clearing. The root element carries
data-wf-debug
to trigger auto-init. The component opens as
position: fixed
at the bottom of the viewport with
z-index: 2000
.
Each tab button and its corresponding panel share the same value for
data-wf-panel
. The panel element's
id
must match that value exactly. The tab whose panel should be active on the first load gets
is-active
added server-side (or JavaScript restores the last open tab from localStorage).
Each panel is a
div.wf-debug-panel
with a matching
id
and
data-wf-panel
. Panels are
display: none
by default; the active panel gets
is-active
and becomes scrollable at
--wf-dbg-panel-height
(default 200px). Use
<p>
tags for key–value rows and
<pre>
for multi-line code output.
The panel with
data-wf-panel="contentQueries"
automatically renders
<pre>
tags in the theme's query color (
--wf-dbg-query-color
, default
#db7de9
) with a transparent background.
HTML
<div id="contentQueries" class="wf-debug-panel" data-wf-panel="contentQueries">
<pre>SELECT * FROM users WHERE id = 42</pre>
<pre>SELECT r.name FROM roles r
JOIN user_roles ur ON r.id = ur.role_id
WHERE ur.user_id = 42</pre>
</div>
Clear Button
The clear button sends a
POST
request to the URL stored in
data-wf-url
, with the
data-wf-ajax-action
value passed as the
action
body parameter. The request includes an
X-Requested-With: XMLHttpRequest
header. The button is disabled while the request is in flight to prevent double submission. Panels and localStorage state are not touched by the clear action.
The debug panel is intentionally dark-themed (independent of the page theme). All colors, sizes, and timing values are controlled by CSS custom properties on
:root
- override them in your stylesheet to customize the appearance without touching component CSS.
Auto-init runs on
DOMContentLoaded
and stores the instance at
el._wfDebug
. For manual control, import
WojoDebug
and call
init()
- it returns the instance for chaining.
Initialization
JavaScript
// Auto-init (no code needed - runs on DOMContentLoaded):
// <div class="wf-debug" data-wf-debug>...</div>
// Access auto-init instance:
const dbg = document.querySelector('[data-wf-debug]')._wfDebug
// Manual init:
import { WojoDebug } from './wf-debug.js'
const dbg = new WojoDebug(el).init()
// Custom storage key (default: 'wf-debug-state'):
const dbg = new WojoDebug(el, { storageKey: 'my-debug' }).init()
// - or via HTML attribute:
// <div class="wf-debug" data-wf-debug data-wf-storage-key="my-debug">
Methods
JavaScript
const dbg = document.querySelector('[data-wf-debug]')._wfDebug
// Open a specific tab panel by its ID:
dbg.open('contentQueries')
// Collapse all panels (same as clicking the toggle arrow):
dbg.close()
// Remove all event listeners (teardown):
dbg.destroy()
Method / Option
Description
new WojoDebug(el[, opts])
Constructor. opts.storageKey overrides the localStorage key (default: 'wf-debug-state')
.init()
Wires all event listeners and restores the last panel from localStorage. Returns the instance.
.open(panelId)
Activates the tab and panel matching panelId, sets data-wf-open on the root, saves state to localStorage
.close()
Removes is-active from all tabs and panels, removes data-wf-open, saves 'none' to localStorage
.destroy()
Removes all event listeners attached by this instance
data-wf-storage-key
HTML attribute on the root element - overrides storageKey option
Events
All events are dispatched on the root
.wf-debug
element and bubble. The
wf:debug-clear
event is cancelable - call
e.preventDefault()
to abort the AJAX request before it fires.
JavaScript
const panel = document.querySelector('[data-wf-debug]')
// Panel opened - tab switched
panel.addEventListener('wf:debug-open', e => {
console.log('opened panel:', e.detail.panelId)
})
// Panel collapsed (toggle arrow clicked)
panel.addEventListener('wf:debug-close', () => {
console.log('debug panel collapsed')
})
// Before AJAX clear - cancelable
panel.addEventListener('wf:debug-clear', e => {
// e.detail: { url, action, btn }
if (!confirm('Clear the debug log?')) {
e.preventDefault() // abort the request
}
})
// After successful AJAX clear
panel.addEventListener('wf:debug-cleared', e => {
// e.detail: { url, action, data }
console.log('log cleared, server response:', e.detail.data)
})
Event
Cancelable
detail
Fired when
wf:debug-open
No
{ panelId }
A tab panel is opened
wf:debug-close
No
-
Toggle arrow collapses all panels
wf:debug-clear
Yes
{ url, action, btn }
Clear button clicked, before the POST request
wf:debug-cleared
No
{ url, action, data }
Server responded successfully to the clear POST
Class Reference
Class / Attribute
Element
Description
Root
wf-debug
div
Root element - position: fixed, bottom of viewport, full width, z-index: 2000
data-wf-debug
Root
Triggers auto-init on DOMContentLoaded
data-wf-storage-key
Root
Custom localStorage key for state persistence (default: wf-debug-state)
data-wf-open
Root
Present when any panel is open (JS-managed); rotates toggle arrow 180°
Layout
wf-debug-wrapper
div
Inner wrapper with dark background and horizontal padding
wf-debug-legend
div
Horizontal bar containing the label, toggle, tabs, and clear button
Legend elements
wf-debug-label
span
Static "Debug" label text
wf-debug-arrow
div
Toggle button wrapper
wf-debug-toggle
button
Collapse/expand button - icon rotates 180° when panel is open
data-wf-debug-toggle
Toggle button
Marks the toggle button for the click handler
wf-debug-tab
button
Tab button; data-wf-panel value must match the target panel's id
is-active
Tab / Panel
Active state - set by JS; can be pre-set server-side for the default open tab
wf-debug-clear
button
AJAX clear button (red, opacity 0.8)
data-wf-debug-clear
Clear button
Marks the clear button; data-wf-url + data-wf-ajax-action configure the POST
Panels
wf-debug-panel
div
Content panel – hidden (display:none) until is-active; scrollable at --wf-dbg-panel-height
data-wf-panel
Tab / Panel
Links tab buttons to panels – value must match the panel's id attribute