Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| de:modul:m291:learningunits:lu07:loesungen:a_debugging [2026/03/22 15:51] – angelegt gkoch | de:modul:m291:learningunits:lu07:loesungen:a_debugging [2026/03/22 22:17] (aktuell) – gkoch | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | ==== Häufige JS-Bugs aus dem Accordion-Projekt | + | ====== LU07: Lösungen – Accordion |
| - | **Bug: Fehlende Dateiendung**: | + | |
| + | Vergleichen Sie die Lösungen mit Ihrem Debugging-Protokoll: | ||
| + | | ||
| + | | ||
| + | * Welches Werkzeug hätte Ihnen dort geholfen? | ||
| + | |||
| + | |||
| + | ===== Bugs 1 und 2 (identisch in allen Varianten) ===== | ||
| + | |||
| + | ==== Bug 1 – Fehlende Dateiendung | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| <code html> | <code html> | ||
| - | <!-- ❌ Dateiendung fehlt – Browser | + | <!-- ❌ Dateiendung fehlt – Browser |
| <link href=" | <link href=" | ||
| - | <script src=" | ||
| - | <!-- ✅ Korrekt | + | <!-- ✅ Fix --> |
| <link href=" | <link href=" | ||
| - | <script src=" | ||
| </ | </ | ||
| </ | </ | ||
| - | **Bug: | + | Dieser Bug erzeugt |
| + | |||
| + | Falls Sie diesen | ||
| + | |||
| + | |||
| + | ==== Bug 2 – Script im ''< | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| - | < | + | < |
| - | // ❌ Wählt nur den ersten Button – forEach funktioniert, | + | < |
| - | const buttons = document.querySelector('.accordion-btn' | + | <!-- → document.querySelectorAll(...) findet keine Buttons, weil sie noch nicht existieren --> |
| + | < | ||
| + | <script src=" | ||
| + | </ | ||
| - | // ✅ Wählt alle Buttons | + | < |
| - | const buttons = document.querySelectorAll(' | + | < |
| + | < | ||
| + | <script src=" | ||
| + | </ | ||
| </ | </ | ||
| </ | </ | ||
| - | **Bug: Fehlender Punkt vor dem Klassennamen** | + | JavaScript läuft sofort, wenn der Browser die Zeile einliest. Steht das Script im ''< |
| + | |||
| + | CSS-Dateien gehören in den ''< | ||
| + | |||
| + | |||
| + | ===== Variante A ===== | ||
| + | |||
| + | ==== Bug 3 – Fehlender Punkt vor dem Klassennamen | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| <code js> | <code js> | ||
| - | // ❌ Sucht nach einem HTML-Tag < | + | // ❌ Sucht nach einem HTML-Tag < |
| const buttons = document.querySelectorAll(' | const buttons = document.querySelectorAll(' | ||
| - | // ✅ Punkt vor Klassennamen nicht vergessen | + | // ✅ Fix: Punkt vor dem Klassennamen nicht vergessen |
| const buttons = document.querySelectorAll(' | const buttons = document.querySelectorAll(' | ||
| </ | </ | ||
| </ | </ | ||
| - | Dieser Fehler erzeugt **keinen roten Fehler** in der Console. Prüfen Sie mit: | + | Ohne den Punkt sucht der Browser nach einem HTML-Element |
| - | <WRAP round box 80% center> | + | |
| - | <code js> | + | |
| - | console.log('Gefundene Buttons:', | + | |
| - | </ | + | |
| - | </ | + | |
| - | **Bug: Variablenname-Konflikt | + | Der entscheidende Schritt: '' |
| + | |||
| + | |||
| + | ==== Bug 4 – Tippfehler '' | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| - | < | + | < |
| - | // ❌ Aussen heisst die Variable | + | /* ❌ 'heihgt' |
| - | // → der äussere ' | + | .panel { |
| - | button.forEach((button) => { | + | |
| - | | + | |
| - | // ... | + | |
| - | if (!panelIsOpen) { | + | } |
| - | panelElement.classList.add(' | + | |
| - | | + | |
| - | } | + | |
| - | | + | |
| - | }); | + | |
| - | // ✅ Klare, unterschiedliche Namen | + | /* ✅ Fix */ |
| - | buttons.forEach((button) => { | + | .panel { |
| - | | + | |
| - | // ... | + | |
| - | if (!panelIsOpen) { | + | |
| - | panelElement.classList.add(' | + | } |
| - | | + | |
| - | } | + | |
| - | | + | |
| - | }); | + | |
| </ | </ | ||
| </ | </ | ||
| - | **Bug: Doppeltes classList.add | + | Der Browser ignoriert unbekannte CSS-Eigenschaften kommentarlos – kein Console-Fehler, |
| + | |||
| + | ==== Bug 5 – Doppeltes | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| <code js> | <code js> | ||
| - | // ❌ classList.add(' | + | // ❌ classList.add(' |
| - | // → Panel wird immer geöffnet, nie geschlossen | + | // → Das Panel wird immer geöffnet |
| buttons.forEach((button) => { | buttons.forEach((button) => { | ||
| button.addEventListener(' | button.addEventListener(' | ||
| Zeile 91: | Zeile 107: | ||
| }); | }); | ||
| - | panelElement.classList.add(' | + | panelElement.classList.add(' |
| if (!panelIsOpen) { | if (!panelIsOpen) { | ||
| Zeile 100: | Zeile 116: | ||
| }); | }); | ||
| - | // ✅ Nur innerhalb des if-Blocks | + | // ✅ Fix: classList.add(' |
| buttons.forEach((button) => { | buttons.forEach((button) => { | ||
| button.addEventListener(' | button.addEventListener(' | ||
| Zeile 120: | Zeile 136: | ||
| </ | </ | ||
| - | **Bug: Syntaxfehler in forEach – fehlende öffnende Klammer** | + | Kein Console-Fehler – das Verhalten ist subtil. Was passiert Schritt für Schritt beim Klick auf ein **offenes** Panel: |
| + | - '' | ||
| + | - Die '' | ||
| + | - '' | ||
| + | - Die '' | ||
| + | |||
| + | Das Panel wird also immer geöffnet | ||
| + | |||
| + | |||
| + | ===== Variante B ===== | ||
| + | |||
| + | ==== Bug 3 – Tippfehler '' | ||
| + | |||
| + | <WRAP round box 80% center> | ||
| + | <code css> | ||
| + | /* ❌ ' | ||
| + | .panel.open { | ||
| + | height: auto; | ||
| + | opacty: 1; | ||
| + | } | ||
| + | |||
| + | /* ✅ Fix */ | ||
| + | .panel.open { | ||
| + | height: auto; | ||
| + | opacity: 1; | ||
| + | } | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Das Accordion funktioniert scheinbar – der Button-Pfeil dreht sich, der Bereich klappt auf. Aber der Inhalt bleibt unsichtbar, weil '' | ||
| + | |||
| + | ==== Bug 4 – '' | ||
| <WRAP round box 80% center> | <WRAP round box 80% center> | ||
| <code js> | <code js> | ||
| - | // ❌ Syntaxfehler: | + | // ❌ querySelector gibt nur das erste gefundene Element zurück – kein Array, keine NodeList |
| + | const buttons = document.querySelector(' | ||
| + | |||
| + | // ✅ Fix: querySelectorAll gibt alle gefundenen Elemente als NodeList zurück | ||
| + | const buttons = document.querySelectorAll(' | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | Falls Sie nur den ersten Button getestet haben, schien alles zu funktionieren. '' | ||
| + | |||
| + | |||
| + | ==== Bug 5 – Fehlendes '' | ||
| + | |||
| + | <WRAP round box 80% center> | ||
| + | <code js> | ||
| + | // ❌ ' | ||
| + | buttons.forEach((button) => { | ||
| + | button.addEventListener(' | ||
| + | const panelElement = e.target.nextElementSibling; | ||
| + | }); | ||
| + | }); | ||
| + | |||
| + | // ✅ Fix: ' | ||
| + | buttons.forEach((button) => { | ||
| + | button.addEventListener(' | ||
| + | const panelElement = e.target.nextElementSibling; | ||
| + | }); | ||
| + | }); | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Der Fehler erscheint erst beim Klick, nicht beim Laden der Seite – weil der Callback erst dann ausgeführt wird. Die Console zeigt '' | ||
| + | |||
| + | Das Event-Objekt '' | ||
| + | |||
| + | |||
| + | ===== Variante C ===== | ||
| + | |||
| + | ==== Bug 3 – Syntaxfehler | ||
| + | |||
| + | <WRAP round box 80% center> | ||
| + | <code js> | ||
| + | // ❌ Öffnende Klammer | ||
| // → Console: Uncaught SyntaxError: | // → Console: Uncaught SyntaxError: | ||
| buttons.forEach(andererButton) => { | buttons.forEach(andererButton) => { | ||
| Zeile 130: | Zeile 221: | ||
| }); | }); | ||
| - | // ✅ Korrekt | + | // ✅ Fix: Klammern um den Parameter ergänzen |
| buttons.forEach((andererButton) => { | buttons.forEach((andererButton) => { | ||
| andererButton.nextElementSibling.classList.remove(' | andererButton.nextElementSibling.classList.remove(' | ||
| Zeile 136: | Zeile 227: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| + | Ein '' | ||
| + | |||
| + | |||
| + | ==== Bug 4 – Tippfehler '' | ||
| + | |||
| + | <WRAP round box 80% center> | ||
| + | <code css> | ||
| + | /* ❌ ' | ||
| + | /* → height bleibt auf dem Browser-Standard (auto), Panels sind immer sichtbar */ | ||
| + | .panel { | ||
| + | heigth: 0; | ||
| + | opacity: 0; | ||
| + | overflow: hidden; | ||
| + | } | ||
| + | |||
| + | /* ✅ Fix */ | ||
| + | .panel { | ||
| + | height: 0; | ||
| + | opacity: 0; | ||
| + | overflow: hidden; | ||
| + | } | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Dieser Bug ist das Gegenteil von Variante A: Dort öffneten sich die Panels nicht, weil '' | ||
| + | |||
| + | |||
| + | ==== Bug 5 – '' | ||
| + | |||
| + | <WRAP round box 80% center> | ||
| + | <code js> | ||
| + | // ❌ nextSibling gibt den unsichtbaren Text-Node zwischen den Tags zurück | ||
| + | // → kein DOM-Element → TypeError: Cannot read properties of undefined (reading ' | ||
| + | const panelElement = e.target.nextSibling; | ||
| + | |||
| + | // ✅ Fix: nextElementSibling überspringt Text-Nodes | ||
| + | const panelElement = e.target.nextElementSibling; | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Im HTML-Code sieht man zwischen ''< | ||
| + | |||
| + | Öffnen Sie den **Elements-Tab** und klappen Sie die Accordion-Struktur auf: Sie sehen zwischen den Tags ''# | ||
| + | |||
| + | |||