Skip to content

Kapitel 21: Umfassende Projekte (Praxis- vertiefung)

In diesem Kapitel programmieren wir größere Anwendungen zur Vertiefung Ihres Wissens.

21.1 Studenten-Verwaltungssystem

Ein System zur Verwaltung von Studentendaten.

Funktionen

  1. Studenten hinzufügen (Name, Matrikelnummer, Fachrichtung)
  2. Studenten suchen (Nach Name oder Matrikelnummer)
  3. Studenten löschen
  4. Noten eingeben (Für jeden Studenten)
  5. Durchschnittsnote berechnen
  6. Daten im localStorage speichern

HTML-Struktur

html
<h1>Studenten-Verwaltungssystem</h1>

<!-- Eingabeformular -->
<div>
    <h2>Neuen Studenten hinzufügen</h2>
    <input type="text" id="name" placeholder="Name">
    <input type="text" id="matrikel" placeholder="Matrikelnummer">
    <input type="text" id="fachrichtung" placeholder="Fachrichtung">
    <button id="hinzufuegenBtn">Hinzufügen</button>
</div>

<!-- Suchleiste -->
<div>
    <h2>Suchen</h2>
    <input type="text" id="suche" placeholder="Namen oder Matrikelnummer...">
    <button id="suchenBtn">Suchen</button>
</div>

<!-- Studentenliste -->
<div>
    <h2>Studentenliste</h2>
    <table border="1" id="studentenTabelle">
        <thead>
            <tr>
                <th>Name</th>
                <th>Matrikelnummer</th>
                <th>Fachrichtung</th>
                <th>Aktionen</th>
            </tr>
        </thead>
        <tbody id="studentenListe">
            <!-- Dynamisch generiert -->
        </tbody>
    </table>
</div>

<!-- Statistiken -->
<div>
    <h2>Statistiken</h2>
    <p>Gesamtanzahl Studenten: <span id="gesamtAnzahl">0</span></p>
</div>

JavaScript-Logik

javascript
let studenten = JSON.parse(localStorage.getItem("studenten")) || [];

// Studenten anzeigen
function zeigeStudenten() {
    let studentenListe = document.getElementById("studentenListe");
    let gesamtAnzahl = document.getElementById("gesamtAnzahl");
    
    studentenListe.innerHTML = "";
    
    studenten.forEach(function(student, index) {
        let tr = document.createElement("tr");
        
        let nameTd = document.createElement("td");
        nameTd.textContent = student.name;
        
        let matrikelTd = document.createElement("td");
        matrikelTd.textContent = student.matrikel;
        
        let fachrichtungTd = document.createElement("td");
        fachrichtungTd.textContent = student.fachrichtung;
        
        let aktionenTd = document.createElement("td");
        
        let loeschenBtn = document.createElement("button");
        loeschenBtn.textContent = "Löschen";
        loeschenBtn.addEventListener("click", function() {
            studenten.splice(index, 1);
            speichereStudenten();
            zeigeStudenten();
        });
        
        aktionenTd.appendChild(loeschenBtn);
        
        tr.appendChild(nameTd);
        tr.appendChild(matrikelTd);
        tr.appendChild(fachrichtungTd);
        tr.appendChild(aktionenTd);
        
        studentenListe.appendChild(tr);
    });
    
    gesamtAnzahl.textContent = studenten.length;
}

// Studenten speichern
function speichereStudenten() {
    localStorage.setItem("studenten", JSON.stringify(studenten));
}

// Neuen Studenten hinzufügen
document.getElementById("hinzufuegenBtn").addEventListener("click", function() {
    let name = document.getElementById("name").value.trim();
    let matrikel = document.getElementById("matrikel").value.trim();
    let fachrichtung = document.getElementById("fachrichtung").value.trim();
    
    if (name === "" || matrikel === "" || fachrichtung === "") {
        alert("Bitte füllen Sie alle Felder aus!");
        return;
    }
    
    // Prüfen, ob Matrikelnummer bereits existiert
    if (studenten.some(s => s.matrikel === matrikel)) {
        alert("Diese Matrikelnummer existiert bereits!");
        return;
    }
    
    studenten.push({
        name: name,
        matrikel: matrikel,
        fachrichtung: fachrichtung
    });
    
    speichereStudenten();
    zeigeStudenten();
    
    // Formular zurücksetzen
    document.getElementById("name").value = "";
    document.getElementById("matrikel").value = "";
    document.getElementById("fachrichtung").value = "";
});

