JavaScript Anfänger

DOM-Elemente manipulieren

DOM-Elemente manipulieren

Nachdem du Elemente gefunden hast, wird’s spannend: Jetzt ändern wir sie! Texte anpassen, Klassen togglen, neue Elemente erstellen - das macht Webseiten interaktiv.

Text-Inhalt ändern

textContent - Empfohlen

const heading = document.querySelector("h1");

// Lesen
console.log(heading.textContent);

// Setzen
heading.textContent = "Neuer Titel";

// Auch mit HTML-Zeichen (werden escaped - sicher!)
heading.textContent = "<b>Bold</b>";  // Zeigt: <b>Bold</b> als Text

textContent ist die sicherste Methode für User-generierten Content, da HTML-Tags als Text angezeigt und nicht ausgeführt werden.

innerText - Mit Style-Beachtung

// innerText beachtet CSS (display: none, etc.)
const element = document.querySelector(".content");

console.log(element.textContent);  // Alles, auch hidden
console.log(element.innerText);    // Nur sichtbarer Text

Attribute manipulieren

getAttribute / setAttribute

const link = document.querySelector("a");

// Lesen
const href = link.getAttribute("href");
const target = link.getAttribute("target");

// Setzen
link.setAttribute("href", "https://example.com");
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");

Direkte Eigenschaften

const link = document.querySelector("a");
const img = document.querySelector("img");
const input = document.querySelector("input");

// Die meisten Attribute sind auch Eigenschaften
link.href = "https://example.com";
img.src = "/images/foto.jpg";
img.alt = "Beschreibung";
input.value = "Neuer Wert";
input.placeholder = "Eingabe...";

// Boolean-Attribute
input.disabled = true;
input.required = true;
input.checked = true;  // Für Checkboxen

hasAttribute / removeAttribute

const button = document.querySelector("button");

// Prüfen
if (button.hasAttribute("disabled")) {
    console.log("Button ist deaktiviert");
}

// Entfernen
button.removeAttribute("disabled");

Data-Attribute (dataset)

// HTML: <div data-user-id="123" data-role="admin">

const element = document.querySelector("[data-user-id]");

// Lesen (camelCase!)
console.log(element.dataset.userId);    // "123"
console.log(element.dataset.role);      // "admin"

// Setzen
element.dataset.userId = "456";
element.dataset.newProp = "Wert";  // Erstellt data-new-prop

// Löschen
delete element.dataset.role;

Klassen manipulieren

classList - Der moderne Weg

const element = document.querySelector(".box");

// Hinzufügen
element.classList.add("active");
element.classList.add("highlight", "visible");  // Mehrere

// Entfernen
element.classList.remove("active");
element.classList.remove("highlight", "visible");

// Umschalten (toggle)
element.classList.toggle("active");  // An wenn aus, aus wenn an

// Toggle mit Bedingung
element.classList.toggle("active", isLoggedIn);  // Force an/aus

// Prüfen
if (element.classList.contains("active")) {
    console.log("Ist aktiv!");
}

// Ersetzen
element.classList.replace("old-class", "new-class");

className - Der alte Weg

const element = document.querySelector(".box");

// Überschreibt ALLE Klassen!
element.className = "neue-klasse andere-klasse";

// Alle Klassen lesen
console.log(element.className);  // "neue-klasse andere-klasse"

Styles ändern

Inline Styles

const box = document.querySelector(".box");

// Einzelne Styles setzen (camelCase!)
box.style.backgroundColor = "blue";
box.style.color = "white";
box.style.padding = "20px";
box.style.borderRadius = "10px";

// CSS-Property Namen:
// background-color → backgroundColor
// font-size → fontSize
// z-index → zIndex

// Style lesen
console.log(box.style.backgroundColor);  // "blue"

// Style entfernen
box.style.backgroundColor = "";
box.style.removeProperty("background-color");

Mehrere Styles auf einmal

