expand only one sibling at a time

This commit is contained in:
Yisroel Baum 2026-05-04 10:06:06 +03:00
parent 793b0149b8
commit 7e33103bc9
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9

View file

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