Browse code

Allow for multiple GridPosition widgets to work

Benjamin Roth authored on28/02/2025 14:53:21
Showing7 changed files
... ...
@@ -1,4 +1,4 @@
1 1
 <h3><?= $this->generateLabel().$this->xlabel ?></h3>
2
-<div class="grid-container" data-rows="<?= $this->intRows ?>" data-cols="<?= $this->intCols ?>" data-field-id="<?= $this->id ?>">
2
+<div class="vr--grid-pos-container" data-rows="<?= $this->intRows ?>" data-cols="<?= $this->intCols ?>" data-field-id="ctrl_<?= $this->id ?>">
3 3
 </div>
4 4
 <input type="hidden" name="<?= $this->id ?>" id="ctrl_<?= $this->id ?>" value="<?= $this->value ?>">
5 5
\ No newline at end of file
... ...
@@ -6,46 +6,46 @@
6 6
   --header-bg: var(--gp-primary);
7 7
 }
8 8
 
9
-.grid-container {
9
+.vr--grid-pos-container {
10 10
   margin: 3px 0;
11 11
   display: grid;
12 12
   grid-template-columns: repeat(6, 1fr);
13 13
   grid-gap: 5px;
14 14
 }
15
-.grid-container[data-cols="1"] {
15
+.vr--grid-pos-container[data-cols="1"] {
16 16
   grid-template-columns: repeat(1, 1fr);
17 17
 }
18
-.grid-container[data-cols="2"] {
18
+.vr--grid-pos-container[data-cols="2"] {
19 19
   grid-template-columns: repeat(2, 1fr);
20 20
 }
21
-.grid-container[data-cols="3"] {
21
+.vr--grid-pos-container[data-cols="3"] {
22 22
   grid-template-columns: repeat(3, 1fr);
23 23
 }
24
-.grid-container[data-cols="4"] {
24
+.vr--grid-pos-container[data-cols="4"] {
25 25
   grid-template-columns: repeat(4, 1fr);
26 26
 }
27
-.grid-container[data-cols="5"] {
27
+.vr--grid-pos-container[data-cols="5"] {
28 28
   grid-template-columns: repeat(5, 1fr);
29 29
 }
30
-.grid-container[data-cols="6"] {
30
+.vr--grid-pos-container[data-cols="6"] {
31 31
   grid-template-columns: repeat(6, 1fr);
32 32
 }
33
-.grid-container[data-cols="7"] {
33
+.vr--grid-pos-container[data-cols="7"] {
34 34
   grid-template-columns: repeat(7, 1fr);
35 35
 }
36
-.grid-container[data-cols="8"] {
36
+.vr--grid-pos-container[data-cols="8"] {
37 37
   grid-template-columns: repeat(8, 1fr);
38 38
 }
39
-.grid-container[data-cols="9"] {
39
+.vr--grid-pos-container[data-cols="9"] {
40 40
   grid-template-columns: repeat(9, 1fr);
41 41
 }
42
-.grid-container[data-cols="10"] {
42
+.vr--grid-pos-container[data-cols="10"] {
43 43
   grid-template-columns: repeat(10, 1fr);
44 44
 }
45
-.grid-container[data-cols="11"] {
45
+.vr--grid-pos-container[data-cols="11"] {
46 46
   grid-template-columns: repeat(11, 1fr);
47 47
 }
48
-.grid-container[data-cols="12"] {
48
+.vr--grid-pos-container[data-cols="12"] {
49 49
   grid-template-columns: repeat(12, 1fr);
50 50
 }
51 51
 
... ...
@@ -1 +1 @@
1
-:root{--gp-primary:#a80556;--gp-primary-rgb:168, 5, 86;--contao:var(--gp-primary);--contao-rgb:var(--gp-primary-rgb);--header-bg:var(--gp-primary)}.grid-container{margin:3px 0;display:grid;grid-template-columns:repeat(6,1fr);grid-gap:5px}.grid-container[data-cols="1"]{grid-template-columns:repeat(1,1fr)}.grid-container[data-cols="2"]{grid-template-columns:repeat(2,1fr)}.grid-container[data-cols="3"]{grid-template-columns:repeat(3,1fr)}.grid-container[data-cols="4"]{grid-template-columns:repeat(4,1fr)}.grid-container[data-cols="5"]{grid-template-columns:repeat(5,1fr)}.grid-container[data-cols="6"]{grid-template-columns:repeat(6,1fr)}.grid-container[data-cols="7"]{grid-template-columns:repeat(7,1fr)}.grid-container[data-cols="8"]{grid-template-columns:repeat(8,1fr)}.grid-container[data-cols="9"]{grid-template-columns:repeat(9,1fr)}.grid-container[data-cols="10"]{grid-template-columns:repeat(10,1fr)}.grid-container[data-cols="11"]{grid-template-columns:repeat(11,1fr)}.grid-container[data-cols="12"]{grid-template-columns:repeat(12,1fr)}.grid-cell{height:30px;border:1px solid #ccc;cursor:pointer}.grid-cell:hover{background-color:rgba(var(--contao-rgb),.3)}.grid-cell.selected{background-color:var(--contao)}
2 1
\ No newline at end of file
2
+:root{--gp-primary:#a80556;--gp-primary-rgb:168, 5, 86;--contao:var(--gp-primary);--contao-rgb:var(--gp-primary-rgb);--header-bg:var(--gp-primary)}.vr--grid-pos-container{margin:3px 0;display:grid;grid-template-columns:repeat(6,1fr);grid-gap:5px}.vr--grid-pos-container[data-cols="1"]{grid-template-columns:repeat(1,1fr)}.vr--grid-pos-container[data-cols="2"]{grid-template-columns:repeat(2,1fr)}.vr--grid-pos-container[data-cols="3"]{grid-template-columns:repeat(3,1fr)}.vr--grid-pos-container[data-cols="4"]{grid-template-columns:repeat(4,1fr)}.vr--grid-pos-container[data-cols="5"]{grid-template-columns:repeat(5,1fr)}.vr--grid-pos-container[data-cols="6"]{grid-template-columns:repeat(6,1fr)}.vr--grid-pos-container[data-cols="7"]{grid-template-columns:repeat(7,1fr)}.vr--grid-pos-container[data-cols="8"]{grid-template-columns:repeat(8,1fr)}.vr--grid-pos-container[data-cols="9"]{grid-template-columns:repeat(9,1fr)}.vr--grid-pos-container[data-cols="10"]{grid-template-columns:repeat(10,1fr)}.vr--grid-pos-container[data-cols="11"]{grid-template-columns:repeat(11,1fr)}.vr--grid-pos-container[data-cols="12"]{grid-template-columns:repeat(12,1fr)}.grid-cell{height:30px;border:1px solid #ccc;cursor:pointer}.grid-cell:hover{background-color:rgba(var(--contao-rgb),.3)}.grid-cell.selected{background-color:var(--contao)}
3 3
\ No newline at end of file
... ...
@@ -6,7 +6,7 @@
6 6
   --header-bg: var(--gp-primary);
7 7
 }
8 8
 
9
-.grid-container {
9
+.vr--grid-pos-container {
10 10
   margin: 3px 0;
11 11
   display: grid;
12 12
   grid-template-columns: repeat(6, 1fr);
... ...
@@ -1,95 +1,102 @@
1 1
 function init() {
2
-  const gridContainer = document.querySelector('.grid-container');
2
+  const gridContainers = document.querySelectorAll('.vr--grid-pos-container');
3 3
 
4
-  if (!gridContainer) return;
4
+  if (!gridContainers.length) return;
5 5
 
6
-  // Werte aus den data-Attributen holen oder Standardwerte setzen
7
-  const gridRows = parseInt(gridContainer.dataset.rows) || 1; // Standardwert für Reihen: 5
8
-  const gridCols = parseInt(gridContainer.dataset.cols) || 6; // Standardwert für Spalten: 5
9
-  let selectedIndices = [];
10
-
11
-  // Grid erstellen
12
-  const fragment = document.createDocumentFragment();
13
-  // Erstelle die Zellen basierend auf Reihen und Spalten (gridRows * gridCols)
14
-  for (let i = 0; i < gridRows * gridCols; i++)
6
+  for (const gridContainer of gridContainers)
15 7
   {
16
-    const gridItem = document.createElement('div');
17
-    gridItem.classList.add('grid-cell');
18
-    gridItem.dataset.index = i; // Weise jeder Zelle ihren Index zu
19
-    gridItem.addEventListener('click', () => toggleCell(i)); // Event für Klick hinzufügen
20
-    fragment.appendChild(gridItem);
8
+
9
+    // Werte aus den data-Attributen holen oder Standardwerte setzen
10
+    gridContainer.gridRows = parseInt(gridContainer.dataset.rows) || 1; // Standardwert für Reihen: 5
11
+    gridContainer.gridCols = parseInt(gridContainer.dataset.cols) || 6; // Standardwert für Spalten: 5
12
+    gridContainer.dataField = document.getElementById(gridContainer.dataset.fieldId);
13
+
14
+    gridContainer.selectedIndices = gridContainer.selectedIndices || [];
15
+
16
+    // Grid erstellen
17
+    const fragment = document.createDocumentFragment();
18
+    // Erstelle die Zellen basierend auf Reihen und Spalten (gridRows * gridCols)
19
+    for (let i = 0; i < gridContainer.gridRows * gridContainer.gridCols; i++)
20
+    {
21
+      const gridItem = document.createElement('div');
22
+      gridItem.classList.add('grid-cell');
23
+      gridItem.dataset.index = i; // Weise jeder Zelle ihren Index zu
24
+      gridItem.addEventListener('click', () => toggleCell(gridContainer,i)); // Event für Klick hinzufügen
25
+      fragment.appendChild(gridItem);
26
+    }
27
+    gridContainer.appendChild(fragment);
28
+    loadSelection(gridContainer);
21 29
   }
22
-  gridContainer.appendChild(fragment);
23 30
 
24 31
   /**
25 32
    * Zelle ein-/auswählen
26 33
    * @param {number} index - Der Index der Zelle
27 34
    */
28
-  function toggleCell(index) {
29
-    if (selectedIndices.includes(index))
35
+  function toggleCell(gridContainer,index) {
36
+    if (gridContainer.selectedIndices.includes(index))
30 37
     {
31 38
       // Zelle abwählen
32
-      removeRowOrColumn(index);
39
+      removeRowOrColumn(gridContainer,index);
33 40
     } else
34 41
     {
35 42
       // Zelle hinzufügen
36
-      selectedIndices.push(index);
37
-      fillSelection(); // Rechteck auffüllen
43
+      gridContainer.selectedIndices.push(index);
44
+      fillSelection(gridContainer); // Rechteck auffüllen
38 45
     }
39 46
 
40
-    updateGrid(); // Visuelle Aktualisierung
41
-    saveSelection(); // Speicherung der Auswahl
47
+    updateGrid(gridContainer); // Visuelle Aktualisierung
48
+    saveSelection(gridContainer); // Speicherung der Auswahl
42 49
   }
43 50
 
44 51
   /**
45 52
    * Entfernt eine Zeile oder eine Spalte basierend auf dem Index
46 53
    * @param {number} index - Der Index der Zelle
47 54
    */
48
-  function removeRowOrColumn(index) {
49
-    const row = Math.floor(index / gridCols); // Berechnet die aktuelle Reihe
50
-    const col = index % gridCols; // Berechnet die aktuelle Spalte
55
+  function removeRowOrColumn(gridContainer,index) {
56
+    const row = Math.floor(index / gridContainer.gridCols); // Berechnet die aktuelle Reihe
57
+    const col = index % gridContainer.gridCols; // Berechnet die aktuelle Spalte
51 58
 
52 59
     if (col === 0)
53 60
     {
54 61
       // Entferne die gesamte Reihe, wenn das Feld in der ersten Spalte ist
55 62
       // UND entferne alle darunterliegenden Reihen
56
-      selectedIndices = selectedIndices.filter(cell => {
57
-        const cellRow = Math.floor(cell / gridCols);
63
+      gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => {
64
+        const cellRow = Math.floor(cell / gridContainer.gridCols);
58 65
         return cellRow < row; // Entferne alle Reihen >= der aktuellen
59 66
       });
60 67
     } else
61 68
     {
62 69
       // Entferne die gesamte Spalte, wenn das Feld NICHT in der ersten Spalte ist
63
-      selectedIndices = selectedIndices.filter(cell => {
64
-        const cellCol = cell % gridCols;
70
+      gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => {
71
+        const cellCol = cell % gridContainer.gridCols;
65 72
         return cellCol !== col;
66 73
       });
67 74
 
68 75
       // Prüfe, ob Spalten rechts entfernt werden müssen, um Lücken zu vermeiden
69
-      adjustRectangleAfterColumnRemoval();
76
+      adjustRectangleAfterColumnRemoval(gridContainer);
70 77
     }
71 78
   }
72 79
 
73 80
   /**
74 81
    * Passt das Rechteck an, indem leere Spalten rechts entfernt werden
75 82
    */
76
-  function adjustRectangleAfterColumnRemoval() {
77
-    if (selectedIndices.length === 0) return;
83
+  function adjustRectangleAfterColumnRemoval(gridContainer) {
84
+    if (gridContainer.selectedIndices.length === 0) return;
78 85
 
79 86
     // Ermittle die minimalen und maximalen Spalten des bestehenden Rechtecks
80
-    const firstCol = Math.min(...selectedIndices.map(cell => cell % gridCols));
81
-    const lastCol = Math.max(...selectedIndices.map(cell => cell % gridCols));
87
+    const firstCol = Math.min(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols));
88
+    const lastCol = Math.max(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols));
82 89
 
83 90
     // Prüfe jede Spalte von links nach rechts
84 91
     for (let col = firstCol; col <= lastCol; col++)
85 92
     {
86 93
       // Überprüfen, ob diese Spalte komplett leer ist
87
-      const isColumnEmpty = !selectedIndices.some(cell => cell % gridCols === col);
94
+      const isColumnEmpty = !gridContainer.selectedIndices.some(cell => cell % gridContainer.gridCols === col);
88 95
 
89 96
       if (isColumnEmpty)
90 97
       {
91 98
         // Entferne alle Zellen in Spalten rechts von der leeren Spalte
92
-        selectedIndices = selectedIndices.filter(cell => cell % gridCols < col);
99
+        gridContainer.selectedIndices = gridContainer.selectedIndices.filter(cell => cell % gridContainer.gridCols < col);
93 100
         break; // Stoppe, wenn wir eine leere Spalte finden
94 101
       }
95 102
     }
... ...
@@ -98,14 +105,14 @@ function init() {
98 105
   /**
99 106
    * Füllt die Auswahl als Rechteck aus
100 107
    */
101
-  function fillSelection() {
102
-    if (selectedIndices.length === 0) return;
108
+  function fillSelection(gridContainer) {
109
+    if (gridContainer.selectedIndices.length === 0) return;
103 110
 
104 111
     // Ermittle die minimalen und maximalen Indizes
105
-    const firstRow = Math.min(...selectedIndices.map(cell => Math.floor(cell / gridCols)));
106
-    const lastRow = Math.max(...selectedIndices.map(cell => Math.floor(cell / gridCols)));
107
-    const firstCol = Math.min(...selectedIndices.map(cell => cell % gridCols));
108
-    const lastCol = Math.max(...selectedIndices.map(cell => cell % gridCols));
112
+    const firstRow = Math.min(...gridContainer.selectedIndices.map(cell => Math.floor(cell / gridContainer.gridCols)));
113
+    const lastRow = Math.max(...gridContainer.selectedIndices.map(cell => Math.floor(cell / gridContainer.gridCols)));
114
+    const firstCol = Math.min(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols));
115
+    const lastCol = Math.max(...gridContainer.selectedIndices.map(cell => cell % gridContainer.gridCols));
109 116
 
110 117
     // Rechteck auffüllen: Alle Zellen zwischen den Ecken hinzufügen
111 118
     const newSelection = [];
... ...
@@ -113,25 +120,25 @@ function init() {
113 120
     {
114 121
       for (let col = firstCol; col <= lastCol; col++)
115 122
       {
116
-        const cellIndex = row * gridCols + col;
123
+        const cellIndex = row * gridContainer.gridCols + col;
117 124
         newSelection.push(cellIndex);
118 125
       }
119 126
     }
120 127
 
121
-    selectedIndices = newSelection; // Aktualisiere die Auswahl
128
+    gridContainer.selectedIndices = newSelection; // Aktualisiere die Auswahl
122 129
   }
123 130
 
124 131
   /**
125 132
    * Aktualisiert die visuelle Darstellung des Grids
126 133
    */
127
-  function updateGrid() {
134
+  function updateGrid(gridContainer) {
128 135
     // Entferne die "selected"-Klasse von allen Zellen
129 136
     gridContainer.querySelectorAll('.grid-cell').forEach(cell => {
130 137
       cell.classList.remove('selected');
131 138
     });
132 139
 
133 140
     // Füge die "selected"-Klasse zu den ausgewählten Zellen hinzu
134
-    selectedIndices.forEach(index => {
141
+    gridContainer.selectedIndices.forEach(index => {
135 142
       gridContainer
136 143
         .querySelector(`.grid-cell[data-index="${index}"]`)
137 144
         ?.classList.add('selected');
... ...
@@ -141,11 +148,23 @@ function init() {
141 148
   /**
142 149
    * Speichert die Auswahl in einem versteckten Eingabeelement
143 150
    */
144
-  function saveSelection() {
145
-    const gridDataInput = document.getElementById('ctrl_vr_gpw_grid');
151
+  function saveSelection(gridContainer) {
152
+    const gridDataInput = gridContainer.dataField;
153
+    if (gridDataInput)
154
+    {
155
+      gridDataInput.value = JSON.stringify(gridContainer.selectedIndices);
156
+    }
157
+  }
158
+
159
+  /**
160
+   * Lädt die Auswahl aus einem versteckten Eingabeelement
161
+   */
162
+  function loadSelection(gridContainer) {
163
+    const gridDataInput = gridContainer.dataField;
146 164
     if (gridDataInput)
147 165
     {
148
-      gridDataInput.value = JSON.stringify(selectedIndices);
166
+      gridContainer.selectedIndices = JSON.parse(gridDataInput.value);
167
+      updateGrid(gridContainer);
149 168
     }
150 169
   }
151 170
 }
... ...
@@ -1 +1 @@
1
-document.addEventListener("DOMContentLoaded",()=>{const gridContainer=document.querySelector(".grid-container");if(!gridContainer)return;const gridRows=parseInt(gridContainer.dataset.rows)||1;const gridCols=parseInt(gridContainer.dataset.cols)||6;let selectedIndices=[];const fragment=document.createDocumentFragment();for(let i=0;i<gridRows*gridCols;i++){const gridItem=document.createElement("div");gridItem.classList.add("grid-cell");gridItem.dataset.index=i;gridItem.addEventListener("click",()=>toggleCell(i));fragment.appendChild(gridItem)}gridContainer.appendChild(fragment);function toggleCell(index){if(selectedIndices.includes(index)){removeRowOrColumn(index)}else{selectedIndices.push(index);fillSelection()}updateGrid();saveSelection()}function removeRowOrColumn(index){const row=Math.floor(index/gridCols);const col=index%gridCols;if(col===0){selectedIndices=selectedIndices.filter(cell=>{const cellRow=Math.floor(cell/gridCols);return cellRow<row})}else{selectedIndices=selectedIndices.filter(cell=>{const cellCol=cell%gridCols;return cellCol!==col});adjustRectangleAfterColumnRemoval()}}function adjustRectangleAfterColumnRemoval(){if(selectedIndices.length===0)return;const firstCol=Math.min(...selectedIndices.map(cell=>cell%gridCols));const lastCol=Math.max(...selectedIndices.map(cell=>cell%gridCols));for(let col=firstCol;col<=lastCol;col++){const isColumnEmpty=!selectedIndices.some(cell=>cell%gridCols===col);if(isColumnEmpty){selectedIndices=selectedIndices.filter(cell=>cell%gridCols<col);break}}}function fillSelection(){if(selectedIndices.length===0)return;const firstRow=Math.min(...selectedIndices.map(cell=>Math.floor(cell/gridCols)));const lastRow=Math.max(...selectedIndices.map(cell=>Math.floor(cell/gridCols)));const firstCol=Math.min(...selectedIndices.map(cell=>cell%gridCols));const lastCol=Math.max(...selectedIndices.map(cell=>cell%gridCols));const newSelection=[];for(let row=firstRow;row<=lastRow;row++){for(let col=firstCol;col<=lastCol;col++){const cellIndex=row*gridCols+col;newSelection.push(cellIndex)}}selectedIndices=newSelection}function updateGrid(){gridContainer.querySelectorAll(".grid-cell").forEach(cell=>{cell.classList.remove("selected")});selectedIndices.forEach(index=>{gridContainer.querySelector(`.grid-cell[data-index="${index}"]`)?.classList.add("selected")})}function saveSelection(){const gridDataInput=document.getElementById("grid-data");if(gridDataInput){gridDataInput.value=JSON.stringify(selectedIndices)}}});
2 1
\ No newline at end of file
2
+function init(){const gridContainers=document.querySelectorAll(".vr--grid-pos-container");if(!gridContainers.length)return;for(const gridContainer of gridContainers){gridContainer.gridRows=parseInt(gridContainer.dataset.rows)||1;gridContainer.gridCols=parseInt(gridContainer.dataset.cols)||6;gridContainer.dataField=document.getElementById(gridContainer.dataset.fieldId);gridContainer.selectedIndices=gridContainer.selectedIndices||[];const fragment=document.createDocumentFragment();for(let i=0;i<gridContainer.gridRows*gridContainer.gridCols;i++){const gridItem=document.createElement("div");gridItem.classList.add("grid-cell");gridItem.dataset.index=i;gridItem.addEventListener("click",()=>toggleCell(gridContainer,i));fragment.appendChild(gridItem)}gridContainer.appendChild(fragment);loadSelection(gridContainer)}function toggleCell(gridContainer,index){if(gridContainer.selectedIndices.includes(index)){removeRowOrColumn(gridContainer,index)}else{gridContainer.selectedIndices.push(index);fillSelection(gridContainer)}updateGrid(gridContainer);saveSelection(gridContainer)}function removeRowOrColumn(gridContainer,index){const row=Math.floor(index/gridContainer.gridCols);const col=index%gridContainer.gridCols;if(col===0){gridContainer.selectedIndices=gridContainer.selectedIndices.filter(cell=>{const cellRow=Math.floor(cell/gridContainer.gridCols);return cellRow<row})}else{gridContainer.selectedIndices=gridContainer.selectedIndices.filter(cell=>{const cellCol=cell%gridContainer.gridCols;return cellCol!==col});adjustRectangleAfterColumnRemoval(gridContainer)}}function adjustRectangleAfterColumnRemoval(gridContainer){if(gridContainer.selectedIndices.length===0)return;const firstCol=Math.min(...gridContainer.selectedIndices.map(cell=>cell%gridContainer.gridCols));const lastCol=Math.max(...gridContainer.selectedIndices.map(cell=>cell%gridContainer.gridCols));for(let col=firstCol;col<=lastCol;col++){const isColumnEmpty=!gridContainer.selectedIndices.some(cell=>cell%gridContainer.gridCols===col);if(isColumnEmpty){gridContainer.selectedIndices=gridContainer.selectedIndices.filter(cell=>cell%gridContainer.gridCols<col);break}}}function fillSelection(gridContainer){if(gridContainer.selectedIndices.length===0)return;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));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}function updateGrid(gridContainer){gridContainer.querySelectorAll(".grid-cell").forEach(cell=>{cell.classList.remove("selected")});gridContainer.selectedIndices.forEach(index=>{gridContainer.querySelector(`.grid-cell[data-index="${index}"]`)?.classList.add("selected")})}function saveSelection(gridContainer){const gridDataInput=gridContainer.dataField;if(gridDataInput){gridDataInput.value=JSON.stringify(selectedIndices)}}function loadSelection(gridContainer){const gridDataInput=gridContainer.dataField;if(gridDataInput){selectedIndices=JSON.parse(gridDataInput.value);updateGrid(gridContainer)}}}document.addEventListener("DOMContentLoaded",()=>{init()});document.addEventListener("turbo:render",()=>{init()});
3 3
\ No newline at end of file
4 4
deleted file mode 100644
... ...
@@ -1,101 +0,0 @@
1
-document.addEventListener('DOMContentLoaded', () => {
2
-  const gridContainer = document.querySelector('.grid-container');
3
-  const gridSize = 5;
4
-  let selectedIndices = [];
5
-
6
-  if (!gridContainer) return;
7
-
8
-  // Grid dynamisch erstellen
9
-  const fragment = document.createDocumentFragment();
10
-  for (let i = 0; i < gridSize * gridSize; i++) {
11
-    const gridItem = document.createElement('div');
12
-    gridItem.classList.add('grid-cell');
13
-    gridItem.dataset.index = i;
14
-    gridItem.addEventListener('click', () => toggleCell(i));
15
-    fragment.appendChild(gridItem);
16
-  }
17
-  gridContainer.appendChild(fragment);
18
-
19
-  function toggleCell(index) {
20
-    const gridItem = gridContainer.querySelector(`.grid-cell[data-index="${index}"]`);
21
-    if (!gridItem) return;
22
-
23
-    if (selectedIndices.includes(index)) {
24
-      // Entfernen, falls bereits ausgewählt
25
-      selectedIndices = selectedIndices.filter(cell => cell !== index);
26
-      gridItem.classList.remove('selected');
27
-    } else if (isSelectable(index)) {
28
-      // Wählen, wenn erste oder angrenzende Zelle
29
-      selectedIndices.push(index);
30
-      gridItem.classList.add('selected');
31
-    } else {
32
-      // Invalid, Auswahl zurücksetzen
33
-      resetSelection(index);
34
-    }
35
-    validateSelection();
36
-    saveSelection();
37
-  }
38
-
39
-  function isSelectable(index) {
40
-    return selectedIndices.length === 0 || selectedIndices.some(selected => isAdjacent(index, selected));
41
-  }
42
-
43
-  function resetSelection(index) {
44
-    selectedIndices = [index];
45
-    resetGrid();
46
-    gridContainer.querySelector(`.grid-cell[data-index="${index}"]`)?.classList.add('selected');
47
-  }
48
-
49
-  function isAdjacent(index1, index2) {
50
-    const rowDiff = Math.abs(Math.floor(index1 / gridSize) - Math.floor(index2 / gridSize));
51
-    const colDiff = Math.abs(index1 % gridSize - index2 % gridSize);
52
-    return (rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);
53
-  }
54
-
55
-  function validateSelection() {
56
-    if (selectedIndices.length <= 1) return;
57
-
58
-    const validSelection = [selectedIndices[0]];
59
-    const remainingCells = selectedIndices.slice(1);
60
-
61
-    while (remainingCells.length > 0) {
62
-      let foundAdjacent = false;
63
-
64
-      for (let i = 0; i < remainingCells.length; i++) {
65
-        if (validSelection.some(selected => isAdjacent(remainingCells[i], selected))) {
66
-          validSelection.push(remainingCells[i]);
67
-          remainingCells.splice(i, 1);
68
-          foundAdjacent = true;
69
-          break;
70
-        }
71
-      }
72
-
73
-      if (!foundAdjacent) {
74
-        selectedIndices = validSelection;
75
-        resetGrid();
76
-        highlightSelection();
77
-        return;
78
-      }
79
-    }
80
-
81
-    selectedIndices = validSelection;
82
-    highlightSelection();
83
-  }
84
-
85
-  function resetGrid() {
86
-    gridContainer.querySelectorAll('.grid-cell').forEach(cell => cell.classList.remove('selected'));
87
-  }
88
-
89
-  function highlightSelection() {
90
-    selectedIndices.forEach(index => {
91
-      gridContainer.querySelector(`.grid-cell[data-index="${index}"]`)?.classList.add('selected');
92
-    });
93
-  }
94
-
95
-  function saveSelection() {
96
-    const gridDataInput = document.getElementById(gridContainer.dataset.fieldId);
97
-    if (gridDataInput) {
98
-      gridDataInput.value = JSON.stringify(selectedIndices);
99
-    }
100
-  }
101
-});