Workspace: Zurueck-Knopf auf allen Seiten

Wunsch: "ich will auch immer bei jeder seite auch immer einen knopf
haben damit ich zurueck gehen kann auf die seite vorher."

Neues gemeinsames Modul assets/js/kopf.js. Blindes history.back() reicht
dafuer nicht: Wer die Adresse direkt eingibt oder gerade von der
Anmeldung kommt, landet damit ausserhalb des Workspace oder wieder im
Anmeldeformular. Deshalb wird zuerst geprueft, woher der Aufruf kam:

  * vorherige Seite im Workspace  -> "Zurueck", history.back()
    (fuehrt wirklich dorthin zurueck, samt Bildlaufposition)
  * kein Verlauf, aber Unterseite -> "Uebersicht", geht zur Startseite
  * kein Verlauf auf der Startseite -> Knopf bleibt verborgen
    Ein Knopf, der nichts tut, ist schlimmer als keiner.

Der Knopf sitzt links in der Kopfleiste, an derselben Stelle wie im
Browser.

Nebenbei aufgeraeumt: Das Abmelden stand bisher in jeder der fuenf
Seitendateien noch einmal -- fuenfmal derselbe Block, fuenfmal eine
Stelle zum Vergessen. Liegt jetzt ebenfalls in kopf.js.

Geprueft: Start nach Login -> verborgen; Aufgaben von Start ->
"Zurueck", fuehrt zurueck; Kalender direkt aufgerufen -> "Uebersicht".
Keine Konsolenfehler, Abmelden funktioniert weiterhin.

