Browse Source

DOM Elements and UI listeners seperated

refactor/modularize
RUSHIL AMBARISH KADU 9 months ago
parent
commit
4a1653253c
  1. 122
      steps/index.html
  2. 158
      steps/src/dom.js

122
steps/index.html

@ -288,15 +288,22 @@
appState
} from './src/state.js';
// --- DOM Element References ---
const canvasContainer = document.getElementById('canvas-container'), canvasPlaceholder = document.getElementById('canvas-placeholder'), videoPlayer = document.getElementById('video-player'), videoPlaceholder = document.getElementById('video-placeholder'), loadJsonBtn = document.getElementById('load-json-btn'), loadVideoBtn = document.getElementById('load-video-btn'), loadCanBtn = document.getElementById('load-can-btn'), jsonFileInput = document.getElementById('json-file-input'), videoFileInput = document.getElementById('video-file-input'), canFileInput = document.getElementById('can-file-input'), playPauseBtn = document.getElementById('play-pause-btn'), stopBtn = document.getElementById('stop-btn'), timelineSlider = document.getElementById('timeline-slider'), frameCounter = document.getElementById('frame-counter'), offsetInput = document.getElementById('offset-input'), speedSlider = document.getElementById('speed-slider'), speedDisplay = document.getElementById('speed-display'), featureToggles = document.getElementById('feature-toggles'), toggleSnrColor = document.getElementById('toggle-snr-color'), toggleClusterColor = document.getElementById('toggle-cluster-color'), toggleInlierColor = document.getElementById('toggle-inlier-color'),
// ADD THIS LINE
toggleStationaryColor = document.getElementById('toggle-stationary-color'),
// END OF ADDED LINE
toggleVelocity = document.getElementById('toggle-velocity'), toggleTracks = document.getElementById('toggle-tracks'), toggleEgoSpeed = document.getElementById('toggle-ego-speed'), toggleFrameNorm = document.getElementById('toggle-frame-norm'), toggleDebugOverlay = document.getElementById('toggle-debug-overlay'), egoSpeedDisplay = document.getElementById('ego-speed-display'), canSpeedDisplay = document.getElementById('can-speed-display'), debugOverlay = document.getElementById('debug-overlay'), snrMinInput = document.getElementById('snr-min-input'), snrMaxInput = document.getElementById('snr-max-input'), applySnrBtn = document.getElementById('apply-snr-btn'), autoOffsetIndicator = document.getElementById('auto-offset-indicator'), clearCacheBtn = document.getElementById('clear-cache-btn'), speedGraphContainer = document.getElementById('speed-graph-container'), speedGraphPlaceholder = document.getElementById('speed-graph-placeholder'), modalContainer = document.getElementById('modal-container'), modalOverlay = document.getElementById('modal-overlay'), modalContent = document.getElementById('modal-content'), modalText = document.getElementById('modal-text'), modalOkBtn = document.getElementById('modal-ok-btn'), modalCancelBtn = document.getElementById('modal-cancel-btn');
const toggleCloseUp = document.getElementById('toggle-close-up');
let modalResolve = null;
// import DOM elements and UI updaters from './src/dom.js';
import {
//---DOM Elements---//
canvasContainer, canvasPlaceholder, videoPlayer, videoPlaceholder,
loadJsonBtn, loadVideoBtn, loadCanBtn, jsonFileInput, videoFileInput,
canFileInput, playPauseBtn, stopBtn, timelineSlider, frameCounter,
offsetInput, speedSlider, speedDisplay, featureToggles, toggleSnrColor,
toggleClusterColor, toggleInlierColor, toggleStationaryColor, toggleVelocity,
toggleTracks, toggleEgoSpeed, toggleFrameNorm, toggleDebugOverlay, egoSpeedDisplay,
canSpeedDisplay, debugOverlay, snrMinInput, snrMaxInput, applySnrBtn, autoOffsetIndicator,
clearCacheBtn, speedGraphContainer, speedGraphPlaceholder, modalContainer, modalOverlay,
modalContent, modalText, modalOkBtn, modalCancelBtn, toggleCloseUp,
//---UI Updaters---//
updateFrame, resetVisualization, updateCanDisplay, updateDebugOverlay
} from './src/dom.js';
// --- DARK MODE: Step 3 - Add the JavaScript Logic ---
const themeToggleBtn = document.getElementById('theme-toggle');
@ -340,10 +347,32 @@
}
});
// --- Custom Modal Logic ---
function showModal(message, isConfirm = false) { return new Promise(resolve => { modalText.textContent = message; modalCancelBtn.classList.toggle('hidden', !isConfirm); modalContainer.classList.remove('hidden'); setTimeout(() => { modalOverlay.classList.remove('opacity-0'); modalContent.classList.remove('scale-95'); }, 10); modalResolve = resolve; }); }
function hideModal(value) { modalOverlay.classList.add('opacity-0'); modalContent.classList.add('scale-95'); setTimeout(() => { modalContainer.classList.add('hidden'); if (modalResolve) modalResolve(value); }, 200); }
modalOkBtn.addEventListener('click', () => hideModal(true)); modalCancelBtn.addEventListener('click', () => hideModal(false)); modalOverlay.addEventListener('click', () => hideModal(false));
// --- Custom Modal Logic --- //
let modalResolve = null;
function showModal(message, isConfirm = false) {
return new Promise(resolve => {
modalText.textContent = message;
modalCancelBtn.classList.toggle('hidden', !isConfirm);
modalContainer.classList.remove('hidden');
setTimeout(() => {
modalOverlay.classList.remove('opacity-0');
modalContent.classList.remove('scale-95');
}
, 10);
modalResolve = resolve;
});
}
function hideModal(value) {
modalOverlay.classList.add('opacity-0');
modalContent.classList.add('scale-95');
setTimeout(() => {
modalContainer.classList.add('hidden');
if (modalResolve) modalResolve(value);
}, 200);
}
modalOkBtn.addEventListener('click', () => hideModal(true));
modalCancelBtn.addEventListener('click', () => hideModal(false));
modalOverlay.addEventListener('click', () => hideModal(false));
// --- IndexedDB for Caching ---
let db; function initDB(callback) { const request = indexedDB.open('visualizerDB', 1); request.onupgradeneeded = function (event) { const db = event.target.result; if (!db.objectStoreNames.contains('files')) { db.createObjectStore('files'); } }; request.onsuccess = function (event) { db = event.target.result; console.log("Database initialized"); if (callback) callback(); }; request.onerror = function (event) { console.error("IndexedDB error:", event.target.errorCode); }; }
@ -915,73 +944,6 @@
requestAnimationFrame(animationLoop);
}
function updateFrame(frame, forceVideoSeek) {
if (!appState.vizData || frame < 0 || frame >= appState.vizData.radarFrames.length) return;
appState.currentFrame = frame;
timelineSlider.value = appState.currentFrame;
frameCounter.textContent = `Frame: ${appState.currentFrame + 1} / ${appState.vizData.radarFrames.length}`;
const frameData = appState.vizData.radarFrames[appState.currentFrame];
if (toggleEgoSpeed.checked && frameData) {
const egoVy_kmh = (frameData.egoVelocity[1] * 3.6).toFixed(1);
egoSpeedDisplay.textContent = `Ego: ${egoVy_kmh} km/h`;
egoSpeedDisplay.classList.remove('hidden');
} else {
egoSpeedDisplay.classList.add('hidden');
}
if (forceVideoSeek && videoPlayer.src && videoPlayer.readyState > 1 && appState.videoStartDate && frameData) {
const offsetMs = parseFloat(offsetInput.value) || 0;
const targetRadarTimeMs = frameData.timestampMs;
const targetVideoTimeSec = (targetRadarTimeMs - offsetMs) / 1000;
if (targetVideoTimeSec >= 0 && targetVideoTimeSec <= videoPlayer.duration) {
if (Math.abs(videoPlayer.currentTime - targetVideoTimeSec) > 0.05) {
videoPlayer.currentTime = targetVideoTimeSec;
}
}
}
if (!appState.isPlaying) {
updateCanDisplay(videoPlayer.currentTime);
updateDebugOverlay(videoPlayer.currentTime);
}
if (appState.p5_instance) appState.p5_instance.redraw();
if (appState.speedGraphInstance && !appState.isPlaying) appState.speedGraphInstance.redraw();
}
function resetVisualization() { appState.isPlaying = false; playPauseBtn.textContent = 'Play'; const numFrames = appState.vizData.radarFrames.length; timelineSlider.max = numFrames > 0 ? numFrames - 1 : 0; updateFrame(0, true); }
function updateCanDisplay(currentMediaTime) { if (appState.canData.length > 0 && videoPlayer.src && appState.videoStartDate) { const videoAbsoluteTimeMs = appState.videoStartDate.getTime() + (currentMediaTime * 1000); const canIndex = findLastCanIndexBefore(videoAbsoluteTimeMs, appState.canData); if (canIndex !== -1) { const currentCanMessage = appState.canData[canIndex]; canSpeedDisplay.textContent = `CAN: ${currentCanMessage.speed} km/h`; canSpeedDisplay.classList.remove('hidden'); } else { canSpeedDisplay.classList.add('hidden'); } } else { canSpeedDisplay.classList.add('hidden'); } }
function updateDebugOverlay(currentMediaTime) {
if (!toggleDebugOverlay.checked) {
debugOverlay.classList.add('hidden');
return;
} debugOverlay.classList.remove('hidden');
let content = [];
if (appState.videoStartDate) {
const videoAbsoluteTimeMs = appState.videoStartDate.getTime() + (currentMediaTime * 1000);
content.push(`Media Time (s): ${currentMediaTime.toFixed(3)}`);
const videoFrame = Math.floor(currentMediaTime * VIDEO_FPS);
content.push(`Video Frame: ${videoFrame}`);
content.push(`Vid Abs Time: ${new Date(videoAbsoluteTimeMs).toISOString().split('T')[1].replace('Z', '')}`);
if (appState.canData.length > 0) {
const canIndex = findLastCanIndexBefore(videoAbsoluteTimeMs, appState.canData);
if (canIndex !== -1) {
const currentCanMessage = appState.canData[canIndex];
content.push(`CAN Abs Time: ${new Date(currentCanMessage.time).toISOString().split('T')[1].replace('Z', '')}`);
content.push(`CAN Speed: ${currentCanMessage.speed} km/h`);
}
else {
content.push('CAN: No data for time');
}
}
}
else {
content.push('Video not loaded...');
} if (appState.vizData) {
content.push(`Radar Frame: ${appState.currentFrame + 1}`);
if (appState.vizData.radarFrames[appState.currentFrame])
content.push(`Radar Abs Time: ${new Date(appState.vizData.radarFrames[appState.currentFrame].timestampMs).toISOString().split('T')[1].replace('Z', '')}`);
} debugOverlay.innerHTML = content.join('<br>');
}
document.addEventListener('DOMContentLoaded', () => {
console.log("DEBUG: DOMContentLoaded fired. Starting session load.");

158
steps/src/dom.js

@ -0,0 +1,158 @@
import { appState } from './state.js';
import { findLastCanIndexBefore } from './utils.js';
import { VIDEO_FPS } from './constants.js';
// --- DOM Element References --- //
export const canvasContainer = document.getElementById('canvas-container');
export const canvasPlaceholder = document.getElementById('canvas-placeholder');
export const videoPlayer = document.getElementById('video-player');
export const videoPlaceholder = document.getElementById('video-placeholder');
export const loadJsonBtn = document.getElementById('load-json-btn');
export const loadVideoBtn = document.getElementById('load-video-btn');
export const loadCanBtn = document.getElementById('load-can-btn');
export const jsonFileInput = document.getElementById('json-file-input');
export const videoFileInput = document.getElementById('video-file-input');
export const canFileInput = document.getElementById('can-file-input');
export const playPauseBtn = document.getElementById('play-pause-btn');
export const stopBtn = document.getElementById('stop-btn');
export const timelineSlider = document.getElementById('timeline-slider');
export const frameCounter = document.getElementById('frame-counter');
export const offsetInput = document.getElementById('offset-input');
export const speedSlider = document.getElementById('speed-slider');
export const speedDisplay = document.getElementById('speed-display');
export const featureToggles = document.getElementById('feature-toggles');
export const toggleSnrColor = document.getElementById('toggle-snr-color');
export const toggleClusterColor = document.getElementById('toggle-cluster-color');
export const toggleInlierColor = document.getElementById('toggle-inlier-color');
export const toggleStationaryColor = document.getElementById('toggle-stationary-color');
export const toggleVelocity = document.getElementById('toggle-velocity');
export const toggleTracks = document.getElementById('toggle-tracks');
export const toggleEgoSpeed = document.getElementById('toggle-ego-speed');
export const toggleFrameNorm = document.getElementById('toggle-frame-norm');
export const toggleDebugOverlay = document.getElementById('toggle-debug-overlay');
export const egoSpeedDisplay = document.getElementById('ego-speed-display');
export const canSpeedDisplay = document.getElementById('can-speed-display');
export const debugOverlay = document.getElementById('debug-overlay');
export const snrMinInput = document.getElementById('snr-min-input');
export const snrMaxInput = document.getElementById('snr-max-input');
export const applySnrBtn = document.getElementById('apply-snr-btn');
export const autoOffsetIndicator = document.getElementById('auto-offset-indicator');
export const clearCacheBtn = document.getElementById('clear-cache-btn');
export const speedGraphContainer = document.getElementById('speed-graph-container');
export const speedGraphPlaceholder = document.getElementById('speed-graph-placeholder');
export const modalContainer = document.getElementById('modal-container');
export const modalOverlay = document.getElementById('modal-overlay');
export const modalContent = document.getElementById('modal-content');
export const modalText = document.getElementById('modal-text');
export const modalOkBtn = document.getElementById('modal-ok-btn');
export const modalCancelBtn = document.getElementById('modal-cancel-btn');
export const toggleCloseUp = document.getElementById('toggle-close-up');
//----------------------UPDATE FRAME Function----------------------//
export function updateFrame(frame, forceVideoSeek) {
if (!appState.vizData || frame < 0 || frame >= appState.vizData.radarFrames.length) return;
appState.currentFrame = frame;
timelineSlider.value = appState.currentFrame;
frameCounter.textContent = `Frame: ${appState.currentFrame + 1} / ${appState.vizData.radarFrames.length}`;
const frameData = appState.vizData.radarFrames[appState.currentFrame];
if (toggleEgoSpeed.checked && frameData) {
const egoVy_kmh = (frameData.egoVelocity[1] * 3.6).toFixed(1);
egoSpeedDisplay.textContent = `Ego: ${egoVy_kmh} km/h`;
egoSpeedDisplay.classList.remove('hidden');
} else {
egoSpeedDisplay.classList.add('hidden');
}
if (forceVideoSeek && videoPlayer.src && videoPlayer.readyState > 1 && appState.videoStartDate && frameData) {
const offsetMs = parseFloat(offsetInput.value) || 0;
const targetRadarTimeMs = frameData.timestampMs;
const targetVideoTimeSec = (targetRadarTimeMs - offsetMs) / 1000;
if (targetVideoTimeSec >= 0 && targetVideoTimeSec <= videoPlayer.duration) {
if (Math.abs(videoPlayer.currentTime - targetVideoTimeSec) > 0.05) {
videoPlayer.currentTime = targetVideoTimeSec;
}
}
}
if (!appState.isPlaying) {
updateCanDisplay(videoPlayer.currentTime);
updateDebugOverlay(videoPlayer.currentTime);
}
if (appState.p5_instance) appState.p5_instance.redraw();
if (appState.speedGraphInstance && !appState.isPlaying) appState.speedGraphInstance.redraw();
}
//----------------------RESET VISUALIZATION Function----------------------//
export function resetVisualization() {
appState.isPlaying = false;
playPauseBtn.textContent = 'Play';
const numFrames = appState.vizData.radarFrames.length;
timelineSlider.max = numFrames > 0 ? numFrames - 1 : 0;
updateFrame(0, true);
}
//----------------------CAN DISPLAY UPDATE Function----------------------//
export function updateCanDisplay(currentMediaTime) {
if (appState.canData.length > 0 && videoPlayer.src && appState.videoStartDate) {
const videoAbsoluteTimeMs = appState.videoStartDate.getTime() + (currentMediaTime * 1000);
const canIndex = findLastCanIndexBefore(videoAbsoluteTimeMs, appState.canData);
if (canIndex !== -1) {
const currentCanMessage = appState.canData[canIndex];
canSpeedDisplay.textContent = `CAN: ${currentCanMessage.speed} km/h`;
canSpeedDisplay.classList.remove('hidden');
}
else {
canSpeedDisplay.classList.add('hidden');
}
}
else {
canSpeedDisplay.classList.add('hidden');
}
}
//----------------------DEBUG OVERLAY UPDATE Function----------------------//
export function updateDebugOverlay(currentMediaTime) {
if (!toggleDebugOverlay.checked) {
debugOverlay.classList.add('hidden');
return;
} debugOverlay.classList.remove('hidden');
let content = [];
if (appState.videoStartDate) {
const videoAbsoluteTimeMs = appState.videoStartDate.getTime() + (currentMediaTime * 1000);
content.push(`Media Time (s): ${currentMediaTime.toFixed(3)}`);
const videoFrame = Math.floor(currentMediaTime * VIDEO_FPS);
content.push(`Video Frame: ${videoFrame}`);
content.push(`Vid Abs Time: ${new Date(videoAbsoluteTimeMs).toISOString().split('T')[1].replace('Z', '')}`);
if (appState.canData.length > 0) {
const canIndex = findLastCanIndexBefore(videoAbsoluteTimeMs, appState.canData);
if (canIndex !== -1) {
const currentCanMessage = appState.canData[canIndex];
content.push(`CAN Abs Time: ${new Date(currentCanMessage.time).toISOString().split('T')[1].replace('Z', '')}`);
content.push(`CAN Speed: ${currentCanMessage.speed} km/h`);
}
else {
content.push('CAN: No data for time');
}
}
}
else {
content.push('Video not loaded...');
} if (appState.vizData) {
content.push(`Radar Frame: ${appState.currentFrame + 1}`);
if (appState.vizData.radarFrames[appState.currentFrame])
content.push(`Radar Abs Time: ${new Date(appState.vizData.radarFrames[appState.currentFrame].timestampMs).toISOString().split('T')[1].replace('Z', '')}`);
} debugOverlay.innerHTML = content.join('<br>');
}
Loading…
Cancel
Save