feat: Mobil genau ein Bereich, Umschalter oben links statt Splitter
Auf 375 px ist für zwei Bereiche kein Platz. Die stufenlose Aufteilung (D17) hat das nur verwaltet: Jede Stellung war ein Kompromiss, in dem beide Bereiche zu klein waren, und sinnvoll waren praktisch nur die Extreme — also genau das, was ein Umschalter direkt anbietet. Der Splitter kostete dabei dauerhaft eine zweite Titelzeile plus Griff. Jetzt: Diagramm ODER Text über die ganze Fläche, oben links ein Knopf zum Umschalten. Er zeigt das Ziel, nicht den Zustand — anders als der Modus-Wähler daneben, der drei Zustände hat; hier sieht man am ganzen Bildschirm, welcher gilt. Umgesetzt als zwei feste Knöpfe, je einer pro Titelzeile, die daher kein Icon wechseln müssen. Der Bereichstitel „DIAGRAMM" entfällt, der Dokumenten-Wähler steht neben dem Umschalter (er gehört zum Textbereich, D22), die übrigen Aktions-Knöpfe werden mitgeschaltet und bleiben komprimiert. Falle beim Bauen: Ein display:none-Panel misst sich zu null, und render() läuft bei jedem Tastendruck im Textbereich. Gemessen nach einer Eingabe bei verborgenem Diagramm: Pfad-Linie weg, null Stationspunkte, kein --stem-x. setMobilePane() zeichnet deshalb beim Umschalten neu (zum Diagramm dieselben vier Schritte wie applyLayout, zum Text renderLineNos) — danach wieder 48 px Pfadlänge, 5 Punkte, --stem-x 67,4px. Die Sprünge (D25) holen den nötigen Bereich selbst nach vorn. Zustand in werkbaum-ui gemerkt. Entfallen: --drow auf Mobil, --pmin-d/-e, syncPanelMins, setMobileDrow, Titelzeilen-Tippen. Desktop unverändert (nachgeprüft). SPEC §9, D17 (Nachtrag) und frontend/CLAUDE.md nachgezogen; paneToText/ paneToDiagram in allen neun Sprachen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ad2f3bab14
commit
ec086eb526
@@ -197,6 +197,52 @@ und die vollständige Sprachliste dennoch erreichbar (frühere Lösung
|
|||||||
Voreinstellung greift nur, wenn noch **keine** gespeicherte Nutzerwahl vorliegt
|
Voreinstellung greift nur, wenn noch **keine** gespeicherte Nutzerwahl vorliegt
|
||||||
(eine bewusste Abschaltung bleibt so erhalten, siehe localStorage-Persistenz).
|
(eine bewusste Abschaltung bleibt so erhalten, siehe localStorage-Persistenz).
|
||||||
|
|
||||||
|
**Nachtrag — auf Mobil ist jetzt immer genau EIN Bereich zu sehen; der Splitter
|
||||||
|
entfällt dort ganz.** Die oben beschriebene stufenlose Aufteilung hat das
|
||||||
|
eigentliche Problem nur verwaltet, statt es zu lösen: Auf 375 px ist für zwei
|
||||||
|
Bereiche kein Platz. Jede Aufteilung war ein Kompromiss, in dem **beide**
|
||||||
|
Bereiche zu klein waren, und die praktisch einzigen sinnvollen Stellungen waren
|
||||||
|
ohnehin die Extreme — also genau das, was ein Umschalter direkt anbietet. Der
|
||||||
|
Splitter kostete außerdem dauerhaft eine zweite Titelzeile plus 14 px Griff für
|
||||||
|
etwas, das man auf dem Telefon nicht dosiert, sondern wechselt.
|
||||||
|
|
||||||
|
**Der Umschalter zeigt das Ziel, nicht den Zustand.** Damit weicht er bewusst
|
||||||
|
vom Modus-Wähler daneben ab, der das aktive Icon zeigt und reihum schaltet:
|
||||||
|
Der hat drei Zustände, die man ohne Anzeige nicht auseinanderhält; hier gibt es
|
||||||
|
zwei, und welcher gerade gilt, sieht man am ganzen Bildschirm. Ein Knopf, der
|
||||||
|
den Zustand anzeigt, den man ohnehin vor sich hat, sagt nichts — einer, der
|
||||||
|
das Ziel zeigt, sagt, was passiert. Umgesetzt als **zwei feste Knöpfe**, je
|
||||||
|
einer pro Titelzeile: Weil immer nur eine Zeile sichtbar ist, braucht keiner
|
||||||
|
sein Icon zu wechseln.
|
||||||
|
|
||||||
|
**Der Dokumenten-Wähler steht neben dem Umschalter** und damit nur im
|
||||||
|
Textbereich. Das ist keine Platzentscheidung, sondern die richtige Zuordnung:
|
||||||
|
Er bestimmt, *welchen Text* man bearbeitet (D22) — im Diagrammbereich wäre er
|
||||||
|
ein Fremdkörper. Die übrigen Aktions-Knöpfe bleiben, wo sie sind, und werden
|
||||||
|
dadurch von selbst mitgeschaltet; ihre komprimierte Mobil-Form (Modus-Wähler
|
||||||
|
als Reihum-Icon, Download als Overlay) bleibt unverändert.
|
||||||
|
|
||||||
|
**Die Falle beim Bauen: ein `display:none`-Panel misst sich zu null.** Der
|
||||||
|
verborgene Bereich wird wirklich ausgeblendet — nur so bekommt der sichtbare
|
||||||
|
die ganze Höhe. Alles, was aus der Live-Geometrie zeichnet, liefert dann aber
|
||||||
|
Unsinn, und `render()` läuft bei **jedem Tastendruck** im Textbereich.
|
||||||
|
Nachgemessen nach einer Eingabe bei verborgenem Diagramm: Pfad-Linie **weg**,
|
||||||
|
null Stationspunkte, kein `--stem-x`. Das Umschalten zeichnet deshalb neu —
|
||||||
|
zum Diagramm hin dieselben vier Schritte wie ein Moduswechsel
|
||||||
|
(`applyOptStairs`, `alignStems`, `drawCheapPath`, `drawDepLinks`), zum Text hin
|
||||||
|
der Zeilennummern-Streifen, der ebenso am Spiegel misst (D33). Danach wieder
|
||||||
|
48 px Pfadlänge, 5 Punkte, `--stem-x: 67,4px`.
|
||||||
|
|
||||||
|
Der sichtbare Bereich wird in `werkbaum-ui` gemerkt — global über alle
|
||||||
|
Dokumente wie der übrige Ansichts-Zustand (D22). Die Sprünge zwischen Diagramm
|
||||||
|
und Text (D25) holen den nötigen Bereich selbst nach vorn: `revealEditor()`
|
||||||
|
schaltet auf Text (wie es auf dem Desktop ein zugeklapptes Panel aufklappt),
|
||||||
|
`focusNodeOfCaret()` auf das Diagramm — und zwar **vor** dem Zentrieren, sonst
|
||||||
|
misst sich der Zielknoten noch zu null. Entfallen sind damit `--drow` auf
|
||||||
|
Mobil, die Grid-Minima `--pmin-d`/`--pmin-e`, `syncPanelMins()`,
|
||||||
|
`setMobileDrow()` und das Titelzeilen-Tippen; Desktop behält Splitter,
|
||||||
|
Presets und Fenster-Buttons unverändert.
|
||||||
|
|
||||||
## D18 — Günstigsten Pfad per Inversion zeigen, fehlende Größe = M
|
## D18 — Günstigsten Pfad per Inversion zeigen, fehlende Größe = M
|
||||||
Der kostengünstigste Weg durch den Baum wird hervorgehoben (Umschalter im
|
Der kostengünstigste Weg durch den Baum wird hervorgehoben (Umschalter im
|
||||||
Diagramm-Kopf, Default an, Zustand persistiert). Nötig sind bei **all of** alle
|
Diagramm-Kopf, Default an, Zustand persistiert). Nötig sind bei **all of** alle
|
||||||
|
|||||||
+13
-10
@@ -391,16 +391,19 @@ Siehe D29.
|
|||||||
(50 %-Höhe) weiterhin auf der Knotenmitte liegt.
|
(50 %-Höhe) weiterhin auf der Knotenmitte liegt.
|
||||||
|
|
||||||
### Kleiner Bildschirm (mobil)
|
### Kleiner Bildschirm (mobil)
|
||||||
Ab schmaler Breite (≤ 640 px, z. B. Smartphone) werden Diagramm und Texteditor
|
Ab schmaler Breite (≤ 640 px, z. B. Smartphone) ist **immer genau ein Bereich**
|
||||||
**gestapelt** und über den **Splitter** frei geteilt: Ziehen verteilt beliebig,
|
zu sehen — Diagramm **oder** Text, jeweils über die ganze Fläche. Oben links in
|
||||||
jederzeit erneut verstellbar; die beiden **Titelzeilen bleiben dabei immer
|
der Titelzeile schaltet ein **Knopf** auf den anderen um; er zeigt das Ziel
|
||||||
stehen** (jedes Panel schrumpft höchstens bis auf seine volle Titelzeile — die
|
(Textzeilen bzw. Baum), denn den Zustand hat man ohnehin vor sich. Es gibt hier
|
||||||
Zeilen-Minima entsprechen den gemessenen Kopfhöhen). Ein **Antippen einer
|
weder Splitter noch Min/Normal/Max-Buttons — es ist nichts zu teilen. Der
|
||||||
Titelzeile klappt dieses Panel ganz aus** (das andere schrumpft auf seine
|
Bereichstitel „DIAGRAMM" entfällt; die Zeile wird für Umschalter und Aktionen
|
||||||
Titelzeile). Es gibt hier kein diskretes Minimieren/Einrasten mehr (kein Snap,
|
gebraucht. Der **Dokumenten-Wähler** steht direkt neben dem Umschalter und ist
|
||||||
keine Min/Normal/Max-Buttons) — die Aufteilung ist durchgehend stufenlos.
|
damit genau dann zu sehen, wenn der Text vorn ist. Die übrigen
|
||||||
Voreinstellung ist Diagramm maximiert (Editor als Titelzeile). Die **Legende**
|
**Aktions-Knöpfe** bleiben rechts in der Titelzeile und werden mit
|
||||||
bekommt hier einen eigenen
|
umgeschaltet — jeder Bereich zeigt seine eigenen, in der unten beschriebenen
|
||||||
|
komprimierten Form. Der sichtbare Bereich wird gemerkt; ein Sprung zwischen
|
||||||
|
Diagramm und Text (§9) holt den nötigen Bereich selbst nach vorn.
|
||||||
|
Voreinstellung ist das Diagramm. Die **Legende** bekommt hier einen eigenen
|
||||||
Umschalter im Editor-Kopf (statt der dauerhaften „AGENDA“-Zeile), damit sie
|
Umschalter im Editor-Kopf (statt der dauerhaften „AGENDA“-Zeile), damit sie
|
||||||
zugeklappt keinen Platz kostet. Der **Modus-Wähler** zeigt nur das aktive Icon
|
zugeklappt keinen Platz kostet. Der **Modus-Wähler** zeigt nur das aktive Icon
|
||||||
und schaltet bei jedem Tippen reihum weiter (horizontal → kompakt → vertikal →
|
und schaltet bei jedem Tippen reihum weiter (horizontal → kompakt → vertikal →
|
||||||
|
|||||||
+13
-6
@@ -383,12 +383,19 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
|
|||||||
der any-of-Teilbaum. `alignStems()` misst deshalb nach jedem `render()` (und
|
der any-of-Teilbaum. `alignStems()` misst deshalb nach jedem `render()` (und
|
||||||
in `applyLayout`) die Knotenmitte und setzt `--stem-x`; Fallback im CSS ist
|
in `applyLayout`) die Knotenmitte und setzt `--stem-x`; Fallback im CSS ist
|
||||||
`50%`. Messwerte durch `zoom` zurückrechnen, sonst stimmt es nur bei 100 %.
|
`50%`. Messwerte durch `zoom` zurückrechnen, sonst stimmt es nur bei 100 %.
|
||||||
- Kleiner Bildschirm: `body.mobile` (per `matchMedia`, ≤ 640 px) stapelt
|
- Kleiner Bildschirm: `body.mobile` (per `matchMedia`, ≤ 640 px) zeigt **genau
|
||||||
Diagramm/Editor mit **stufenlosem** Splitter (kein Snap/Collapse wie auf
|
einen** Bereich — `body.pane-diagram` bzw. `body.pane-text`, umgeschaltet über
|
||||||
Desktop): der Gutter-Drag ruft `setMobileDrow()` (klemmt `--drow` zwischen den
|
je einen festen Knopf pro Titelzeile (`#paneToText`/`#paneToDiagram`,
|
||||||
Kopfhöhen `--pmin-d`/`--pmin-e`, per `syncPanelMins()` gemessen), ein Tipp auf
|
`setMobilePane()`); kein Splitter, keine Fenster-Buttons (D17-Nachtrag).
|
||||||
eine Titelzeile maximiert das Panel. `applyLayout` ruft auf Mobil **kein**
|
**Der verborgene Bereich ist `display:none` und misst sich damit zu null** —
|
||||||
`applySplit` (das würde `--drow` löschen). Dazu eigener Legenden-Umschalter
|
`setMobilePane()` MUSS neu zeichnen: zum Diagramm hin dieselben vier Schritte
|
||||||
|
wie `applyLayout` (`applyOptStairs`/`alignStems`/`drawCheapPath`/
|
||||||
|
`drawDepLinks`), zum Text hin `renderLineNos()`. Ohne das ist nach dem Tippen
|
||||||
|
im Textbereich die Pfad-Linie weg (gemessen). Die Sprünge (D25) schalten den
|
||||||
|
Bereich selbst um: `revealEditor()` auf Text, `focusNodeOfCaret()` aufs
|
||||||
|
Diagramm — **vor** dem Zentrieren. Zustand in `werkbaum-ui` (`mobilePane`),
|
||||||
|
Variable oben bei `padView` deklariert (saveUI liest sie).
|
||||||
|
`applyLayout` ruft auf Mobil **kein** `applySplit`. Dazu eigener Legenden-Umschalter
|
||||||
(`#legendBtn`), schlanke Sprachwahl, Download-Overlay; Default Vollbild +
|
(`#legendBtn`), schlanke Sprachwahl, Download-Overlay; Default Vollbild +
|
||||||
Diagramm maximiert. Layout-CSS hängt an `body.mobile`, nicht an einer eigenen
|
Diagramm maximiert. Layout-CSS hängt an `body.mobile`, nicht an einer eigenen
|
||||||
`@media`-Regel — beide Seiten müssen denselben 640-px-Schwellwert nutzen
|
`@media`-Regel — beide Seiten müssen denselben 640-px-Schwellwert nutzen
|
||||||
|
|||||||
@@ -46,6 +46,12 @@
|
|||||||
<div class="app" id="app">
|
<div class="app" id="app">
|
||||||
<div class="panel editor">
|
<div class="panel editor">
|
||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
|
<!-- Gegenstück zum Knopf im Diagramm-Kopf (D17-Nachtrag). Der
|
||||||
|
Dokumenten-Wähler steht direkt daneben und ist damit genau dann zu
|
||||||
|
sehen, wenn der Text vorn ist — er gehört zu diesem Bereich. -->
|
||||||
|
<button type="button" class="copybtn panetoggle" id="paneToDiagram" data-i18n-title="paneToDiagram" data-i18n-aria="paneToDiagram" title="Zum Diagramm wechseln" aria-label="Zum Diagramm wechseln">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="3" width="6" height="4" rx="1"/><rect x="2.5" y="17" width="6" height="4" rx="1"/><rect x="15.5" y="17" width="6" height="4" rx="1"/><path d="M12 7V13M5.5 13H18.5M5.5 13V17M18.5 13V17"/></svg>
|
||||||
|
</button>
|
||||||
<span class="doctrigger" id="docTrigger" role="button" tabindex="0" aria-haspopup="menu" aria-expanded="false" data-i18n-title="docSwitchTooltip" data-i18n-aria="docSwitchTooltip" title="Dokument wählen oder verwalten" aria-label="Dokument wählen oder verwalten">
|
<span class="doctrigger" id="docTrigger" role="button" tabindex="0" aria-haspopup="menu" aria-expanded="false" data-i18n-title="docSwitchTooltip" data-i18n-aria="docSwitchTooltip" title="Dokument wählen oder verwalten" aria-label="Dokument wählen oder verwalten">
|
||||||
<span class="docname" id="docName"></span>
|
<span class="docname" id="docName"></span>
|
||||||
<svg class="doc-caret" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
|
<svg class="doc-caret" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
|
||||||
@@ -135,6 +141,13 @@
|
|||||||
|
|
||||||
<div class="panel right">
|
<div class="panel right">
|
||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
|
<!-- Nur auf kleinem Bildschirm (D17-Nachtrag): dort ist immer genau ein
|
||||||
|
Bereich zu sehen, und dieser Knopf schaltet auf den anderen um. Er
|
||||||
|
zeigt das Ziel, nicht den Zustand — der Zustand ist der Bereich, den
|
||||||
|
man gerade vor sich hat. -->
|
||||||
|
<button type="button" class="copybtn panetoggle" id="paneToText" data-i18n-title="paneToText" data-i18n-aria="paneToText" title="Zum Text wechseln" aria-label="Zum Text wechseln">
|
||||||
|
<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="M4 6h16M4 10h16M4 14h10M4 18h13"/></svg>
|
||||||
|
</button>
|
||||||
<span data-i18n="diagramTitle">Diagramm</span>
|
<span data-i18n="diagramTitle">Diagramm</span>
|
||||||
<button type="button" class="copybtn togglebtn" id="showc" aria-pressed="false" data-i18n-title="discardedTooltip" data-i18n-aria="discardedTooltip" title="Verworfene Knoten samt Teilbaum ein-/ausblenden" aria-label="Verworfene Knoten samt Teilbaum ein-/ausblenden">
|
<button type="button" class="copybtn togglebtn" id="showc" aria-pressed="false" data-i18n-title="discardedTooltip" data-i18n-aria="discardedTooltip" title="Verworfene Knoten samt Teilbaum ein-/ausblenden" aria-label="Verworfene Knoten samt Teilbaum ein-/ausblenden">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="6" width="18" height="12" rx="2" stroke-dasharray="3 2.5"/><path d="M7 12h10"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="6" width="18" height="12" rx="2" stroke-dasharray="3 2.5"/><path d="M7 12h10"/></svg>
|
||||||
|
|||||||
+71
-41
@@ -56,6 +56,10 @@ let cheapPathOn = true;
|
|||||||
kann — weiter unten stünde sie dann noch in der temporalen Todeszone. */
|
kann — weiter unten stünde sie dann noch in der temporalen Todeszone. */
|
||||||
const PAD_VIEWS = ['both', 'pad', 'text'];
|
const PAD_VIEWS = ['both', 'pad', 'text'];
|
||||||
let padView = 'both';
|
let padView = 'both';
|
||||||
|
/* Sichtbarer Bereich auf kleinem Bildschirm (D17-Nachtrag): dort ist immer
|
||||||
|
genau einer zu sehen. Aus demselben Grund hier oben deklariert wie `padView`
|
||||||
|
— saveUI() liest ihn und läuft schon aus applySplit() heraus. */
|
||||||
|
let mobilePane = 'diagram';
|
||||||
/* Cursor-Zeile (D25) — bleibt `null`, bis der Cursor das erste Mal bewegt wurde,
|
/* Cursor-Zeile (D25) — bleibt `null`, bis der Cursor das erste Mal bewegt wurde,
|
||||||
sonst wäre nach dem Laden ungefragt die Wurzel markiert. Hier oben deklariert
|
sonst wäre nach dem Laden ungefragt die Wurzel markiert. Hier oben deklariert
|
||||||
wie `padView`: der Zeilennummern-Streifen (D33) liest sie, und der hängt an
|
wie `padView`: der Zeilennummern-Streifen (D33) liest sie, und der hängt an
|
||||||
@@ -802,9 +806,10 @@ function revealEditor(){
|
|||||||
saveUI();
|
saveUI();
|
||||||
}
|
}
|
||||||
if(isMobile()){
|
if(isMobile()){
|
||||||
const raw = app.style.getPropertyValue('--drow');
|
/* Auf Mobil ist der Text womöglich gar nicht vorn — dann holt der Sprung
|
||||||
const collapsed = raw ? parseFloat(raw) > mobileMaxDrow() - 40 : splitState === 'b';
|
ihn nach vorn, so wie er auf dem Desktop ein zugeklapptes Panel aufklappt
|
||||||
if(collapsed) setMobileDrow(app.getBoundingClientRect().height * 0.45, true);
|
(D17-Nachtrag). */
|
||||||
|
setMobilePane('text', true);
|
||||||
} else if(splitState === 'b'){
|
} else if(splitState === 'b'){
|
||||||
splitState = 'normal';
|
splitState = 'normal';
|
||||||
applySplit();
|
applySplit();
|
||||||
@@ -983,6 +988,10 @@ function focusNodeOfCaret(){
|
|||||||
const el = out.querySelector('.node[data-line="' + line + '"]');
|
const el = out.querySelector('.node[data-line="' + line + '"]');
|
||||||
if(!el) return; /* Kommentar, Leerzeile, ausgeblendet Verworfenes */
|
if(!el) return; /* Kommentar, Leerzeile, ausgeblendet Verworfenes */
|
||||||
caretLine = line;
|
caretLine = line;
|
||||||
|
/* Die Gegenrichtung zu revealEditor(): Auf Mobil steht der Text vorn, das
|
||||||
|
Diagramm ist verborgen — dort zu zentrieren zeigte auf nichts. Muss VOR
|
||||||
|
dem Scrollen laufen, sonst misst sich der Knoten noch zu null. */
|
||||||
|
if(isMobile()) setMobilePane('diagram', true);
|
||||||
/* Erst den Fokus (ohne eigenes Scrollen), dann hervorheben und zentrieren.
|
/* Erst den Fokus (ohne eigenes Scrollen), dann hervorheben und zentrieren.
|
||||||
Die Hervorhebung ist **dieselbe wie beim Zeilenwechsel** — Puls
|
Die Hervorhebung ist **dieselbe wie beim Zeilenwechsel** — Puls
|
||||||
eingeschlossen; der Unterschied ist allein, dass hier bewusst zentriert
|
eingeschlossen; der Unterschied ist allein, dass hier bewusst zentriert
|
||||||
@@ -1052,24 +1061,29 @@ function applySplit(){
|
|||||||
/* Setzt einen Minimier-Zustand während des Ziehens nur bei Änderung. */
|
/* Setzt einen Minimier-Zustand während des Ziehens nur bei Änderung. */
|
||||||
function snapTo(state){ if(splitState!==state){ splitState = state; applySplit(); } }
|
function snapTo(state){ if(splitState!==state){ splitState = state; applySplit(); } }
|
||||||
|
|
||||||
/* ---------- Mobil: freie Aufteilung (kontinuierlich, kein Snap/Collapse) ----------
|
/* ---------- Mobil: genau EIN Bereich, Umschalter oben links (D17-Nachtrag) ----------
|
||||||
Beide Titelzeilen bleiben stehen: die Grid-Zeilen-Minima --pmin-d/--pmin-e
|
Auf kleinem Bildschirm gibt es nichts zu teilen — Diagramm ODER Text füllt
|
||||||
entsprechen den (gemessenen) Kopfzeilenhöhen. --drow steuert die Diagramm-
|
die Fläche, ein Knopf im Kopf schaltet um. Der frühere Splitter samt --drow,
|
||||||
Höhe; das Tippen auf eine Titelzeile setzt sie auf ein Extrem. */
|
Grid-Minima (--pmin-d/--pmin-e) und Titelzeilen-Tippen ist damit entfallen. */
|
||||||
function headPx(sel){ return Math.ceil(document.querySelector(sel).getBoundingClientRect().height); }
|
function applyMobilePane(){
|
||||||
function syncPanelMins(){
|
document.body.classList.toggle('pane-diagram', mobilePane === 'diagram');
|
||||||
app.style.setProperty('--pmin-d', headPx('.panel.right .panel-head') + 'px');
|
document.body.classList.toggle('pane-text', mobilePane === 'text');
|
||||||
app.style.setProperty('--pmin-e', headPx('.panel.editor .panel-head') + 'px');
|
|
||||||
}
|
}
|
||||||
function cssPx(name, fallback){ return parseFloat(getComputedStyle(app).getPropertyValue(name)) || fallback; }
|
function setMobilePane(pane, save){
|
||||||
function mobileMinDrow(){ return cssPx('--pmin-d', 49); }
|
mobilePane = pane;
|
||||||
function mobileMaxDrow(){ return app.getBoundingClientRect().height - 14 - cssPx('--pmin-e', 44); }
|
applyMobilePane();
|
||||||
function setMobileDrow(px, save){
|
/* Ein Panel mit `display:none` misst sich zu **null**. Alles, was aus der
|
||||||
const v = Math.max(mobileMinDrow(), Math.min(px, mobileMaxDrow()));
|
Live-Geometrie zeichnet, muss deshalb nach dem Sichtbarwerden neu laufen —
|
||||||
splitState = 'custom';
|
im Diagramm dieselben vier Schritte wie beim Moduswechsel (applyLayout),
|
||||||
app.style.setProperty('--drow', v + 'px');
|
im Editor der Zeilennummern-Streifen, der am Spiegel misst (D33). */
|
||||||
|
if(pane === 'diagram'){ applyOptStairs(); alignStems(); drawCheapPath(); drawDepLinks(); }
|
||||||
|
else renderLineNos();
|
||||||
if(save) saveUI();
|
if(save) saveUI();
|
||||||
}
|
}
|
||||||
|
document.getElementById('paneToText')
|
||||||
|
.addEventListener('click', () => setMobilePane('text', true));
|
||||||
|
document.getElementById('paneToDiagram')
|
||||||
|
.addEventListener('click', () => setMobilePane('diagram', true));
|
||||||
document.querySelectorAll('.winbtn').forEach(b => {
|
document.querySelectorAll('.winbtn').forEach(b => {
|
||||||
b.addEventListener('click', e => {
|
b.addEventListener('click', e => {
|
||||||
/* Fenster-Buttons sind maßgeblich: nicht zum Titelzeilen-Restore durchreichen */
|
/* Fenster-Buttons sind maßgeblich: nicht zum Titelzeilen-Restore durchreichen */
|
||||||
@@ -1081,13 +1095,9 @@ document.querySelectorAll('.winbtn').forEach(b => {
|
|||||||
[editorPanel, diagramPanel].forEach(panel => {
|
[editorPanel, diagramPanel].forEach(panel => {
|
||||||
panel.querySelector('.panel-head').addEventListener('click', e => {
|
panel.querySelector('.panel-head').addEventListener('click', e => {
|
||||||
if(e.target.closest('button, label, input')) return; /* Bedienelemente behalten ihre Funktion */
|
if(e.target.closest('button, label, input')) return; /* Bedienelemente behalten ihre Funktion */
|
||||||
if(isMobile()){
|
/* Auf Mobil ist immer genau ein Panel zu sehen — es gibt keins, das per
|
||||||
/* Tippen auf eine Titelzeile klappt DIESES Panel ganz aus (das andere
|
Titelzeile hervorzuholen wäre; das erledigt der Umschalter (D17-Nachtrag). */
|
||||||
schrumpft auf seine Titelzeile) — funktioniert in jeder Aufteilung. */
|
if(isMobile()) return;
|
||||||
clearCollapse();
|
|
||||||
setMobileDrow(panel === diagramPanel ? mobileMaxDrow() : 0, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Desktop: nur ein minimiertes Panel per Titelzeile wiederherstellen. */
|
/* Desktop: nur ein minimiertes Panel per Titelzeile wiederherstellen. */
|
||||||
if(!panel.classList.contains('collapsed')) return;
|
if(!panel.classList.contains('collapsed')) return;
|
||||||
splitState = 'normal';
|
splitState = 'normal';
|
||||||
@@ -1115,12 +1125,6 @@ const SNAP = 72;
|
|||||||
gutter.addEventListener('pointermove', e => {
|
gutter.addEventListener('pointermove', e => {
|
||||||
if(!dragging) return;
|
if(!dragging) return;
|
||||||
const rect = app.getBoundingClientRect();
|
const rect = app.getBoundingClientRect();
|
||||||
if(isMobile()){
|
|
||||||
/* Frei ziehen; die Grid-Minima (--pmin) halten beide Titelzeilen sichtbar.
|
|
||||||
Kein Snap/Collapse — so bleibt der Splitter jederzeit beweglich. */
|
|
||||||
setMobileDrow(e.clientY - rect.top, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(app.classList.contains('side')){
|
if(app.classList.contains('side')){
|
||||||
const w = e.clientX - rect.left, maxw = rect.width - 14;
|
const w = e.clientX - rect.left, maxw = rect.width - 14;
|
||||||
if(w <= SNAP) snapTo('b'); /* Editor auf Titelzeile */
|
if(w <= SNAP) snapTo('b'); /* Editor auf Titelzeile */
|
||||||
@@ -1149,10 +1153,9 @@ function endDrag(e){
|
|||||||
}
|
}
|
||||||
gutter.addEventListener('pointerup', endDrag);
|
gutter.addEventListener('pointerup', endDrag);
|
||||||
gutter.addEventListener('pointercancel', endDrag);
|
gutter.addEventListener('pointercancel', endDrag);
|
||||||
/* Doppelklick auf den Splitter stellt die normale Aufteilung wieder her
|
/* Doppelklick auf den Splitter stellt die normale Aufteilung wieder her.
|
||||||
(auf Mobil: Diagramm maximiert). */
|
(Auf Mobil gibt es keinen Splitter mehr — D17-Nachtrag.) */
|
||||||
gutter.addEventListener('dblclick', () => {
|
gutter.addEventListener('dblclick', () => {
|
||||||
if(isMobile()){ clearCollapse(); setMobileDrow(mobileMaxDrow(), true); return; }
|
|
||||||
splitState = 'normal'; applySplit();
|
splitState = 'normal'; applySplit();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1275,6 +1278,8 @@ const I18N = {
|
|||||||
imprint:"Impressum",
|
imprint:"Impressum",
|
||||||
privacy:"Datenschutz",
|
privacy:"Datenschutz",
|
||||||
legendTooltip:"Legende ein-/ausblenden",
|
legendTooltip:"Legende ein-/ausblenden",
|
||||||
|
paneToText:"Zum Text wechseln",
|
||||||
|
paneToDiagram:"Zum Diagramm wechseln",
|
||||||
ghostTooltip:"Ab Größe M sollte ein Element weiter untergliedert werden.",
|
ghostTooltip:"Ab Größe M sollte ein Element weiter untergliedert werden.",
|
||||||
jumpHint:"Alt+Klick: zur Zeile im Text",
|
jumpHint:"Alt+Klick: zur Zeile im Text",
|
||||||
padReadonly:"Wird im Pad bearbeitet — hier nur lesen.",
|
padReadonly:"Wird im Pad bearbeitet — hier nur lesen.",
|
||||||
@@ -1353,6 +1358,8 @@ const I18N = {
|
|||||||
imprint:"Imprint (Impressum)",
|
imprint:"Imprint (Impressum)",
|
||||||
privacy:"Privacy",
|
privacy:"Privacy",
|
||||||
legendTooltip:"Show/hide legend",
|
legendTooltip:"Show/hide legend",
|
||||||
|
paneToText:"Switch to the text",
|
||||||
|
paneToDiagram:"Switch to the diagram",
|
||||||
ghostTooltip:"From size M upward, an item should be broken down further.",
|
ghostTooltip:"From size M upward, an item should be broken down further.",
|
||||||
jumpHint:"Alt+click: jump to the line in the text",
|
jumpHint:"Alt+click: jump to the line in the text",
|
||||||
padReadonly:"Edited in the pad — read-only here.",
|
padReadonly:"Edited in the pad — read-only here.",
|
||||||
@@ -1431,6 +1438,8 @@ const I18N = {
|
|||||||
imprint:"Aviso legal (Impressum)",
|
imprint:"Aviso legal (Impressum)",
|
||||||
privacy:"Privacidad",
|
privacy:"Privacidad",
|
||||||
legendTooltip:"Mostrar u ocultar la leyenda",
|
legendTooltip:"Mostrar u ocultar la leyenda",
|
||||||
|
paneToText:"Cambiar al texto",
|
||||||
|
paneToDiagram:"Cambiar al diagrama",
|
||||||
ghostTooltip:"A partir de la talla M, un elemento debería desglosarse más.",
|
ghostTooltip:"A partir de la talla M, un elemento debería desglosarse más.",
|
||||||
jumpHint:"Alt+clic: ir a la línea en el texto",
|
jumpHint:"Alt+clic: ir a la línea en el texto",
|
||||||
padReadonly:"Se edita en el pad — aquí solo lectura.",
|
padReadonly:"Se edita en el pad — aquí solo lectura.",
|
||||||
@@ -1509,6 +1518,8 @@ const I18N = {
|
|||||||
imprint:"Mentions légales (Impressum)",
|
imprint:"Mentions légales (Impressum)",
|
||||||
privacy:"Confidentialité",
|
privacy:"Confidentialité",
|
||||||
legendTooltip:"Afficher/masquer la légende",
|
legendTooltip:"Afficher/masquer la légende",
|
||||||
|
paneToText:"Passer au texte",
|
||||||
|
paneToDiagram:"Passer au diagramme",
|
||||||
ghostTooltip:"À partir de la taille M, un élément devrait être décomposé davantage.",
|
ghostTooltip:"À partir de la taille M, un élément devrait être décomposé davantage.",
|
||||||
jumpHint:"Alt+clic : aller à la ligne dans le texte",
|
jumpHint:"Alt+clic : aller à la ligne dans le texte",
|
||||||
padReadonly:"Modifié dans le pad — lecture seule ici.",
|
padReadonly:"Modifié dans le pad — lecture seule ici.",
|
||||||
@@ -1587,6 +1598,8 @@ const I18N = {
|
|||||||
imprint:"Nota prawna (Impressum)",
|
imprint:"Nota prawna (Impressum)",
|
||||||
privacy:"Prywatność",
|
privacy:"Prywatność",
|
||||||
legendTooltip:"Pokaż/ukryj legendę",
|
legendTooltip:"Pokaż/ukryj legendę",
|
||||||
|
paneToText:"Przełącz na tekst",
|
||||||
|
paneToDiagram:"Przełącz na diagram",
|
||||||
ghostTooltip:"Od rozmiaru M element powinien być dalej podzielony.",
|
ghostTooltip:"Od rozmiaru M element powinien być dalej podzielony.",
|
||||||
jumpHint:"Alt+kliknięcie: przejdź do wiersza w tekście",
|
jumpHint:"Alt+kliknięcie: przejdź do wiersza w tekście",
|
||||||
padReadonly:"Edytowane w padzie — tu tylko do czytania.",
|
padReadonly:"Edytowane w padzie — tu tylko do czytania.",
|
||||||
@@ -1665,6 +1678,8 @@ const I18N = {
|
|||||||
imprint:"Выходные данные (Impressum)",
|
imprint:"Выходные данные (Impressum)",
|
||||||
privacy:"Конфиденциальность",
|
privacy:"Конфиденциальность",
|
||||||
legendTooltip:"Показать/скрыть легенду",
|
legendTooltip:"Показать/скрыть легенду",
|
||||||
|
paneToText:"Перейти к тексту",
|
||||||
|
paneToDiagram:"Перейти к диаграмме",
|
||||||
ghostTooltip:"Начиная с размера M элемент следует далее декомпозировать.",
|
ghostTooltip:"Начиная с размера M элемент следует далее декомпозировать.",
|
||||||
jumpHint:"Alt+клик: перейти к строке в тексте",
|
jumpHint:"Alt+клик: перейти к строке в тексте",
|
||||||
padReadonly:"Редактируется в паде — здесь только чтение.",
|
padReadonly:"Редактируется в паде — здесь только чтение.",
|
||||||
@@ -1743,6 +1758,8 @@ const I18N = {
|
|||||||
imprint:"प्रकाशन विवरण (Impressum)",
|
imprint:"प्रकाशन विवरण (Impressum)",
|
||||||
privacy:"गोपनीयता",
|
privacy:"गोपनीयता",
|
||||||
legendTooltip:"लेजेंड दिखाएँ/छिपाएँ",
|
legendTooltip:"लेजेंड दिखाएँ/छिपाएँ",
|
||||||
|
paneToText:"टेक्स्ट पर जाएँ",
|
||||||
|
paneToDiagram:"आरेख पर जाएँ",
|
||||||
ghostTooltip:"आकार M से ऊपर किसी तत्व को और अधिक उप-विभाजित करना चाहिए।",
|
ghostTooltip:"आकार M से ऊपर किसी तत्व को और अधिक उप-विभाजित करना चाहिए।",
|
||||||
jumpHint:"Alt+क्लिक: टेक्स्ट में उस पंक्ति पर जाएँ",
|
jumpHint:"Alt+क्लिक: टेक्स्ट में उस पंक्ति पर जाएँ",
|
||||||
padReadonly:"पैड में संपादित होता है — यहाँ केवल पढ़ें।",
|
padReadonly:"पैड में संपादित होता है — यहाँ केवल पढ़ें।",
|
||||||
@@ -1821,6 +1838,8 @@ const I18N = {
|
|||||||
imprint:"法律声明(Impressum)",
|
imprint:"法律声明(Impressum)",
|
||||||
privacy:"隐私",
|
privacy:"隐私",
|
||||||
legendTooltip:"显示/隐藏图例",
|
legendTooltip:"显示/隐藏图例",
|
||||||
|
paneToText:"切换到文本",
|
||||||
|
paneToDiagram:"切换到图表",
|
||||||
brandTooltip:"「Werkbaum」大致意为‘工作之树’——即工作分解结构(WBS)之树。",
|
brandTooltip:"「Werkbaum」大致意为‘工作之树’——即工作分解结构(WBS)之树。",
|
||||||
fullscreenTooltip:"全屏——面板占据整个窗口宽度",
|
fullscreenTooltip:"全屏——面板占据整个窗口宽度",
|
||||||
discardedTooltip:"显示/隐藏已放弃的节点及其子树",
|
discardedTooltip:"显示/隐藏已放弃的节点及其子树",
|
||||||
@@ -1899,6 +1918,8 @@ const I18N = {
|
|||||||
imprint:"運営者情報(Impressum)",
|
imprint:"運営者情報(Impressum)",
|
||||||
privacy:"プライバシー",
|
privacy:"プライバシー",
|
||||||
legendTooltip:"凡例を表示/非表示",
|
legendTooltip:"凡例を表示/非表示",
|
||||||
|
paneToText:"テキストに切り替え",
|
||||||
|
paneToDiagram:"ダイアグラムに切り替え",
|
||||||
brandTooltip:"「Werkbaum」はおおよそ『作業の木』の意味 — 作業分解構成図(WBS)のツリーです。",
|
brandTooltip:"「Werkbaum」はおおよそ『作業の木』の意味 — 作業分解構成図(WBS)のツリーです。",
|
||||||
fullscreenTooltip:"全画面 — パネルがウィンドウ幅いっぱいを使用",
|
fullscreenTooltip:"全画面 — パネルがウィンドウ幅いっぱいを使用",
|
||||||
discardedTooltip:"破棄したノードとその下位ツリーを表示/非表示",
|
discardedTooltip:"破棄したノードとその下位ツリーを表示/非表示",
|
||||||
@@ -2226,6 +2247,9 @@ function saveUI(){
|
|||||||
padView: padView,
|
padView: padView,
|
||||||
pcol: app.style.getPropertyValue('--pcol') || null,
|
pcol: app.style.getPropertyValue('--pcol') || null,
|
||||||
prow: app.style.getPropertyValue('--prow') || null,
|
prow: app.style.getPropertyValue('--prow') || null,
|
||||||
|
/* Sichtbarer Bereich auf kleinem Bildschirm (D17-Nachtrag) — ebenfalls
|
||||||
|
global über alle Dokumente wie der übrige Ansichts-Zustand. */
|
||||||
|
mobilePane: mobilePane,
|
||||||
zoom: zoom,
|
zoom: zoom,
|
||||||
fullscreen: document.body.classList.contains('fullscreen')
|
fullscreen: document.body.classList.contains('fullscreen')
|
||||||
}));
|
}));
|
||||||
@@ -2263,6 +2287,7 @@ function restoreState(){
|
|||||||
/* Legende (D26): Aufteilung gilt unabhängig vom Preset des großen Splitters. */
|
/* Legende (D26): Aufteilung gilt unabhängig vom Preset des großen Splitters. */
|
||||||
if(ui && ui.hcol) app.style.setProperty('--hcol', ui.hcol);
|
if(ui && ui.hcol) app.style.setProperty('--hcol', ui.hcol);
|
||||||
if(ui && ui.hrow) app.style.setProperty('--hrow', ui.hrow);
|
if(ui && ui.hrow) app.style.setProperty('--hrow', ui.hrow);
|
||||||
|
if(ui && (ui.mobilePane === 'diagram' || ui.mobilePane === 'text')) mobilePane = ui.mobilePane;
|
||||||
if(ui && PAD_VIEWS.indexOf(ui.padView) >= 0) padView = ui.padView;
|
if(ui && PAD_VIEWS.indexOf(ui.padView) >= 0) padView = ui.padView;
|
||||||
if(ui && ui.pcol) app.style.setProperty('--pcol', ui.pcol);
|
if(ui && ui.pcol) app.style.setProperty('--pcol', ui.pcol);
|
||||||
if(ui && ui.prow) app.style.setProperty('--prow', ui.prow);
|
if(ui && ui.prow) app.style.setProperty('--prow', ui.prow);
|
||||||
@@ -2929,14 +2954,19 @@ function applyMobile(){
|
|||||||
const m = isMobile();
|
const m = isMobile();
|
||||||
document.body.classList.toggle('mobile', m);
|
document.body.classList.toggle('mobile', m);
|
||||||
if(m) collapseLangsel(); /* Sprachleiste eingeklappt starten (Overlay-Logik) */
|
if(m) collapseLangsel(); /* Sprachleiste eingeklappt starten (Overlay-Logik) */
|
||||||
if(!m) return;
|
if(!m){
|
||||||
/* Freie Aufteilung (kontinuierlich): kein Desktop-Collapse. Ist noch keine
|
/* Zurück auf Desktop: die Pane-Klassen abräumen, sonst bliebe ein Panel
|
||||||
Aufteilung gesetzt (frisch oder Alt-Preset), Diagramm maximieren (Editor
|
ausgeblendet — die Regeln hängen zwar an `body.mobile`, aber ein
|
||||||
bleibt als Titelzeile); eine gespeicherte --drow bleibt erhalten. */
|
stehengebliebener Zustand ist beim nächsten Verkleinern verwirrend. */
|
||||||
|
document.body.classList.remove('pane-diagram', 'pane-text');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Genau ein Bereich (D17-Nachtrag): kein Desktop-Collapse, keine Aufteilung.
|
||||||
|
Die frühere freie --drow-Größe wird abgeräumt — sie hat hier keine
|
||||||
|
Bedeutung mehr und störte die Grid-Zeile. */
|
||||||
clearCollapse();
|
clearCollapse();
|
||||||
syncPanelMins(); /* Grid-Minima = aktuelle Kopfzeilenhöhen */
|
app.style.removeProperty('--drow');
|
||||||
if(app.style.getPropertyValue('--drow')) splitState = 'custom';
|
applyMobilePane();
|
||||||
else setMobileDrow(mobileMaxDrow(), true);
|
|
||||||
/* Default Vollbild auf kleinem Bildschirm — nur ohne gespeicherte Wahl. */
|
/* Default Vollbild auf kleinem Bildschirm — nur ohne gespeicherte Wahl. */
|
||||||
if(!hadStoredUI && !document.body.classList.contains('fullscreen')){
|
if(!hadStoredUI && !document.body.classList.contains('fullscreen')){
|
||||||
document.body.classList.add('fullscreen');
|
document.body.classList.add('fullscreen');
|
||||||
|
|||||||
+32
-20
@@ -126,11 +126,12 @@
|
|||||||
Vertikal (Toggle an, .side): Editor links, Diagramm rechts.
|
Vertikal (Toggle an, .side): Editor links, Diagramm rechts.
|
||||||
Zwischen beiden liegt ein verschiebbarer Gutter (Splitter). */
|
Zwischen beiden liegt ein verschiebbarer Gutter (Splitter). */
|
||||||
.app{
|
.app{
|
||||||
/* Defaults der laufzeit-gesetzten Custom-Properties (JS setzt sie als
|
/* Defaults der laufzeit-gesetzten Custom-Properties (JS setzt --col/--drow
|
||||||
Inline-Style: --col/--drow per Splitter, --pmin-d/-e per syncPanelMins).
|
als Inline-Style per Splitter). Werte = die bisherigen var()-Fallbacks;
|
||||||
Werte = die bisherigen var()-Fallbacks; die JS-Erkennung „hat der Nutzer
|
die JS-Erkennung „hat der Nutzer gezogen?" liest app.style (Inline) und
|
||||||
gezogen?" liest app.style (Inline) und bleibt davon unberührt. */
|
bleibt davon unberührt. (--pmin-d/-e hielten auf Mobil die beiden
|
||||||
--col:360px;--drow:60%;--pmin-d:49px;--pmin-e:44px;
|
Titelzeilen frei — entfallen mit dem Ein-Bereich-Modell, D17-Nachtrag.) */
|
||||||
|
--col:360px;--drow:60%;
|
||||||
max-width:1200px;width:100%;margin:0 auto;
|
max-width:1200px;width:100%;margin:0 auto;
|
||||||
flex:1 1 auto;min-height:0;
|
flex:1 1 auto;min-height:0;
|
||||||
display:grid;gap:0;
|
display:grid;gap:0;
|
||||||
@@ -397,6 +398,7 @@
|
|||||||
.dlmenu{display:inline-flex;gap:3px}
|
.dlmenu{display:inline-flex;gap:3px}
|
||||||
.dltrigger{display:none}
|
.dltrigger{display:none}
|
||||||
.legendbtn{display:none} /* nur auf kleinem Bildschirm sichtbar */
|
.legendbtn{display:none} /* nur auf kleinem Bildschirm sichtbar */
|
||||||
|
.panetoggle{display:none} /* ebenso: dort gibt es nur einen Bereich */
|
||||||
/* Dokument-Wähler: der Name des aktiven Dokuments in der Editor-Titelzeile ist
|
/* Dokument-Wähler: der Name des aktiven Dokuments in der Editor-Titelzeile ist
|
||||||
zugleich der Auslöser eines Dropdowns zum Wechseln/Anlegen/Umbenennen/Löschen
|
zugleich der Auslöser eines Dropdowns zum Wechseln/Anlegen/Umbenennen/Löschen
|
||||||
(localStorage-Dokumente, noch kein Backend). */
|
(localStorage-Dokumente, noch kein Backend). */
|
||||||
@@ -1046,26 +1048,36 @@
|
|||||||
oder = gestrichelt grau. */
|
oder = gestrichelt grau. */
|
||||||
|
|
||||||
/* ---------- Kleiner Bildschirm (Smartphone) ----------
|
/* ---------- Kleiner Bildschirm (Smartphone) ----------
|
||||||
body.mobile wird per matchMedia (<=640px) gesetzt. Standardmäßig ist ein
|
body.mobile wird per matchMedia (<=640px) gesetzt. Es ist **immer genau ein
|
||||||
Bereich groß, der andere schrumpft auf seine Titelzeile und dient als
|
Bereich** zu sehen (Diagramm ODER Text); oben links schaltet ein Knopf um.
|
||||||
Umschalter (Tippen bringt ihn nach vorn). Die Min/Normal/Max-Buttons
|
Die Min/Normal/Max-Buttons und der Splitter entfallen hier ganz — es gibt
|
||||||
entfallen; geteilt wird weiterhin über den **Splitter**, der sichtbar
|
nichts zu teilen. Die Legende bekommt einen eigenen Umschalter statt der
|
||||||
bleibt. Das gestapelte Layout inkl. Gutter liefert bereits die
|
dauerhaften „AGENDA“-Zeile. Siehe D17-Nachtrag. */
|
||||||
820-px-Regel weiter oben. Die Legende bekommt einen eigenen Umschalter
|
|
||||||
statt der dauerhaften „AGENDA“-Zeile. */
|
|
||||||
body.mobile .winbtns{display:none}
|
body.mobile .winbtns{display:none}
|
||||||
/* Mobil: freie Aufteilung per Splitter — beide Titelzeilen bleiben IMMER
|
/* Ein Bereich füllt die Fläche; der andere ist `display:none` (nicht bloß
|
||||||
stehen (Zeilen-Minimum --pmin ≈ Titelzeilenhöhe). Kein diskretes
|
zusammengeschoben) — nur so bekommt der sichtbare die ganze Höhe, ohne
|
||||||
Minimieren/Snap; ein zusammengeschobenes Panel schrumpft nur bis auf seine
|
dass eine zweite Titelzeile sie anknabbert. Die Kehrseite steht in
|
||||||
volle Titelzeile (Körper flext auf 0, Panel ist overflow:hidden). Gilt auch
|
app.js: Ein verborgenes Diagramm misst sich zu 0, deshalb wird die
|
||||||
für den Seitenmodus, der auf Mobil ohnehin gestapelt ist. Der Drag setzt
|
Geometrie beim Zurückschalten neu gezeichnet. */
|
||||||
--drow (JS klemmt), das Tippen auf eine Titelzeile maximiert das Panel. */
|
|
||||||
body.mobile .app,
|
body.mobile .app,
|
||||||
body.mobile .app.side{
|
body.mobile .app.side{
|
||||||
grid-template-columns:minmax(0,1fr);
|
grid-template-columns:minmax(0,1fr);
|
||||||
grid-template-rows:minmax(var(--pmin-d,49px),var(--drow,60%)) 14px minmax(var(--pmin-e,44px),1fr);
|
grid-template-rows:minmax(0,1fr);
|
||||||
grid-template-areas:"diagram" "gutter" "editor";
|
grid-template-areas:"pane";
|
||||||
}
|
}
|
||||||
|
body.mobile .gutter{display:none}
|
||||||
|
body.mobile .panel.editor,
|
||||||
|
body.mobile .panel.right{grid-area:pane}
|
||||||
|
body.pane-diagram.mobile .panel.editor{display:none}
|
||||||
|
body.pane-text.mobile .panel.right{display:none}
|
||||||
|
/* Der Bereichstitel „DIAGRAMM" entfällt — welcher Bereich vorn ist, sagt der
|
||||||
|
Inhalt; die Zeile wird für den Umschalter und die Aktionen gebraucht. */
|
||||||
|
body.mobile .panel.right .panel-head>span[data-i18n="diagramTitle"]{display:none}
|
||||||
|
/* Umschalter oben links; er übernimmt vom entfallenen Titel das
|
||||||
|
`margin-right:auto`, damit die Aktions-Knöpfe rechts stehen bleiben. Im
|
||||||
|
Editor-Kopf tut das weiterhin der Dokumenten-Wähler daneben. */
|
||||||
|
body.mobile .panetoggle{display:inline-flex}
|
||||||
|
body.mobile .panel.right .panetoggle{margin-right:auto}
|
||||||
/* Untertitel: Kurzfassung, garantiert einzeilig (Ellipsis als Sicherung) */
|
/* Untertitel: Kurzfassung, garantiert einzeilig (Ellipsis als Sicherung) */
|
||||||
body.mobile .sub-full{display:none}
|
body.mobile .sub-full{display:none}
|
||||||
body.mobile .sub-short{display:inline}
|
body.mobile .sub-short{display:inline}
|
||||||
|
|||||||
Reference in New Issue
Block a user