From 4d08c3db5529f015c82832ca5fa318a4826a57b0 Mon Sep 17 00:00:00 2001 From: Dennis Eisold Date: Thu, 30 Apr 2026 22:11:55 +0200 Subject: [PATCH] Add quiz mode toggle to chapter/section toolbar Adds a button to the existing top-right button group on chapter and section pages that hides everything outside of the breadcrumb, the heading, the rendered questions and the link to the next section or chapter at the end of the page. The state is persisted via localStorage so it survives navigation. On pages without questions a small notice is shown instead. Replaces the previously published userscript by integrating the same behaviour directly into the site. --- assets/script.js | 82 +++++++++++++++++++++++++++++++++++++ assets/style-course.css | 40 ++++++++++++++++++ templates/html/chapter.html | 3 +- templates/html/section.html | 3 +- 4 files changed, 126 insertions(+), 2 deletions(-) diff --git a/assets/script.js b/assets/script.js index 634aae6..59854d6 100644 --- a/assets/script.js +++ b/assets/script.js @@ -9,6 +9,7 @@ document.addEventListener("DOMContentLoaded", function() { for (var i = 0; i < els.length; i++) { shuffleChildren(els[i]); } + initQuizMode(); }); function answer(el, correct) { @@ -18,6 +19,87 @@ function answer(el, correct) { el.classList.add("wrong") } +(function () { + var NOTICE_ID = "quiz-mode-notice"; + var STORAGE_KEY = "quiz-mode-enabled"; + var QUIZ_CLASS = "quiz-mode-active"; + var HAS_Q_CLASS = "quiz-has-questions"; + + function pageHasQuestions() { + return document.querySelector(".course .question") !== null; + } + + function tagSectionTail() { + var course = document.querySelector(".course"); + if (!course) return false; + var tagged = course.querySelectorAll("[data-quiz-tail]"); + for (var i = 0; i < tagged.length; i++) { + tagged[i].removeAttribute("data-quiz-tail"); + } + var children = course.children; + for (var j = 0; j < children.length; j++) { + var child = children[j]; + if (child.tagName !== "DIV") continue; + var text = (child.textContent || "").toLowerCase(); + if (text.indexOf("weiter zum nächsten abschnitt") !== -1 || + text.indexOf("weiter zum nächsten kapitel") !== -1) { + child.setAttribute("data-quiz-tail", ""); + return true; + } + } + return false; + } + + function showNotice(text) { + var n = document.getElementById(NOTICE_ID); + if (!n) { + n = document.createElement("div"); + n.id = NOTICE_ID; + document.body.appendChild(n); + } + n.textContent = text; + } + + function hideNotice() { + var n = document.getElementById(NOTICE_ID); + if (n) n.parentNode.removeChild(n); + } + + function updateButton(btn, on) { + btn.setAttribute("aria-pressed", on ? "true" : "false"); + btn.classList.toggle("active", on); + btn.title = on ? "Alles anzeigen" : "Nur Fragen anzeigen"; + } + + function setQuizMode(on) { + var hasQ = pageHasQuestions(); + document.body.classList.toggle(HAS_Q_CLASS, hasQ); + if (on && hasQ) tagSectionTail(); + document.body.classList.toggle(QUIZ_CLASS, on); + var btn = document.getElementById("quiz-mode-toggle"); + if (btn) updateButton(btn, on); + if (on && !hasQ) { + showNotice("Keine Fragen auf dieser Seite gefunden."); + } else { + hideNotice(); + } + } + + window.initQuizMode = function () { + var btn = document.getElementById("quiz-mode-toggle"); + if (!btn) return; + btn.addEventListener("click", function () { + var next = !document.body.classList.contains(QUIZ_CLASS); + setQuizMode(next); + try { localStorage.setItem(STORAGE_KEY, next ? "1" : "0"); } catch (e) {} + }); + var initial = false; + try { initial = localStorage.getItem(STORAGE_KEY) === "1"; } catch (e) {} + if (initial) setQuizMode(true); + else updateButton(btn, false); + }; +})(); + /* var els = document.querySelectorAll(".question .question-text"); diff --git a/assets/style-course.css b/assets/style-course.css index 7a12ad3..6a31f23 100644 --- a/assets/style-course.css +++ b/assets/style-course.css @@ -446,3 +446,43 @@ span.formula { .course .katex-display { margin: 1em 0em; } + +/* Quiz-Modus */ +#quiz-mode-toggle { + cursor: pointer; +} +#quiz-mode-toggle.active { + background: #0a7a2a; + border-color: #0a7a2a; + color: #fff; +} +#quiz-mode-toggle.active svg { + fill: #fff; +} + +#quiz-mode-notice { + position: fixed; + top: 12px; + right: 12px; + z-index: 99999; + max-width: 260px; + padding: 8px 12px; + font: 500 13px/1.35 system-ui, -apple-system, sans-serif; + color: #333; + background: #fff3cd; + border: 1px solid #ffe69c; + border-radius: 6px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); +} + +body.quiz-mode-active.quiz-has-questions .course > * { + display: none !important; +} +body.quiz-mode-active.quiz-has-questions .course > .course-toolbar, +body.quiz-mode-active.quiz-has-questions .course > h1, +body.quiz-mode-active.quiz-has-questions .course > nav, +body.quiz-mode-active.quiz-has-questions .course > .question, +body.quiz-mode-active.quiz-has-questions .course > [data-quiz-tail], +body.quiz-mode-active.quiz-has-questions .course > [data-quiz-tail] ~ * { + display: revert !important; +} diff --git a/templates/html/chapter.html b/templates/html/chapter.html index 746d539..665c794 100644 --- a/templates/html/chapter.html +++ b/templates/html/chapter.html @@ -1,10 +1,11 @@ -
+
{% if chapter["video_url"] %} {% endif %} +
diff --git a/templates/html/section.html b/templates/html/section.html index 91583f0..640cf4e 100644 --- a/templates/html/section.html +++ b/templates/html/section.html @@ -1,10 +1,11 @@ -
+
{% if section["video_url"] %} {% endif %} +