// Suchen
document.getElementById("suchenBtn").addEventListener("click", function() {
    let suchbegriff = document.getElementById("suche").value.trim().toLowerCase();
    
    if (suchbegriff === "") {
        zeigeStudenten();  // Alle anzeigen
        return;
    }
    
    let ergebnis = studenten.filter(function(student) {
        return student.name.toLowerCase().includes(suchbegriff) || 
               student.matrikel.includes(suchbegriff);
    });
    
    let studentenListe = document.getElementById("studentenListe");
    studentenListe.innerHTML = "";
    
    ergebnis.forEach(function(student, index) {
        let tr = document.createElement("tr");
        
        let nameTd = document.createElement("td");
        nameTd.textContent = student.name;
        
        let matrikelTd = document.createElement("td");
        matrikelTd.textContent = student.matrikel;
        
        let fachrichtungTd = document.createElement("td");
        fachrichtungTd.textContent = student.fachrichtung;
        
        let aktionenTd = document.createElement("td");
        
        let loeschenBtn = document.createElement("button");
        loeschenBtn.textContent = "Löschen";
        loeschenBtn.addEventListener("click", function() {
            // Originalindex finden
            let originalIndex = studenten.findIndex(s => s.matrikel === student.matrikel);
            if (originalIndex !== -1) {
                studenten.splice(originalIndex, 1);
                speichereStudenten();
                zeigeStudenten();
            }
        });
        
        aktionenTd.appendChild(loeschenBtn);
        
        tr.appendChild(nameTd);
        tr.appendChild(matrikelTd);
        tr.appendChild(fachrichtungTd);
        tr.appendChild(aktionenTd);
        
        studentenListe.appendChild(tr);
    });
});

// Beim Laden anzeigen
window.addEventListener("load", zeigeStudenten);

21.2 Responsiver Warenkorb

Ein Warenkorb-System mit lokaler Speicherung.

Funktionen

  1. Produkte anzeigen (Vom Server simuliert)
  2. In Warenkorb legen
  3. Warenkorb anzeigen
  4. Menge ändern
  5. Produkt entfernen
  6. Gesamtpreis berechnen
  7. Responsiv (Mobile-optimiert)

HTML-Struktur

html
<h1>Onlineshop</h1>

<!-- Produktliste -->
<div id="produktListe">
    <!-- Dynamisch generiert -->
</div>

<!-- Warenkorb -->
<div id="warenkorb">
    <h2>Warenkorb</h2>
    <div id="warenkorbListe">
        <!-- Dynamisch generiert -->
    </div>
    <p>Gesamtpreis: <span id="gesamtpreis">0.00</span> €</p>
    <button id="checkoutBtn">Zur Kasse</button>
</div>

CSS (Responsive)

css
/* Grundlegendes Styling */
#produktListe {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
}

.produkt {
    border: 1px solid #ccc;
    padding: 10px;
    width: 200px;
}

#warenkorb {
    margin-top: 30px;
    border-top: 2px solid #333;
    padding-top: 20px;
}

.warenkorbItem {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
}

/* Responsive Design */
@media (max-width: 768px) {
    #produktListe {
        flex-direction: column;
    }
    
    .produkt {
        width: 100%;
    }
}

JavaScript-Logik

javascript
// Simulierte Produktdaten
let produkte = [
    { id: 1, name: "Laptop", preis: 999.99, bild: "laptop.jpg" },
    { id: 2, name: "Smartphone", preis: 499.99, bild: "smartphone.jpg" },
    { id: 3, name: "Kopfhörer", preis: 99.99, bild: "kopfhoerer.jpg" }
];

let warenkorb = JSON.parse(localStorage.getItem("warenkorb")) || [];

// Produkte anzeigen
function zeigeProdukte() {
    let produktListe = document.getElementById("produktListe");
    produktListe.innerHTML = "";
    
    produkte.forEach(function(produkt) {
        let div = document.createElement("div");
        div.classList.add("produkt");
        
        div.innerHTML = `
            <img src="${produkt.bild}" alt="${produkt.name}" style="width:100%;">
            <h3>${produkt.name}</h3>
            <p>Preis: ${produkt.preis.toFixed(2)} €</p>
            <button onclick="inWarenkorbLegen(${produkt.id})">In Warenkorb</button>
        `;
        
        produktListe.appendChild(div);
    });
}

