// events.js — wires up DOM listeners. Idempotent so app.js can call // init() once on load. (function () { 'use strict'; var state = window.app.state; var tree = window.app.modules.tree; var loader = window.app.modules.loader; function status(msg, kind) { var el = document.getElementById('statusBar'); if (!el) return; el.textContent = msg || ''; el.classList.remove('status-bar--error', 'status-bar--info'); if (kind === 'error') el.classList.add('status-bar--error'); if (kind === 'info') el.classList.add('status-bar--info'); } function statusError(msg) { status(msg, 'error'); } function statusInfo(msg) { status(msg, 'info'); } function statusClear() { status('', null); } async function pickLocalDir() { if (typeof window.showDirectoryPicker !== 'function') { statusError('Your browser does not support local folder selection. Use a recent Chromium-based browser, or open this page via zddc-server.'); return; } var handle; try { handle = await window.showDirectoryPicker({ mode: 'read' }); } catch (e) { // User cancelled — silent return; } state.source = 'fs'; state.rootHandle = handle; state.currentPath = handle.name + '/'; var raw; try { raw = await loader.fetchFsChildren(handle); } catch (e) { statusError('Failed to read directory: ' + e.message); return; } tree.setRoot(raw); showBrowseRoot(); document.getElementById('currentPath').textContent = state.currentPath; tree.render(); statusInfo('Loaded ' + raw.length + ' item' + (raw.length === 1 ? '' : 's')); } function showBrowseRoot() { var empty = document.getElementById('emptyState'); var root = document.getElementById('browseRoot'); if (empty) empty.classList.add('hidden'); if (root) root.classList.remove('hidden'); } function init() { // Header buttons var btn = document.getElementById('addDirectoryBtn'); if (btn) btn.addEventListener('click', pickLocalDir); // Filter input var filter = document.getElementById('filterInput'); if (filter) { filter.addEventListener('input', function () { tree.setFilter(filter.value); }); } // Sort headers var ths = document.querySelectorAll('#browseTable thead th.sortable'); for (var i = 0; i < ths.length; i++) { (function (th) { th.addEventListener('click', function () { tree.setSort(th.dataset.sort); }); })(ths[i]); } // Tree-row clicks (event delegation on tbody). var tbody = document.getElementById('browseTbody'); if (tbody) { tbody.addEventListener('click', function (e) { var row = e.target.closest('tr.tree-row'); if (!row) return; var isDir = row.dataset.isdir === 'true'; if (!isDir) { // Let the tag's natural target=_blank handle file // clicks. Don't intercept. return; } // Folder: toggle on chevron OR anywhere on the row except // the file link (no link in folder rows). e.preventDefault(); tree.toggleFolder(parseInt(row.dataset.id, 10)); }); } } // Public API window.app.modules.events = { init: init, statusError: statusError, statusInfo: statusInfo, statusClear: statusClear, showBrowseRoot: showBrowseRoot }; })();