// Mit cssText
box.style.cssText = "background: blue; color: white; padding: 20px;";

// Mit Object.assign
Object.assign(box.style, {
    backgroundColor: "blue",
    color: "white",
    padding: "20px"
});

Computed Styles (berechnete Werte)

const box = document.querySelector(".box");

// getComputedStyle zeigt alle aktiven Styles
const styles = getComputedStyle(box);

console.log(styles.width);           // "200px" (berechneter Wert)
console.log(styles.backgroundColor); // "rgb(0, 0, 255)"
console.log(styles.display);         // "block"

Best Practice: Klassen statt Inline Styles

// Nicht optimal
element.style.backgroundColor = "red";
element.style.padding = "20px";
element.style.borderRadius = "10px";

// Besser: CSS-Klasse verwenden
element.classList.add("error-box");

// In CSS:
// .error-box {
//     background-color: red;
//     padding: 20px;
//     border-radius: 10px;
// }

Elemente erstellen

createElement

// Element erstellen
const div = document.createElement("div");
const paragraph = document.createElement("p");
const button = document.createElement("button");

// Eigenschaften setzen
div.className = "card";
div.id = "card-1";

paragraph.textContent = "Ein neuer Paragraph";

button.textContent = "Klick mich";
button.classList.add("btn", "btn-primary");

// Event Listener hinzufügen
button.addEventListener("click", () => {
    console.log("Geklickt!");
});

Komplexere Strukturen bauen

function createCard(title, description, imageUrl) {
    // Container
    const card = document.createElement("div");
    card.className = "card";

    // Bild
    const img = document.createElement("img");
    img.src = imageUrl;
    img.alt = title;
    img.className = "card-image";

    // Body
    const body = document.createElement("div");
    body.className = "card-body";

    // Titel
    const h3 = document.createElement("h3");
    h3.textContent = title;

    // Beschreibung
    const p = document.createElement("p");
    p.textContent = description;

    // Zusammenbauen
    body.appendChild(h3);
    body.appendChild(p);
    card.appendChild(img);
    card.appendChild(body);

    return card;
}

// Verwenden
const card = createCard("Titel", "Beschreibung", "/img.jpg");
document.querySelector("#cards").appendChild(card);

Elemente einfügen

appendChild / append

const container = document.querySelector(".container");
const newElement = document.createElement("div");

// appendChild - ein Element
container.appendChild(newElement);

// append - mehrere Elemente und Text
const p = document.createElement("p");
const span = document.createElement("span");
container.append(p, span, "Auch Text möglich");

prepend - Am Anfang

const list = document.querySelector("ul");
const newItem = document.createElement("li");
newItem.textContent = "Erstes Item";

// Am Anfang einfügen
list.prepend(newItem);

before / after - Neben einem Element

const referenz = document.querySelector("#referenz");
const neuesElement = document.createElement("div");

// Vor dem Element
referenz.before(neuesElement);
referenz.before("Text davor");

// Nach dem Element
referenz.after(neuesElement);

insertBefore (klassisch)

const parent = document.querySelector(".parent");
const newChild = document.createElement("div");
const referenz = document.querySelector("#referenz");

// Vor referenz einfügen
parent.insertBefore(newChild, referenz);

insertAdjacentElement

const element = document.querySelector(".target");

// Position: "beforebegin", "afterbegin", "beforeend", "afterend"
const newDiv = document.createElement("div");
element.insertAdjacentElement("afterbegin", newDiv);

// Text einfügen
element.insertAdjacentText("beforeend", "Neuer Text");
beforebegin
<div>
    afterbegin
    ... Inhalt ...
    beforeend
</div>
afterend

Elemente entfernen

remove() - Modern

const element = document.querySelector("#to-remove");
element.remove();

removeChild (klassisch)

const parent = document.querySelector(".parent");
const child = document.querySelector(".child");
parent.removeChild(child);