// In Warenkorb legen
function inWarenkorbLegen(produktId) {
    let produkt = produkte.find(p => p.id === produktId);
    
    // Prüfen, ob bereits im Warenkorb
    let vorhandenesItem = warenkorb.find(item => item.id === produktId);
    
    if (vorhandenesItem) {
        vorhandenesItem.menge++;
    } else {
        warenkorb.push({
            id: produkt.id,
            name: produkt.name,
            preis: produkt.preis,
            menge: 1
        });
    }
    
    speichereWarenkorb();
    zeigeWarenkorb();
}

// Warenkorb anzeigen
function zeigeWarenkorb() {
    let warenkorbListe = document.getElementById("warenkorbListe");
    let gesamtpreisElement = document.getElementById("gesamtpreis");
    
    warenkorbListe.innerHTML = "";
    let gesamtpreis = 0;
    
    warenkorb.forEach(function(item, index) {
        let div = document.createElement("div");
        div.classList.add("warenkorbItem");
        
        let itemGesamtpreis = item.preis * item.menge;
        gesamtpreis += itemGesamtpreis;
        
        div.innerHTML = `
            <span>${item.name} (${item.menge}x)</span>
            <span>${itemGesamtpreis.toFixed(2)} €</span>
            <div>
                <button onclick="mengeAendern(${index}, 'minus')">-</button>
                <span>${item.menge}</span>
                <button onclick="mengeAendern(${index}, 'plus')">+</button>
                <button onclick="itemEntfernen(${index})">Entfernen</button>
            </div>
        `;
        
        warenkorbListe.appendChild(div);
    });
    
    gesamtpreisElement.textContent = gesamtpreis.toFixed(2);
}

// Menge ändern
function mengeAendern(index, aktion) {
    if (aktion === "plus") {
        warenkorb[index].menge++;
    } else if (aktion === "minus") {
        if (warenkorb[index].menge > 1) {
            warenkorb[index].menge--;
        } else {
            // Wenn menge 1 ist und minus geklickt wird → entfernen
            warenkorb.splice(index, 1);
        }
    }
    
    speichereWarenkorb();
    zeigeWarenkorb();
}

// Item entfernen
function itemEntfernen(index) {
    warenkorb.splice(index, 1);
    speichereWarenkorb();
    zeigeWarenkorb();
}

// Warenkorb speichern
function speichereWarenkorb() {
    localStorage.setItem("warenkorb", JSON.stringify(warenkorb));
}

// Zur Kasse (simuliert)
document.getElementById("checkoutBtn").addEventListener("click", function() {
    if (warenkorb.length === 0) {
        alert("Ihr Warenkorb ist leer!");
        return;
    }
    
    alert("Vielen Dank für Ihren Einkauf! (Simuliert)");
    warenkorb = [];
    speichereWarenkorb();
    zeigeWarenkorb();
});

// Beim Laden anzeigen
window.addEventListener("load", function() {
    zeigeProdukte();
    zeigeWarenkorb();
});

21.3 Wetter-Abfrage-Tool

Ein Tool, das Wetterdaten von einer API abruft.

Funktionen

  1. Stadt eingeben (Vom Benutzer)
  2. Wetterdaten abrufen (Über API)
  3. Wetter anzeigen (Temperatur, Luftfeuchtigkeit, etc.)
  4. Fehlerbehandlung (Wenn Stadt nicht gefunden)

HTML-Struktur

html
<h1>Wetter-Abfrage</h1>
<input type="text" id="stadtInput" placeholder="Stadtname eingeben...">
<button id="suchenBtn">Suchen</button>
<div id="wetterAnzeige">
    <!-- Wetterdaten werden hier angezeigt -->
</div>

JavaScript-Logik

javascript
let apiKey = "DEIN_API_SCHLUESSEL";  // Ersetzen Sie mit echtem API-Schlüssel
let apiUrl = "https://api.openweathermap.org/data/2.5/weather";

document.getElementById("suchenBtn").addEventListener("click", function() {
    let stadt = document.getElementById("stadtInput").value.trim();
    
    if (stadt === "") {
        alert("Bitte geben Sie einen Stadtnamen ein!");
        return;
    }
    
    wetterAbrufen(stadt);
});

