diff --git a/web/09/labor/loesungen/0102/go.mod b/web/09/labor/loesungen/0102/go.mod new file mode 100644 index 0000000..8851874 --- /dev/null +++ b/web/09/labor/loesungen/0102/go.mod @@ -0,0 +1,5 @@ +module uebung04 + +go 1.24.5 + +require github.com/lib/pq v1.10.9 diff --git a/web/09/labor/loesungen/0102/go.sum b/web/09/labor/loesungen/0102/go.sum new file mode 100644 index 0000000..aeddeae --- /dev/null +++ b/web/09/labor/loesungen/0102/go.sum @@ -0,0 +1,2 @@ +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= diff --git a/web/09/labor/loesungen/0102/uebung0102.go b/web/09/labor/loesungen/0102/uebung0102.go new file mode 100644 index 0000000..1a98429 --- /dev/null +++ b/web/09/labor/loesungen/0102/uebung0102.go @@ -0,0 +1,177 @@ +package main + +import ( + "database/sql" + "fmt" + "log" + "net/http" + "strconv" + "strings" + + _ "github.com/lib/pq" +) + +func insertToDB(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + if r.Method == "OPTIONS" { + w.WriteHeader(http.StatusNoContent) + return + } + + if r.Method != http.MethodPost { + http.Error(w, "Nur POST-Methode erlaubt.", http.StatusMethodNotAllowed) + return + } + + err := r.ParseForm() + if err != nil { + http.Error(w, "Fehler beim Parsen des Formulars", http.StatusBadRequest) + return + } + + if len(r.PostForm) == 0 { + http.Error(w, "Kein POST-Formular gesendet", http.StatusBadRequest) + return + } + + name := r.PostForm.Get("name") + hobbies := r.PostForm["hobby"] + // Umwandlung in einen String mit Komma-Trennung + hobbiesAsString := strings.Join(hobbies, ", ") + alter, err := strconv.Atoi(r.PostForm.Get("alter")) + if err != nil { + log.Println("Parameter konnte nicht korrekt verarbeitet werden:", err) + http.Error(w, "Benutzereingabe fehlerhaft.", http.StatusBadRequest) + return + } + + // Verbindungszeichenfolge: Benutzername, Passwort, DB-Name, Host, Port + connStr := "user=devuser password=devpass dbname=devdb host=localhost port=5432 sslmode=disable" + + // Verbindung zur Datenbank öffnen + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Println("Fehler beim Öffnen der Verbindung:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + defer db.Close() + + // Verbindung testen + err = db.Ping() + if err != nil { + log.Println("Datenbank nicht erreichbar:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + log.Println("Verbindung erfolgreich hergestellt.") + + // INSERT-Anweisung vorbereiten + query := `INSERT INTO personen (name, hobbies, alter) VALUES ($1, $2, $3)` + // INSERT-Anweisung ausführen + _, err = db.Exec(query, name, hobbiesAsString, alter) + if err != nil { + log.Println("Fehler beim Einfügen:", err) + http.Error(w, "Datensatz konnte nicht gespeichert werden.", http.StatusInternalServerError) + return + } + log.Println("Datensatz erfolgreich eingefügt.") + + fmt.Fprintln(w, "Ihre Hobbies wurden erfolgreich gespeichert.") +} + +func updateInDB(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + if r.Method == "OPTIONS" { + w.WriteHeader(http.StatusNoContent) + return + } + + if r.Method != http.MethodPost { + http.Error(w, "Nur POST-Methode erlaubt.", http.StatusMethodNotAllowed) + return + } + + err := r.ParseForm() + if err != nil { + http.Error(w, "Fehler beim Parsen des Formulars", http.StatusBadRequest) + return + } + + if len(r.PostForm) == 0 { + http.Error(w, "Kein POST-Formular gesendet", http.StatusBadRequest) + return + } + + name := r.PostForm.Get("name") + hobbies := r.PostForm["hobby"] + // Umwandlung in einen String mit Komma-Trennung + hobbiesAsString := strings.Join(hobbies, ", ") + alter, err := strconv.Atoi(r.PostForm.Get("alter")) + if err != nil { + log.Println("Parameter konnte nicht korrekt verarbeitet werden:", err) + http.Error(w, "Benutzereingabe fehlerhaft.", http.StatusBadRequest) + return + } + + // Verbindungszeichenfolge: Benutzername, Passwort, DB-Name, Host, Port + connStr := "user=devuser password=devpass dbname=devdb host=localhost port=5432 sslmode=disable" + + // Verbindung zur Datenbank öffnen + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Println("Fehler beim Öffnen der Verbindung:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + defer db.Close() + + // Verbindung testen + err = db.Ping() + if err != nil { + log.Println("Datenbank nicht erreichbar:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + log.Println("Verbindung erfolgreich hergestellt.") + + // UPDATE-Anweisung vorbereiten + query := `UPDATE personen SET hobbies = $1, alter = $2 WHERE name = $3` + // UPDATE-Anweisung ausführen + result, err := db.Exec(query, hobbiesAsString, alter, name) + if err != nil { + log.Println("Fehler beim Aktualisieren:", err) + http.Error(w, "Datensatz konnte nicht aktualisiert werden.", http.StatusInternalServerError) + return + } + // Prüfen, wie viele Zeilen angepasst wurden + rows, err := result.RowsAffected() + if err != nil { + log.Println("Fehler beim Prüfen der angepassten Zeilen:", err) + http.Error(w, "Datensatz konnte nicht aktualisiert werden.", http.StatusInternalServerError) + return + } + if rows == 0 { + log.Println("Kein Datensatz mit diesem Namen gefunden.") + http.Error(w, "Datensatz konnte nicht aktualisiert werden.", http.StatusInternalServerError) + return + } + log.Println("Datensatz erfolgreich aktualisiert.") + + fmt.Fprintln(w, "Ihre Hobbies wurden erfolgreich aktualisiert.") +} + +func main() { + http.HandleFunc("/insert", insertToDB) + http.HandleFunc("/update", updateInDB) + fmt.Println("Server läuft auf localhost:8080...") + log.Fatal(http.ListenAndServe(":8080", nil)) +} diff --git a/web/09/labor/loesungen/0102/uebung0102.html b/web/09/labor/loesungen/0102/uebung0102.html new file mode 100644 index 0000000..68c612d --- /dev/null +++ b/web/09/labor/loesungen/0102/uebung0102.html @@ -0,0 +1,33 @@ + + + + + + + Hobbies + + + +

Hobbies

+
+ + + +

+ + +
+
+ + +
+ + + \ No newline at end of file diff --git a/web/10/labor/loesungen/uebung01.js b/web/10/labor/loesungen/uebung01.js new file mode 100644 index 0000000..1cad385 --- /dev/null +++ b/web/10/labor/loesungen/uebung01.js @@ -0,0 +1,10 @@ +const zahlen = [38, 0, 226, 384, 111, 500383]; + +for (let i = 0; i < zahlen.length; i++) { + const z = zahlen[i]; + const ergebnis = (z === 0) + ? "Null" + : (z % 2 === 0 ? "Gerade Zahl" : "Ungerade Zahl"); + + console.log(z, ": ", ergebnis); +} \ No newline at end of file diff --git a/web/10/labor/loesungen/uebung02.js b/web/10/labor/loesungen/uebung02.js new file mode 100644 index 0000000..b6d1c2f --- /dev/null +++ b/web/10/labor/loesungen/uebung02.js @@ -0,0 +1,17 @@ +const sortiment = JSON.parse( +`[{ "produkt": "Joghurt", "preis": 2.49 }, + { "produkt": "Brot", "preis": 3.29 }, + { "produkt": "Käse", "preis": 8.99 }, + { "produkt": "Duschgel","preis": 2.79 } +]`); + +const rabattiert = sortiment.map( + x => ( + { + produkt: x.produkt, + preis: parseFloat((x.preis * 0.9).toFixed(2)) + } +) +); + +console.log(rabattiert); \ No newline at end of file diff --git a/web/11/demos/01_events.html b/web/11/demos/01_events.html new file mode 100644 index 0000000..31f3901 --- /dev/null +++ b/web/11/demos/01_events.html @@ -0,0 +1,19 @@ + + + + + + Events + + + + +

Noch nichts passiert...

+ + +

+ + + + + \ No newline at end of file diff --git a/web/11/demos/01_events.js b/web/11/demos/01_events.js new file mode 100644 index 0000000..6ff1083 --- /dev/null +++ b/web/11/demos/01_events.js @@ -0,0 +1,20 @@ +// Button-Click-Event +const button = document.getElementById("klickButton"); +const ausgabe = document.getElementById("ausgabe"); + +button.addEventListener("click", () => { + ausgabe.textContent = "Button wurde geklickt!"; +}); + +// Input-Event +const eingabe = document.getElementById("eingabe"); +const eingabeAusgabe = document.getElementById("eingabeAusgabe"); + +eingabe.addEventListener("input", () => { + eingabeAusgabe.textContent = "Du hast eingegeben: " + eingabe.value; +}); + +// Mouseover-Event +button.addEventListener("mouseover", () => { + ausgabe.textContent = "Maus über dem Button!"; +}); \ No newline at end of file diff --git a/web/11/demos/02_validierung.html b/web/11/demos/02_validierung.html new file mode 100644 index 0000000..092900a --- /dev/null +++ b/web/11/demos/02_validierung.html @@ -0,0 +1,31 @@ + + + + + Formularvalidierung mit Live-Feedback + + +

Registrierung

+ +
+ + + +

+ + + + +

+ + + + +

+ + +
+ + + + \ No newline at end of file diff --git a/web/11/demos/02_validierung.js b/web/11/demos/02_validierung.js new file mode 100644 index 0000000..5a0a1f9 --- /dev/null +++ b/web/11/demos/02_validierung.js @@ -0,0 +1,78 @@ +document.addEventListener("DOMContentLoaded", () => { + const form = document.getElementById("contactForm"); + + const username = document.getElementById("username"); + const email = document.getElementById("email"); + const age = document.getElementById("age"); + + const usernameError = document.getElementById("usernameError"); + const emailError = document.getElementById("emailError"); + const ageError = document.getElementById("ageError"); + +// // --- Live-Feedback --- + username.addEventListener("input", () => { + const value = username.value.trim().toLowerCase(); + if (!value) { + usernameError.textContent = "Benutzername darf nicht leer sein."; + } else if (value === "admin") { + usernameError.textContent = "Der Benutzername 'admin' ist nicht erlaubt."; + } else { + usernameError.textContent = ""; + } + }); + + email.addEventListener("input", () => { + if (!email.validity.valid) { + emailError.textContent = "Bitte eine gültige E-Mail-Adresse eingeben."; + } else { + emailError.textContent = ""; + } + }); + + age.addEventListener("input", () => { + if (!age.validity.valid) { + if (age.validity.valueMissing) { + ageError.textContent = "Bitte das Alter angeben."; + } else if (age.validity.rangeUnderflow) { + ageError.textContent = "Du musst mindestens 18 Jahre alt sein."; + } else if (age.validity.rangeOverflow) { + ageError.textContent = "Das Alter darf 99 nicht überschreiten."; + } else { + ageError.textContent = "Ungültige Eingabe."; + } + } else { + ageError.textContent = ""; + } + }); + + // --- Prüfung beim Absenden --- + form.addEventListener("submit", (event) => { + let valid = true; + + // Benutzername prüfen + const value = username.value.trim().toLowerCase(); + if (!value) { + usernameError.textContent = "Benutzername darf nicht leer sein."; + valid = false; + } else if (value === "admin") { + usernameError.textContent = "Der Benutzername 'admin' ist nicht erlaubt."; + valid = false; + } + + // E-Mail prüfen + if (!email.validity.valid) { + emailError.textContent = "Bitte eine gültige E-Mail-Adresse eingeben."; + valid = false; + } + + // Alter prüfen + if (!age.validity.valid) { + ageError.textContent = "Bitte ein gültiges Alter zwischen 18 und 99 eingeben."; + valid = false; + } + + if (!valid) { + event.preventDefault(); // verhindert das Absenden + } + }); +}); \ No newline at end of file diff --git a/web/11/labor/11_aufgaben.md b/web/11/labor/11_aufgaben.md new file mode 100644 index 0000000..a57032a --- /dev/null +++ b/web/11/labor/11_aufgaben.md @@ -0,0 +1,41 @@ +# Übungsblatt 11 + +## 1. Javascript-Übung: DOM und Events + +**Aufgabenstellung**: Erstellen Sie eine interaktive Webseite, die ein Bild zum Start der Pfingstferien anzeigt. + +#### Arbeitsschritte + +1. Erstellen Sie zunächst eine HTML-Seite mit der Überschrift (erste Ebene): "Endlich Pfingstferien!". +2. Darunter ist ein Button-Element mit der Aufschrift "Ferien starten 🌞". +3. Sobald der Button geklickt wurde: + 1. wird die alte Überschrift durch diese ersetzt: "Schöne und erholsame Pfingstferien!" + 2. erscheint diese [Bild](Pfingstrose.jpg) unterhalb der Überschrift (*Tipp*: [w3schools.com: Image](https://www.w3schools.com/jsref/prop_img_src.asp)) + 3. der Button verschwindet + +All dies soll in einem Javascript-Programm gesteuert werden, dass Sie in Ihre HTML-Seite einbinden. + +## 2. Javascript-Übung: Validierung und Events + +**Aufgabenstellung**: Erstellen Sie eine interaktive Webseite, in der Nutzer:innen den Namen ihres Lieblingshelden der [Paw‑Patrol](https://de.wikipedia.org/wiki/PAW_Patrol) eingeben können und daraufhin einen passenden Spruch angezeigt bekommen. + +#### Arbeitsschritte + +1. Verwenden Sie dazu das vorgebene HTML-Formular [pawpatrol.html](pawpatrol.html). +2. Erstellen Sie eine zugehörige JavaScript‑Datei, in der Sie ein Objekt mit den erlaubten Figuren und deren typischen Sprüchen hinterlegen: + +``` +"Chase": "Chase ist auf Spur!" +"Marshall": "Ich bin startklar!" +"Skye": "Diese Pfote hebt ab!" +"Rocky": "Wegwerfen? Kommt nicht in die Tüte!" +"Rubble": "Rubble ist zur Stelle!" +"Zuma": "Los geht’s ins Wasser!" +"Everest": "Eis und Schnee – ich bin bereit!" +"Tracker": "Ich höre alles!" +``` + +3. Bei Absenden des Formulars (`submit`) prüfen Sie mit Ihrem JavaScript, ob der eingegebene Name mit einem der Namen aus dem Objekt übereinstimmt. + - Falls *ja*, geben Sie eine Bestätigungsmeldung in Abschnitt mit `id="meldung"` sowie den passenden Spruch der Figur in dem Abschnitt mit `id="spruch"` aus. + - Falls *nein*, erscheint eine Fehlermeldung im Abschnitt mit `id="meldung"`, die darauf hinweist, dass nur Paw‑Patrol‑Namen erlaubt sind. +4. Testen Sie Ihr Javascript mit Hilfe des vorgegebenen HTML-Formulars. \ No newline at end of file diff --git a/web/11/labor/Pfingstrose.jpg b/web/11/labor/Pfingstrose.jpg new file mode 100644 index 0000000..35d0c8b Binary files /dev/null and b/web/11/labor/Pfingstrose.jpg differ diff --git a/web/11/labor/pawpatrol.html b/web/11/labor/pawpatrol.html new file mode 100644 index 0000000..0069c25 --- /dev/null +++ b/web/11/labor/pawpatrol.html @@ -0,0 +1,23 @@ + + + + + + + Paw Patrol - Helfer auf vier Pfoten + + + +

Lieblings-Fellfreund

+
+ + + +
+

+

+ + + + + \ No newline at end of file