- termin 1: geschichte, grundlagen, html - termin 2: netzwerke, protokolle, css - termin 3: interaktivitaet, javascript
1134 lines
21 KiB
Markdown
1134 lines
21 KiB
Markdown
---
|
||
marp: true
|
||
theme: gaia
|
||
paginate: true
|
||
backgroundColor: #fff
|
||
header: "Grundlagen IT- und Internettechnik"
|
||
footer: "Michael Czechowski – HdM Stuttgart – WS 2025/26"
|
||
title: "Tag 3: Interaktivität & JavaScript"
|
||
---
|
||
|
||
<style>
|
||
section {
|
||
font-size: 1.7rem;
|
||
}
|
||
h2 {
|
||
color: var(--color-dimmed);
|
||
}
|
||
</style>
|
||
|
||
<!-- _class: invert -->
|
||
<!-- _header: '' -->
|
||
<!-- _footer: '' -->
|
||
|
||

|
||
|
||
# Grundlagen IT- und Internettechnik
|
||
|
||
**223015b** · Modul "Technik 1" · 1. Semester
|
||
Digital- und Medienwirtschaft
|
||
Hochschule der Medien Stuttgart
|
||
|
||
**Wintersemester 2025/26**
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Tag 3 – 24.01.2026
|
||
## Interaktivität & JavaScript
|
||
|
||
---
|
||
|
||
# Rückblick
|
||
|
||
**Tag 1:** Geschichte, Von-Neumann, HTML
|
||
**Tag 2:** Netzwerke, DNS, HTTP, CSS
|
||
|
||
**Eure Portfolio-Seiten?**
|
||
- Wer hat mehrere Seiten?
|
||
- Wer hat ein Kontaktformular?
|
||
- Wer hat responsive Design?
|
||
|
||
<!--
|
||
Portfolio-Seiten zeigen lassen (freiwillig)
|
||
Probleme besprechen
|
||
-->
|
||
|
||
---
|
||
|
||
# Heute
|
||
|
||
**Vormittag:**
|
||
- Was ist JavaScript?
|
||
- Variablen, Datentypen, Operatoren
|
||
- Funktionen & Kontrollstrukturen
|
||
|
||
**Nachmittag:**
|
||
- Das DOM: HTML mit JS manipulieren
|
||
- Events: Auf NutzerInnen reagieren
|
||
- Projekt: Interaktive Webseite
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Teil 1: JavaScript-Grundlagen
|
||
## Die Sprache des Webs
|
||
|
||
---
|
||
|
||
# Was ist JavaScript?
|
||
|
||
**Die einzige Programmiersprache, die im Browser läuft!**
|
||
|
||
- **1995:** In 10 Tagen entwickelt (Brendan Eich, Netscape)
|
||
- **Heute:** Überall – Browser, Server, Apps, IoT
|
||
|
||
**Nicht verwechseln:**
|
||
- Java ≠ JavaScript (komplett unterschiedlich!)
|
||
- "JavaScript ist zu Java wie Carpet zu Car"
|
||
|
||
<!--
|
||
Ursprünglich "Mocha", dann "LiveScript", dann "JavaScript" (Marketing!)
|
||
ECMAScript = offizieller Standard
|
||
Aktuelle Version: ES2024
|
||
-->
|
||
|
||
---
|
||
|
||
# JavaScript-Timeline
|
||
|
||
| Jahr | Meilenstein |
|
||
|------|-------------|
|
||
| **1995** | JavaScript erfunden (Netscape) |
|
||
| **1997** | ECMAScript-Standard (ECMA-262) |
|
||
| **2005** | AJAX revolutioniert Web (Gmail, Google Maps) |
|
||
| **2008** | V8 Engine (Chrome) – JS wird schnell |
|
||
| **2009** | Node.js – JS auf dem Server |
|
||
| **2015** | ES6 – Modernes JavaScript |
|
||
|
||
<!--
|
||
V8 = Googles JS-Engine, macht JS schnell
|
||
Node.js = JavaScript außerhalb des Browsers
|
||
ES6 = großes Update mit vielen Features
|
||
-->
|
||
|
||
---
|
||
|
||
# JavaScript einbinden
|
||
|
||
**Option 1: Externe Datei (empfohlen!)**
|
||
```html
|
||
<body>
|
||
<!-- Inhalt -->
|
||
<script src="script.js"></script>
|
||
</body>
|
||
```
|
||
|
||
**Option 2: Inline**
|
||
```html
|
||
<script>
|
||
console.log("Hallo Welt!");
|
||
</script>
|
||
```
|
||
|
||
⚠️ Script am **Ende** des `<body>` – damit HTML zuerst lädt!
|
||
|
||
<!--
|
||
Externe Datei = wiederverwendbar, cachebar
|
||
Script am Ende = DOM ist fertig geladen
|
||
Oder: defer-Attribut
|
||
-->
|
||
|
||
---
|
||
|
||
# Die Konsole: Euer bester Freund
|
||
|
||
**Browser DevTools → Console**
|
||
- Windows/Linux: `F12` oder `Strg+Shift+I`
|
||
- Mac: `Cmd+Option+I`
|
||
|
||
```javascript
|
||
console.log("Hallo Welt!");
|
||
console.log(42);
|
||
console.log("Die Antwort ist:", 42);
|
||
```
|
||
|
||
**Direkt in der Konsole tippen und Enter!**
|
||
|
||
<!--
|
||
Console = REPL (Read-Eval-Print-Loop)
|
||
Perfekt zum Experimentieren
|
||
Fehler werden hier auch angezeigt
|
||
-->
|
||
|
||
---
|
||
|
||
# Variablen: Daten speichern
|
||
|
||
```javascript
|
||
// Modern (empfohlen)
|
||
let alter = 25; // Kann geändert werden
|
||
const name = "Max"; // Konstante (nicht änderbar)
|
||
|
||
// Alt (vermeiden!)
|
||
var stadt = "Stuttgart"; // Problematisches Scoping
|
||
```
|
||
|
||
**Regeln:**
|
||
- Beginnt mit Buchstabe, `_` oder `$`
|
||
- Keine Leerzeichen, keine Sonderzeichen
|
||
- Case-sensitive: `name` ≠ `Name`
|
||
|
||
<!--
|
||
let = für Werte die sich ändern
|
||
const = für Konstanten (Standardwahl!)
|
||
var = alte Syntax, hat Scoping-Probleme
|
||
-->
|
||
|
||
---
|
||
|
||
# Datentypen
|
||
|
||
```javascript
|
||
// String (Text)
|
||
const text = "Hallo";
|
||
const text2 = 'Welt';
|
||
const text3 = `Hallo ${text2}`; // Template Literal
|
||
|
||
// Number (Zahl)
|
||
const ganzzahl = 42;
|
||
const kommazahl = 3.14;
|
||
|
||
// Boolean (Wahrheitswert)
|
||
const istWahr = true;
|
||
const istFalsch = false;
|
||
|
||
// Undefined & Null
|
||
let unbekannt; // undefined
|
||
const nichts = null; // null (bewusst leer)
|
||
```
|
||
|
||
<!--
|
||
typeof prüft den Typ
|
||
Template Literals mit Backticks!
|
||
Keine Unterscheidung int/float
|
||
-->
|
||
|
||
---
|
||
|
||
# Arrays: Listen
|
||
|
||
```javascript
|
||
const farben = ["rot", "grün", "blau"];
|
||
|
||
// Zugriff (0-basiert!)
|
||
console.log(farben[0]); // "rot"
|
||
console.log(farben[2]); // "blau"
|
||
|
||
// Länge
|
||
console.log(farben.length); // 3
|
||
|
||
// Hinzufügen
|
||
farben.push("gelb"); // Am Ende
|
||
farben.unshift("weiß"); // Am Anfang
|
||
|
||
// Entfernen
|
||
farben.pop(); // Letztes Element
|
||
farben.shift(); // Erstes Element
|
||
```
|
||
|
||
<!--
|
||
Index startet bei 0!
|
||
farben[3] = viertes Element
|
||
Arrays sind veränderbar auch bei const
|
||
-->
|
||
|
||
---
|
||
|
||
# Objects: Strukturierte Daten
|
||
|
||
```javascript
|
||
const person = {
|
||
vorname: "Max",
|
||
nachname: "Mustermann",
|
||
alter: 25,
|
||
hobbies: ["Lesen", "Sport"]
|
||
};
|
||
|
||
// Zugriff
|
||
console.log(person.vorname); // "Max"
|
||
console.log(person["nachname"]); // "Mustermann"
|
||
|
||
// Ändern
|
||
person.alter = 26;
|
||
|
||
// Hinzufügen
|
||
person.beruf = "Student";
|
||
```
|
||
|
||
<!--
|
||
Key-Value-Paare
|
||
Punkt-Notation oder Bracket-Notation
|
||
Verschachtelt möglich
|
||
-->
|
||
|
||
---
|
||
|
||
# Operatoren
|
||
|
||
```javascript
|
||
// Arithmetik
|
||
5 + 3 // 8 (Addition)
|
||
5 - 3 // 2 (Subtraktion)
|
||
5 * 3 // 15 (Multiplikation)
|
||
5 / 3 // 1.666... (Division)
|
||
5 % 3 // 2 (Modulo/Rest)
|
||
5 ** 3 // 125 (Potenz)
|
||
|
||
// Vergleich
|
||
5 === 3 // false (strikt gleich)
|
||
5 !== 3 // true (strikt ungleich)
|
||
5 > 3 // true
|
||
5 >= 3 // true
|
||
|
||
// Logisch
|
||
true && false // false (UND)
|
||
true || false // true (ODER)
|
||
!true // false (NICHT)
|
||
```
|
||
|
||
<!--
|
||
=== strikt (Typ + Wert)
|
||
== loose (nur Wert) – VERMEIDEN!
|
||
"5" == 5 ist true, "5" === 5 ist false
|
||
-->
|
||
|
||
---
|
||
|
||
# Hands-On: Variablen & Konsole (20 Min)
|
||
|
||
**In der Browser-Konsole:**
|
||
|
||
1. Erstelle Variablen für dich:
|
||
```javascript
|
||
const name = "Dein Name";
|
||
let alter = 20;
|
||
const hobbies = ["Hobby1", "Hobby2"];
|
||
```
|
||
|
||
2. Gib sie aus:
|
||
```javascript
|
||
console.log(`Ich bin ${name}, ${alter} Jahre alt.`);
|
||
console.log("Meine Hobbies:", hobbies);
|
||
```
|
||
|
||
3. Erstelle ein `person`-Objekt und greife auf Properties zu
|
||
|
||
---
|
||
|
||
# Funktionen: Code wiederverwenden
|
||
|
||
```javascript
|
||
// Funktion definieren
|
||
function grüßen(name) {
|
||
return `Hallo ${name}!`;
|
||
}
|
||
|
||
// Funktion aufrufen
|
||
const nachricht = grüßen("Max");
|
||
console.log(nachricht); // "Hallo Max!"
|
||
|
||
// Arrow Function (modern)
|
||
const addieren = (a, b) => {
|
||
return a + b;
|
||
};
|
||
|
||
// Kurzform (bei einem Ausdruck)
|
||
const verdoppeln = x => x * 2;
|
||
```
|
||
|
||
<!--
|
||
function = klassische Syntax
|
||
Arrow Functions = modern, kürzer
|
||
Parameter = Eingabe
|
||
return = Rückgabe
|
||
-->
|
||
|
||
---
|
||
|
||
# Kontrollstrukturen: if/else
|
||
|
||
```javascript
|
||
const alter = 18;
|
||
|
||
if (alter >= 18) {
|
||
console.log("Volljährig");
|
||
} else if (alter >= 16) {
|
||
console.log("Fast volljährig");
|
||
} else {
|
||
console.log("Minderjährig");
|
||
}
|
||
|
||
// Ternärer Operator (Kurzform)
|
||
const status = alter >= 18 ? "Erwachsen" : "Kind";
|
||
```
|
||
|
||
<!--
|
||
Bedingung in Klammern
|
||
Code-Block in geschweiften Klammern
|
||
Ternär für einfache Fälle
|
||
-->
|
||
|
||
---
|
||
|
||
# Schleifen: Wiederholen
|
||
|
||
```javascript
|
||
// for-Schleife
|
||
for (let i = 0; i < 5; i++) {
|
||
console.log(i); // 0, 1, 2, 3, 4
|
||
}
|
||
|
||
// for...of (Arrays)
|
||
const farben = ["rot", "grün", "blau"];
|
||
for (const farbe of farben) {
|
||
console.log(farbe);
|
||
}
|
||
|
||
// forEach (Array-Methode)
|
||
farben.forEach(farbe => {
|
||
console.log(farbe);
|
||
});
|
||
|
||
// while
|
||
let count = 0;
|
||
while (count < 3) {
|
||
console.log(count);
|
||
count++;
|
||
}
|
||
```
|
||
|
||
<!--
|
||
for = wenn Anzahl bekannt
|
||
for...of = für Arrays/Iterables
|
||
forEach = Array-Methode
|
||
while = solange Bedingung wahr
|
||
-->
|
||
|
||
---
|
||
|
||
# Nützliche Array-Methoden
|
||
|
||
```javascript
|
||
const zahlen = [1, 2, 3, 4, 5];
|
||
|
||
// map: Transformieren
|
||
const verdoppelt = zahlen.map(x => x * 2);
|
||
// [2, 4, 6, 8, 10]
|
||
|
||
// filter: Filtern
|
||
const groß = zahlen.filter(x => x > 2);
|
||
// [3, 4, 5]
|
||
|
||
// find: Erstes Element finden
|
||
const gefunden = zahlen.find(x => x > 3);
|
||
// 4
|
||
|
||
// reduce: Aggregieren
|
||
const summe = zahlen.reduce((acc, x) => acc + x, 0);
|
||
// 15
|
||
```
|
||
|
||
<!--
|
||
Funktionale Programmierung
|
||
Sehr mächtig für Datenverarbeitung
|
||
Originales Array bleibt unverändert
|
||
-->
|
||
|
||
---
|
||
|
||
# Hands-On: Funktionen & Schleifen (30 Min)
|
||
|
||
**Erstellt `script.js`:**
|
||
|
||
1. Funktion die prüft ob Zahl gerade ist:
|
||
```javascript
|
||
function istGerade(zahl) {
|
||
// Dein Code
|
||
}
|
||
```
|
||
|
||
2. Funktion die Array-Summe berechnet
|
||
|
||
3. Schleife die 1-10 ausgibt und "Fizz" für durch 3 teilbare, "Buzz" für durch 5 teilbare Zahlen
|
||
|
||
**Tipp:** `zahl % 2 === 0` prüft ob gerade
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Pause
|
||
## 15 Minuten
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Teil 2: Das DOM
|
||
## HTML mit JavaScript manipulieren
|
||
|
||
---
|
||
|
||
# Was ist das DOM?
|
||
|
||
**D**ocument **O**bject **M**odel
|
||
|
||
- Browser parst HTML → Baumstruktur
|
||
- JavaScript kann diesen Baum **lesen und ändern**
|
||
- Jedes HTML-Element = ein "Node"
|
||
|
||
```
|
||
document
|
||
└── html
|
||
├── head
|
||
│ └── title
|
||
└── body
|
||
├── h1
|
||
└── p
|
||
```
|
||
|
||
<!--
|
||
DOM = Programmierschnittstelle für HTML
|
||
document = Wurzel des Baums
|
||
Jedes Element ist ein Objekt
|
||
-->
|
||
|
||
---
|
||
|
||
# Elemente finden
|
||
|
||
```javascript
|
||
// Einzelnes Element (erstes gefundene)
|
||
document.getElementById("meinId");
|
||
document.querySelector(".meineKlasse");
|
||
document.querySelector("nav > a");
|
||
|
||
// Mehrere Elemente (NodeList)
|
||
document.getElementsByClassName("meineKlasse");
|
||
document.querySelectorAll("p");
|
||
|
||
// Beispiel
|
||
const titel = document.querySelector("h1");
|
||
console.log(titel.textContent); // Text auslesen
|
||
```
|
||
|
||
<!--
|
||
getElementById = schnellste Methode
|
||
querySelector = CSS-Selektor (flexibel!)
|
||
querySelectorAll = alle Treffer
|
||
-->
|
||
|
||
---
|
||
|
||
# Elemente manipulieren
|
||
|
||
```javascript
|
||
const element = document.querySelector("#meinElement");
|
||
|
||
// Text ändern
|
||
element.textContent = "Neuer Text";
|
||
element.innerHTML = "<strong>HTML</strong> möglich";
|
||
|
||
// Attribute ändern
|
||
element.setAttribute("class", "neu");
|
||
element.id = "neueId";
|
||
element.href = "https://example.com";
|
||
|
||
// Styles ändern
|
||
element.style.color = "red";
|
||
element.style.backgroundColor = "blue";
|
||
element.style.display = "none"; // Verstecken
|
||
```
|
||
|
||
<!--
|
||
textContent = nur Text
|
||
innerHTML = HTML interpretieren
|
||
style = Inline-Styles (camelCase!)
|
||
-->
|
||
|
||
---
|
||
|
||
# Klassen manipulieren
|
||
|
||
```javascript
|
||
const element = document.querySelector(".box");
|
||
|
||
// Klasse hinzufügen
|
||
element.classList.add("aktiv");
|
||
|
||
// Klasse entfernen
|
||
element.classList.remove("inaktiv");
|
||
|
||
// Klasse umschalten
|
||
element.classList.toggle("sichtbar");
|
||
|
||
// Klasse prüfen
|
||
if (element.classList.contains("aktiv")) {
|
||
console.log("Element ist aktiv");
|
||
}
|
||
```
|
||
|
||
<!--
|
||
classList = moderne API
|
||
Besser als className direkt ändern
|
||
toggle schaltet hin und her
|
||
-->
|
||
|
||
---
|
||
|
||
# Elemente erstellen
|
||
|
||
```javascript
|
||
// Neues Element erstellen
|
||
const neuerAbsatz = document.createElement("p");
|
||
neuerAbsatz.textContent = "Ich bin neu!";
|
||
neuerAbsatz.classList.add("highlight");
|
||
|
||
// In DOM einfügen
|
||
const container = document.querySelector("#container");
|
||
container.appendChild(neuerAbsatz); // Am Ende
|
||
container.prepend(neuerAbsatz); // Am Anfang
|
||
container.insertBefore(neuerAbsatz, anderesElement);
|
||
|
||
// Element entfernen
|
||
neuerAbsatz.remove();
|
||
```
|
||
|
||
<!--
|
||
createElement = Element im Speicher
|
||
appendChild = in DOM einfügen
|
||
remove = aus DOM entfernen
|
||
-->
|
||
|
||
---
|
||
|
||
# Hands-On: DOM manipulieren (30 Min)
|
||
|
||
**HTML:**
|
||
```html
|
||
<div id="output"></div>
|
||
<ul id="liste"></ul>
|
||
```
|
||
|
||
**Aufgaben (in script.js):**
|
||
|
||
1. Ändere den Text von `#output`
|
||
2. Füge 5 `<li>`-Elemente zur Liste hinzu (mit Schleife!)
|
||
3. Gib jedem geraden Element eine Klasse `highlight`
|
||
4. Style `.highlight` in CSS (z.B. andere Farbe)
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Mittagspause
|
||
## 60 Minuten
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Teil 3: Events
|
||
## Auf NutzerInnen reagieren
|
||
|
||
---
|
||
|
||
# Was sind Events?
|
||
|
||
**NutzerInnen interagieren mit der Seite:**
|
||
- Klicken
|
||
- Tippen
|
||
- Scrollen
|
||
- Formulare absenden
|
||
|
||
**JavaScript kann darauf reagieren!**
|
||
|
||
<!--
|
||
Event = Ereignis
|
||
Event Handler = Reaktion darauf
|
||
Interaktive Webseiten durch Events
|
||
-->
|
||
|
||
---
|
||
|
||
# Event Listener
|
||
|
||
```javascript
|
||
const button = document.querySelector("#meinButton");
|
||
|
||
// Event Listener hinzufügen
|
||
button.addEventListener("click", function() {
|
||
console.log("Button wurde geklickt!");
|
||
});
|
||
|
||
// Mit Arrow Function
|
||
button.addEventListener("click", () => {
|
||
console.log("Klick!");
|
||
});
|
||
|
||
// Mit benannter Funktion
|
||
function handleClick() {
|
||
console.log("Klick!");
|
||
}
|
||
button.addEventListener("click", handleClick);
|
||
```
|
||
|
||
<!--
|
||
addEventListener = moderne Methode
|
||
Mehrere Listener pro Element möglich
|
||
Erstes Argument = Event-Typ
|
||
Zweites Argument = Callback-Funktion
|
||
-->
|
||
|
||
---
|
||
|
||
# Wichtige Events
|
||
|
||
| Event | Auslöser |
|
||
|-------|----------|
|
||
| `click` | Mausklick |
|
||
| `dblclick` | Doppelklick |
|
||
| `mouseover` / `mouseout` | Maus drüber/weg |
|
||
| `keydown` / `keyup` | Taste gedrückt/losgelassen |
|
||
| `input` | Eingabe in Formularfeld |
|
||
| `change` | Wert geändert (nach Blur) |
|
||
| `submit` | Formular abgesendet |
|
||
| `load` | Seite fertig geladen |
|
||
| `scroll` | Scrollen |
|
||
|
||
<!--
|
||
Viele weitere Events verfügbar
|
||
MDN für vollständige Liste
|
||
-->
|
||
|
||
---
|
||
|
||
# Das Event-Objekt
|
||
|
||
```javascript
|
||
button.addEventListener("click", function(event) {
|
||
console.log(event.type); // "click"
|
||
console.log(event.target); // Das geklickte Element
|
||
console.log(event.clientX); // Maus-X-Position
|
||
console.log(event.clientY); // Maus-Y-Position
|
||
});
|
||
|
||
// Tastatur-Events
|
||
document.addEventListener("keydown", function(event) {
|
||
console.log(event.key); // "a", "Enter", "Escape"
|
||
console.log(event.code); // "KeyA", "Enter", "Escape"
|
||
});
|
||
```
|
||
|
||
<!--
|
||
event = automatisch übergeben
|
||
Enthält Infos über das Event
|
||
target = auslösendes Element
|
||
-->
|
||
|
||
---
|
||
|
||
# Event.preventDefault()
|
||
|
||
```javascript
|
||
// Link ohne Navigation
|
||
const link = document.querySelector("a");
|
||
link.addEventListener("click", function(event) {
|
||
event.preventDefault(); // Verhindert Standardaktion
|
||
console.log("Link geklickt, aber keine Navigation!");
|
||
});
|
||
|
||
// Formular ohne Absenden
|
||
const form = document.querySelector("form");
|
||
form.addEventListener("submit", function(event) {
|
||
event.preventDefault(); // Seite lädt nicht neu
|
||
console.log("Formular verarbeiten...");
|
||
});
|
||
```
|
||
|
||
<!--
|
||
preventDefault = Standardverhalten stoppen
|
||
Wichtig für SPAs und AJAX
|
||
Formular-Validierung ohne Reload
|
||
-->
|
||
|
||
---
|
||
|
||
# Beispiel: Toggle Dark Mode
|
||
|
||
```javascript
|
||
const toggleButton = document.querySelector("#darkModeToggle");
|
||
const body = document.body;
|
||
|
||
toggleButton.addEventListener("click", () => {
|
||
body.classList.toggle("dark-mode");
|
||
|
||
// Button-Text ändern
|
||
if (body.classList.contains("dark-mode")) {
|
||
toggleButton.textContent = "☀️ Light Mode";
|
||
} else {
|
||
toggleButton.textContent = "🌙 Dark Mode";
|
||
}
|
||
});
|
||
```
|
||
|
||
```css
|
||
.dark-mode {
|
||
background: #1a1a1a;
|
||
color: #eee;
|
||
}
|
||
```
|
||
|
||
<!--
|
||
Klassisches UI-Pattern
|
||
Kein Neuladen der Seite
|
||
State in Klasse gespeichert
|
||
-->
|
||
|
||
---
|
||
|
||
# Beispiel: Formular-Validierung
|
||
|
||
```javascript
|
||
const form = document.querySelector("#kontaktForm");
|
||
const emailInput = document.querySelector("#email");
|
||
const errorMessage = document.querySelector("#error");
|
||
|
||
form.addEventListener("submit", function(event) {
|
||
const email = emailInput.value;
|
||
|
||
if (!email.includes("@")) {
|
||
event.preventDefault();
|
||
errorMessage.textContent = "Bitte gültige E-Mail eingeben!";
|
||
errorMessage.style.display = "block";
|
||
}
|
||
});
|
||
|
||
// Live-Feedback
|
||
emailInput.addEventListener("input", function() {
|
||
if (emailInput.value.includes("@")) {
|
||
errorMessage.style.display = "none";
|
||
}
|
||
});
|
||
```
|
||
|
||
<!--
|
||
Client-Side Validation
|
||
Zusätzlich zu HTML-Validation
|
||
UX: Sofortiges Feedback
|
||
Server-Validation trotzdem nötig!
|
||
-->
|
||
|
||
---
|
||
|
||
# Hands-On: Interaktive Features (45 Min)
|
||
|
||
**Baut in eure Seite ein:**
|
||
|
||
1. **Dark Mode Toggle**
|
||
- Button der Klasse auf `body` toggelt
|
||
- CSS für `.dark-mode`
|
||
|
||
2. **Accordion/FAQ**
|
||
- Klick auf Frage → Antwort erscheint/verschwindet
|
||
- Tipp: `classList.toggle()` + CSS `display: none/block`
|
||
|
||
3. **Formular-Validierung**
|
||
- Prüft ob Felder ausgefüllt
|
||
- Zeigt Fehlermeldung
|
||
|
||
**Hilfe:** https://nextlevelshit.github.io/web-engineering-mandala/
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Pause
|
||
## 15 Minuten
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Teil 4: Alles zusammen
|
||
## Projekt & Ausblick
|
||
|
||
---
|
||
|
||
# Projekt: Interaktive Portfolio-Seite
|
||
|
||
**Ihr habt jetzt alle Bausteine:**
|
||
|
||
- **HTML:** Struktur
|
||
- **CSS:** Design
|
||
- **JavaScript:** Interaktivität
|
||
|
||
**Kombiniert sie!**
|
||
|
||
---
|
||
|
||
# Projekt-Anforderungen
|
||
|
||
**Must-Have:**
|
||
- [ ] Semantisches HTML
|
||
- [ ] Responsive CSS (Mobile + Desktop)
|
||
- [ ] Mindestens 2 interaktive Features mit JS
|
||
|
||
**Nice-to-Have:**
|
||
- [ ] Dark Mode
|
||
- [ ] Animationen/Transitions
|
||
- [ ] Formular mit Validierung
|
||
- [ ] Dynamisch generierte Inhalte
|
||
|
||
**Zeit:** 60 Minuten
|
||
|
||
---
|
||
|
||
# Beispiel: Todo-Liste
|
||
|
||
```javascript
|
||
const form = document.querySelector("#todoForm");
|
||
const input = document.querySelector("#todoInput");
|
||
const liste = document.querySelector("#todoListe");
|
||
|
||
form.addEventListener("submit", function(event) {
|
||
event.preventDefault();
|
||
|
||
if (input.value.trim() === "") return;
|
||
|
||
const li = document.createElement("li");
|
||
li.textContent = input.value;
|
||
|
||
// Löschen per Klick
|
||
li.addEventListener("click", () => li.remove());
|
||
|
||
liste.appendChild(li);
|
||
input.value = ""; // Input leeren
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
# Modernes JavaScript: Kurzer Ausblick
|
||
|
||
**Was ihr als nächstes lernen könnt:**
|
||
|
||
| Thema | Beschreibung |
|
||
|-------|--------------|
|
||
| **Fetch API** | Daten von Servern laden |
|
||
| **Async/Await** | Asynchrone Programmierung |
|
||
| **LocalStorage** | Daten im Browser speichern |
|
||
| **Frameworks** | React, Vue, Svelte |
|
||
| **Node.js** | JavaScript auf dem Server |
|
||
|
||
<!--
|
||
Fetch = HTTP-Requests aus JS
|
||
Frameworks für größere Apps
|
||
Node.js für Backend
|
||
-->
|
||
|
||
---
|
||
|
||
# Fetch: Daten laden
|
||
|
||
```javascript
|
||
// Daten von API laden
|
||
fetch("https://api.example.com/data")
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
console.log(data);
|
||
})
|
||
.catch(error => {
|
||
console.error("Fehler:", error);
|
||
});
|
||
|
||
// Mit async/await (moderner)
|
||
async function ladeDaten() {
|
||
try {
|
||
const response = await fetch("https://api.example.com/data");
|
||
const data = await response.json();
|
||
console.log(data);
|
||
} catch (error) {
|
||
console.error("Fehler:", error);
|
||
}
|
||
}
|
||
```
|
||
|
||
<!--
|
||
APIs = Schnittstellen zu Daten
|
||
JSON = JavaScript Object Notation
|
||
async/await = lesbarere Syntax
|
||
-->
|
||
|
||
---
|
||
|
||
# LocalStorage: Daten speichern
|
||
|
||
```javascript
|
||
// Speichern
|
||
localStorage.setItem("name", "Max");
|
||
localStorage.setItem("settings", JSON.stringify({
|
||
darkMode: true,
|
||
language: "de"
|
||
}));
|
||
|
||
// Laden
|
||
const name = localStorage.getItem("name");
|
||
const settings = JSON.parse(localStorage.getItem("settings"));
|
||
|
||
// Löschen
|
||
localStorage.removeItem("name");
|
||
localStorage.clear(); // Alles löschen
|
||
```
|
||
|
||
<!--
|
||
Daten bleiben nach Browser-Neustart
|
||
Max 5-10 MB
|
||
Nur Strings → JSON.stringify/parse
|
||
-->
|
||
|
||
---
|
||
|
||
# Frontend-Frameworks
|
||
|
||
**React** (Meta/Facebook)
|
||
```jsx
|
||
function Button() {
|
||
const [count, setCount] = useState(0);
|
||
return <button onClick={() => setCount(count + 1)}>
|
||
Klicks: {count}
|
||
</button>;
|
||
}
|
||
```
|
||
|
||
**Vue.js** (Evan You)
|
||
```vue
|
||
<template>
|
||
<button @click="count++">Klicks: {{ count }}</button>
|
||
</template>
|
||
<script setup>
|
||
import { ref } from 'vue';
|
||
const count = ref(0);
|
||
</script>
|
||
```
|
||
|
||
<!--
|
||
Frameworks für größere Apps
|
||
Komponenten-basiert
|
||
State Management eingebaut
|
||
-->
|
||
|
||
---
|
||
|
||
# Ressourcen zum Weiterlernen
|
||
|
||
**Dokumentation:**
|
||
- MDN Web Docs: https://developer.mozilla.org/de/
|
||
|
||
**Interaktiv lernen:**
|
||
- HTML: https://nextlevelshit.github.io/html-over-js/
|
||
- CSS: https://codecrispi.es/
|
||
- JS Visualisierung: https://nextlevelshit.github.io/web-engineering-mandala/
|
||
|
||
**Kurse:**
|
||
- freeCodeCamp: https://freecodecamp.org
|
||
- The Odin Project: https://theodinproject.com
|
||
|
||
---
|
||
|
||
# Tools für die Praxis
|
||
|
||
**Editoren:**
|
||
- VS Code (empfohlen)
|
||
- WebStorm (JetBrains)
|
||
- Neovim (für Terminal-Fans)
|
||
|
||
**Online-Editoren:**
|
||
- CodePen: https://codepen.io
|
||
- StackBlitz: https://stackblitz.com
|
||
|
||
**Versionskontrolle:**
|
||
- Git + GitHub/GitLab
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Fragen & Abschluss
|
||
|
||
---
|
||
|
||
# Was ihr gelernt habt
|
||
|
||
**Tag 1:**
|
||
- Geschichte der Informatik (Hollerith → Internet)
|
||
- Von-Neumann-Architektur
|
||
- HTML-Grundlagen
|
||
|
||
**Tag 2:**
|
||
- Netzwerke, DNS, HTTP
|
||
- CSS: Selektoren, Box-Modell, Flexbox
|
||
|
||
**Tag 3:**
|
||
- JavaScript: Variablen, Funktionen, Schleifen
|
||
- DOM-Manipulation
|
||
- Events & Interaktivität
|
||
|
||
---
|
||
|
||
# Ihr könnt jetzt...
|
||
|
||
✅ Den historischen Kontext von IT verstehen
|
||
✅ Erklären wie das Internet funktioniert
|
||
✅ HTML-Seiten strukturieren
|
||
✅ CSS für Layout und Design nutzen
|
||
✅ JavaScript für Interaktivität einsetzen
|
||
✅ **Mit EntwicklerInnen auf Augenhöhe sprechen!**
|
||
|
||
---
|
||
|
||
# Feedback
|
||
|
||
**Was hat gut funktioniert?**
|
||
**Was könnte besser sein?**
|
||
**Welche Themen wünscht ihr euch für die Zukunft?**
|
||
|
||
---
|
||
|
||
<!-- _class: lead -->
|
||
|
||
# Danke!
|
||
|
||
**Kontakt:** michael.czechowski@lehre.dhbw-stuttgart.de
|
||
**Repository:** git.librete.ch/hdm/223015b
|
||
|
||
**Ressourcen:**
|
||
- https://nextlevelshit.github.io/html-over-js/
|
||
- https://codecrispi.es/
|
||
- https://nextlevelshit.github.io/web-engineering-mandala/
|
||
|
||
---
|
||
|
||
# Lizenz
|
||
|
||
Diese Präsentation ist lizenziert unter **Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)**
|
||
|
||
Basiert auf Material von:
|
||
- Markus Thamm / Wolfgang Gruel (HdM Stuttgart)
|
||
- Michael Czechowski
|
||
|
||
Vollständige Lizenz: https://creativecommons.org/licenses/by-sa/4.0/
|