feat: ein neues Dokument beginnt mit seinem Namen (D51)
„+ Neu" legte das Dokument unter „Unbenannt" an und setzte den Cursor ins leere Textfeld; das Umbenennen war ein eigener, zweiter Gang durchs Menü — und wurde entsprechend oft nicht gemacht. Jetzt öffnet sich unmittelbar das Inline-Umbenennen (D22) mit ausgewähltem Vorschlag: tippen ersetzt ihn, Enter bestätigt. Das Dokument existiert vorher: angelegt, gespeichert und aktiviert wie bisher, nur der Fokus geht ins Namensfeld statt ins Textfeld. Ein Abbruch verwirft nichts — Esc behält den Vorschlag. Der Gegenentwurf (erst benennen, dann anlegen) hätte ein Dokument im Schwebezustand gebraucht. Nach dem Benennen geht es im Textfeld weiter — Anlegen heißt schreiben wollen. Der Merker `renameIsNew` unterscheidet diesen Fall vom gewöhnlichen Umbenennen aus dem Menü, das unverändert bleibt (Menü bleibt offen, Fokus wandert nicht); `closeDocMenu()` setzt ihn mit zurück, sonst trüge ein abgebrochener Vorgang seine Sonderbehandlung in den nächsten hinein. Nachgemessen: Nach „+ Neu" hat das Eingabefeld den Fokus und der Vorschlag ist vollständig markiert. Enter mit „Sprint 15" -> Titelzeile, `werkbaum-docs` und Fokus im leeren Textfeld stimmen. Esc -> Vorschlag bleibt, Menü zu, Fokus im Text. Bestehendes Dokument umbenennen -> Menü bleibt offen, Fokus bleibt. 236 Tests grün. Grenze der Prüfung, benannt: Der Fokusverlust ließ sich nur als zugestelltes Ereignis prüfen, nicht als echter Fokuswechsel — ein synthetisches `.blur()` löst im Automaten keinen aus. Gegenprobe am unveränderten Pfad zeigt dasselbe, es ist also die Werkzeuggrenze und keine Regression (Lehre aus D25). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ec338eb558
commit
e554b6d9b8
@@ -3247,3 +3247,44 @@ und bei 320 px.
|
|||||||
`overflow` gibt, entscheidet damit über alles, was aus ihr herausragen soll —
|
`overflow` gibt, entscheidet damit über alles, was aus ihr herausragen soll —
|
||||||
Menüs, Tooltips, Overlays. In `frontend/CLAUDE.md` steht das jetzt bei der
|
Menüs, Tooltips, Overlays. In `frontend/CLAUDE.md` steht das jetzt bei der
|
||||||
Kopfzeilen-Stolperfalle.
|
Kopfzeilen-Stolperfalle.
|
||||||
|
|
||||||
|
## D51 — Ein neues Dokument beginnt mit seinem Namen
|
||||||
|
Bisher legte „+ Neu" das Dokument unter „Unbenannt" an und setzte den Cursor
|
||||||
|
ins leere Textfeld. Das Umbenennen war ein eigener, zweiter Gang durchs Menü —
|
||||||
|
und wurde entsprechend oft nicht gemacht: Wer drei Pläne führt, hat drei
|
||||||
|
„Unbenannt". Jetzt öffnet sich unmittelbar das Inline-Umbenennen (D22) mit
|
||||||
|
**ausgewähltem** Vorschlag; tippen ersetzt ihn, Enter bestätigt.
|
||||||
|
|
||||||
|
**Das Dokument existiert vorher.** Angelegt, gespeichert und aktiviert wird wie
|
||||||
|
bisher; nur der Fokus geht ins Namensfeld statt ins Textfeld. Ein **Abbruch
|
||||||
|
verwirft nichts** — Esc behält den Vorschlag „Unbenannt", so wie es vorher der
|
||||||
|
Normalfall war. Der Gegenentwurf (erst benennen, dann anlegen) hätte ein
|
||||||
|
Dokument im Schwebezustand gebraucht und die Frage aufgeworfen, was bei Esc
|
||||||
|
passiert; das ist mehr Mechanik für weniger Verlässlichkeit.
|
||||||
|
|
||||||
|
**Nach dem Benennen geht es im Textfeld weiter.** Anlegen heißt schreiben
|
||||||
|
wollen — den Namen zu vergeben ist die erste Hälfte der Geste, nicht ihr Zweck.
|
||||||
|
Der Merker `renameIsNew` unterscheidet diesen Fall vom gewöhnlichen Umbenennen
|
||||||
|
aus dem Menü, das unverändert bleibt (Menü bleibt offen, Fokus wandert nicht).
|
||||||
|
Er wird in `closeDocMenu()` mit zurückgesetzt, sonst trüge ein abgebrochener
|
||||||
|
Vorgang seine Sonderbehandlung in den nächsten hinein.
|
||||||
|
|
||||||
|
Für alle drei Wege aus dem Eingabefeld gilt dasselbe: **Enter**, **Esc** und
|
||||||
|
**Fokusverlust** benennen (bzw. behalten den Vorschlag), schließen das Menü und
|
||||||
|
setzen den Cursor in den Text. Auf dem Telefon ist das zugleich der Moment, in
|
||||||
|
dem die Bildschirmtastatur gebraucht wird — `keyboardOnJump(false)` steht schon
|
||||||
|
da, aus demselben Grund (D25: neues, leeres Dokument = tippen ist gemeint).
|
||||||
|
|
||||||
|
**Nachgemessen:** Nach „+ Neu" trägt das Eingabefeld den Fokus, der Vorschlag
|
||||||
|
ist vollständig markiert (`selectionStart` 0 bis Länge). Enter mit „Sprint 15":
|
||||||
|
Titelzeile, `werkbaum-docs` und der Fokus im leeren Textfeld stimmen. Esc:
|
||||||
|
Vorschlag bleibt, Menü zu, Fokus im Text. Umbenennen eines bestehenden
|
||||||
|
Dokuments: Menü bleibt offen, Fokus bleibt, wo er war.
|
||||||
|
|
||||||
|
**Grenze der Prüfung, benannt:** Der Fokusverlust ließ sich nur als
|
||||||
|
**zugestelltes Ereignis** prüfen, nicht als echter Fokuswechsel — ein
|
||||||
|
synthetisches `.blur()` löst im Automaten keinen aus. Gegenprobe am
|
||||||
|
**unveränderten** Pfad (bestehendes Dokument umbenennen): dort passiert
|
||||||
|
ebenfalls nichts, es ist also die Werkzeuggrenze und keine Regression. Dieselbe
|
||||||
|
Lehre wie in D25 und D17-Nachtrag 4 — was die Geräteumgebung stellt, beweist
|
||||||
|
der Emulator nicht.
|
||||||
|
|||||||
+26
-3
@@ -2603,6 +2603,9 @@ function updateDocName(){
|
|||||||
updatePadLink(); /* Schreibschutz + Pad-Knopf hängen am aktiven Dokument (D31) */
|
updatePadLink(); /* Schreibschutz + Pad-Knopf hängen am aktiven Dokument (D31) */
|
||||||
}
|
}
|
||||||
let renamingId = null; /* id des gerade inline umbenannten Dokuments (oder null) */
|
let renamingId = null; /* id des gerade inline umbenannten Dokuments (oder null) */
|
||||||
|
/* Kam das Umbenennen von einem frisch angelegten Dokument? Dann geht es danach
|
||||||
|
im Textfeld weiter — Anlegen heißt schreiben wollen (D51). */
|
||||||
|
let renameIsNew = false;
|
||||||
function renderDocMenu(){
|
function renderDocMenu(){
|
||||||
docList.innerHTML = docs.map(d => {
|
docList.innerHTML = docs.map(d => {
|
||||||
if(d.id === renamingId){
|
if(d.id === renamingId){
|
||||||
@@ -2664,7 +2667,7 @@ function restoreDoc(){
|
|||||||
closeDocMenu();
|
closeDocMenu();
|
||||||
}
|
}
|
||||||
function openDocMenu(){ renderDocMenu(); updateRestoreBtn(); docMenu.hidden = false; docTrigger.setAttribute('aria-expanded', 'true'); }
|
function openDocMenu(){ renderDocMenu(); updateRestoreBtn(); docMenu.hidden = false; docTrigger.setAttribute('aria-expanded', 'true'); }
|
||||||
function closeDocMenu(){ renamingId = null; docMenu.hidden = true; docTrigger.setAttribute('aria-expanded', 'false'); }
|
function closeDocMenu(){ renamingId = null; renameIsNew = false; docMenu.hidden = true; docTrigger.setAttribute('aria-expanded', 'false'); }
|
||||||
function toggleDocMenu(){ docMenu.hidden ? openDocMenu() : closeDocMenu(); }
|
function toggleDocMenu(){ docMenu.hidden ? openDocMenu() : closeDocMenu(); }
|
||||||
/* Beim Wechseln/Anlegen/Löschen zuerst den aktuellen Editortext ins aktive
|
/* Beim Wechseln/Anlegen/Löschen zuerst den aktuellen Editortext ins aktive
|
||||||
Dokument sichern, dann das Ziel laden und neu rendern. */
|
Dokument sichern, dann das Ziel laden und neu rendern. */
|
||||||
@@ -2728,6 +2731,11 @@ function switchDoc(id){
|
|||||||
loadActiveIntoEditor();
|
loadActiveIntoEditor();
|
||||||
persistDocs();
|
persistDocs();
|
||||||
}
|
}
|
||||||
|
/* Ein neues Dokument beginnt mit seinem Namen (D51): Statt es unter „Neues
|
||||||
|
Dokument" abzulegen und den Cursor ins leere Textfeld zu setzen, öffnet sich
|
||||||
|
sofort das Inline-Umbenennen mit **ausgewähltem** Vorschlag — tippen ersetzt
|
||||||
|
ihn, Enter bestätigt. Wer nichts eingibt, behält den Vorschlag; das Dokument
|
||||||
|
ist bereits angelegt, ein Abbruch verwirft es nicht. */
|
||||||
function newDoc(){
|
function newDoc(){
|
||||||
flushActive();
|
flushActive();
|
||||||
const d = { id: uid(), name: uniqueName(t('docNewName')), text: '' };
|
const d = { id: uid(), name: uniqueName(t('docNewName')), text: '' };
|
||||||
@@ -2737,11 +2745,23 @@ function newDoc(){
|
|||||||
loadActiveIntoEditor();
|
loadActiveIntoEditor();
|
||||||
persistDocs();
|
persistDocs();
|
||||||
keyboardOnJump(false); /* neues, leeres Dokument = tippen ist gemeint */
|
keyboardOnJump(false); /* neues, leeres Dokument = tippen ist gemeint */
|
||||||
|
renamingId = d.id;
|
||||||
|
renameIsNew = true;
|
||||||
|
renderDocMenu(); /* setzt den Fokus ins Eingabefeld und markiert es */
|
||||||
|
}
|
||||||
|
/* Nach dem Benennen eines frisch angelegten Dokuments geht es im Textfeld
|
||||||
|
weiter — die zweite Hälfte derselben Geste. Gilt auch für Esc: Der Vorschlag
|
||||||
|
bleibt dann stehen, das Dokument existiert ohnehin. */
|
||||||
|
function finishNewDoc(){
|
||||||
|
if(!renameIsNew) return;
|
||||||
|
renameIsNew = false;
|
||||||
|
closeDocMenu();
|
||||||
src.focus();
|
src.focus();
|
||||||
}
|
}
|
||||||
function renameDoc(){
|
function renameDoc(){
|
||||||
if(!activeDoc()) return;
|
if(!activeDoc()) return;
|
||||||
renamingId = activeId; /* aktives Dokument inline umbenennen */
|
renamingId = activeId; /* aktives Dokument inline umbenennen */
|
||||||
|
renameIsNew = false;
|
||||||
renderDocMenu();
|
renderDocMenu();
|
||||||
}
|
}
|
||||||
function commitRename(){
|
function commitRename(){
|
||||||
@@ -2752,8 +2772,9 @@ function commitRename(){
|
|||||||
renamingId = null;
|
renamingId = null;
|
||||||
if(d && val){ d.name = val; persistDocs(); updateDocName(); }
|
if(d && val){ d.name = val; persistDocs(); updateDocName(); }
|
||||||
renderDocMenu();
|
renderDocMenu();
|
||||||
|
finishNewDoc();
|
||||||
}
|
}
|
||||||
function cancelRename(){ renamingId = null; renderDocMenu(); }
|
function cancelRename(){ renamingId = null; renderDocMenu(); finishNewDoc(); }
|
||||||
function deleteDoc(){
|
function deleteDoc(){
|
||||||
const d = activeDoc();
|
const d = activeDoc();
|
||||||
if(!d) return;
|
if(!d) return;
|
||||||
@@ -3091,7 +3112,9 @@ docList.addEventListener('click', e => {
|
|||||||
switchDoc(btn.dataset.id);
|
switchDoc(btn.dataset.id);
|
||||||
closeDocMenu();
|
closeDocMenu();
|
||||||
});
|
});
|
||||||
document.getElementById('docNew').addEventListener('click', e => { e.stopPropagation(); newDoc(); renderDocMenu(); });
|
/* `newDoc()` zeichnet das Menü selbst neu — es geht direkt ins Umbenennen
|
||||||
|
(D51), und ein zweiter Durchlauf baute das Eingabefeld nur noch einmal auf. */
|
||||||
|
document.getElementById('docNew').addEventListener('click', e => { e.stopPropagation(); newDoc(); });
|
||||||
document.getElementById('docRename').addEventListener('click', e => { e.stopPropagation(); renameDoc(); });
|
document.getElementById('docRename').addEventListener('click', e => { e.stopPropagation(); renameDoc(); });
|
||||||
document.getElementById('docDelete').addEventListener('click', e => { e.stopPropagation(); deleteDoc(); });
|
document.getElementById('docDelete').addEventListener('click', e => { e.stopPropagation(); deleteDoc(); });
|
||||||
document.getElementById('docRestore').addEventListener('click', e => { e.stopPropagation(); restoreDoc(); });
|
document.getElementById('docRestore').addEventListener('click', e => { e.stopPropagation(); restoreDoc(); });
|
||||||
|
|||||||
Reference in New Issue
Block a user