function init() { const gridContainers = document.querySelectorAll('.vr--grid-pos-container'); if (!gridContainers.length) return; for (const gridContainer of gridContainers) { // Werte aus den data-Attributen holen oder Standardwerte setzen gridContainer.gridRows = parseInt(gridContainer.dataset.rows) || 1; // Standardwert für Reihen: 5 gridContainer.gridCols = parseInt(gridContainer.dataset.cols) || 6; // Standardwert für Spalten: 5 gridContainer.dataField = document.getElementById(gridContainer.dataset.fieldId); gridContainer.selectedIndices = gridContainer.selectedIndices || []; // Grid erstellen const fragment = document.createDocumentFragment(); // Erstelle die Zellen basierend auf Reihen und Spalten (gridRows * gridCols) for (let i = 0; i < gridContainer.gridRows * gridContainer.gridCols; i++) { const gridItem = document.createElement('div'); gridItem.classList.add('grid-cell'); gridItem.dataset.index = i; // Weise jeder Zelle ihren Index zu gridItem.addEventListener('click', () => toggleCell(gridContainer,i)); // Event für Klick hinzufügen fragment.appendChild(gridItem); } gridContainer.appendChild(fragment); loadSelection(gridContainer); } /** * Zelle ein-/auswählen * @param {number} index - Der Index der Zelle */ function toggleCell(gridContainer,index) { if (gridContainer.selectedIndices.includes(index)) { // Zelle abwählen removeRowOrColumn(gridContainer,index); } else { // Zelle hinzufügen gridContainer.selectedIndices.push(index); fillSelection(gridContainer); // Rechteck auffüllen } updateGrid(gridContainer); // Visuelle Aktualisierung saveSelection(gridContainer); // Speicherung der Auswahl } /** * Entfernt eine Zeile oder eine Spalte basierend auf dem Index * @param {number} index - Der Index der Zelle */ function removeRowOrColumn(gridContainer,index) { const row = Math.floor(index / gridContainer.gridCols); // Berechnet die aktuelle Reihe const col = index % gridContainer.gridCols; // Berechnet die aktuelle Spalte if (col === 0) { // Entferne die gesamte Reihe, wenn das Feld in der ersten Spalte ist // UND entferne alle darunterliegenden Reihen gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => { const cellRow = Math.floor(cell / gridContainer.gridCols); return cellRow < row; // Entferne alle Reihen >= der aktuellen }); } else { // Entferne die gesamte Spalte, wenn das Feld NICHT in der ersten Spalte ist gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => { const cellCol = cell % gridContainer.gridCols; return cellCol !== col; }); // Prüfe, ob Spalten rechts entfernt werden müssen, um Lücken zu vermeiden adjustRectangleAfterColumnRemoval(gridContainer); } } /** * Passt das Rechteck an, indem leere Spalten rechts entfernt werden */ function adjustRectangleAfterColumnRemoval(gridContainer) { if (gridContainer.selectedIndices.length === 0) return; // Ermittle die minimalen und maximalen Spalten des bestehenden Rechtecks const firstCol = Math.min(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols)); const lastCol = Math.max(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols)); // Prüfe jede Spalte von links nach rechts for (let col = firstCol; col <= lastCol; col++) { // Überprüfen, ob diese Spalte komplett leer ist const isColumnEmpty = !gridContainer.selectedIndices.some(cell => cell % gridContainer.gridCols === col); if (isColumnEmpty) { // Entferne alle Zellen in Spalten rechts von der leeren Spalte gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => cell % gridContainer.gridCols < col); break; // Stoppe, wenn wir eine leere Spalte finden } } } /** * Füllt die Auswahl als Rechteck aus */ function fillSelection(gridContainer) { if (gridContainer.selectedIndices.length === 0) return; // Ermittle die minimalen und maximalen Indizes const firstRow = Math.min(...gridContainer.selectedIndices.map(cell => Math.floor(cell / gridContainer.gridCols))); const lastRow = Math.max(...gridContainer.selectedIndices.map(cell => Math.floor(cell / gridContainer.gridCols))); const firstCol = Math.min(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols)); const lastCol = Math.max(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols)); // Rechteck auffüllen: Alle Zellen zwischen den Ecken hinzufügen const newSelection = []; for (let row = firstRow; row <= lastRow; row++) { for (let col = firstCol; col <= lastCol; col++) { const cellIndex = row * gridContainer.gridCols + col; newSelection.push(cellIndex); } } gridContainer.selectedIndices = newSelection; // Aktualisiere die Auswahl } /** * Aktualisiert die visuelle Darstellung des Grids */ function nupdateGrid(gridContainer) { // Entferne die "selected"-Klasse von allen Zellen gridContainer.querySelectorAll('.grid-cell').forEach(cell => { cell.classList.remove('selected'); }); // Füge die "selected"-Klasse zu den ausgewählten Zellen hinzu gridContainer.selectedIndices.forEach(index => { gridContainer .querySelector(`.grid-cell[data-index="${index}"]`) ?.classList.add('selected'); }); } function updateGrid(gridContainer) { const cells = gridContainer.querySelectorAll('.grid-cell'); const { selectedIndices, gridCols } = gridContainer; cells.forEach((cell, index) => { cell.classList.remove('selected', 'selectable'); if (selectedIndices.includes(index)) { cell.classList.add('selected'); // Markiere ausgewählte Zellen } else { cell.classList.add('selectable'); // Markiere verfügbare Zellen } }); } /** * Speichert die Auswahl in einem versteckten Eingabeelement */ function saveSelection(gridContainer) { const gridDataInput = gridContainer.dataField; if (gridDataInput) { gridDataInput.value = JSON.stringify(gridContainer.selectedIndices); } } /** * Lädt die Auswahl aus einem versteckten Eingabeelement */ function loadSelection(gridContainer) { const gridDataInput = gridContainer.dataField; if (gridDataInput) { gridContainer.selectedIndices = JSON.parse(gridDataInput.value); updateGrid(gridContainer); } } } document.addEventListener('DOMContentLoaded', () => {init()}); document.addEventListener('turbo:render', () => {init()});