// Wetter abrufen (mit Fetch API)
async function wetterAbrufen(stadt) {
    let wetterAnzeige = document.getElementById("wetterAnzeige");
    wetterAnzeige.innerHTML = "Lädt...";
    
    try {
        let antwort = await fetch(`${apiUrl}?q=${stadt}&appid=${apiKey}&units=metric&lang=de`);
        
        if (!antwort.ok) {
            throw new Error("Stadt nicht gefunden!");
        }
        
        let daten = await antwort.json();
        zeigeWetter(daten);
        
    } catch (fehler) {
        wetterAnzeige.innerHTML = `<p style="color:red;">Fehler: ${fehler.message}</p>`;
    }
}

// Wetter anzeigen
function zeigeWetter(daten) {
    let wetterAnzeige = document.getElementById("wetterAnzeige");
    
    let stadt = daten.name;
    let land = daten.sys.country;
    let temp = daten.main.temp;
    let beschreibung = daten.weather[0].description;
    let luftfeuchtigkeit = daten.main.humidity;
    let windGeschwindigkeit = daten.wind.speed;
    
    wetterAnzeige.innerHTML = `
        <h2>Wetter in ${stadt}, ${land}</h2>
        <p><strong>Temperatur:</strong> ${temp} °C</p>
        <p><strong>Beschreibung:</strong> ${beschreibung}</p>
        <p><strong>Luftfeuchtigkeit:</strong> ${luftfeuchtigkeit}%</p>
        <p><strong>Windgeschwindigkeit:</strong> ${windGeschwindigkeit} m/s</p>
    `;
}

Hinweis:

  • Sie müssen einen API-Schlüssel von OpenWeatherMap erhalten.
  • Ersetzen Sie DEIN_API_SCHLUESSEL mit Ihrem echtem Schlüssel.

21.4 Persönlicher Lebenslauf-Generator

Ein Tool, das einen Lebenslauf basierend auf Benutzereingaben generiert.

Funktionen

  1. Persönliche Daten eingeben (Name, Kontakt, etc.)
  2. Bildungsweg hinzufügen
  3. Berufserfahrung hinzufügen
  4. Fähigkeiten hinzufügen
  5. Lebenslauf als Text "exportieren"

HTML-Struktur

html
<h1>Lebenslauf-Generator</h1>

<form id="lebenslaufForm">
    <h2>Persönliche Daten</h2>
    <input type="text" id="name" placeholder="Vollständiger Name" required>
    <input type="email" id="email" placeholder="E-Mail" required>
    <input type="tel" id="telefon" placeholder="Telefonnummer">
    <textarea id="zusammenfassung" placeholder="Kurze Zusammenfassung..."></textarea>
    
    <h2>Bildungsweg</h2>
    <div id="bildungContainer">
        <div class="bildungEintrag">
            <input type="text" placeholder="Abschluss">
            <input type="text" placeholder="Institution">
            <input type="text" placeholder="Jahr">
        </div>
    </div>
    <button type="button" id="bildungHinzufuegenBtn">Bildung hinzufügen</button>
    
    <h2>Berufserfahrung</h2>
    <div id="berufContainer">
        <div class="berufEintrag">
            <input type="text" placeholder="Position">
            <input type="text" placeholder="Unternehmen">
            <input type="text" placeholder="Dauer">
        </div>
    </div>
    <button type="button" id="berufHinzufuegenBtn">Berufserfahrung hinzufügen</button>
    
    <h2>Fähigkeiten</h2>
    <textarea id="faehigkeiten" placeholder="Fähigkeiten (durch Kommas getrennt)"></textarea>
    
    <button type="submit">Lebenslauf generieren</button>
</form>

<div id="lebenslaufAusgabe" style="display:none;">
    <h2>Ihr Lebenslauf</h2>
    <pre id="lebenslaufText"></pre>
    <button id="kopierenBtn">Text kopieren</button>
</div>

JavaScript-Logik

javascript
// Bildungseintrag hinzufügen
document.getElementById("bildungHinzufuegenBtn").addEventListener("click", function() {
    let container = document.getElementById("bildungContainer");
    let div = document.createElement("div");
    div.classList.add("bildungEintrag");
    div.innerHTML = `
        <input type="text" placeholder="Abschluss">
        <input type="text" placeholder="Institution">
        <input type="text" placeholder="Jahr">
        <button type="button" class="eintragEntfernenBtn">Entfernen</button>
    `;
    container.appendChild(div);
    
    // Entfernen-Button Event
    div.querySelector(".eintragEntfernenBtn").addEventListener("click", function() {
        container.removeChild(div);
    });
});

