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:
mhoennig
2026-08-23 14:47:19 +02:00
co-authored by Claude Fable 5
parent ec338eb558
commit e554b6d9b8
2 changed files with 67 additions and 3 deletions
+26 -3
View File
@@ -2603,6 +2603,9 @@ function updateDocName(){
updatePadLink(); /* Schreibschutz + Pad-Knopf hängen am aktiven Dokument (D31) */
}
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(){
docList.innerHTML = docs.map(d => {
if(d.id === renamingId){
@@ -2664,7 +2667,7 @@ function restoreDoc(){
closeDocMenu();
}
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(); }
/* Beim Wechseln/Anlegen/Löschen zuerst den aktuellen Editortext ins aktive
Dokument sichern, dann das Ziel laden und neu rendern. */
@@ -2728,6 +2731,11 @@ function switchDoc(id){
loadActiveIntoEditor();
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(){
flushActive();
const d = { id: uid(), name: uniqueName(t('docNewName')), text: '' };
@@ -2737,11 +2745,23 @@ function newDoc(){
loadActiveIntoEditor();
persistDocs();
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();
}
function renameDoc(){
if(!activeDoc()) return;
renamingId = activeId; /* aktives Dokument inline umbenennen */
renameIsNew = false;
renderDocMenu();
}
function commitRename(){
@@ -2752,8 +2772,9 @@ function commitRename(){
renamingId = null;
if(d && val){ d.name = val; persistDocs(); updateDocName(); }
renderDocMenu();
finishNewDoc();
}
function cancelRename(){ renamingId = null; renderDocMenu(); }
function cancelRename(){ renamingId = null; renderDocMenu(); finishNewDoc(); }
function deleteDoc(){
const d = activeDoc();
if(!d) return;
@@ -3091,7 +3112,9 @@ docList.addEventListener('click', e => {
switchDoc(btn.dataset.id);
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('docDelete').addEventListener('click', e => { e.stopPropagation(); deleteDoc(); });
document.getElementById('docRestore').addEventListener('click', e => { e.stopPropagation(); restoreDoc(); });