x0/x0.js

90 lines
2.5 KiB
JavaScript
Raw Normal View History

2023-12-24 00:32:43 +01:00
/** x0
* Lazy web pages.
*
* [x0-mods] - modules to load
* [x0-module-root] - set module src root
*/
if (window['x0']) {
throw new Error("window.x0 already declared.", window.x0);
}
class x0 {
#rootElement;
#cfg = {
moduleSource: "./x0/modules/",
modules: [],
init: true
}
#hooks = {
moduleRemove: {}
}
#moduleStorage = {};
constructor(rootElement = document.querySelector("html")) {
this.#rootElement = rootElement;
this.#updateConfig();
if (this.#cfg.init)
this.#updateScriptElements();
}
#getAttribute(name, level) {
return this.#rootElement.getAttribute(`x${level ?? ''}-${name}`)
}
#updateConfig() {
this.#cfg.moduleSource = this.#getAttribute("module-root", 0) ?? this.#cfg.moduleSource;
this.#cfg.modules = this.#getAttribute("mods", 0)?.split(",") ?? this.#cfg.modules;
this.#cfg.init = (this.#getAttribute("init", 0) ?? "true") == "true"
}
#updateScriptElements() {
this.#cfg.modules
.forEach(m => {
if (this.#rootElement.querySelector(`[x0-m="${m}"]`)) return;
let script = document.createElement("script");
script.src = this.#cfg.moduleSource + m + ".js";
script.setAttribute("x0-m", m);
this.#rootElement.appendChild(script);
})
this.#rootElement
.querySelectorAll("[x0-m]")
.forEach(e => {
if (!this.#cfg.modules.includes(e.getAttribute("x0-m"))) {
this.#removeModule(e.getAttribute("x0-m"));
e.remove();
}
})
}
#removeModule(module) {
if (this.#hooks.moduleRemove[module])
this.#hooks.moduleRemove[module](this.#moduleStorage[module] ?? {}); // run module remove hook
if (this.#moduleStorage[module])
this.#moduleStorage[module] = undefined;
}
registerModuleRemoveHook(module, callback) {
if (this.#hooks.moduleRemove[module]) return null;
this.#hooks.moduleRemove[module] = callback;
}
/** registerStorage
* Register a storage.
* This can only happen once per module.
*/
registerStorage(module) {
if (this.#moduleStorage[module]) return null;
this.#moduleStorage[module] = {};
return this.#moduleStorage[module];
}
update() {
this.#updateConfig();
this.#updateScriptElements();
}
}
window.x0 = new x0();