kcalculator/jst.js

76 lines
2.3 KiB
JavaScript
Raw Permalink Normal View History

2022-09-08 22:55:43 +02:00
const JST = {
_cachedTemplates: {},
_fetchTemplate: (name) => {
if (JST._cachedTemplates[name] !== undefined) {
return new Promise(resolve => resolve(JST._cachedTemplates[name]));
}
return fetch(`/templates/${name}.html`).then(resp => resp.text()).then(resp => {
const div = document.createElement("div");
div.innerHTML = resp;
const template = div.querySelector("template");
JST._cachedTemplates[name] = template;
return template;
});
},
// load returns a Promise for the template node
load: (templateName, visitedTemplates) => {
visitedTemplates = visitedTemplates ?? [];
const visited = visitedTemplates.includes(templateName);
visitedTemplates.push(templateName);
if (visited) {
const errorMsg = document.createElement("span");
errorMsg.textContent = `recursive templates: ${visitedTemplates.join(" → ")}`;
errorMsg.style.color = "red";
return new Promise(resolve => resolve(errorMsg));
}
return JST._fetchTemplate(templateName).then(template => {
const c = template.content.cloneNode(true);
JST.init(c, visitedTemplates);
return c;
});
},
// replaceElement replaces the given element with the template node
replaceElement: async (templateName, element) => {
await JST._replaceElement(templateName, element, []);
},
_replaceElement: async (templateName, element, visitedTemplates) => {
element.textContent = "";
await JST.load(templateName, visitedTemplates).then(node => element.replaceWith(node))
},
// replaceChildren removes all children in element and adds the template node
replaceChildren: async (templateName, element) => {
element = element ?? document.querySelector("main");
const node = await JST.load(templateName);
while (element.hasChildNodes()) {
element.removeChild(element.firstChild);
}
element.appendChild(node);
},
// append appends the template node to elements childrens
append: async (templateName, element) => {
element = element ?? document.querySelector("main");
const node = await JST.load(templateName);
element.appendChild(node);
},
init: (element, visitedTemplates) => {
element = element ?? document;
visitedTemplates = visitedTemplates ?? [];
element.querySelectorAll("jst-template").forEach(element => JST._replaceElement(element.textContent, element, visitedTemplates));
}
}
window.addEventListener("load", () => JST.init());