Alle Kinder entfernen

const container = document.querySelector(".container");

// Methode 1: replaceChildren (modern und empfohlen)
container.replaceChildren();

// Methode 2: Loop (behält Kontrolle)
while (container.firstChild) {
    container.removeChild(container.firstChild);
}

// Methode 3: textContent leeren
container.textContent = "";

Elemente ersetzen

const altesElement = document.querySelector("#alt");
const neuesElement = document.createElement("div");
neuesElement.textContent = "Neu!";

// Methode 1: replaceWith (modern)
altesElement.replaceWith(neuesElement);

// Methode 2: replaceChild (klassisch)
altesElement.parentNode.replaceChild(neuesElement, altesElement);

Elemente klonen

const original = document.querySelector(".template");

// Shallow Clone (nur das Element)
const clone1 = original.cloneNode(false);

// Deep Clone (mit allen Kindern)
const clone2 = original.cloneNode(true);

// Event Listener werden NICHT geklont!
// Du musst sie neu hinzufügen.

Template-Element

<template id="card-template">
    <div class="card">
        <h3 class="card-title"></h3>
        <p class="card-description"></p>
    </div>
</template>
const template = document.querySelector("#card-template");

function createCardFromTemplate(title, description) {
    // Template-Inhalt klonen
    const clone = template.content.cloneNode(true);

    // Werte einsetzen (sicher mit textContent!)
    clone.querySelector(".card-title").textContent = title;
    clone.querySelector(".card-description").textContent = description;

    return clone;
}

// Verwenden
const cards = document.querySelector("#cards");
cards.appendChild(createCardFromTemplate("Titel 1", "Beschreibung 1"));
cards.appendChild(createCardFromTemplate("Titel 2", "Beschreibung 2"));

DocumentFragment für Performance

Bei vielen Elementen: Erst sammeln, dann einmal einfügen:

const container = document.querySelector("#container");
const fragment = document.createDocumentFragment();

// 100 Elemente erstellen (kein Reflow!)
for (let i = 0; i < 100; i++) {
    const div = document.createElement("div");
    div.textContent = `Item ${i}`;
    fragment.appendChild(div);
}

// Ein einziges Mal einfügen (ein Reflow)
container.appendChild(fragment);

Praktisches Beispiel: Todo-Liste

const form = document.querySelector("#todo-form");
const input = document.querySelector("#todo-input");
const list = document.querySelector("#todo-list");

function createTodoItem(text) {
    const li = document.createElement("li");
    li.className = "todo-item";

    const span = document.createElement("span");
    span.textContent = text;  // Sicher: textContent
    span.className = "todo-text";

    const deleteBtn = document.createElement("button");
    deleteBtn.textContent = "Löschen";
    deleteBtn.className = "delete-btn";
    deleteBtn.addEventListener("click", () => li.remove());

    span.addEventListener("click", () => {
        li.classList.toggle("completed");
    });

    li.appendChild(span);
    li.appendChild(deleteBtn);

    return li;
}

form.addEventListener("submit", (e) => {
    e.preventDefault();
    const text = input.value.trim();

    if (text) {
        list.appendChild(createTodoItem(text));
        input.value = "";
    }
});

Zusammenfassung

OperationMethode
Text ändernelement.textContent = "..."
Attribut setzenelement.setAttribute("attr", "value")
Klasse hinzufügenelement.classList.add("class")
Klasse togglenelement.classList.toggle("class")
Style ändernelement.style.property = "value"
Element erstellendocument.createElement("tag")
Einfügen am Endeparent.appendChild(element)
Einfügen am Anfangparent.prepend(element)
Entfernenelement.remove()
Klonenelement.cloneNode(true)

Übung: Erstelle eine dynamische Tabelle: Gegeben ist ein Array von Objekten, generiere daraus eine HTML-Tabelle mit Kopfzeile und Datenzeilen.