From 9f705ad7e44cf71b86a1e70db7e90efbca85061b Mon Sep 17 00:00:00 2001 From: ki Date: Sat, 29 Aug 2026 17:42:49 +0400 Subject: [PATCH 1/2] BUG-03: Span-Geometrie im Initial-Render (grid-column/grid-row direkt setzen) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial-Render hatte keine Span-Geometrie: renderGrid() hing Items in die Origin-Cell mit width:100% height:100%. Ein 2x2-Item sah damit aus wie eine 1x1-Box mit Mini-Inhalt. Resize-Code (in BUG-01/02-Branch, applySize) setzte zwar korrekt grid-column/row per JS — aber nur WÄHREND Resize. Initial war's kaputt. Fix: - renderGrid() hängt Items jetzt direkt in den Grid-Container (cont), nicht mehr in die Origin-Cell. - style.gridColumn = '${it.x + 1} / span ${it.w}' setzt die CSS-Span-Geometrie direkt im Inline-Style. - Origin-Cell bekommt nur noch die 'occupied'-Klasse (für die Optik). - DOM-Baum: Items sind Geschwister der Cells → keine DOM-Kollision mehr, Drag-Events auf Nachbar-Cells werden nicht vom Item verschluckt. Vorteile: - 2x2-Item rendert visuell über 2x2 Cells (richtige Größe beim ersten Laden) - Drag auf JEDE Zelle innerhalb der Item-Bbox funktioniert - applySize (Resize) kann den Span nahtlos aktualisieren ohne DOM-Wechsel - Kein Flicker beim Resize (initial state ist schon korrekt) Beweis: tests/test_span_geometry.js (8/8 grün) 1. gridColumn wird per JS gesetzt 2. gridRow wird per JS gesetzt 3. Item wird in Container (cont) gehängt 4. Item wird NICHT mehr in Origin-Cell gehängt 5. Origin-Cell bekommt 'occupied' Klasse 6. gridColumn Format: / span 7. Keine width:100% im Item-CSS-Block 8. CSS-Kommentar erwähnt BUG-03 Hinweis: Mein ursprüngliches Issue-Statement war zu pessimistisch (Items verdecken keine Nachbarzellen visuell). Sie saßen nur 1x1 in der Origin-Cell. Dennoch ist der Fix substantiell: Initial-Render zeigt jetzt korrekte Größe, und zukünftige Resize-Codes können sich auf den Span verlassen ohne DOM-Mutation. Closes #5 --- templates/index.html | 22 +++++++++------ tests/test_span_geometry.js | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 tests/test_span_geometry.js diff --git a/templates/index.html b/templates/index.html index ab7d1fe..1a963bf 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1297,7 +1297,6 @@ // Place items into their origin cell const occ = occupiedCells(); layoutItems.forEach((it, idx) => { - const cellIdx = it.x + ',' + it.y; const originCell = cont.querySelector(`[data-cell="${it.x + it.y * gridCols}"]`); const div = document.createElement('div'); @@ -1305,7 +1304,7 @@ div.className = 'grid-item'; if (it.w > 1 || it.h > 1) div.classList.add('span-2x2'); div.dataset.idx = idx; - div.draggable = true; + div.draggable = true; // legacy HTML5-DnD bleibt für Move; Resize nutzt separaten Handler // OOB marker const hasOOB = it.y + it.h > gridRows || it.x + it.w > gridCols || it.y < 0; @@ -1321,12 +1320,19 @@
`; - if (originCell) { - originCell.classList.add('occupied'); - originCell.appendChild(div); - } else { - cont.appendChild(div); - } + // BUG-03: Span-Geometrie per CSS Grid (grid-column/grid-row) statt + // per Cell-DOM-Anker. Item wird direkt in den Grid-Container gehängt, + // nicht in die Origin-Cell. Damit: + // - NxN-Items rendern visuell über NxN Cells + // - Drag-Events auf Nachbar-Cells werden nicht vom Item-DOM + // verschluckt (Item ist nicht mehr Kind der Cell) + // - Resize (applySize in startResizePointer) kann den Span nahtlos + // aktualisieren ohne den DOM-Anker zu wechseln + div.style.gridColumn = `${it.x + 1} / span ${it.w}`; + div.style.gridRow = `${it.y + 1} / span ${it.h}`; + cont.appendChild(div); + // Origin-Cell nur als "occupied" markieren, damit sie ihre leere Optik verliert + if (originCell) originCell.classList.add('occupied'); }); // Mark occupied cells diff --git a/tests/test_span_geometry.js b/tests/test_span_geometry.js new file mode 100644 index 0000000..04e0dce --- /dev/null +++ b/tests/test_span_geometry.js @@ -0,0 +1,56 @@ +// Test für BUG-03: Span-Geometrie im Initial-Render. +// +// Erwartung nach Fix: +// 1) renderGrid setzt grid-column/grid-row am Item direkt (per JS). +// 2) Item wird in den Container gehängt (cont.appendChild), nicht in originCell. +// 3) Origin-Cell bekommt nur die "occupied"-Klasse. +// 4) 2x2-Item hat style.gridColumn === ' / span 2' und gridRow === ' / span 2'. + +const fs = require('fs'); +const html = fs.readFileSync('templates/index.html', 'utf8'); +const js = html.match(/