diff --git a/public/javascript/JSON.js b/public/javascript/JSON.js index f78b59f..108ecd6 100644 --- a/public/javascript/JSON.js +++ b/public/javascript/JSON.js @@ -2,14 +2,17 @@ createJsonTree({ container: domElement, data: jsonData, + expandInitially = true // optional: expand all nodes onChange: (data) => { }, // optional: callback on change onSave: (data) => { } // optional: if set, a save button will be added }); -*/function createJsonTree({ +*/ +function createJsonTree({ container, data, onChange = () => {}, - onSave = null + onSave = null, + expandInitially = true }) { container.innerHTML = ""; container.classList.add("json-tree-root"); @@ -19,6 +22,8 @@ createJsonTree({ let lastSnapshot = clone(data); + const expandedPaths = new Set(); + function clone(obj) { return JSON.parse(JSON.stringify(obj)); } @@ -104,34 +109,53 @@ createJsonTree({ render(); } + function collectPaths(obj, path = "root") { + if (typeof obj !== "object" || obj === null) return; + + expandedPaths.add(path); + + const entries = Array.isArray(obj) + ? obj.map((v, i) => [i, v]) + : Object.entries(obj); + + for (const [k, v] of entries) { + collectPaths(v, `${path}.${k}`); + } + } + + if (expandInitially) { + collectPaths(data); + } + function render() { container.innerHTML = ""; - const controls = document.createElement("div"); - controls.className = "json-controls"; - - const undoBtn = document.createElement("button"); - undoBtn.className = "monolyth"; - undoBtn.textContent = "Undo"; - undoBtn.onclick = undo; - - const redoBtn = document.createElement("button"); - redoBtn.className = "monolyth"; - redoBtn.textContent = "Redo"; - redoBtn.onclick = redo; - - controls.appendChild(undoBtn); - controls.appendChild(redoBtn); - if (onSave) { + const controls = document.createElement("div"); + controls.className = "json-controls"; + + const undoBtn = document.createElement("button"); + undoBtn.className = "monolyth"; + undoBtn.textContent = "Undo"; + undoBtn.onclick = undo; + + const redoBtn = document.createElement("button"); + redoBtn.className = "monolyth"; + redoBtn.textContent = "Redo"; + redoBtn.onclick = redo; + const saveBtn = document.createElement("button"); saveBtn.className = "monolyth"; saveBtn.textContent = "Save"; saveBtn.onclick = save; + + controls.appendChild(undoBtn); + controls.appendChild(redoBtn); controls.appendChild(saveBtn); + + container.appendChild(controls); } - container.appendChild(controls); container.appendChild(renderNode(data, null, null, "root", 0)); } @@ -177,10 +201,24 @@ createJsonTree({ const children = document.createElement("div"); children.className = "json-children"; - keyLabel.onclick = toggle.onclick = () => { - children.classList.toggle("collapsed"); + const toggleState = () => { + if (expandedPaths.has(path)) { + expandedPaths.delete(path); + children.classList.add("collapsed"); + } else { + expandedPaths.add(path); + children.classList.remove("collapsed"); + } }; + keyLabel.onclick = toggle.onclick = toggleState; + + if (expandedPaths.has(path)) { + children.classList.remove("collapsed"); + } else { + children.classList.add("collapsed"); + } + addBtn.onclick = () => { let newKey = ""; let newValue; @@ -210,7 +248,6 @@ createJsonTree({ if (!isArray) { const input = document.querySelector('#newJsonKeyName'); newKey = input?.value?.trim(); - if (!newKey) return; } @@ -331,6 +368,7 @@ createJsonTree({ wrapper.appendChild(keySpan); wrapper.appendChild(span); + if (key !== null) wrapper.appendChild(removeBtn); return wrapper; diff --git a/public/styles/os.css b/public/styles/os.css index ba3f2e3..f3b5f7c 100644 --- a/public/styles/os.css +++ b/public/styles/os.css @@ -14,16 +14,19 @@ body, html { margin:0; padding:0; height:100%; overflow: hidden; font-family: va .window-content { display: flex; flex-direction: column; flex:1; padding:8px; overflow: auto; } .window[class="max"] .window-resize-handle { display: none; } -.window-resize-n, .window-resize-s { position: absolute; left: 8px; right: 8px; height: 8px; z-index: 10; } +.window-resize-s { position: absolute; left: 8px; right: 8px; height: 8px; z-index: 10; } +.window-resize-n { position: absolute; left: 8px; right: 16px; height: 8px; z-index: 10; } .window-resize-n { top: -4px;cursor: var(--theme-cursor-resize-vertical); } .window-resize-s { bottom: -4px;cursor: var(--theme-cursor-resize-vertical); } -.window-resize-e, .window-resize-w { position: absolute;top: 8px;bottom: 8px;width: 8px;z-index: 10; } +.window-resize-w { position: absolute;top: 8px;bottom: 8px;width: 8px;z-index: 10; } +.window-resize-e { position: absolute;top: 16px;bottom: 8px;width: 8px;z-index: 10; } .window-resize-e { right: -4px;cursor: var(--theme-cursor-resize-horizontal); } .window-resize-w { left: -4px;cursor: var(--theme-cursor-resize-horizontal); } -.window-resize-ne, .window-resize-nw, .window-resize-se, .window-resize-sw { position: absolute;width: 16px;height: 16px;z-index: 11; } -.window-resize-ne { top: -6px;right: -6px;cursor: var(--theme-cursor-resize-45); } +.window-resize-nw, .window-resize-se, .window-resize-sw { position: absolute;width: 16px;height: 16px;z-index: 11; } +.window-resize-ne { position: absolute;width: 8px;height: 8x;z-index: 11; } +.window-resize-ne { top: -3px;right: -3px;cursor: var(--theme-cursor-resize-45); } .window-resize-nw { top: -6px;left: -6px;cursor: var(--theme-cursor-resize-270); } .window-resize-se { bottom: -6px;right: -6px;cursor: var(--theme-cursor-resize-270); } .window-resize-sw { bottom: -6px;left: -6px;cursor: var(--theme-cursor-resize-45); } diff --git a/public/styles/table.css b/public/styles/table.css index 54090b4..d4c76b7 100644 --- a/public/styles/table.css +++ b/public/styles/table.css @@ -17,7 +17,7 @@ table.border * { border:1px solid white; } /* #region performance optimizing */ -table thead { position:sticky; top:0; z-index:20; will-change:transform; transform:translateZ(0);} +table thead { position:sticky; top:0; z-index:20; } /* #endregion */ diff --git a/public/views/integrated/serverinfo.hbs b/public/views/integrated/serverinfo.hbs index 4e32335..32d0b59 100644 --- a/public/views/integrated/serverinfo.hbs +++ b/public/views/integrated/serverinfo.hbs @@ -8,8 +8,8 @@ -