Some checks failed
Tests / test-java-8-war-generation (push) Failing after 8s
Tests / test-mvn-livecycle (11) (push) Failing after 6s
Tests / test-mvn-livecycle (17) (push) Failing after 6s
Tests / test-embedded (11) (push) Has been skipped
Tests / test-embedded (17) (push) Has been skipped
Tests / test-mvn-jetty-run (11) (push) Has been skipped
Tests / test-mvn-jetty-run (17) (push) Has been skipped
Tests / test-jetty (11) (push) Has been skipped
Tests / test-jetty (17) (push) Has been skipped
Tests / test-tomcat (11) (push) Has been skipped
Tests / test-tomcat (17) (push) Has been skipped
86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
(function() {
|
|
function isFolder(node) {
|
|
return Array.isArray(node.nodes) && node.nodes.length > 0;
|
|
}
|
|
|
|
function renderNode(node, expandedPaths, depth) {
|
|
const li = document.createElement("li");
|
|
li.dataset.id = node.id || "";
|
|
const row = document.createElement("div");
|
|
row.className = "row";
|
|
row.style.paddingLeft = `${(depth + 1) * 1.2}rem`;
|
|
|
|
const caret = document.createElement("span");
|
|
caret.className = "caret";
|
|
const folder = isFolder(node);
|
|
const expanded = expandedPaths.has(node.id) || depth === 0;
|
|
caret.textContent = folder ? (expanded ? "▾" : "▸") : "";
|
|
row.appendChild(caret);
|
|
|
|
const label = document.createElement("span");
|
|
label.className = "label " + (folder ? "icon-folder" : "icon-file");
|
|
label.textContent = node.text || node.id || "";
|
|
row.appendChild(label);
|
|
|
|
if (node.meta) {
|
|
const meta = document.createElement("span");
|
|
meta.className = "meta";
|
|
meta.textContent = node.meta;
|
|
row.appendChild(meta);
|
|
}
|
|
|
|
li.appendChild(row);
|
|
|
|
if (folder) {
|
|
const ul = document.createElement("ul");
|
|
ul.className = "btv";
|
|
ul.style.display = expanded ? "block" : "none";
|
|
node.nodes.forEach(child => {
|
|
ul.appendChild(renderNode(child, expandedPaths, depth + 1));
|
|
});
|
|
li.appendChild(ul);
|
|
}
|
|
return li;
|
|
}
|
|
|
|
function create(container, data, { expandedPaths = new Set(), onClick, onDblClick } = {}) {
|
|
if (!container) return;
|
|
container.innerHTML = "";
|
|
const ul = document.createElement("ul");
|
|
ul.className = "btv";
|
|
data.forEach(node => ul.appendChild(renderNode(node, expandedPaths, 0)));
|
|
|
|
ul.addEventListener("click", evt => {
|
|
const row = evt.target.closest(".row");
|
|
const li = evt.target.closest("li");
|
|
if (!li) return;
|
|
const sub = li.querySelector(":scope > ul");
|
|
if (sub) {
|
|
const caret = row?.querySelector(".caret") || li.querySelector(":scope > .row .caret");
|
|
const hidden = sub.style.display === "none";
|
|
sub.style.display = hidden ? "block" : "none";
|
|
if (caret) caret.textContent = hidden ? "▾" : "▸";
|
|
if (hidden) {
|
|
expandedPaths.add(li.dataset.id);
|
|
} else {
|
|
expandedPaths.delete(li.dataset.id);
|
|
}
|
|
}
|
|
onClick?.(li.dataset.id || "");
|
|
});
|
|
|
|
ul.addEventListener("dblclick", evt => {
|
|
const li = evt.target.closest("li");
|
|
if (!li) return;
|
|
const sub = li.querySelector(":scope > ul");
|
|
if (!sub) {
|
|
onDblClick?.(li.dataset.id || "");
|
|
}
|
|
});
|
|
|
|
container.appendChild(ul);
|
|
}
|
|
|
|
window.BootstrapTreeView = { create };
|
|
})();
|