diff --git a/public/css/bootstrap.css b/public/css/bootstrap.css
index 1b3d067..0f54449 100644
--- a/public/css/bootstrap.css
+++ b/public/css/bootstrap.css
@@ -37,14 +37,14 @@
display: none;
}
-#bootstrap-screen > section {
+#bootstrap-screen > .bootstrap-card {
width: min(100%, 42rem);
box-sizing: border-box;
padding: clamp(1.1rem, 4vw, 1.8rem);
border: 1px solid rgb(214 224 214 / 80%);
border-radius: clamp(1.4rem, 5vw, 2rem);
box-shadow: var(--bootstrap-shadow);
- background: rgb(255 255 255 / 96%);
+ background: var(--bootstrap-card-bg);
}
.bootstrap-brand {
@@ -305,7 +305,7 @@
padding-left: max(.75rem, env(safe-area-inset-left));
}
- #bootstrap-screen > section {
+ #bootstrap-screen > .bootstrap-card {
padding: 1rem;
}
diff --git a/public/index.html b/public/index.html
index 1233a29..a057d05 100644
--- a/public/index.html
+++ b/public/index.html
@@ -92,7 +92,7 @@
-
Datenschutzfreundlich: Keine Werbung, kein Tracking und derzeit keine Cookies.
+
Cookies: Diese Anwendung setzt derzeit keine Cookies und verwendet weder Werbung noch Tracking.
-
+
+ - Lokalen Speicher prüfen
- jQuery laden
- jQuery UI laden
- Anwendungsmodule laden
diff --git a/public/js/bootstrap-loader.js b/public/js/bootstrap-loader.js
index 244d4d7..44b8da5 100644
--- a/public/js/bootstrap-loader.js
+++ b/public/js/bootstrap-loader.js
@@ -2,8 +2,9 @@
'use strict';
const versions = Object.freeze({ app: '0.12.14', jquery: '4.0.0', jqueryUi: '1.14.2' });
- const steps = ['jquery', 'jquery-ui', 'modules', 'server', 'routes', 'location'];
+ 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 …',
@@ -22,6 +23,7 @@
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)}`;
@@ -43,7 +45,7 @@
}
function nextPendingStep() {
- return steps.find(step => !document.querySelector(`[data-step="${step}"]`)?.classList.contains('done'));
+ return steps.find(step => !completedSteps.has(step));
}
function announceStep(step) {
@@ -51,12 +53,16 @@
}
function mark(step, state) {
+ if (!steps.includes(step)) return;
+
const item = document.querySelector(`[data-step="${step}"]`);
- if (!item) return;
- item.classList.remove('done', 'failed');
- item.classList.add(state);
- item.dataset.state = state;
- progress.value = document.querySelectorAll('#bootstrap-steps .done').length;
+ 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}`);
@@ -114,6 +120,7 @@
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 });
@@ -137,6 +144,8 @@
async function boot() {
ready = false;
+ completedSteps.clear();
+ if (progress) progress.value = 0;
screen.setAttribute('aria-busy', 'true');
screen.classList.remove('ready');
readyText.hidden = true;
@@ -150,9 +159,9 @@
}
try {
- setStatusText('Lokalen Speicher prüfen …', true);
+ setStatusText(stepLabels.storage, true);
await cleanupOldProgress();
- announceStep('jquery');
+ mark('storage', 'done');
await loadScript(
`vendor/jquery/jquery-${versions.jquery}.min.js`,
diff --git a/test/bootstrap-screen-layout.test.js b/test/bootstrap-screen-layout.test.js
index 24a4d79..48e9e78 100644
--- a/test/bootstrap-screen-layout.test.js
+++ b/test/bootstrap-screen-layout.test.js
@@ -12,7 +12,7 @@ async function read(relativePath) {
test('bootstrap screen remains vertically scrollable on small displays', async () => {
const css = await read('public/css/bootstrap.css');
const bootstrapRule = css.match(/#bootstrap-screen\s*\{([\s\S]*?)\}/)?.[1] ?? '';
- const cardRule = css.match(/#bootstrap-screen\s*>\s*section\s*\{([\s\S]*?)\}/)?.[1] ?? '';
+ const cardRule = css.match(/#bootstrap-screen\s*>\s*\.bootstrap-card\s*\{([\s\S]*?)\}/)?.[1] ?? '';
assert.match(bootstrapRule, /overflow-y:\s*auto/);
assert.match(bootstrapRule, /overflow-x:\s*hidden/);
diff --git a/test/bootstrap-start-ui.test.js b/test/bootstrap-start-ui.test.js
index 05ac1e6..a7681ca 100644
--- a/test/bootstrap-start-ui.test.js
+++ b/test/bootstrap-start-ui.test.js
@@ -34,9 +34,13 @@ test('bootstrap status text fades between loading steps and is replaced by the s
assert.match(fadingRule, /opacity:\s*0/);
assert.match(loader, /statusText\.classList\.add\('is-fading'\)/);
assert.match(loader, /statusText\.classList\.remove\('is-fading'\)/);
+ assert.match(loader, /storage:\s*'Lokalen Speicher prüfen …'/);
assert.match(loader, /server:\s*'Server prüfen …'/);
assert.match(loader, /routes:\s*'Routen laden …'/);
assert.match(loader, /location:\s*'Standort ermitteln …'/);
assert.match(loader, /actionStatus\?\.classList\.add\('is-leaving'\)/);
assert.match(loader, /enter\.classList\.add\('is-visible'\)/);
+ assert.match(loader, /const completedSteps = new Set\(\)/);
+ assert.doesNotMatch(loader, /dataset\.state/);
+ assert.match(loader, /event\.stopPropagation\?\.\(\)/);
});