- index.html: minimal shell with <template> elements for all repeated DOM structures (node-item, device-group, device-item, ctrl-group, ctrl-row, capture-badge); links external style.css - style.css: all styles extracted from index.html - lib/dom.mjs: by_id, qs, clone, show, hide helpers - app.mjs: persistent SSE node list replaces Discover button; clicking a node connects to it; uses clone()/replaceChildren() throughout; no innerHTML for structure; event wiring at bottom Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
2.1 KiB
HTML
95 lines
2.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Video Node Inspector</title>
|
|
<link rel="stylesheet" href="/style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<div id="topbar">
|
|
<div id="status-dot"></div>
|
|
<h1>Video Node Inspector</h1>
|
|
<span id="status-text">not connected</span>
|
|
<button id="btn-disconnect" hidden>Disconnect</button>
|
|
</div>
|
|
|
|
<div id="main">
|
|
<div id="node-panel" class="panel">
|
|
<h2>Nodes</h2>
|
|
<div id="node-list">
|
|
<div class="empty">Discovering…</div>
|
|
</div>
|
|
<div id="manual-connect">
|
|
<input type="text" id="inp-host" placeholder="host">
|
|
<input type="number" id="inp-port" placeholder="port">
|
|
<button id="btn-connect" class="primary">+</button>
|
|
</div>
|
|
</div>
|
|
<div id="device-panel" class="panel">
|
|
<h2>
|
|
Devices
|
|
<button id="btn-refresh-devices" class="compact" style="margin-left:auto">↻</button>
|
|
</h2>
|
|
<div id="device-list">
|
|
<div class="empty">Select a node</div>
|
|
</div>
|
|
</div>
|
|
<div id="controls-panel" class="panel">
|
|
<h2>
|
|
<span id="controls-title">Controls</span>
|
|
<label class="continuous-label">
|
|
<input type="checkbox" id="chk-continuous"> continuous
|
|
</label>
|
|
</h2>
|
|
<div id="controls-scroll">
|
|
<div class="empty">Select a device</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toast-container"></div>
|
|
|
|
<template id="t-node-item">
|
|
<div class="node-item">
|
|
<div class="n-name"></div>
|
|
<div class="n-addr"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<template id="t-device-group">
|
|
<div class="device-group">
|
|
<div class="device-group-header"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<template id="t-device-item">
|
|
<div class="device-item">
|
|
<div class="d-path"></div>
|
|
<div class="d-meta"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<template id="t-capture-badge">
|
|
<span class="capture-badge">capture</span>
|
|
</template>
|
|
|
|
<template id="t-ctrl-group">
|
|
<div class="ctrl-group">
|
|
<div class="ctrl-group-title"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<template id="t-ctrl-row">
|
|
<div class="ctrl-row">
|
|
<div class="ctrl-label"></div>
|
|
<div class="ctrl-input"></div>
|
|
<div class="ctrl-value-display"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script type="module" src="/app.mjs"></script>
|
|
</body>
|
|
</html>
|