diff --git a/public/js/text.js b/public/js/text.js index 9dab122..aca2210 100644 --- a/public/js/text.js +++ b/public/js/text.js @@ -1,4 +1,4 @@ -const expandedNodeIds = new Set(); +const expandedChildByParent = new Map(); let activeNodeId = null; document.addEventListener('DOMContentLoaded', () => { @@ -102,7 +102,10 @@ function renderTree(nodes, textId, depth = 0) { const addBtn = document.createElement('button'); addBtn.textContent = 'Add child'; addBtn.className = 'add-child'; - addBtn.addEventListener('click', () => toggleAddForm(li, node.id, textId)); + addBtn.addEventListener( + 'click', + () => toggleAddForm(li, node.id, node.parentNodeId, textId) + ); li.appendChild(addBtn); const bulkBtn = document.createElement('button'); @@ -110,31 +113,32 @@ function renderTree(nodes, textId, depth = 0) { bulkBtn.className = 'bulk-add-children'; bulkBtn.addEventListener( 'click', - () => toggleBulkAddForm(li, node.id, textId) + () => toggleBulkAddForm(li, node.id, node.parentNodeId, textId) ); li.appendChild(bulkBtn); if (node.children.length > 0) { const childUl = renderTree(node.children, textId, depth + 1); const childrenVisible = - expandedNodeIds.has(node.id) || depth === 0; - if (childrenVisible) { - expandedNodeIds.add(node.id); - } + depth === 0 || + expandedChildByParent.get(node.parentNodeId) === node.id; childUl.style.display = childrenVisible ? '' : 'none'; const toggleBtn = document.createElement('button'); toggleBtn.className = 'toggle-children'; toggleBtn.textContent = childrenVisible ? '▼' : '▶'; toggleBtn.addEventListener('click', () => { - const isHidden = childUl.style.display === 'none'; - childUl.style.display = isHidden ? '' : 'none'; - toggleBtn.textContent = isHidden ? '▼' : '▶'; - if (isHidden) { - expandedNodeIds.add(node.id); - } else { - expandedNodeIds.delete(node.id); + if (depth === 0) { + return; } + const expandedSibling = + expandedChildByParent.get(node.parentNodeId); + if (expandedSibling === node.id) { + expandedChildByParent.delete(node.parentNodeId); + } else { + expandedChildByParent.set(node.parentNodeId, node.id); + } + fetchAndRenderNodes(textId); }); li.appendChild(toggleBtn); @@ -161,7 +165,7 @@ function closeAllAddForms() { }); } -function toggleAddForm(li, parentNodeId, textId) { +function toggleAddForm(li, parentNodeId, grandparentId, textId) { const existing = li.querySelector('input.child-title'); if (existing) { existing.remove(); @@ -184,7 +188,7 @@ function toggleAddForm(li, parentNodeId, textId) { const title = input.value.trim(); if (!title) return; - expandedNodeIds.add(parentNodeId); + expandedChildByParent.set(grandparentId, parentNodeId); fetch('/api/nodes', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -211,7 +215,7 @@ function toggleAddForm(li, parentNodeId, textId) { input.focus(); } -function toggleBulkAddForm(li, parentNodeId, textId) { +function toggleBulkAddForm(li, parentNodeId, grandparentId, textId) { const existing = li.querySelector('input.bulk-title'); if (existing) { existing.remove(); @@ -242,7 +246,7 @@ function toggleBulkAddForm(li, parentNodeId, textId) { const count = parseInt(countInput.value); if (!titlePrefix || !count || count < 1) return; - expandedNodeIds.add(parentNodeId); + expandedChildByParent.set(grandparentId, parentNodeId); fetch('/api/nodes/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json' },