Files
Wegwichtel/public/js/bootstrap-loader.js
T
Florian Zumpe bd13a479b1
Sonarqube Scanner / Build and analyze (push) Failing after 19s
fix test logic
2026-09-27 20:39:24 +02:00

210 lines
6.9 KiB
JavaScript

(function () {
'use strict';
const versions = Object.freeze({ app: '0.12.14', jquery: '4.0.0', jqueryUi: '1.14.2' });
const steps = ['storage', 'jquery', 'jquery-ui', 'modules', 'server', 'routes', 'location'];
const stepLabels = Object.freeze({
storage: 'Lokalen Speicher prüfen …',
jquery: 'jQuery laden …',
'jquery-ui': 'jQuery UI laden …',
modules: 'Anwendungsmodule laden …',
server: 'Server prüfen …',
routes: 'Routen laden …',
location: 'Standort ermitteln …'
});
const screen = document.getElementById('bootstrap-screen');
const progress = document.getElementById('bootstrap-progress');
const errorBox = document.getElementById('bootstrap-error');
const retry = document.getElementById('bootstrap-retry');
const enter = document.getElementById('bootstrap-enter');
const readyText = document.getElementById('bootstrap-ready');
const cleanupStatus = document.getElementById('storage-cleanup-status');
const actionStatus = document.getElementById('bootstrap-action-status');
const statusText = document.getElementById('bootstrap-status-text');
let ready = false;
let statusTransition = 0;
const completedSteps = new Set();
const versioned = path => `${path}${path.includes('?') ? '&' : '?'}v=${encodeURIComponent(versions.app)}`;
function setStatusText(text, immediate = false) {
if (!statusText) return;
statusTransition += 1;
const transition = statusTransition;
if (immediate) {
statusText.textContent = text;
statusText.classList.remove('is-fading');
return;
}
statusText.classList.add('is-fading');
globalThis.setTimeout(() => {
if (transition !== statusTransition) return;
statusText.textContent = text;
statusText.classList.remove('is-fading');
}, 180);
}
function nextPendingStep() {
return steps.find(step => !completedSteps.has(step));
}
function announceStep(step) {
if (stepLabels[step]) setStatusText(stepLabels[step]);
}
function mark(step, state) {
if (!steps.includes(step)) return;
const item = document.querySelector(`[data-step="${step}"]`);
item?.classList?.remove('done', 'failed');
if (state === 'done') completedSteps.add(step);
else completedSteps.delete(step);
item?.classList?.add(state);
if (progress) progress.value = completedSteps.size;
if (state === 'failed') {
setStatusText(`Fehler bei: ${stepLabels[step] || step}`);
return;
}
if (state === 'done') {
const next = nextPendingStep();
if (next) announceStep(next);
}
}
function loadScript(src, test) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = versioned(src);
script.async = false;
script.onload = () => {
if (test && !test()) reject(new Error(`Selbsttest fehlgeschlagen: ${src}`));
else resolve();
};
script.onerror = () => reject(new Error(`Datei konnte nicht geladen werden: ${src}`));
document.head.appendChild(script);
});
}
function initializeJqueryUi() {
const $ = globalThis.jQuery;
$('#bootstrap-retry').button({ icon: 'ui-icon-refresh' });
$('#bootstrap-enter').button();
$('.back-button').button();
$('#clear-route-search').button({ icon: 'ui-icon-close', showLabel: false });
$('#slide-prev').button();
$('#slide-next').button();
}
function updateCleanupProgress(removed, total) {
cleanupStatus.textContent = `Entferne alte Streckendaten aus dem Speicher (${removed} / ${total})`;
cleanupStatus.hidden = false;
}
async function cleanupOldProgress() {
cleanupStatus.hidden = true;
await globalThis.Wegwichtel.PrivacyStorage.cleanupExpired(updateCleanupProgress);
}
function isActivation(event) {
if (event.type === 'keydown') return event.key === 'Enter' || event.key === ' ';
if (event.type !== 'pointerup') return false;
if (event.isPrimary === false) return false;
return event.pointerType !== 'mouse' || event.button === 0;
}
function openApplication(event) {
if (!ready || !isActivation(event)) return;
if (event.target !== enter && event.target.closest('button, input, label, a, dialog')) return;
event.preventDefault();
event.stopPropagation?.();
screen.hidden = true;
document.getElementById('app-shell').hidden = false;
globalThis.Wegwichtel.App.navigate('#routes-page', { replace: true });
}
function showReadyState() {
ready = true;
screen.setAttribute('aria-busy', 'false');
screen.classList.add('ready');
readyText.hidden = false;
setStatusText('Vorbereitung abgeschlossen.');
actionStatus?.classList.add('is-leaving');
enter.hidden = false;
globalThis.requestAnimationFrame(() => enter.classList.add('is-visible'));
globalThis.setTimeout(() => {
if (actionStatus) actionStatus.hidden = true;
}, 220);
enter.focus();
}
async function boot() {
ready = false;
completedSteps.clear();
if (progress) progress.value = 0;
screen.setAttribute('aria-busy', 'true');
screen.classList.remove('ready');
readyText.hidden = true;
enter.hidden = true;
enter.classList.remove('is-visible');
errorBox.hidden = true;
retry.hidden = true;
if (actionStatus) {
actionStatus.hidden = false;
actionStatus.classList.remove('is-leaving');
}
try {
setStatusText(stepLabels.storage, true);
await cleanupOldProgress();
mark('storage', 'done');
await loadScript(
`vendor/jquery/jquery-${versions.jquery}.min.js`,
() => globalThis.jQuery?.fn?.jquery === versions.jquery
);
mark('jquery', 'done');
await loadScript(
`vendor/jquery-ui/jquery-ui-${versions.jqueryUi}.min.js`,
() => globalThis.jQuery?.ui?.version === versions.jqueryUi
);
initializeJqueryUi();
mark('jquery-ui', 'done');
for (const module of ['config', 'api-client', 'distance', 'geolocation', 'orientation', 'slideshow', 'audio-player', 'vibration', 'app']) {
await loadScript(`js/${module}.js`, () => Boolean(globalThis.Wegwichtel));
}
mark('modules', 'done');
await globalThis.Wegwichtel.App.initialize({ markStep: mark });
showReadyState();
} catch (error) {
console.error(error);
const current = nextPendingStep();
if (current) mark(current, 'failed');
errorBox.textContent = error.message;
errorBox.hidden = false;
retry.hidden = false;
}
}
function retryBoot(event) {
if (!isActivation(event)) return;
event.preventDefault();
event.stopPropagation();
location.reload();
}
retry.addEventListener('pointerup', retryBoot);
retry.addEventListener('keydown', retryBoot);
enter.addEventListener('pointerup', openApplication);
enter.addEventListener('keydown', openApplication);
screen.addEventListener('pointerup', openApplication);
boot();
}());