json-dropdown-tools
Version:
A tool to generate dropdown menus from JSON as HTML or JS modules
97 lines (82 loc) • 2.52 kB
JavaScript
// menu-tools.js
// -----------------------
// Utility to normalize IDs
// -----------------------
function normalizeId(label) {
return label
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^a-z0-9\-]/g, "");
}
// -----------------------
// HTML Generator
// -----------------------
function menuToHtml(obj) {
function build(node) {
if (node.type === "separator") {
return `<li class="separator"></li>`;
}
if (node.type === "item") {
const id = node.id || normalizeId(node.label);
let html = `<li id="${id}" data-action="${node.action || ""}">${node.label}`;
if (node.items) {
const submenu = build({ type: "menu", id: node.id, label: node.label, items: node.items });
html += submenu;
}
html += `</li>`;
return html;
}
if (node.type === "menu") {
const id = node.id || normalizeId(node.label);
const children = node.items.map(build).join("");
return `<ul id="${id}">${children}</ul>`;
}
throw new Error(`Unknown type: ${node.type}`);
}
return build(obj);
}
// -----------------------
// JS Module Generator
// -----------------------
function generateMenuJs(json) {
return `
export function renderMenu(container, actionHandler) {
const data = ${JSON.stringify(json, null, 2)};
function normalizeId(label) {
return label.toLowerCase().replace(/\\s+/g, "-").replace(/[^a-z0-9\\-]/g, "");
}
function build(obj) {
if (obj.type === "separator") {
const li = document.createElement("li");
li.className = "separator";
return li;
}
if (obj.type === "item") {
const li = document.createElement("li");
li.id = obj.id || normalizeId(obj.label);
li.textContent = obj.label;
if (obj.action) {
li.dataset.action = obj.action;
li.addEventListener("click", () => actionHandler(obj.action));
}
if (obj.items) {
const ul = build({ type: "menu", items: obj.items, id: obj.id, label: obj.label });
li.appendChild(ul);
}
return li;
}
if (obj.type === "menu") {
const ul = document.createElement("ul");
ul.id = obj.id || normalizeId(obj.label);
obj.items.forEach(child => ul.appendChild(build(child)));
return ul;
}
throw new Error(\`Unknown type: \${obj.type}\`);
}
container.appendChild(build(data));
}`;
}
// -----------------------
// Export the tools
// -----------------------
export { normalizeId, menuToHtml, generateMenuJs };