Nur statische Dateien, kein Neustart noetig.
This commit is contained in:
2026-08-28 00:35:26 +02:00
parent ef79659f8f
commit 75d05d05d2
12 changed files with 100 additions and 26 deletions
+22
View File
@@ -38,6 +38,28 @@ body.start {
.kopfleiste .marke { margin: 0; font-size: .72rem; }
/* Zurück-Knopf. Steht ganz links, weil dort jeder ihn erwartet -- gleiche
Stelle wie im Browser. Bleibt verborgen (hidden), wenn es nichts gibt,
wohin er führen könnte; das entscheidet kopf.js. */
.zurueck-knopf {
flex: 0 0 auto;
padding: 7px 13px;
background: rgba(255, 255, 255, .045);
border: 1px solid var(--rand);
border-radius: 9px;
color: var(--text-leise);
font: inherit; font-size: .82rem;
cursor: pointer;
white-space: nowrap;
transition: background var(--tempo), border-color var(--tempo), color var(--tempo);
}
.zurueck-knopf:hover {
background: rgba(255, 255, 255, .08);
border-color: var(--rand-hell);
color: var(--text);
}
.zurueck-knopf:active { transform: translateX(-1px); }
.kopfleiste__rechts { display: flex; align-items: center; gap: 12px; }
.wer {
-5
View File
@@ -252,11 +252,6 @@ Das laesst sich nicht rueckgaengig machen. Erledigte Aufgaben sollten normalerwe
/* ---------- Start ----------------------------------------------------- */
$('abmelden').addEventListener('click', async () => {
try { await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' }); }
catch { /* egal */ }
location.assign('/workspace/');
});
(async () => {
try {
-5
View File
@@ -235,11 +235,6 @@
/* ---------- Start -------------------------------------------------------- */
$('abmelden').addEventListener('click', async () => {
try { await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' }); }
catch { /* egal */ }
location.assign('/workspace/');
});
(async () => {
try {
+68
View File
@@ -0,0 +1,68 @@
/* ===================================================================
Gemeinsames Verhalten der Kopfleiste: Zurück-Knopf und Abmelden.
Liegt bewusst in einer eigenen Datei. Vorher stand das Abmelden in
jeder Seitendatei noch einmal -- fünfmal derselbe Block, fünfmal eine
Stelle zum Vergessen, wenn sich etwas ändert.
=================================================================== */
(() => {
'use strict';
const START = '/workspace/start.html';
/* Gibt es eine sinnvolle vorherige Seite INNERHALB des Workspace?
Blindes history.back() reicht nicht: Wer die Adresse direkt eingibt
oder gerade von der Anmeldung kommt, landet damit außerhalb des
Workspace oder wieder im Anmeldeformular. Deshalb wird zuerst
geprüft, woher der Aufruf kam. */
function hatVorherigeSeite() {
if (!document.referrer) return false;
let u;
try { u = new URL(document.referrer); } catch { return false; }
if (u.origin !== location.origin) return false;
if (!u.pathname.startsWith('/workspace/')) return false;
/* Die Anmeldeseite ist kein sinnvolles Ziel -- wer angemeldet ist,
würde dort sofort wieder weitergeleitet. */
if (u.pathname === '/workspace/' || u.pathname.endsWith('/index.html')) return false;
/* Gleiche Seite heißt: neu geladen, nicht hergekommen. */
if (u.pathname === location.pathname) return false;
return true;
}
const knopf = document.getElementById('zurueck');
if (knopf) {
const aufStartseite = location.pathname.endsWith('/start.html');
if (hatVorherigeSeite()) {
knopf.hidden = false;
knopf.addEventListener('click', () => {
/* history.back() statt eines festen Ziels: Es führt wirklich
dorthin zurück, wo man war -- samt Bildlaufposition. Nur wenn
es keine Historie gibt, wird ersatzweise umgeleitet. */
if (history.length > 1) history.back();
else location.assign(START);
});
} else if (!aufStartseite) {
/* Kein Verlauf, aber wir sind in einem Unterbereich: dann wenigstens
ein Weg zur Übersicht. */
knopf.hidden = false;
knopf.textContent = '← Übersicht';
knopf.addEventListener('click', () => location.assign(START));
}
/* Auf der Startseite ohne Verlauf bleibt der Knopf aus -- ein Knopf,
der nichts tut, ist schlimmer als keiner. */
}
const abmelden = document.getElementById('abmelden');
if (abmelden) {
abmelden.addEventListener('click', async () => {
abmelden.disabled = true;
try {
await fetch('/workspace/api/abmelden', {
method: 'POST', credentials: 'same-origin',
});
} catch { /* Auch ohne Antwort weiterleiten -- das Cookie läuft ohnehin ab. */ }
location.assign('/workspace/');
});
}
})();
-5
View File
@@ -183,11 +183,6 @@
/* ---------- Start ------------------------------------------------------- */
$('abmelden').addEventListener('click', async () => {
try { await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' }); }
catch { /* egal */ }
location.assign('/workspace/');
});
(async () => {
try {
-5
View File
@@ -90,11 +90,6 @@
} catch { /* umgeleitet */ } finally { knopf.disabled = false; }
});
$('abmelden').addEventListener('click', async () => {
try { await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' }); }
catch { /* egal */ }
location.assign('/workspace/');
});
(async () => {
try {
-6
View File
@@ -123,12 +123,6 @@
}
}
$('abmelden').addEventListener('click', async () => {
try {
await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' });
} catch { /* Auch ohne Antwort weiterleiten - das Cookie ist dann spätestens abgelaufen. */ }
location.assign('/workspace/');
});
laden();
})();
+2
View File
@@ -15,6 +15,7 @@
<body class="start">
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>&#8592; Zurück</button>
<p class="marke"><a class="zurueck" href="start.html">Creator&nbsp;Workspace</a> · Aufgaben</p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
@@ -128,6 +129,7 @@
</form>
</dialog>
<script src="assets/js/kopf.js" defer></script>
<script src="assets/js/aufgaben.js" defer></script>
</body>
</html>
+2
View File
@@ -16,6 +16,7 @@
<body class="start">
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>&#8592; Zurück</button>
<p class="marke"><a class="zurueck" href="start.html">Creator&nbsp;Workspace</a> · Kalender</p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
@@ -88,6 +89,7 @@
</main>
<script src="assets/js/kopf.js" defer></script>
<script src="assets/js/kalender.js" defer></script>
</body>
</html>
+2
View File
@@ -16,6 +16,7 @@
<body class="start">
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>&#8592; Zurück</button>
<p class="marke"><a class="zurueck" href="start.html">Creator&nbsp;Workspace</a> · Personen</p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
@@ -81,6 +82,7 @@
</main>
<script src="assets/js/kopf.js" defer></script>
<script src="assets/js/personen.js" defer></script>
</body>
</html>
+2
View File
@@ -16,6 +16,7 @@
<body class="start">
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>&#8592; Zurück</button>
<p class="marke"><a class="zurueck" href="start.html">Creator&nbsp;Workspace</a> · Profil</p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
@@ -121,6 +122,7 @@
</main>
<script src="assets/js/kopf.js" defer></script>
<script src="assets/js/profil.js" defer></script>
</body>
</html>
+2
View File
@@ -14,6 +14,7 @@
<body class="start">
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>&#8592; Zurück</button>
<p class="marke">Dogfather&nbsp;Universe · Creator&nbsp;Workspace</p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
@@ -47,6 +48,7 @@
</p>
</main>
<script src="assets/js/kopf.js" defer></script>
<script src="assets/js/start.js" defer></script>
</body>
</html>