// Berufseintrag hinzufügen
document.getElementById("berufHinzufuegenBtn").addEventListener("click", function() {
    let container = document.getElementById("berufContainer");
    let div = document.createElement("div");
    div.classList.add("berufEintrag");
    div.innerHTML = `
        <input type="text" placeholder="Position">
        <input type="text" placeholder="Unternehmen">
        <input type="text" placeholder="Dauer">
        <button type="button" class="eintragEntfernenBtn">Entfernen</button>
    `;
    container.appendChild(div);
    
    // Entfernen-Button Event
    div.querySelector(".eintragEntfernenBtn").addEventListener("click", function() {
        container.removeChild(div);
    });
});

// Formular absenden
document.getElementById("lebenslaufForm").addEventListener("submit", function(event) {
    event.preventDefault();
    
    // Daten sammeln
    let name = document.getElementById("name").value;
    let email = document.getElementById("email").value;
    let telefon = document.getElementById("telefon").value;
    let zusammenfassung = document.getElementById("zusammenfassung").value;
    
    // Bildungsdaten
    let bildungEintraege = document.querySelectorAll(".bildungEintrag");
    let bildung = [];
    bildungEintraege.forEach(function(eintrag) {
        let inputs = eintrag.querySelectorAll("input");
        bildung.push({
            abschluss: inputs[0].value,
            institution: inputs[1].value,
            jahr: inputs[2].value
        });
    });
    
    // Berufsdaten
    let berufEintraege = document.querySelectorAll(".berufEintrag");
    let beruf = [];
    berufEintraege.forEach(function(eintrag) {
        let inputs = eintrag.querySelectorAll("input");
        beruf.push({
            position: inputs[0].value,
            unternehmen: inputs[1].value,
            dauer: inputs[2].value
        });
    });
    
    // Fähigkeiten
    let faehigkeitenText = document.getElementById("faehigkeiten").value;
    let faehigkeiten = faehigkeitenText.split(",").map(f => f.trim());
    
    // Lebenslauf generieren
    let lebenslauf = `LEBENSLAUF

${name}
${email}
${telefon}

ZUSAMMENFASSUNG
${zusammenfassung}

BILDUNGSWEG
`;
    
    bildung.forEach(function(eintrag) {
        lebenslauf += `${eintrag.abschluss}, ${eintrag.institution} (${eintrag.jahr})
`;
    });
    
    lebenslauf += `
BERUFSERFAHRUNG
`;
    
    beruf.forEach(function(eintrag) {
        lebenslauf += `${eintrag.position} bei ${eintrag.unternehmen} (${eintrag.dauer})
`;
    });
    
    lebenslauf += `
FÄHIGKEITEN
${faehigkeiten.join(", ")}
`;
    
    // Anzeigen
    document.getElementById("lebenslaufText").textContent = lebenslauf;
    document.getElementById("lebenslaufAusgabe").style.display = "block";
});

// Text kopieren
document.getElementById("kopierenBtn").addEventListener("click", function() {
    let text = document.getElementById("lebenslaufText").textContent;
    navigator.clipboard.writeText(text)
        .then(function() {
            alert("Lebenslauf in Zwischenablage kopiert!");
        })
        .catch(function(err) {
            console.error("Fehler beim Kopieren:", err);
        });
});

📝 Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • ✅ Studenten-Verwaltungssystem (CRUD, localStorage)
  • ✅ Responsiver Warenkorb (E-Commerce Grundlagen)
  • ✅ Wetter-Abfrage-Tool (API-Aufruf mit Fetch)
  • ✅ Persönlicher Lebenslauf-Generator (Formularverarbeitung)

➡️ Nächster Schritt

Im nächsten Kapitel lernen wir Werkzeuge - empfohlene Tools für JavaScript-Entwickler!


Übung:

  1. Erweitern Sie das Studenten-Verwaltungssystem mit Notenverwaltung
  2. Fügen Sie dem Warenkorb eine Suche hinzu
  3. Erweitern Sie das Wetter-Tool mit 5-Tage-Vorhersage
  4. Fügen Sie dem Lebenslauf-Generator ein Profilbild-Upload hinzu

Frei für alle Anfänger