From 2b02d887679af6ebc9df7808003d9635ed4c740a Mon Sep 17 00:00:00 2001 From: Dogfather Date: Mon, 28 Sep 2026 14:13:07 +0200 Subject: [PATCH] =?UTF-8?q?Die=20Regieleiste=20steht=20jetzt=20=C3=BCber?= =?UTF-8?q?=20dem=20Saal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filipe: „ich hätte das gerne oben also nicht in dieser kachel sondern über der kachel wo die videos laufen werden und das soll extrem perfektioniert werden." WARUM DAS MEHR IST ALS EIN UMHÄNGEN Die Register standen INNERHALB des einklappbaren Teils. Wer die Regie zuklappte, um mehr Bild zu haben, hatte sie nicht mehr — und genau dann braucht man sie. Oben ändert sich ihre Aufgabe: aus dem Inhaltsverzeichnis einer Schublade wird eine Steuerleiste über der Sendung. Daraus folgen vier Dinge, die vorher nicht nötig waren: 1. EIN REGISTER MACHT DIE ZUGEKLAPPTE REGIE AUF. Vorher wechselte nur der Reiter, die Tafel lag im zugeklappten Teil — sichtbar passierte nichts. Nur auf, nie zu: Zugemacht wird mit dem Griff. Ein Knopf, der beim zweiten Druck das Gegenteil tut, versteckt irgendwann etwas, das jemand gerade liest. 2. SIE BRICHT NICHT UM, SIE ROLLT. Sieben Register in zwei Zeilen kosten am oberen Rand rund 90 px — und zwar dem Video. Gemessen: eine Zeile auf 1440 px wie auf 390 px, dort mit Einrasten und weichen Rändern als Auskunft, dass es weitergeht. 3. SIE LÖST EIN, WAS `role="tablist"` VERSPRICHT. Pfeiltasten wandern, Pos1/Ende springen, genau ein Register liegt in der Tabulatorfolge. Steht die Rolle im Markup und tut das Programm es nicht, sagt ein Vorleser etwas an, was nicht stimmt — schlimmer als keine Rolle. Gemessen wird das gedrückt, nicht gelesen: fünf Tastendrücke, und Fokus, Auswahl und offene Tafel müssen jedes Mal dasselbe sagen. 4. EINE GLEITENDE MARKE zeigt, wo man steht — Glas mit Lichtkante, darunter ein roter Streifen zur offenen Tafel. Ist die Regie zugeklappt, wird er leise: Der Streifen führt dann nirgendwohin. Dazu ein Schild „Regie" links (am Handy weg), damit die sieben Wörter am oberen Rand nicht wie eine zweite Navigation aussehen. DER FEHLER, DER MICH ZWEI ANLÄUFE GEKOSTET HAT Die Leiste war im Browser 1 px hoch, ihre Register standen 55 px hoch daneben und ragten über das Video. Ursache: 900 Zeilen weiter unten stand eine ZWEITE `grid-template-rows` für `.saal` (aus der Zeit, als der Saal zwei Zeilen hatte). Sie stand später und gewann — die Leiste landete in der `1fr`-Zeile und bekam null Pixel. Und fast hätte ich das Falsche repariert: Beim Durchprobieren habe ich `style.gridTemplateRows` gesetzt — ein Stilattribut schlägt jede Regel im Stilblatt. Damit „funktionierten" `auto` und `min-content` gleich gut, weil beide die zweite Regel aushebelten, und es sah nach einem Unterschied zwischen den beiden aus. Erst nach dem Entfernen der Doppelung hat die Gegenprobe gezeigt: `auto` tut es genauso. Eine Probe, die mehr ändert als das, wonach man sucht, beantwortet eine andere Frage. Es gibt jetzt eine Prüfung, dass genau EINE Regel die Zeilen des Saals bestimmt. ZWEI WEITERE FUNDE AUS DER MESSUNG Am Handy blieben bei offener Regie 131 px für das Bild — ein Streifen. Mein erster Versuch (62dvh → 52dvh) machte es auf 75 px SCHLECHTER: Die Ursache lag woanders, die Leiste des Pults bricht dort in vier Zeilen um und ist rund 200 px hoch, wovon ein Anteil der Fensterhöhe nichts wissen kann. Mit `min(52dvh, 19rem)` sind es 210 px. Und die Spendenkarte wurde als „steht aus dem Bild heraus" gemeldet: 413 statt 430 px, links −1. 413 ist genau das 0,96-fache — die Messung hatte die Karte im Ausblenden erwischt. Sie wartet jetzt auf `data-da="ja"` und misst nur, was ganz da ist. GEPRUEFT pruef-reaktion 280 (vorher 260), 0 Fehler — Abschnitt 18 neu. mess-reaktion: Rückgabewert 0, kein ACHTUNG; misst die Leiste jetzt auf 1440 und auf 390 px, samt Tastatur und Aufklappen. Dazu grün: handy, buehne, struktur, css-klassen, tippziele. Co-Authored-By: Claude Opus 5 --- server/mess-reaktion.mjs | 236 +++++- server/pruef-reaktion.mjs | 100 +++ workspace/anruf-probe.html | 10 +- workspace/app.webmanifest | 8 +- workspace/assets/css/reaktion.css | 244 +++++- workspace/assets/js/reaktion.js | 131 +++- workspace/aufgaben.html | 38 +- workspace/automation.html | 32 +- workspace/befinden.html | 34 +- workspace/bereich.html | 44 +- workspace/bewerben.html | 38 +- workspace/bewerbungen.html | 36 +- workspace/buehne.html | 2 +- workspace/calls.html | 34 +- workspace/chat.html | 40 +- workspace/content.html | 34 +- workspace/crew-index.html | 12 +- workspace/crew.webmanifest | 8 +- workspace/dateien.html | 34 +- workspace/entwicklung.html | 36 +- workspace/hilfe.html | 30 +- workspace/index.html | 10 +- workspace/kalender.html | 34 +- workspace/leistung.html | 32 +- workspace/material.html | 32 +- workspace/notizen.html | 28 +- workspace/personen.html | 32 +- workspace/profil.html | 36 +- workspace/reaktion.html | 1163 +++++++++++++++-------------- workspace/rechte.html | 34 +- workspace/report.html | 36 +- workspace/scouting.html | 32 +- workspace/start.html | 32 +- workspace/startcheck.html | 34 +- workspace/steckbrief.html | 36 +- workspace/support.html | 28 +- workspace/tafel.html | 6 +- workspace/talente.html | 36 +- workspace/team.html | 32 +- workspace/teamlage.html | 34 +- workspace/teilen.html | 30 +- workspace/treff-moderation.html | 32 +- workspace/treff-regeln.html | 32 +- workspace/uebersicht.html | 32 +- workspace/unsere-seiten.html | 30 +- workspace/unterstuetzen.html | 32 +- workspace/werdegang.html | 32 +- workspace/willkommen.html | 30 +- workspace/wissen.html | 34 +- 49 files changed, 1917 insertions(+), 1255 deletions(-) diff --git a/server/mess-reaktion.mjs b/server/mess-reaktion.mjs index 367cc7e2..ceec9ca6 100644 --- a/server/mess-reaktion.mjs +++ b/server/mess-reaktion.mjs @@ -685,6 +685,172 @@ if (zuschauer.konsole.length) console.log(" KONSOLE:", zuschauer.konsole.slice Abzeichen UND ein zweiter Knopf dazugekommen. Genau so ist am 28.09. die Regie 197 px uebergelaufen: Die Rechnung ging auf, die Wirklichkeit nicht. */ +/* ---- Die Regieleiste ueber dem Saal ----------------------------- + + Filipe, 28.09.2026: „ich haette das gerne oben also nicht in dieser + kachel sondern ueber der kachel wo die videos laufen werden." + + GEMESSEN WIRD, WAS SIE KOSTET UND WAS SIE KANN. Eine Leiste am + oberen Rand nimmt Hoehe -- und zwar dem Video, um das es geht. + Zwei Zeilen statt einer waeren rund 90 Pixel, und das sieht man + auf dem Bildschirmfoto nicht, weil beides „eine Leiste" ist. */ +console.log(""); +console.log(" --- Die Regieleiste ---"); +{ + const leiste = await host.seite.evaluate(() => { + const l = document.getElementById("regieleiste"); + const r = document.getElementById("reiter"); + const kino = document.getElementById("teil-live"); + if (!l || !r || !kino) return null; + const lr = l.getBoundingClientRect(); + const kr = kino.getBoundingClientRect(); + const knoepfe = [...r.querySelectorAll(".reiter__knopf")]; + return { + hoch: Math.round(lr.height), + oben: Math.round(lr.top), + /* STEHT SIE WIRKLICH UEBER DEM KINO? Das ist die Frage, nicht + ob sie irgendwo existiert. */ + ueberDemKino: lr.bottom <= kr.top + 1, + knoepfe: knoepfe.length, + /* EINE ZEILE ODER ZWEI? Gemessen an den Oberkanten -- wenn + zwei Knoepfe verschieden hoch sitzen, bricht sie um. */ + zeilen: new Set(knoepfe.map((k) => Math.round(k.getBoundingClientRect().top))).size, + kleinster: Math.min(...knoepfe.map((k) => Math.round(k.getBoundingClientRect().height))), + rollt: r.scrollWidth > r.clientWidth, + /* Genau EIN Register in der Tabulatorfolge. */ + imTabulator: knoepfe.filter((k) => k.tabIndex === 0).length, + marke: (() => { + const m = document.getElementById("reiter-marke"); + if (!m || m.hidden) return null; + const mr = m.getBoundingClientRect(); + const a = knoepfe.find((k) => k.getAttribute("aria-selected") === "true"); + const ar = a.getBoundingClientRect(); + return { + breit: Math.round(mr.width), + /* Sitzt sie unter dem gewaehlten Register? */ + versatz: Math.round(Math.abs(mr.left - ar.left)), + gleichBreit: Math.abs(mr.width - ar.width) < 2, + }; + })(), + }; + }); + + if (!leiste) { + console.log(" ACHTUNG: Die Regieleiste gibt es nicht."); + ausgang = 1; + } else { + console.log(` ${leiste.knoepfe} Register in ${leiste.zeilen} Zeile(n), ` + + `Leiste ${leiste.hoch} px hoch bei y=${leiste.oben}, ` + + `kleinstes Ziel ${leiste.kleinster} px, rollt=${leiste.rollt}`); + console.log(` Ueber dem Kino: ${leiste.ueberDemKino} · ` + + `im Tabulator: ${leiste.imTabulator} · ` + + `Marke ${leiste.marke ? `${leiste.marke.breit} px, Versatz ${leiste.marke.versatz} px` : "(keine)"}`); + + if (!leiste.ueberDemKino) { + console.log(" ACHTUNG: Die Leiste steht nicht ueber dem Kino."); + ausgang = 1; + } + if (leiste.zeilen !== 1) { + console.log(" ACHTUNG: Die Register brechen um -- das kostet das Video Hoehe."); + ausgang = 1; + } + if (leiste.kleinster < 44) { + console.log(" ACHTUNG: Ein Register ist kleiner als 44 px."); + ausgang = 1; + } + if (leiste.imTabulator !== 1) { + console.log(" ACHTUNG: Der Tabulator wandert nicht -- sieben Schritte bis zum Inhalt."); + ausgang = 1; + } + if (!leiste.marke || leiste.marke.versatz > 2 || !leiste.marke.gleichBreit) { + console.log(" ACHTUNG: Die Marke sitzt nicht unter dem gewaehlten Register."); + ausgang = 1; + } + } + + /* ---- DIE TASTATUR MUSS TUN, WAS `role=tablist` VERSPRICHT ---- + Ein Versprechen im Markup, das das Programm nicht einloest, ist + schlimmer als gar keines: Der Vorleser sagt etwas an, was nicht + stimmt. Also wird es gedrueckt, nicht gelesen. */ + await host.seite.evaluate(() => { + document.querySelector('#reiter .reiter__knopf[data-tafel="sendung"]').focus(); + }); + const tasten = []; + for (const [taste, wohin] of [["ArrowRight", "rechts"], ["ArrowRight", "rechts"], + ["ArrowLeft", "links"], ["End", "ans Ende"], ["Home", "an den Anfang"]]) { + await host.seite.keyboard.press(taste); + await host.seite.waitForTimeout(220); + const wo = await host.seite.evaluate(() => { + const a = document.activeElement; + const g = [...document.querySelectorAll("#reiter .reiter__knopf")] + .find((k) => k.getAttribute("aria-selected") === "true"); + const t = [...document.querySelectorAll(".pult-tafel")].find((x) => !x.hidden); + return { + fokus: a?.dataset?.tafel || "(?)", + gewaehlt: g?.dataset?.tafel || "(?)", + tafel: t?.dataset?.tafel || "(keine)", + }; + }); + tasten.push(`${wohin}->${wo.fokus}`); + /* FOKUS, AUSWAHL UND OFFENE TAFEL MUESSEN DASSELBE SAGEN. + Laufen sie auseinander, zeigt die Regie eine andere Tafel als + das hervorgehobene Register -- und man stellt etwas ein, von + dem man glaubt, es gehoere woandershin. */ + if (wo.fokus !== wo.gewaehlt || wo.gewaehlt !== wo.tafel) { + console.log(` ACHTUNG: Fokus ${wo.fokus}, gewaehlt ${wo.gewaehlt}, ` + + `offen ${wo.tafel} -- das passt nicht zusammen.`); + ausgang = 1; + } + } + console.log(` Tastatur: ${tasten.join(" · ")}`); + + /* ---- EIN REGISTER MACHT DIE ZUGEKLAPPTE REGIE AUF ---- + Seit die Leiste oben steht, kann das Pult zu sein, waehrend man + ein Register waehlt. Ohne das waere der Knopf einer, bei dem + sichtbar nichts passiert. */ + await host.seite.click("#pult-griff").catch(() => { }); + await host.seite.waitForTimeout(400); + const zu = await host.seite.evaluate(() => + document.getElementById("pult").dataset.auf); + await host.seite.click('#reiter .reiter__knopf[data-tafel="ton"]').catch(() => { }); + await host.seite.waitForTimeout(500); + const danach = await host.seite.evaluate(() => ({ + auf: document.getElementById("pult").dataset.auf, + tafel: [...document.querySelectorAll(".pult-tafel")].find((x) => !x.hidden)?.dataset.tafel, + sichtbar: (() => { + const t = document.getElementById("tafel-ton"); + const r = t.getBoundingClientRect(); + return r.height > 0 && r.top < window.innerHeight; + })(), + })); + console.log(` Regie zugeklappt (auf=${zu}), Register „Ton" gedrueckt ` + + `-> auf=${danach.auf}, offen=${danach.tafel}, sichtbar=${danach.sichtbar}`); + if (zu !== "nein" || danach.auf !== "ja" || !danach.sichtbar) { + console.log(" ACHTUNG: Ein Register macht die zugeklappte Regie nicht auf."); + ausgang = 1; + } + await bild(host.seite, "20-regieleiste"); + + /* ---- WAS SIE DEM VIDEO KOSTET ---- + Die eigentliche Frage bei einer Leiste am oberen Rand. */ + const platz = await host.seite.evaluate(() => { + const l = document.getElementById("regieleiste").getBoundingClientRect(); + const k = document.getElementById("teil-live").getBoundingClientRect(); + const s2 = document.getElementById("saal").getBoundingClientRect(); + return { + leiste: Math.round(l.height), kino: Math.round(k.height), saal: Math.round(s2.height), + ueber: Math.max(0, document.documentElement.scrollHeight + - document.documentElement.clientHeight), + }; + }); + console.log(` Saal ${platz.saal} px = Leiste ${platz.leiste} + Kino ${platz.kino} ` + + `+ Regie, senkrecht ueber ${platz.ueber} px`); + if (platz.ueber > 6 || platz.kino < 200) { + console.log(" ACHTUNG: Die Leiste nimmt dem Bild zu viel oder die Seite laeuft ueber."); + ausgang = 1; + } +} + /* ---- Die Gestaltung der Spendenkarten --------------------------- Filipe: „mach paar fertige und so dass ich auch hochladen kann. @@ -785,7 +951,7 @@ const messeKarte = async (erwartet) => { Messung bestaetigte eine Aenderung, die gar nicht angekommen ist. */ await host.seite.waitForFunction( - (soll) => [...document.querySelectorAll(".spendenkarte")].some((k2) => + (soll) => [...document.querySelectorAll('.spendenkarte[data-da="ja"]')].some((k2) => k2.querySelector(".spendenkarte__wer")?.textContent === "Probe" && Math.abs(parseFloat(getComputedStyle(k2).fontSize) - soll) < 0.5), erwartet, { timeout: 16000 }, @@ -798,7 +964,12 @@ const messeKarte = async (erwartet) => { die Irre gefuehrt. */ await host.seite.waitForTimeout(700); return host.seite.evaluate(() => { - const k2 = [...document.querySelectorAll(".spendenkarte")] + /* `data-da="ja"` HEISST: GANZ DA. Beim Hereinkommen UND beim + Verschwinden steht die Karte auf `translateX(-28px) scale(.96)` + -- gemessen wurden dadurch 413 statt 430 Pixel (genau das + 0,96-fache) und ein linker Rand von -1. Beides war kein + Fehler der Karte, sondern ein Blick zur falschen Zeit. */ + const k2 = [...document.querySelectorAll('.spendenkarte[data-da="ja"]')] .find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe"); if (!k2) return null; const r = k2.getBoundingClientRect(); @@ -886,7 +1057,7 @@ if (!kGross || !kKlein) { /* ---- Und die Farbe? ---- */ const farbe = await host.seite.evaluate(() => { - const k2 = [...document.querySelectorAll(".spendenkarte")] + const k2 = [...document.querySelectorAll('.spendenkarte[data-da="ja"]')] .find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe"); return k2 ? getComputedStyle(k2).getPropertyValue("--sp-farbe").trim() : ""; }); @@ -1396,6 +1567,65 @@ await gast2.kontext.close(); await zuschauer.kontext.close(); { + /* ==== DIE REGIELEISTE AM HANDY ================================== + Sieben Register auf 390 Pixel passen nicht nebeneinander -- sie + muss rollen. Gemessen wird beides: dass sie rollt, und dass sie + trotzdem nur EINE Zeile hoch ist. Umbrechen waere die stille + Alternative, und die kostet das Video 44 Pixel. */ + { + const chef = await alsWer("admin", 390, 844); + await chef.seite.goto(`${BASIS}/workspace/reaktion.html`, { waitUntil: "domcontentloaded" }); + await chef.seite.waitForTimeout(2600); + const l = await chef.seite.evaluate(() => { + const r = document.getElementById("reiter"); + const le = document.getElementById("regieleiste"); + if (!r || le.hidden) return null; + const k = [...r.querySelectorAll(".reiter__knopf")]; + const rr = r.getBoundingClientRect(); + return { + hoch: Math.round(le.getBoundingClientRect().height), + zeilen: new Set(k.map((x) => Math.round(x.getBoundingClientRect().top))).size, + rollt: r.scrollWidth > r.clientWidth + 1, + sichtbar: k.filter((x) => { + const q = x.getBoundingClientRect(); + return q.left >= rr.left - 1 && q.right <= rr.right + 1; + }).length, + schild: !!document.querySelector(".regieleiste__schild")?.offsetParent, + ueber: Math.max(0, document.documentElement.scrollWidth + - document.documentElement.clientWidth), + }; + }); + if (!l) { + console.log(" ACHTUNG: Am Handy gibt es die Regieleiste nicht."); + ausgang = 1; + } else { + console.log(` Handy-Regie: ${l.hoch} px, ${l.zeilen} Zeile(n), rollt=${l.rollt}, ` + + `${l.sichtbar} von 7 im Bild, Schild=${l.schild}, seitlich ${l.ueber} px`); + if (l.zeilen !== 1 || !l.rollt || l.ueber > 0 || l.schild) { + console.log(" ACHTUNG: Die Regieleiste am Handy bricht um, rollt nicht " + + "oder schiebt die Seite breiter."); + ausgang = 1; + } + } + /* WAS BLEIBT VOM BILD, WENN DIE REGIE OFFEN IST? + Am Handy ist das die eigentliche Frage. Ein Kinosaal von 131 + Pixeln ist kein Bild mehr, sondern ein Streifen -- und man + merkt es erst, wenn man mitten in der Sendung etwas einstellen + will und nicht mehr sieht, worueber man redet. */ + const platzHandy = await chef.seite.evaluate(() => { + const g = (id) => Math.round(document.getElementById(id).getBoundingClientRect().height); + return { saal: g("saal"), leiste: g("regieleiste"), kino: g("teil-live"), pult: g("pult") }; + }); + console.log(` Handy offen: Saal ${platzHandy.saal} = Leiste ${platzHandy.leiste} ` + + `+ Kino ${platzHandy.kino} + Regie ${platzHandy.pult}`); + if (platzHandy.kino < 190) { + console.log(" ACHTUNG: Bei offener Regie bleibt vom Bild fast nichts."); + ausgang = 1; + } + await bild(chef.seite, "21-regieleiste-handy"); + await chef.kontext.close(); + } + const handy = await alsWer("gast2", 390, 844); await handy.seite.goto(`${BASIS}/workspace/reaktion.html`, { waitUntil: "networkidle" }); await handy.seite.waitForTimeout(4000); diff --git a/server/pruef-reaktion.mjs b/server/pruef-reaktion.mjs index 7d958a58..89a89176 100644 --- a/server/pruef-reaktion.mjs +++ b/server/pruef-reaktion.mjs @@ -1552,6 +1552,106 @@ melde("=== 17. Tempo, Anordnung und das zweite Video ==="); } } + +/* ======================================================================= + 18. DIE REGIELEISTE UEBER DEM SAAL + + Filipe, 28.09.2026: „ich haette das gerne oben also nicht in dieser + kachel sondern ueber der kachel wo die videos laufen werden." + + Geprueft wird hier, was sich aus dem Quelltext beweisen laesst -- + Lage, Verdrahtung, Versprechen. Wie hoch sie ist und ob die Marke + sitzt, misst `mess-reaktion` im Browser; das kann kein Quelltext. + ======================================================================= */ +melde(""); +melde("=== 18. Die Regieleiste ==="); +{ + const html = readFileSync(join(HIER, "..", "workspace", "reaktion.html"), "utf8"); + const css = readFileSync(join(HIER, "..", "workspace", "assets", "css", "reaktion.css"), "utf8"); + const js = readFileSync(join(HIER, "..", "workspace", "assets", "js", "reaktion.js"), "utf8"); + + /* ---- SIE STEHT UEBER DEM SAAL, NICHT DARIN ---- + Die Reihenfolge im Dokument ist die Aussage. Waere sie wieder im + Pult, stuende sie weiter unten -- und niemandem fiele es auf, + solange sie „irgendwo" da ist. */ + const iLeiste = html.indexOf('id="regieleiste"'); + const iKino = html.indexOf('id="teil-live"'); + const iPult = html.indexOf('id="pult"'); + ok(iLeiste > 0, "es gibt die Regieleiste"); + ok(iLeiste < iKino, `sie steht vor dem Kino (${iLeiste} < ${iKino})`); + ok(iLeiste < iPult, "und vor dem Pult"); + ok(html.indexOf('id="reiter"') < iPult, + "die Register stehen nicht mehr im Pult"); + + /* ---- JEDES REGISTER ZEIGT AUF EINE TAFEL, DIE ES GIBT ---- + `aria-controls` ist ein Versprechen an Hilfsmittel. Zeigt es ins + Leere, sagt der Vorleser eine Tafel an, die niemand oeffnen + kann -- und gemerkt haette es nie jemand. */ + const reiter = [...html.matchAll(/data-tafel="([a-z]+)"[^>]*aria-controls="([^"]+)"/g)] + .concat([...html.matchAll(/aria-controls="([^"]+)"[^>]*data-tafel="([a-z]+)"/g)] + .map((m) => [m[0], m[2], m[1]])); + ok(reiter.length >= 7, `${reiter.length} Register gefunden`); + const ohneTafel = reiter.filter(([, , ziel]) => !html.includes(`id="${ziel}"`)); + ok(ohneTafel.length === 0, + ohneTafel.length + ? `ZEIGT INS LEERE: ${ohneTafel.map((x) => x[2]).join(", ")}` + : "jedes Register zeigt auf eine Tafel, die es gibt"); + ok(!html.includes('id="tafel-gibtesnicht"'), + "Gegenprobe: eine erfundene Tafel gibt es nicht"); + + /* ---- DAS VERSPRECHEN VON `role=tablist` ---- + Steht die Rolle im Markup und loest das Programm sie nicht ein, + sagt ein Vorleser etwas an, was nicht stimmt. Das ist schlimmer + als gar keine Rolle. */ + ok(/id="reiter"[^>]*role="tablist"/.test(html), "die Leiste ist eine Registerleiste"); + /* Die Anfuehrungszeichen bleiben draussen -- im Quelltext steht + `'Home'`, in dieser Pruefung stand zuerst `"Home"`, und daran + ist sie gescheitert. Eine Pruefung, die die Schreibweise der + Anfuehrungszeichen mitprueft, prueft die falsche Sache. */ + for (const taste of ["ArrowRight", "ArrowLeft", "Home", "End"]) { + ok(js.includes(taste), `das Programm kennt „${taste}"`); + } + ok(/tabIndex\s*=\s*gewaehlt \? 0 : -1/.test(js), + "genau ein Register liegt in der Tabulatorfolge"); + + /* ---- EIN REGISTER MACHT DIE ZUGEKLAPPTE REGIE AUF ---- + Seit die Leiste oben steht, kann das Pult zu sein. Ohne diese + Zeile waere jedes Register bei zugeklappter Regie ein Knopf, + bei dem sichtbar nichts passiert. */ + ok(/pult\.dataset\.auf = 'ja'/.test(js) && /reiterWechseln/.test(js), + "ein Register klappt die Regie auf"); + + /* ---- DIE MARKE UND IHRE ZWEITE ANZEIGE ---- + Was gerechnet wird, braucht etwas daneben, das nicht rechnet. */ + ok(html.includes('id="reiter-marke"'), "es gibt die gleitende Marke"); + ok(/offsetLeft/.test(js) && /offsetWidth/.test(js) && /offsetHeight/.test(js), + "sie wird aus gemessenen Werten gesetzt, nicht gerechnet"); + const knopfRegel = css.match(/\.reiter__knopf\[aria-selected="true"\] \{[^}]*\}/); + ok(!!knopfRegel && /color:/.test(knopfRegel[0]), + "das gewaehlte Register traegt ausserdem eine eigene Farbe"); + + /* ---- SIE GEHOERT NICHT IN DEN STREAM ---- + Der Buehnenmodus zeigt nur, was Zuschauer sehen sollen. Eine + Regieleiste im Stream waere die Bedienung im Bild. */ + ok(/body\[data-nur="buehne"\][^{]*\.regieleiste/.test(css.replace(/\s+/g, " ")), + "im Buehnenmodus ist sie weg"); + + /* ---- NUR EINE STELLE SAGT, WIE HOCH DIE ZEILEN SIND ---- + Bis zum 28.09. standen zwei Angaben in derselben Datei; die + spaetere gewann und gab der Leiste null Pixel. Zwei Regeln fuer + dieselbe Frage sind keine Sicherheit. */ + const zeilen = [...css.matchAll(/^\s*\.saal[^{]*\{[^}]*grid-template-rows/gm)] + .concat([...css.matchAll(/^\.saal \{ grid-template-rows/gm)]); + ok(zeilen.length === 1, + zeilen.length === 1 + ? "genau eine Regel bestimmt die Zeilen des Saals" + : `${zeilen.length} Regeln bestimmen die Zeilen -- eine davon wird ignoriert`); + + /* ---- UND SIE GEHOERT NUR DENEN, DIE SENDEN ---- */ + ok(/leiste\.hidden = !lage\.ich\.host/.test(js), + "nur wer die Sendung fuehrt, sieht sie"); +} + melde(""); melde(`${geprueft} Pruefungen, ${fehler} Fehler`); melde(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG"); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 23f4c42f..f5a5d74f 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +