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());