Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 217 additions & 49 deletions index_tmpl.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>

{{- define "struct"}}
<div class="col">
Expand All @@ -7,64 +7,232 @@
<div class="typename">{{.Type}}</div>
<select id="{{.SelectID}}" multiple size="{{.SelectSize}}">
{{- range .Fields }}
<option value="{{.Key}}" title="{{ .Label }} : {{ .Type }}">{{ .Padding }}{{ .Label }}:&nbsp;{{ .ValueString }}</option>
<option value="{{.Key}}" title="{{ .Label }} : {{ .Type }}">
{{ .Padding }}{{ .Label }}:&nbsp;{{ .ValueString }}
</option>
{{- end }}
</select>
<script>
<!-- update visible size of select -->
{
const n = document.getElementById('{{.SelectID}}');
const n = document.getElementById("{{.SelectID}}");
n.setAttribute("size", n.options.length);
}
</script>
{{- if not .NotLive }}
<div class="buttonbar">
<button class="btn" title="explore all selected in the row below" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'down');">&ddarr;</button>
<button class="btn" title="explore all selected in columns on the right" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'right');">&rrarr;</button>
<button class="btn" title="explore all selected in the row above" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'up');">&uuarr;</button>
{{- if .HasZeros }}
<button class="btn" title="hide or show fields with zero values" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'toggleZeros');">z</button>
{{- end}}
{{- if .IsRoot }}
<button class="btn" title="remove all objects except the roots" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'clear');">c</button>
{{- else }}
<button class="btn" title="remove the object from this page" onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'remove');">x</button>
{{- end }}
</div>
{{- end}}
{{- end }}
<div class="buttonbar">
<button
class="btn"
title="explore all selected in the row below"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'down');"
>
&ddarr;
</button>
<button
class="btn"
title="explore all selected in columns on the right"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'right');"
>
&rrarr;
</button>
<button
class="btn"
title="explore all selected in the row above"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'up');"
>
&uuarr;
</button>
{{- if .HasZeros }}
<button
class="btn"
title="hide or show fields with zero values"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'toggleZeros');"
>
z
</button>
{{- end}} {{- if .IsRoot }}
<button
class="btn"
title="remove all objects except the roots"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'clear');"
>
c
</button>
{{- else }}
<button
class="btn"
title="remove the object from this page"
onclick="javascript:explore({{.Row}},{{.Column}},getElementById('{{.SelectID}}'),'remove');"
>
x
</button>
{{- end }}
</div>
{{- end}} {{- end }}
</div>
{{- end}}


<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="color-scheme" content="light dark"/>

<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ADD8E6FF"/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#21292c"/>

<title>Struct Explorer</title>

<script>{{.Script}}</script>
<style>{{.Style}}</style>
</head>

<body>
<table>
{{- range .Rows }}
<tr>
{{- range .Cells}}
<td>
{{ template "struct" . }}
</td>
{{- end }}
</tr>
{{- end }}
</table>
<p style="font-size: x-small;" >&copy; 2024 <a href="https://github.com/emicklei/structexplorer">structexplorer</a></p>
</body>
</html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="color-scheme" content="light dark" />

<meta
name="theme-color"
media="(prefers-color-scheme: light)"
content="#ADD8E6FF"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#21292c"
/>

<title>Struct Explorer</title>

<script>
{{.Script}}
</script>
<style>
{{.Style}}
</style>
</head>

<body>
<table>
{{- range .Rows }}
<tr>
{{- range .Cells}}
<td>{{ template "struct" . }}</td>
{{- end }}
</tr>
{{- end }}
</table>
<p style="font-size: x-small;margin-top:10px'">
&copy; 2025
<a href="https://github.com/emicklei/structexplorer"
>structexplorer</a
>
<span id="theme-toggle" class="theme-toggle" title="Toggle Theme"
>🔄</span
>
</p>

