// === APPLICATION INIT === function parseHash() { const h = window.location.hash.replace(/^#\/?/, "").replace(/\/?$/, "").split("/").filter(Boolean); if (h[0] && ["hst","flg","itm","loc","ply"].includes(h[0].toLowerCase())) { state.base = h[0].toLowerCase(); } if (h[1] && ["grid","tree","graph"].includes(h[1].toLowerCase())) { state.view = h[1].toLowerCase(); } } function updateHash() { const p = [state.base]; if (state.view !== "grid") p.push(state.view); window.location.hash = "/" + p.join("/") + "/"; } async function init() { parseHash(); // Update UI to match state document.querySelectorAll(".base-btn").forEach(b => b.classList.toggle("active", b.dataset.base === state.base) ); document.querySelectorAll(".view-tab").forEach(t => t.classList.toggle("active", t.dataset.view === state.view) ); // Show loading document.getElementById("grid-view").innerHTML = '
Cargando
'; // Fetch initial data await Promise.all([fetchTags(), fetchGroups(), fetchLibraries()]); // Render UI renderGroups(); renderLibraries(); renderView(); } // === EVENT BINDINGS === document.addEventListener("DOMContentLoaded", () => { // Base selector document.querySelectorAll(".base-btn").forEach(b => b.onclick = async () => { document.querySelectorAll(".base-btn").forEach(x => x.classList.remove("active")); b.classList.add("active"); state.base = b.dataset.base; // Reset state state.group = "all"; state.library = "all"; state.libraryMembers.clear(); state.search = ""; state.graphEdges = []; state.treeEdges = []; clearSelection(); closeDetail(); document.getElementById("search").value = ""; updateHash(); // Reload document.getElementById("grid-view").innerHTML = '
Cargando
'; await fetchTags(); await fetchGroups(); renderGroups(); renderView(); }); // View tabs document.querySelectorAll(".view-tab").forEach(t => t.onclick = () => { document.querySelectorAll(".view-tab").forEach(x => x.classList.remove("active")); t.classList.add("active"); state.view = t.dataset.view; updateHash(); closeDetail(); renderView(); }); // Search let st; document.getElementById("search").oninput = e => { clearTimeout(st); st = setTimeout(() => { state.search = e.target.value; renderView(); }, 200); }; // Language selector document.getElementById("lang-select").addEventListener("change", function(e) { state.lang = this.value; renderView(); if (state.selectedTag) showDetail(state.selectedTag.mrf); }); // Selection mode document.getElementById("btn-sel").onclick = () => { state.selectionMode = !state.selectionMode; document.getElementById("btn-sel").classList.toggle("active", state.selectionMode); if (!state.selectionMode) { state.selected.clear(); updateSelCount(); } renderView(); }; // Get selected document.getElementById("btn-get").onclick = () => { if (!state.selected.size) return toast("No hay seleccionados"); navigator.clipboard.writeText([...state.selected].join("\n")) .then(() => toast(`Copiados ${state.selected.size} mrfs`)); }; // API modal document.getElementById("btn-api").onclick = () => document.getElementById("api-modal").classList.add("open"); document.getElementById("api-modal-close").onclick = () => document.getElementById("api-modal").classList.remove("open"); document.getElementById("api-modal").onclick = e => { if (e.target.id === "api-modal") e.target.classList.remove("open"); }; // Hash change window.onhashchange = () => { parseHash(); init(); }; // Keyboard shortcuts document.onkeydown = e => { if (e.key === "Escape") { closeDetail(); document.getElementById("api-modal").classList.remove("open"); if (state.selectionMode) { clearSelection(); renderView(); } } if (e.key === "/" && document.activeElement.tagName !== "INPUT") { e.preventDefault(); document.getElementById("search").focus(); } }; // Start app init(); });