174 lines
4.8 KiB
JavaScript
174 lines
4.8 KiB
JavaScript
const EVENT_MODULE_LOADED = "module-loaded";
|
|
|
|
class Startup {
|
|
constructor(modules) {
|
|
this.modules = modules;
|
|
this.cb = null;
|
|
this.isErrored = false;
|
|
this.isAllLoadedFired = false;
|
|
document.addEventListener(EVENT_MODULE_LOADED, this.allModulesLoaded.bind(this));
|
|
}
|
|
|
|
setCb(cb) {
|
|
this.cb = cb;
|
|
}
|
|
|
|
setErrCb(cb) {
|
|
this.errCb = cb;
|
|
}
|
|
|
|
finishModule(name) {
|
|
name = Startup.getName(name);
|
|
this.modules[name] = !0;
|
|
PrettyConsole.debug(name, "Module Loading Done");
|
|
document.dispatchEvent(new CustomEvent(EVENT_MODULE_LOADED, {detail: name}));
|
|
}
|
|
|
|
moduleErrored(name, error) {
|
|
name = Startup.getName(name);
|
|
if (this.errCb) {
|
|
this.errCb(name, error);
|
|
}
|
|
this.isErrored = true;
|
|
document.dispatchEvent(new CustomEvent(`module-errored`, {
|
|
data: {name, error}
|
|
}));
|
|
}
|
|
|
|
isModuleLoaded(names, cb) {
|
|
let self = this;
|
|
if (typeof names === 'string') {
|
|
names = [names];
|
|
}
|
|
let pendingModules = names.filter(function (module) {
|
|
return !self.modules[Startup.getName(module)]
|
|
});
|
|
if (pendingModules.length > 0) {
|
|
function listener() {
|
|
document.removeEventListener(EVENT_MODULE_LOADED, listener);
|
|
self.isModuleLoaded.bind(self)(pendingModules, cb);
|
|
}
|
|
|
|
document.addEventListener(EVENT_MODULE_LOADED, listener);
|
|
} else {
|
|
cb();
|
|
}
|
|
}
|
|
|
|
registerModule(name) {
|
|
this.modules[Startup.getName(name)] = false;
|
|
}
|
|
|
|
allModulesLoaded() {
|
|
if (this.isErrored) {
|
|
return false;
|
|
}
|
|
if (this.isAllLoadedFired) {
|
|
return true;
|
|
}
|
|
for (let module in this.modules) {
|
|
if (this.modules.hasOwnProperty(module) && !this.modules[module]) {
|
|
return false;
|
|
}
|
|
}
|
|
this.isAllLoadedFired = true;
|
|
if (this.cb) {
|
|
this.cb();
|
|
}
|
|
document.dispatchEvent(new CustomEvent('startupFin'));
|
|
return true;
|
|
}
|
|
|
|
ignite() {
|
|
document.dispatchEvent(new CustomEvent('ignite'));
|
|
}
|
|
|
|
registerInit(onInit) {
|
|
document.addEventListener('ignite', onInit);
|
|
}
|
|
|
|
loadOtherJsFiles(files) {
|
|
for (let file of files) {
|
|
this.registerModule(file[1]);
|
|
let script = document.createElement('script');
|
|
script.onload = () => {
|
|
moduleLoader.finishModule(file[1]);
|
|
}
|
|
script.onerror = (err) => {
|
|
moduleLoader.moduleErrored(file[1], err);
|
|
}
|
|
script.src = file[0];
|
|
document.body.appendChild(script);
|
|
}
|
|
}
|
|
|
|
static getName(name) {
|
|
if (typeof name === 'function') {
|
|
return name.name;
|
|
}
|
|
return name;
|
|
}
|
|
}
|
|
|
|
class Loader {
|
|
constructor() {
|
|
document.addEventListener(EVENT_MODULE_LOADED, this.loadProgress.bind(this));
|
|
document.addEventListener('startupFin', this.finish.bind(this));
|
|
this.loadingText = document.querySelector('v-loading-text');
|
|
this.loadingPerc = document.querySelector('v-loading-stats');
|
|
this.loadingScreen = document.querySelector('v-loading-screen');
|
|
this.loaded = 0;
|
|
this.toLoad = 0;
|
|
this.isErrored = false;
|
|
}
|
|
|
|
addToLoadItem(i) {
|
|
this.toLoad += i;
|
|
}
|
|
|
|
addLoadedItems(i) {
|
|
this.loaded += i;
|
|
this.loadProgress();
|
|
}
|
|
|
|
loadProgress() {
|
|
if (this.isErrored) return;
|
|
let loaded = 0,
|
|
keys = Object.keys(moduleLoader.modules);
|
|
for (let key of keys) {
|
|
if (moduleLoader.modules[key]) {
|
|
loaded++;
|
|
}
|
|
}
|
|
loaded += this.loaded;
|
|
let toLoad = keys.length + this.toLoad;
|
|
const perc = ((loaded / toLoad) * 100).toFixed(2) + "%";
|
|
this.loadingScreen.style.setProperty('--loading-scale', perc);
|
|
this.loadingPerc.innerText = `${loaded} / ${toLoad} (${perc})`;
|
|
}
|
|
|
|
onError(module, error) {
|
|
this.isErrored = true;
|
|
this.loadingText.innerText = "Errored";
|
|
this.loadingPerc.innerHTML = `Module ${module} failed to load<br>${error}`;
|
|
this.loadingScreen.style.setProperty('--loading-color', '#fa0000');
|
|
PrettyConsole.error("Startup", `Module ${module} failed to load`)
|
|
}
|
|
|
|
finish() {
|
|
document.removeEventListener('module-loaded-progress', this.loadProgress.bind(this));
|
|
}
|
|
}
|
|
|
|
const moduleLoader = new Startup({
|
|
'Startup': false,
|
|
});
|
|
const loader = new Loader();
|
|
moduleLoader.setErrCb(loader.onError.bind(loader));
|
|
const preLoader = new PreLoader();
|
|
moduleLoader.isModuleLoaded('PreLoader', () => {
|
|
moduleLoader.loadOtherJsFiles([
|
|
['/out/app/app.min.js', 'app.js'],
|
|
]);
|
|
});
|