<script>
(function () {
const toggleButton = document.getElementById("theme-toggle");
const THEME_KEY = "preferred-theme";
const themes = ["auto", "light", "dark"];
let currentThemeIndex = 0;
let mediaQueryList = window.matchMedia(
"(prefers-color-scheme: dark)",
);
let systemThemeChangeListener = null;

// Apply Theme
function applyTheme(theme) {
if (theme === "auto") {
applyAutoTheme();
addSystemThemeListener();
} else {
document.body.classList.remove("light", "dark");
if (theme === "light") {
document.body.classList.add("light");
} else if (theme === "dark") {
document.body.classList.add("dark");
}
removeSystemThemeListener();
}
updateToggleIcon(theme);
}

// Update Toggle Icon based on theme
function updateToggleIcon(theme) {
switch (theme) {
case "light":
toggleButton.textContent = "☀️";
toggleButton.title = "Light Theme";
break;
case "dark":
toggleButton.textContent = "🌙";
toggleButton.title = "Dark Theme";
break;
case "auto":
default:
toggleButton.textContent = "🔄";
toggleButton.title = "Auto Theme";
break;
}
}

// Get Preferred Theme from localStorage
function getPreferredTheme() {
return localStorage.getItem(THEME_KEY) || "auto";
}

// Set Preferred Theme to localStorage
function setPreferredTheme(theme) {
localStorage.setItem(THEME_KEY, theme);
}

// Initialize Theme
function initTheme() {
const preferredTheme = getPreferredTheme();
currentThemeIndex = themes.indexOf(preferredTheme);
applyTheme(preferredTheme);
}

// Toggle Theme on Click
toggleButton.addEventListener("click", () => {
currentThemeIndex = (currentThemeIndex + 1) % themes.length;
const selectedTheme = themes[currentThemeIndex];
setPreferredTheme(selectedTheme);
applyTheme(selectedTheme);
});

// Apply Auto Theme based on system preference
function applyAutoTheme() {
const prefersDark = mediaQueryList.matches;
document.body.classList.remove("light", "dark");
if (prefersDark) {
document.body.classList.add("dark");
} else {
document.body.classList.add("light");
}
}

// Add system theme change listener
function addSystemThemeListener() {
if (!systemThemeChangeListener) {
systemThemeChangeListener = (e) => {
applyAutoTheme();
};
mediaQueryList.addEventListener(
"change",
systemThemeChangeListener,
);
}
}

// Remove system theme change listener
function removeSystemThemeListener() {
if (systemThemeChangeListener) {
mediaQueryList.removeEventListener(
"change",
systemThemeChangeListener,
);
systemThemeChangeListener = null;
}
}

// Initialize on page load
initTheme();
})();
</script>
</body>
</html>
70 changes: 63 additions & 7 deletions style.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
:root {
--background-color: #ADD8E6FF;
--font-color: #2c2c2c;
--background-color: #add8e6ff; /* Default (Auto) Light Background */
--font-color: #2c2c2c; /* Default (Auto) Font Color */
}

@media (prefers-color-scheme: dark) {
:root {
--background-color: #21292c;
--font-color: #c1c1c1;
--background-color: #21292c; /* Default Dark Background */
--font-color: #c1c1c1; /* Default Dark Font Color */
}
}

Expand All @@ -20,26 +20,73 @@ body {

body {
margin: 4px;
/* padding: 1rem 1.5rem; */
box-sizing: border-box;
font-family: monospace, monospace;

background-color: var(--background-color);
transition:
background-color 0.3s,
color 0.3s; /* Smooth transition */
}

/* Base styles for select and option */
select {
font-size: 14px;
overflow-y: hidden;
font-family: monospace, monospace;
color: var(--font-color);
background-color: var(--background-color); /* Base background color */
border: 1px solid #ccc; /* Optional: Add a border for better visibility */
height: 100%;
width: 100%;
appearance: none; /* Remove default arrow for consistency */
padding: 4px; /* Add some padding */
box-sizing: border-box;
transition:
background-color 0.3s,
color 0.3s; /* Smooth transition */
}

option {
padding: 2px;
background-color: var(
--background-color
); /* Ensure options match the theme */
color: var(--font-color); /* Ensure text color matches the theme */
}

/* Theme-specific overrides */
body.light {
--background-color: #add8e6ff; /* Light Theme Background */
--font-color: #2c2c2c; /* Light Theme Font Color */
}

body.dark {
--background-color: #21292c; /* Dark Theme Background */
--font-color: #c1c1c1; /* Dark Theme Font Color */
}

/* Ensure select and option respect theme-specific background */
body.light select {
background-color: #ffffff; /* Explicitly set to white for Light Theme */
color: var(--font-color);
}

body.light option {
background-color: #ffffff; /* Explicitly set to white for Light Theme */
color: var(--font-color);
}

body.dark select {
background-color: #21292c; /* Explicitly set to dark for Dark Theme */
color: var(--font-color);
}

body.dark option {
background-color: #21292c; /* Explicitly set to dark for Dark Theme */
color: var(--font-color);
}

/* Additional Styles */
td {
vertical-align: top;
}
Expand Down Expand Up @@ -74,4 +121,13 @@ td {
.buttonbar .btn {
font-size: 14px;
margin: 0;
}
}

/* Toggle Button Styling */
.theme-toggle {
cursor: pointer;
margin-left: 8px;
font-size: 16px;
vertical-align: middle;
user-select: none;
}
Loading