feat: von Station zu Station des günstigsten Pfads (D47)
Mit dem status-bewussten Pfad (D46) zeigt das Diagramm die offene Front — im mitgelieferten Plan 24 Stationen, verteilt über einen Baum von über 20 000 px Breite. Sie zu sehen war damit gelöst, sie abzugehen nicht. Der neue Knopf im Diagramm-Kopf holt sie der Reihe nach in die Mitte: erster Druck die erste (was als Nächstes dran ist), jeder weitere die nächste, nach der letzten wieder die erste. Der Sprung fasst nur das Diagramm an — zentrieren, hervorheben, Tastaturfokus, also buchstäblich die Behandlung des ausdrücklichen Alt+Klicks (D25) samt Puls und hervorgehobenen Abhängigkeits-Kanten. In den Text führt von dort Alt+Enter, dieselbe Geste wie überall. Ohne eigenen Zustand: Fortgesetzt wird am gerade hervorgehobenen Knoten. Ein gemerkter Index wäre schlechter — der Baum wird bei jedem Tastendruck neu gebaut, die Stationsliste ändert sich unter ihm. Verborgen, solange es keine Station gibt (Pfad aus, oder alles erledigt); der Tooltip nennt die Anzahl. i18n `leanNextTooltip` in neun Sprachen. Die Mobil-Kopfzeile trug den neunten Knopf nicht mehr — D17-Nachtrag 5 hatte sie gerade erst auf acht zurechtgemessen. Nachgemessen: bei 375 px reicht es nach Lücke 8->6 px und Innenabstand 10->8 px weiterhin (345 px Inhalt, 359 px Platz, 14 px Luft); bei 320 px passen neun Fingerziele arithmetisch nicht, und unter 29 px zu gehen hat D17-Nachtrag 5 abgelehnt. Die Zeile schiebt dort deshalb (`overflow-x:auto`, Balken ausgeblendet) — 41 px Schiebeweg, Kopfhöhe unverändert 49 px, alle neun Elemente in voller Größe erreichbar. Dabei ein älterer, stiller Fehler gefunden: Bei Platzmangel schrumpfte der Modus-Wähler — das einzige Element ohne feste Größe — auf einen 2-px-Strich zusammen, während sein Icon 38 px breit darüber hinausragte; er sah aus wie ein Trennstrich und war unbenutzbar. `flex:0 0 auto` an allen Kindern der Zeile stellt das ab. 236 Tests grün. SPEC §9 und D47 halten es fest; der Plan bekommt den Knoten als `[x]` (noch nicht deployt), frontend/CLAUDE.md die Kopfzeilen-Stolperfalle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c4a6ff57d4
commit
ecc1b632f6
@@ -2997,3 +2997,77 @@ um genau zwei Knoten (`[x] Zielgruppenanalyse`, `[x] Sitemap` verlieren
|
|||||||
Status-Hälfte ist damit gebaut. Offen bleibt die **Nutzen-Achse** (Ausbaustufen:
|
Status-Hälfte ist damit gebaut. Offen bleibt die **Nutzen-Achse** (Ausbaustufen:
|
||||||
ist eine Gruppe komplett realisiert, zur nächsten per Nutzen gewählten Stufe
|
ist eine Gruppe komplett realisiert, zur nächsten per Nutzen gewählten Stufe
|
||||||
weiterspringen) — die braucht erst ein Nutzen-Attribut und den Aufwands-Rollup.
|
weiterspringen) — die braucht erst ein Nutzen-Attribut und den Aufwands-Rollup.
|
||||||
|
|
||||||
|
## D47 — Von Station zu Station: ein Knopf, der geht, statt zu schalten
|
||||||
|
Mit dem status-bewussten Pfad (D46) zeigt das Diagramm die offene Front — im
|
||||||
|
mitgelieferten Plan 24 Stationen, verteilt über einen Baum von über 20 000 px
|
||||||
|
Breite. Sie **zu sehen** ist damit gelöst, sie **abzugehen** nicht: Man müsste
|
||||||
|
jede von Hand suchen. Der Knopf im Diagramm-Kopf holt sie der Reihe nach in die
|
||||||
|
Mitte.
|
||||||
|
|
||||||
|
**Der einzige Knopf im Diagramm-Kopf, der kein Umschalter ist.** „Verworfene
|
||||||
|
einblenden" (D4), „günstigster Pfad" (D18) und die Falt-Voreinstellung (D44)
|
||||||
|
beschreiben je einen Zustand; dieser löst eine **Bewegung** aus. Deshalb kein
|
||||||
|
`aria-pressed` und keine gedrückte Optik — er sieht aus wie „kopieren" und
|
||||||
|
„herunterladen", die ebenfalls etwas *tun*.
|
||||||
|
|
||||||
|
**Der Sprung fasst nur das Diagramm an** (Nutzer): zentrieren, hervorheben,
|
||||||
|
Tastaturfokus — buchstäblich die Behandlung des ausdrücklichen Alt+Klicks
|
||||||
|
(D25-Nachtrag 1), inklusive Puls und der Hervorhebung der
|
||||||
|
Abhängigkeits-Kanten (D41). Erwogen war, zusätzlich die Schreibmarke auf die
|
||||||
|
Zeile zu setzen; das kostete aber den Fokus im Baum (der nächste Druck müsste
|
||||||
|
ihn zurückholen) und wäre auf dem Telefon bei jedem Sprung ein Bereichswechsel
|
||||||
|
weg vom Diagramm. Der Weg in den Text steht direkt daneben offen: **Alt+Enter**
|
||||||
|
am fokussierten Knoten, dieselbe Geste wie überall.
|
||||||
|
|
||||||
|
**Nach der letzten wieder die erste** (Nutzer). Ein Knopf, der am Ende
|
||||||
|
aufhört, wirkt kaputt und bräuchte eine eigene Rückstell-Geste; dass man wieder
|
||||||
|
oben ist, sieht man am Baum.
|
||||||
|
|
||||||
|
**Kein Zähler am Knopf** (Nutzer). Der „Was ist neu?"-Knopf trägt einen, hier
|
||||||
|
wäre er ein zehntes Element in einer Zeile, die schon knapp ist — die Zahl der
|
||||||
|
offenen Stationen steht stattdessen im **Tooltip** („… (24 offen)"), wo sie
|
||||||
|
nichts kostet.
|
||||||
|
|
||||||
|
**Kein eigener Zustand: fortgesetzt wird am hervorgehobenen Knoten.** Ein
|
||||||
|
gemerkter Index wäre die naheliegende Lösung und die schlechtere: Der Baum wird
|
||||||
|
bei **jedem Tastendruck** neu gebaut, die Stationsliste ändert sich unter dem
|
||||||
|
Index, und er zeigte danach auf etwas anderes. `currentNodeEl` (D25) überlebt
|
||||||
|
den Neubau dagegen von selbst, weil es aus der Cursor-Zeile neu abgeleitet
|
||||||
|
wird. Liegt der hervorgehobene Knoten nicht auf einer Station — etwa weil
|
||||||
|
jemand zwischendurch im Text getippt hat —, beginnt der Gang wieder vorn. Das
|
||||||
|
ist kein Notbehelf, sondern die richtige Antwort auf „zeig mir, was als
|
||||||
|
Nächstes dran ist".
|
||||||
|
|
||||||
|
**Verborgen, solange es nichts anzuspringen gibt** — bei ausgeschaltetem Pfad
|
||||||
|
(dann gibt es keine Stationen) ebenso wie bei einem durchweg erledigten Plan.
|
||||||
|
Dieselbe Zurückhaltung wie beim „Was ist neu?"-Knopf (D28).
|
||||||
|
|
||||||
|
**Die Kopfzeile hat das nicht mehr getragen — und das war kein Fehler des
|
||||||
|
Knopfes.** D17-Nachtrag 5 hatte die Zeile gerade erst auf acht Elemente
|
||||||
|
zurechtgemessen und dabei `flex-wrap:nowrap` als Riegel gesetzt, damit aus
|
||||||
|
einem stillen Umbruch ein sichtbarer Überlauf wird. Der neunte Knopf hat den
|
||||||
|
Riegel prompt ausgelöst — nachgemessen aber anders als erwartet:
|
||||||
|
|
||||||
|
- Bei **375 px** passte es weiterhin, nachdem die Lücke von 8 auf 6 px und der
|
||||||
|
Innenabstand von 10 auf 8 px ging: 345 px Inhalt, 359 px Platz, **14 px
|
||||||
|
Luft**, eine Reihe.
|
||||||
|
- Bei **320 px** ist es Arithmetik: 345 px Inhalt gegen 304 px Platz. Neun
|
||||||
|
fingergroße Ziele passen dort nicht, und unter 29 px zu gehen hat
|
||||||
|
D17-Nachtrag 5 ausdrücklich abgelehnt.
|
||||||
|
|
||||||
|
**Dabei ein älterer, stiller Fehler gefunden:** Bei Platzmangel schrumpfte
|
||||||
|
nicht etwa irgendetwas gleichmäßig — der **Modus-Wähler** ist das einzige
|
||||||
|
Element ohne feste Größe und wurde auf einen **2-px-Strich** zusammengedrückt,
|
||||||
|
während sein Icon 38 px breit darüber hinausragte. Das Bedienelement war
|
||||||
|
unbenutzbar und sah aus wie ein Trennstrich. `flex:0 0 auto` an allen Kindern
|
||||||
|
der Zeile stellt das ab: Niemand wird mehr zerdrückt.
|
||||||
|
|
||||||
|
**Darum schiebt die Zeile jetzt, statt zu zerdrücken oder abzuschneiden:**
|
||||||
|
`overflow-x:auto` auf dem Kopf (Scrollbalken ausgeblendet — auf Touch-Geräten
|
||||||
|
sind sie ohnehin Overlay). Bei 375 px ändert die Regel nichts, weil nichts
|
||||||
|
überläuft; bei 320 px bleiben alle neun Elemente in voller Größe erreichbar
|
||||||
|
(nachgemessen: 41 px Schiebeweg, Kopfhöhe unverändert 49 px, Modus-Wähler
|
||||||
|
wieder 40 px breit). Das ist die ehrliche Fortschreibung der D17-Regel: Der
|
||||||
|
Riegel sollte einen unbemerkten Layout-Wechsel verhindern, nicht ein
|
||||||
|
Bedienelement opfern.
|
||||||
|
|||||||
@@ -529,6 +529,19 @@ Restarbeit ist dann seine); ist ein ganzer Zweig erledigt, hat er keine. Linie,
|
|||||||
abgetönte Kopie und Punkte erscheinen bei aktivem Umschalter auch im
|
abgetönte Kopie und Punkte erscheinen bei aktivem Umschalter auch im
|
||||||
Grafikexport. Siehe D18, D46.
|
Grafikexport. Siehe D18, D46.
|
||||||
|
|
||||||
|
**Von Station zu Station.** Neben dem Umschalter steht ein **Knopf**, der die
|
||||||
|
Stationen der Reihe nach anspringt: Der erste Druck holt die **erste** — das,
|
||||||
|
was als Nächstes dran ist —, jeder weitere die nächste, nach der letzten wieder
|
||||||
|
die erste. Gegangen wird die Dokument-Reihenfolge, also dieselbe, in der die
|
||||||
|
Linie durch die Stationen fädelt. Der Knoten wird **zentriert, hervorgehoben
|
||||||
|
und bekommt den Tastaturfokus** — dieselbe Behandlung wie beim ausdrücklichen
|
||||||
|
Alt+Klick (§9, Sprung zwischen Diagramm und Text); von dort führt **Alt+Enter**
|
||||||
|
in die zugehörige Textzeile. Fortgesetzt wird am gerade hervorgehobenen Knoten:
|
||||||
|
Steht der auf einer Station, geht es bei der nächsten weiter, sonst wieder
|
||||||
|
vorn. Der Knopf ist **verborgen**, solange es keine Station gibt — bei
|
||||||
|
ausgeschaltetem Pfad ebenso wie bei einem durchweg erledigten Plan; sein
|
||||||
|
Tooltip nennt die Zahl der offenen Stationen. Siehe D47.
|
||||||
|
|
||||||
### Diagramm aus einer URL laden (`?sourceUrl=`)
|
### Diagramm aus einer URL laden (`?sourceUrl=`)
|
||||||
Der Editor kann den Notationstext aus einer externen Textdatei beziehen:
|
Der Editor kann den Notationstext aus einer externen Textdatei beziehen:
|
||||||
`…?sourceUrl=https://example.org/plan.txt` (relative Angaben werden gegen die
|
`…?sourceUrl=https://example.org/plan.txt` (relative Angaben werden gegen die
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ entscheiden, **bevor** Code entsteht.
|
|||||||
M-Badge. Angefangenes (`[~]`/`[/]`) zählt weiter voll, maßgeblich ist der
|
M-Badge. Angefangenes (`[~]`/`[/]`) zählt weiter voll, maßgeblich ist der
|
||||||
intrinsische Status. Kein neuer Umschalter — der vorhandene ändert seine
|
intrinsische Status. Kein neuer Umschalter — der vorhandene ändert seine
|
||||||
Bedeutung. `tests/frontier.test.js`.
|
Bedeutung. `tests/frontier.test.js`.
|
||||||
|
- [x] Von Station zu Station springen (Knopf im Diagramm-Kopf).
|
||||||
|
→ Umgesetzt (D47): `jumpToLeanStation()` holt die nächste offene Station
|
||||||
|
in die Mitte (Behandlung wie Alt+Klick, D25), nach der letzten wieder die
|
||||||
|
erste; ohne eigenen Zustand — fortgesetzt wird am hervorgehobenen Knoten.
|
||||||
|
Verborgen, solange es keine Station gibt; i18n `leanNextTooltip` in neun
|
||||||
|
Sprachen. Die Mobil-Kopfzeile musste dafür enger und darf unter 360 px
|
||||||
|
schieben.
|
||||||
- [ ] Nutzen je Knoten (Gegenstück zur Kosten-Größe) — Schreibweise offen,
|
- [ ] Nutzen je Knoten (Gegenstück zur Kosten-Größe) — Schreibweise offen,
|
||||||
SPEC-first (siehe ROADMAP „Kleinere Ideen").
|
SPEC-first (siehe ROADMAP „Kleinere Ideen").
|
||||||
- [ ] Aufwands-Rollup (Größen der Kinder aggregieren) — braucht erst eine
|
- [ ] Aufwands-Rollup (Größen der Kinder aggregieren) — braucht erst eine
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
- [^] Cost model, missing size counts as M (S)
|
- [^] Cost model, missing size counts as M (S)
|
||||||
- [x] Only the open front: what is done costs nothing (S) %% see D46
|
- [x] Only the open front: what is done costs nothing (S) %% see D46
|
||||||
- [^] Metro-map line through the leaves (S)
|
- [^] Metro-map line through the leaves (S)
|
||||||
|
- [x] Step from station to station, one button (S) %% see D47
|
||||||
- [^] #closure: Count the whole dependency closure (M)
|
- [^] #closure: Count the whole dependency closure (M)
|
||||||
- [^] Shared dependencies counted only once (S)
|
- [^] Shared dependencies counted only once (S)
|
||||||
- [^] The cheapest alternative is no longer the local one (M) %% see D34, D42
|
- [^] The cheapest alternative is no longer the local one (M) %% see D34, D42
|
||||||
|
|||||||
@@ -504,3 +504,13 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
|
|||||||
Hash-Rückfall, der Marker-Pfad ist nur zu prüfen, wenn man einen echten
|
Hash-Rückfall, der Marker-Pfad ist nur zu prüfen, wenn man einen echten
|
||||||
`commit/<sha>` in `index.html` einspritzt (danach zurücknehmen!) und
|
`commit/<sha>` in `index.html` einspritzt (danach zurücknehmen!) und
|
||||||
`window.fetch` überschreibt.
|
`window.fetch` überschreibt.
|
||||||
|
- **Diagramm-Kopfzeile auf Mobil (D17-Nachtrag 5, D47):** Die Zeile ist voll —
|
||||||
|
bei 375 px bleiben mit neun Bedienelementen noch 14 px Luft, bei 320 px passt
|
||||||
|
es arithmetisch nicht mehr und die Zeile **schiebt** (`overflow-x:auto`).
|
||||||
|
Wer ein zehntes Element hinzufügt, misst nach (`scrollWidth - clientWidth`
|
||||||
|
am `.panel-head`) und rechnet damit, dass auf 375 px etwas weichen muss.
|
||||||
|
Nicht anfassen: die 29 px Knopfgröße (Fingerziel) und `flex:0 0 auto` an den
|
||||||
|
Kindern — ohne das schrumpft bei Platzmangel ausgerechnet der Modus-Wähler
|
||||||
|
(das einzige Element ohne feste Größe) auf einen 2-px-Strich, während sein
|
||||||
|
Icon darüber hinausragt. Das sieht aus wie ein Trennstrich und ist
|
||||||
|
unbenutzbar.
|
||||||
|
|||||||
@@ -155,6 +155,13 @@
|
|||||||
<button type="button" class="copybtn togglebtn" id="cheapBtn" aria-pressed="true" data-i18n-title="cheapTooltip" data-i18n-aria="cheapTooltip" title="Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück" aria-label="Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück">
|
<button type="button" class="copybtn togglebtn" id="cheapBtn" aria-pressed="true" data-i18n-title="cheapTooltip" data-i18n-aria="cheapTooltip" title="Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück" aria-label="Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="5" cy="6" r="2.5"/><circle cx="19" cy="18" r="2.5"/><path d="M7.5 6H14a3 3 0 0 1 0 6H10a3 3 0 0 0 0 6h6.5"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="5" cy="6" r="2.5"/><circle cx="19" cy="18" r="2.5"/><path d="M7.5 6H14a3 3 0 0 1 0 6H10a3 3 0 0 0 0 6h6.5"/></svg>
|
||||||
</button>
|
</button>
|
||||||
|
<!-- Von Station zu Station des günstigsten Pfads (SPEC §9, D47). Kein
|
||||||
|
Umschalter, sondern eine Bewegung: jeder Druck holt die nächste noch
|
||||||
|
offene Station in die Mitte. Verborgen, solange es keine gibt (wie
|
||||||
|
der „Was ist neu?"-Knopf daneben). -->
|
||||||
|
<button type="button" class="copybtn" id="leanNextBtn" title="Zur nächsten Station des günstigsten Pfads" aria-label="Zur nächsten Station des günstigsten Pfads" hidden>
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2.5 12h5" stroke-dasharray="2.5 2.5"/><circle cx="11" cy="12" r="3"/><path d="M15 12h6M18.5 9.5l2.5 2.5-2.5 2.5"/></svg>
|
||||||
|
</button>
|
||||||
<button type="button" class="copybtn freshbtn" id="freshBtn" title="Neu in Produktion" aria-label="Neu in Produktion" hidden>
|
<button type="button" class="copybtn freshbtn" id="freshBtn" title="Neu in Produktion" aria-label="Neu in Produktion" hidden>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z"/></svg>
|
||||||
<span class="freshcount" id="freshCount" aria-hidden="true">0</span>
|
<span class="freshcount" id="freshCount" aria-hidden="true">0</span>
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ function render(){
|
|||||||
highlightCurrentNode(false);
|
highlightCurrentNode(false);
|
||||||
revealFocusMark(); /* `!!!` ins Bild holen, wenn die Marke neu ist (SPEC §1) */
|
revealFocusMark(); /* `!!!` ins Bild holen, wenn die Marke neu ist (SPEC §1) */
|
||||||
updateFreshBtn(); /* Zähler folgt der gerade gerenderten Menge (D28) */
|
updateFreshBtn(); /* Zähler folgt der gerade gerenderten Menge (D28) */
|
||||||
|
updateLeanBtn(); /* Stationen des Pfads haben sich geändert (D47) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fokusmarke `!!!` (SPEC §1): Der erste markierte Knoten wird ins Bild geholt —
|
/* Fokusmarke `!!!` (SPEC §1): Der erste markierte Knoten wird ins Bild geholt —
|
||||||
@@ -1432,6 +1433,47 @@ cheapBtn.addEventListener('click', () => {
|
|||||||
saveUI();
|
saveUI();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ---------- Von Station zu Station (SPEC §9, D47) ----------
|
||||||
|
Kein Umschalter, sondern eine Bewegung: Jeder Druck holt die nächste noch
|
||||||
|
offene Station des günstigsten Pfads in die Mitte — beim ersten Druck die
|
||||||
|
erste, danach der Reihe nach weiter, nach der letzten wieder von vorn.
|
||||||
|
Gegangen wird die DOM-Reihenfolge, also dieselbe, in der die Pfadlinie durch
|
||||||
|
die Stationen fädelt (D18/D46).
|
||||||
|
|
||||||
|
Ohne eigenen Zustand: Fortgesetzt wird an dem Knoten, der GERADE
|
||||||
|
hervorgehoben ist (`currentNodeEl`, D25). Steht der auf einer Station, geht
|
||||||
|
es bei der nächsten weiter; steht er woanders — etwa weil zwischendurch im
|
||||||
|
Text getippt wurde —, beginnt der Gang wieder vorn, also bei dem, was als
|
||||||
|
Nächstes dran ist. Ein gemerkter Index wäre schlechter: Beim Tippen wird der
|
||||||
|
Baum neu gebaut und die Liste ändert sich unter ihm. */
|
||||||
|
function jumpToLeanStation(){
|
||||||
|
const st = [...out.querySelectorAll('.node.cheap-leaf')];
|
||||||
|
if(!st.length) return;
|
||||||
|
const el = st[(st.indexOf(currentNodeEl) + 1) % st.length]; /* -1 ⇒ die erste */
|
||||||
|
/* Auf Mobil ist das Diagramm womöglich gar nicht vorn — erst holen, sonst
|
||||||
|
misst sich der Zielknoten zu null (D17-Nachtrag 1). */
|
||||||
|
if(isMobile()) setMobilePane('diagram', true);
|
||||||
|
/* Genau die Behandlung des ausdrücklichen Alt+Klicks (D25): Fokus ohne
|
||||||
|
eigenes Scrollen, dann hervorheben, pulsen, zentrieren — und die
|
||||||
|
Abhängigkeits-Kanten des Knotens nehmen es mit (D41). */
|
||||||
|
el.focus({preventScroll: true});
|
||||||
|
caretLine = +el.dataset.line || null;
|
||||||
|
highlightCurrentNode(true, 'center');
|
||||||
|
}
|
||||||
|
const leanNextBtn = document.getElementById('leanNextBtn');
|
||||||
|
leanNextBtn.addEventListener('click', jumpToLeanStation);
|
||||||
|
/* Verborgen, solange es nichts anzuspringen gibt — bei ausgeschaltetem Pfad
|
||||||
|
ebenso wie bei einem durchweg erledigten Plan (D46). Dieselbe Zurückhaltung
|
||||||
|
wie beim „Was ist neu?"-Knopf: ein Knopf, der nichts tut, ist Rauschen. */
|
||||||
|
function updateLeanBtn(){
|
||||||
|
const n = out.querySelectorAll('.node.cheap-leaf').length;
|
||||||
|
leanNextBtn.hidden = !n;
|
||||||
|
if(!n) return;
|
||||||
|
const tip = t('leanNextTooltip', {n});
|
||||||
|
leanNextBtn.title = tip;
|
||||||
|
leanNextBtn.setAttribute('aria-label', tip);
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------- In die Zwischenablage kopieren ---------- */
|
/* ---------- In die Zwischenablage kopieren ---------- */
|
||||||
async function writeClipboard(text){
|
async function writeClipboard(text){
|
||||||
try{ await navigator.clipboard.writeText(text); return; }catch(_){}
|
try{ await navigator.clipboard.writeText(text); return; }catch(_){}
|
||||||
@@ -1516,6 +1558,7 @@ const I18N = {
|
|||||||
riskTooltip:"High Risk – Aufwand noch unklar.",
|
riskTooltip:"High Risk – Aufwand noch unklar.",
|
||||||
discardedTooltip:"Verworfene Knoten samt Teilbaum ein-/ausblenden",
|
discardedTooltip:"Verworfene Knoten samt Teilbaum ein-/ausblenden",
|
||||||
cheapTooltip:"Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück",
|
cheapTooltip:"Günstigsten Pfad hervorheben – nicht benötigte Alternativen treten zurück",
|
||||||
|
leanNextTooltip:"Zur nächsten Station des günstigsten Pfads springen – was als Nächstes dran ist ({n} offen)",
|
||||||
foldSmallTooltip:"Knoten der Größe M und kleiner zuklappen – erneut drücken klappt alle wieder auf",
|
foldSmallTooltip:"Knoten der Größe M und kleiner zuklappen – erneut drücken klappt alle wieder auf",
|
||||||
implicitSizeTooltip:"Keine Größe angegeben – für die Kostenschätzung als M angenommen",
|
implicitSizeTooltip:"Keine Größe angegeben – für die Kostenschätzung als M angenommen",
|
||||||
fullscreenTooltip:"Vollbild – Panels nutzen die ganze Fensterbreite",
|
fullscreenTooltip:"Vollbild – Panels nutzen die ganze Fensterbreite",
|
||||||
@@ -1597,6 +1640,7 @@ const I18N = {
|
|||||||
riskTooltip:"High risk – effort still unclear.",
|
riskTooltip:"High risk – effort still unclear.",
|
||||||
discardedTooltip:"Show/hide discarded nodes and their subtree",
|
discardedTooltip:"Show/hide discarded nodes and their subtree",
|
||||||
cheapTooltip:"Highlight the cheapest path – unneeded alternatives recede",
|
cheapTooltip:"Highlight the cheapest path – unneeded alternatives recede",
|
||||||
|
leanNextTooltip:"Jump to the next station on the cheapest path – what to tackle next ({n} open)",
|
||||||
foldSmallTooltip:"Collapse nodes of size M and smaller – press again to expand them all",
|
foldSmallTooltip:"Collapse nodes of size M and smaller – press again to expand them all",
|
||||||
implicitSizeTooltip:"No size given – assumed as M for the cost estimate",
|
implicitSizeTooltip:"No size given – assumed as M for the cost estimate",
|
||||||
fullscreenTooltip:"Full screen – panels use the full window width",
|
fullscreenTooltip:"Full screen – panels use the full window width",
|
||||||
@@ -1678,6 +1722,7 @@ const I18N = {
|
|||||||
riskTooltip:"Alto riesgo – esfuerzo aún incierto.",
|
riskTooltip:"Alto riesgo – esfuerzo aún incierto.",
|
||||||
discardedTooltip:"Mostrar u ocultar los nodos descartados y su subárbol",
|
discardedTooltip:"Mostrar u ocultar los nodos descartados y su subárbol",
|
||||||
cheapTooltip:"Resaltar la ruta más económica: las alternativas no necesarias se atenúan",
|
cheapTooltip:"Resaltar la ruta más económica: las alternativas no necesarias se atenúan",
|
||||||
|
leanNextTooltip:"Ir a la siguiente estación de la ruta más económica: lo próximo que toca ({n} pendientes)",
|
||||||
foldSmallTooltip:"Plegar los nodos de talla M o menor: pulsa de nuevo para desplegarlos todos",
|
foldSmallTooltip:"Plegar los nodos de talla M o menor: pulsa de nuevo para desplegarlos todos",
|
||||||
implicitSizeTooltip:"Sin tamaño indicado: se asume M para el cálculo de costes",
|
implicitSizeTooltip:"Sin tamaño indicado: se asume M para el cálculo de costes",
|
||||||
fullscreenTooltip:"Pantalla completa – los paneles usan todo el ancho de la ventana",
|
fullscreenTooltip:"Pantalla completa – los paneles usan todo el ancho de la ventana",
|
||||||
@@ -1759,6 +1804,7 @@ const I18N = {
|
|||||||
riskTooltip:"Risque élevé – effort encore incertain.",
|
riskTooltip:"Risque élevé – effort encore incertain.",
|
||||||
discardedTooltip:"Afficher/masquer les nœuds abandonnés et leur sous-arbre",
|
discardedTooltip:"Afficher/masquer les nœuds abandonnés et leur sous-arbre",
|
||||||
cheapTooltip:"Mettre en évidence le chemin le moins coûteux – les alternatives inutiles s'estompent",
|
cheapTooltip:"Mettre en évidence le chemin le moins coûteux – les alternatives inutiles s'estompent",
|
||||||
|
leanNextTooltip:"Aller à la station suivante du chemin le moins coûteux – la prochaine chose à faire ({n} en attente)",
|
||||||
foldSmallTooltip:"Replier les nœuds de taille M et moins – appuyez à nouveau pour tout déplier",
|
foldSmallTooltip:"Replier les nœuds de taille M et moins – appuyez à nouveau pour tout déplier",
|
||||||
implicitSizeTooltip:"Aucune taille indiquée – considérée comme M pour l'estimation des coûts",
|
implicitSizeTooltip:"Aucune taille indiquée – considérée comme M pour l'estimation des coûts",
|
||||||
fullscreenTooltip:"Plein écran – les panneaux occupent toute la largeur de la fenêtre",
|
fullscreenTooltip:"Plein écran – les panneaux occupent toute la largeur de la fenêtre",
|
||||||
@@ -1840,6 +1886,7 @@ const I18N = {
|
|||||||
riskTooltip:"Wysokie ryzyko – nakład jeszcze niejasny.",
|
riskTooltip:"Wysokie ryzyko – nakład jeszcze niejasny.",
|
||||||
discardedTooltip:"Pokaż/ukryj odrzucone węzły wraz z poddrzewem",
|
discardedTooltip:"Pokaż/ukryj odrzucone węzły wraz z poddrzewem",
|
||||||
cheapTooltip:"Wyróżnij najtańszą ścieżkę – niepotrzebne alternatywy są przygaszone",
|
cheapTooltip:"Wyróżnij najtańszą ścieżkę – niepotrzebne alternatywy są przygaszone",
|
||||||
|
leanNextTooltip:"Przejdź do następnej stacji najtańszej ścieżki – co dalej ({n} otwartych)",
|
||||||
foldSmallTooltip:"Zwiń węzły o rozmiarze M i mniejsze – naciśnij ponownie, aby rozwinąć wszystkie",
|
foldSmallTooltip:"Zwiń węzły o rozmiarze M i mniejsze – naciśnij ponownie, aby rozwinąć wszystkie",
|
||||||
implicitSizeTooltip:"Nie podano rozmiaru – przyjęto M do szacowania kosztów",
|
implicitSizeTooltip:"Nie podano rozmiaru – przyjęto M do szacowania kosztów",
|
||||||
fullscreenTooltip:"Pełny ekran – panele wykorzystują całą szerokość okna",
|
fullscreenTooltip:"Pełny ekran – panele wykorzystują całą szerokość okna",
|
||||||
@@ -1921,6 +1968,7 @@ const I18N = {
|
|||||||
riskTooltip:"Высокий риск – оценка ещё не ясна.",
|
riskTooltip:"Высокий риск – оценка ещё не ясна.",
|
||||||
discardedTooltip:"Показать/скрыть отклонённые узлы вместе с поддеревом",
|
discardedTooltip:"Показать/скрыть отклонённые узлы вместе с поддеревом",
|
||||||
cheapTooltip:"Выделить самый дешёвый путь — ненужные альтернативы приглушаются",
|
cheapTooltip:"Выделить самый дешёвый путь — ненужные альтернативы приглушаются",
|
||||||
|
leanNextTooltip:"Перейти к следующей станции самого дешёвого пути — что делать дальше ({n} открыто)",
|
||||||
foldSmallTooltip:"Свернуть узлы размера M и меньше — нажмите ещё раз, чтобы развернуть все",
|
foldSmallTooltip:"Свернуть узлы размера M и меньше — нажмите ещё раз, чтобы развернуть все",
|
||||||
implicitSizeTooltip:"Размер не указан — для оценки затрат принят как M",
|
implicitSizeTooltip:"Размер не указан — для оценки затрат принят как M",
|
||||||
fullscreenTooltip:"Полный экран – панели занимают всю ширину окна",
|
fullscreenTooltip:"Полный экран – панели занимают всю ширину окна",
|
||||||
@@ -2002,6 +2050,7 @@ const I18N = {
|
|||||||
riskTooltip:"उच्च जोखिम – प्रयास अभी अस्पष्ट।",
|
riskTooltip:"उच्च जोखिम – प्रयास अभी अस्पष्ट।",
|
||||||
discardedTooltip:"अस्वीकृत नोड्स और उनके उप-वृक्ष दिखाएँ/छिपाएँ",
|
discardedTooltip:"अस्वीकृत नोड्स और उनके उप-वृक्ष दिखाएँ/छिपाएँ",
|
||||||
cheapTooltip:"सबसे किफ़ायती पथ को उजागर करें – अनावश्यक विकल्प मंद हो जाते हैं",
|
cheapTooltip:"सबसे किफ़ायती पथ को उजागर करें – अनावश्यक विकल्प मंद हो जाते हैं",
|
||||||
|
leanNextTooltip:"सबसे किफ़ायती पथ के अगले पड़ाव पर जाएँ – अगला काम ({n} शेष)",
|
||||||
foldSmallTooltip:"आकार M और उससे छोटे नोड समेटें – सभी को खोलने के लिए फिर दबाएँ",
|
foldSmallTooltip:"आकार M और उससे छोटे नोड समेटें – सभी को खोलने के लिए फिर दबाएँ",
|
||||||
implicitSizeTooltip:"कोई आकार नहीं दिया गया – लागत अनुमान के लिए M माना गया",
|
implicitSizeTooltip:"कोई आकार नहीं दिया गया – लागत अनुमान के लिए M माना गया",
|
||||||
fullscreenTooltip:"पूर्ण स्क्रीन – पैनल पूरी विंडो चौड़ाई का उपयोग करते हैं",
|
fullscreenTooltip:"पूर्ण स्क्रीन – पैनल पूरी विंडो चौड़ाई का उपयोग करते हैं",
|
||||||
@@ -2072,6 +2121,7 @@ const I18N = {
|
|||||||
fullscreenTooltip:"全屏——面板占据整个窗口宽度",
|
fullscreenTooltip:"全屏——面板占据整个窗口宽度",
|
||||||
discardedTooltip:"显示/隐藏已放弃的节点及其子树",
|
discardedTooltip:"显示/隐藏已放弃的节点及其子树",
|
||||||
cheapTooltip:"突出显示成本最低的路径——不需要的备选项将淡化",
|
cheapTooltip:"突出显示成本最低的路径——不需要的备选项将淡化",
|
||||||
|
leanNextTooltip:"跳到成本最低路径的下一站——接下来该做的事(还有 {n} 项)",
|
||||||
foldSmallTooltip:"折叠尺寸 M 及更小的节点——再次点击可全部展开",
|
foldSmallTooltip:"折叠尺寸 M 及更小的节点——再次点击可全部展开",
|
||||||
implicitSizeTooltip:"未指定尺寸——成本估算时按 M 计",
|
implicitSizeTooltip:"未指定尺寸——成本估算时按 M 计",
|
||||||
ghostTooltip:"从 M 号起,元素应进一步细分。",
|
ghostTooltip:"从 M 号起,元素应进一步细分。",
|
||||||
@@ -2153,6 +2203,7 @@ const I18N = {
|
|||||||
fullscreenTooltip:"全画面 — パネルがウィンドウ幅いっぱいを使用",
|
fullscreenTooltip:"全画面 — パネルがウィンドウ幅いっぱいを使用",
|
||||||
discardedTooltip:"破棄したノードとその下位ツリーを表示/非表示",
|
discardedTooltip:"破棄したノードとその下位ツリーを表示/非表示",
|
||||||
cheapTooltip:"最も低コストの経路を強調 – 不要な選択肢は控えめに表示",
|
cheapTooltip:"最も低コストの経路を強調 – 不要な選択肢は控えめに表示",
|
||||||
|
leanNextTooltip:"最も低コストの経路の次の駅へ移動 – 次にやること(残り {n} 件)",
|
||||||
foldSmallTooltip:"サイズ M 以下のノードを折りたたむ – もう一度押すとすべて展開",
|
foldSmallTooltip:"サイズ M 以下のノードを折りたたむ – もう一度押すとすべて展開",
|
||||||
implicitSizeTooltip:"サイズ未指定 – コスト見積もりのため M として扱う",
|
implicitSizeTooltip:"サイズ未指定 – コスト見積もりのため M として扱う",
|
||||||
ghostTooltip:"サイズ M 以上の要素はさらに分解すべきです。",
|
ghostTooltip:"サイズ M 以上の要素はさらに分解すべきです。",
|
||||||
|
|||||||
+16
-2
@@ -1108,8 +1108,22 @@
|
|||||||
Ein-Bereich-Modus überhaupt gibt. Die Knöpfe passen längst — es waren die
|
Ein-Bereich-Modus überhaupt gibt. Die Knöpfe passen längst — es waren die
|
||||||
Abstände: 14 px Lücke mal sieben plus 2×16 px Innenabstand sind mehr als
|
Abstände: 14 px Lücke mal sieben plus 2×16 px Innenabstand sind mehr als
|
||||||
ein Drittel von 375 px. Deshalb hier enger und `nowrap` als Riegel; die
|
ein Drittel von 375 px. Deshalb hier enger und `nowrap` als Riegel; die
|
||||||
Knöpfe selbst bleiben unangetastet (Fingergröße). */
|
Knöpfe selbst bleiben unangetastet (Fingergröße).
|
||||||
body.mobile .panel-head{gap:8px;flex-wrap:nowrap;padding-inline:10px}
|
Mit dem neunten Bedienelement (Stationssprung, D47) noch einmal enger:
|
||||||
|
6 px Lücke und 8 px Innenabstand. Dazu `flex:0 0 auto` — ohne das schrumpft
|
||||||
|
ausgerechnet der Modus-Wähler (das einzige Element ohne feste Größe) bei
|
||||||
|
Platzmangel auf einen 2-px-Strich zusammen, während sein Icon darüber
|
||||||
|
hinausragt. Ein zerdrücktes Bedienelement ist der schlechtere Fehler als
|
||||||
|
ein sichtbarer Überlauf (D17-Nachtrag 5). */
|
||||||
|
body.mobile .panel-head{gap:6px;flex-wrap:nowrap;padding-inline:8px}
|
||||||
|
body.mobile .panel-head>*{flex:0 0 auto}
|
||||||
|
/* Unterhalb von rund 360 px ist es reine Arithmetik: neun Bedienelemente à
|
||||||
|
29 px plus Lücken brauchen mehr, als dort überhaupt da ist (bei 320 px
|
||||||
|
fehlen 41 px). Kleiner als 29 px darf ein Fingerziel nicht werden
|
||||||
|
(D17-Nachtrag 5), also schiebt die Zeile. Bei 375 px bleiben 14 px Luft —
|
||||||
|
dort ändert die Regel nichts, weil nichts überläuft. */
|
||||||
|
body.mobile .panel-head{overflow-x:auto;scrollbar-width:none}
|
||||||
|
body.mobile .panel-head::-webkit-scrollbar{display:none}
|
||||||
/* Inhalte rund 25 % kleiner, damit mehr Plan auf die Fläche passt
|
/* Inhalte rund 25 % kleiner, damit mehr Plan auf die Fläche passt
|
||||||
(D17-Nachtrag 2). Das Diagramm macht das über den CSS-`zoom` (Faktor auf
|
(D17-Nachtrag 2). Das Diagramm macht das über den CSS-`zoom` (Faktor auf
|
||||||
den Nutzer-Zoom, siehe MOBILE_ZOOM in app.js); der Text über die
|
den Nutzer-Zoom, siehe MOBILE_ZOOM in app.js); der Text über die
|
||||||
|
|||||||
Reference in New Issue
Block a user