104 lines
3.1 KiB
JavaScript
104 lines
3.1 KiB
JavaScript
(function () {
|
|
function escapeHtml(str) {
|
|
return String(str)
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
function chunk(arr, size) {
|
|
var out = [];
|
|
for (var i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
|
|
return out;
|
|
}
|
|
|
|
function renderLinksTable(links, columns) {
|
|
columns = columns || 3;
|
|
links = Array.isArray(links) ? links : [];
|
|
|
|
var rows = chunk(links, columns);
|
|
if (rows.length) {
|
|
var last = rows[rows.length - 1];
|
|
while (last.length < columns) last.push(null);
|
|
}
|
|
|
|
var html = "<table>";
|
|
for (var r = 0; r < rows.length; r++) {
|
|
html += "<tr>";
|
|
for (var c = 0; c < columns; c++) {
|
|
var item = rows[r][c];
|
|
if (!item) {
|
|
html += "<td></td>";
|
|
continue;
|
|
}
|
|
|
|
var href = escapeHtml(item.href || "#");
|
|
var label = escapeHtml(item.label || "");
|
|
var img = escapeHtml(item.image || "");
|
|
var alt = escapeHtml(item.alt || item.label || "");
|
|
|
|
html +=
|
|
'<td>' +
|
|
'<a href="' + href + '">' +
|
|
'<img alt="' + alt + '" src="' + img + '">' +
|
|
"<p><b>" + label + "</b></p>" +
|
|
"</a>" +
|
|
"</td>";
|
|
}
|
|
html += "</tr>";
|
|
}
|
|
html += "</table>";
|
|
return html;
|
|
}
|
|
|
|
function renderAllSections(containerId, sectionsObj) {
|
|
var container = document.getElementById(containerId);
|
|
if (!container) return;
|
|
|
|
sectionsObj = sectionsObj || {};
|
|
var keys = Object.keys(sectionsObj);
|
|
|
|
// If you want a custom order, add an "order" number in links.js and sort here.
|
|
// Default: object insertion order.
|
|
var html = "";
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
var section = sectionsObj[key];
|
|
|
|
// support BOTH formats:
|
|
// 1) new format: { title, links: [...] }
|
|
// 2) old format: key: [ ...links... ]
|
|
var title, links;
|
|
if (Array.isArray(section)) {
|
|
title = key; // fallback title
|
|
links = section;
|
|
} else {
|
|
title = section && section.title ? section.title : key;
|
|
links = section && Array.isArray(section.links) ? section.links : [];
|
|
}
|
|
|
|
// Skip empty sections (optional)
|
|
if (!links.length) continue;
|
|
|
|
html += "<h4>" + escapeHtml(title) + "</h4>";
|
|
html += renderLinksTable(links, 3);
|
|
|
|
// divider between sections
|
|
if (i !== keys.length - 1) html += "<hr>";
|
|
}
|
|
|
|
container.innerHTML = html || "<p>No sections defined.</p>";
|
|
}
|
|
|
|
window.addEventListener("DOMContentLoaded", function () {
|
|
// focus search input
|
|
var q = document.getElementById("q");
|
|
if (q) q.focus();
|
|
|
|
renderAllSections("sections", window.LAUNCHPAD_LINKS);
|
|
});
|
|
})();
|
|
|