jQuery / Ein HTML-Tag ändern
Erstellen Sie zum Ändern eines HTML-Tags mit jQuery ein Element des gewünschten Typs und ersetzen Sie das alte. tagName lässt sich nicht umbenennen. Um Eingaben und Ereignisse der Kinder zu behalten, verschieben Sie vor dem Entfernen die wirklichen Kindknoten statt einer HTML-Zeichenfolge.
Tagname und Elementersetzung unterscheiden
Das DOM, Document Object Model, stellt das Dokument als Knotenobjekte dar. Element.tagName ist schreibgeschützt. .attr("tagName", "section") ändert nicht den Elementtyp; auch .prop() kann die schreibgeschützte Eigenschaft nicht sinnvoll umschreiben.
Erstellen Sie mit document.createElement() ein section und ersetzen Sie div durch .replaceWith(). Das äußere Objekt ist neu, selbst wenn nur der Name anders aussieht. Eine Variable mit dem alten div verweist anschließend nicht automatisch auf section.
Die Übung vergleicht Zustände beim Wechsel div zu section, liefert aber keinen vollständigen semantischen Entwurf einer eigenständigen Sektion. Entscheiden Sie anhand des Inhalts und der Überschriftenstruktur. Für reine Darstellung reicht möglicherweise eine Änderung von class und CSS.
Vollständiges Beispiel mit erhaltenen Kindern
Speichern Sie alles als UTF-8 tag-demo.html und öffnen Sie die Datei im Browser. Internet lädt die offizielle jQuery-Datei 4.0.0. Server oder Paketinstallation sind unnötig. Die Kernfunktionen wurden in Windows Edge mit 3.7.1 und 4.0.0 ausgeführt.
div enthält Text, Kommentar, Eingabe und Schaltfläche. Die Schaltfläche besitzt einen direkten Handler, main einen delegierten; div besitzt eigene Daten und einen Handler. Getrennte Zähler machen Unterschiede sichtbar.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Replace a container tag, keep its children</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; margin: 20px; max-width: 760px; }
button, input { font: inherit; max-width: 100%; box-sizing: border-box; }
button { margin: 4px; }
.card { border: 3px solid teal; padding: 16px; margin: 16px 0; }
#result { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<button type="button" id="change">Change div to section</button>
<button type="button" id="reset">Reset</button>
<main id="board"></main>
<pre id="result" aria-live="polite"></pre>
<script>
$(function () {
let original, originalInput, originalNodes;
let childClicks = 0, wrapperClicks = 0, delegatedClicks = 0;
function report() {
const card = document.getElementById("card");
const sameChildren = originalNodes.every((node, i) => card.childNodes[i] === node);
$("#result").text(`tag=${card.localName}\nsame wrapper=${card === original}\nsame children=${sameChildren}\nsame input=${card.querySelector("input") === originalInput}\ninput=${originalInput.value}\nold data=${$(original).data("lesson")}\nchild=${childClicks}; wrapper=${wrapperClicks}; delegated=${delegatedClicks}`);
}
function reset() {
$("#board").empty();
const card = document.createElement("div");
card.id = "card"; card.className = "card";
card.setAttribute("aria-label", "Editable note");
card.append(document.createTextNode("Keep this text. "), document.createComment("keep this comment"));
const input = document.createElement("input");
input.type = "text"; input.value = "First note"; input.setAttribute("aria-label", "Note");
const button = document.createElement("button");
button.type = "button"; button.className = "inspect"; button.textContent = "Inspect";
card.append(input, button); document.getElementById("board").append(card);
original = card; originalInput = input; originalNodes = Array.from(card.childNodes);
childClicks = wrapperClicks = delegatedClicks = 0;
$(card).data("lesson", "old wrapper").on("click", function () { wrapperClicks++; });
$(button).on("click", function () { childClicks++; });
$(input).on("input", report);
$("#change").prop("disabled", false); report();
}
$("#board").on("click.tagLesson", ".inspect", function () { delegatedClicks++; report(); });
$("#change").on("click", function () {
const old = document.getElementById("card");
const replacement = document.createElement("section");
for (const name of ["id", "class", "aria-label"]) {
if (old.hasAttribute(name)) replacement.setAttribute(name, old.getAttribute(name));
}
// Move existing children BEFORE jQuery removes the old wrapper.
$(replacement).append($(old).contents());
$(old).replaceWith(replacement);
$(this).prop("disabled", true); report();
});
$("#reset").on("click", reset);
reset();
});
</script>
</body>
</html>
Anfangsausgabe. same children prüft Identität und Reihenfolge einschließlich Text und Kommentar.
tag=div
same wrapper=true
same children=true
same input=true
input=First note
old data=old wrapper
child=0; wrapper=0; delegated=0
- Ändern Sie First note. Auch
<em>Edited note</em>bleibt Eingabetext und wird nicht als HTML ausgeführt. - Einmal Inspect ergibt child=1, wrapper=1, delegated=1: Schaltfläche, altes div und main reagieren jeweils einmal.
- Change div to section ergibt tag=section, same wrapper=false, same children=true und same input=true. Die Eingabe bleibt, old data ist undefined.
- Erneutes Inspect ergibt child=2, wrapper=1, delegated=2. Der direkte Kind-Handler und die Delegation bleiben, der alte div-Handler wird nicht übertragen.
- Reset erstellt div und Anfangswert neu und setzt Zähler zurück. Für einen frischen Vergleich werden Ihre Änderungen verworfen.
Erhaltene Inhalte und nötige Einrichtung
Entscheidend ist $(replacement).append($(old).contents()) vor der Ersetzung. .contents() umfasst unmittelbare Elemente, Text und Kommentare. append verschiebt vorhandene Objekte und bewahrt damit aktuellen Eingabewert und direkte Kind-Handler. .children() allein würde Text und Kommentare außerhalb der Elemente auslassen.
Danach entfernt .replaceWith() das leere div einschließlich seiner jQuery-Daten und Handler. Wer zuerst ersetzt und später Kinder zurückholt, kann deren Zustand während der Bereinigung verlieren. Das Verfahren bewahrt nicht jeden Zustand: Fokus, Textauswahl und interne Plugin-Referenzen brauchen eigene Prüfung.
id, class und aria-label werden ausdrücklich kopiert. Andere Attribute folgen nicht automatisch. Blindes Kopieren könnte ungültige Attribute, veraltete Rollen oder Inline-Handler übernehmen. Wählen Sie nötige Attribute und prüfen Sie die Bedeutung für Barrierefreiheit. jQuery .data() und HTML-data-*-Attribute sind unterschiedliche Speicher.
.replaceWith() liefert die entfernte ursprüngliche jQuery-Menge zurück, nicht das neue Element. Verwenden Sie danach replacement oder wählen Sie das aktuelle Element erneut. Benötigte Wrapper-Handler müssen ausdrücklich neu eingerichtet oder von einem stabilen Vorfahren delegiert werden.
Grenzen und Fehlersuche
$(old).html() zu lesen und per .html() einzusetzen parst eine Zeichenfolge erneut. Trotz gleicher Optik entstehen neue Kinder: bisherige Objekte, direkte Handler und aktuelle Eingabezustände bleiben dadurch nicht erhalten. Setzen Sie Benutzereingaben auch nicht zu Ersatz-HTML zusammen.
Dies betrifft normale HTML-Container, keinen universellen Konverter für kinderlose input oder img, besondere Tabellenstrukturen, Formularsteuerelemente, SVG oder eigene Elemente. Prüfen Sie zulässige Kinder und Semantik. Der Wechsel button zu a verändert beispielsweise Rolle und Tastaturverhalten.
Bei anderer Darstellung prüfen Sie tagabhängiges CSS wie div.card und Selektoren des alten Tags. id muss eindeutig bleiben; Beschriftungen und Anker müssen passen. Kontrollieren Sie direkte Handler, Delegation, Fokus, zugängliche Bedeutung und Wiederherstellung auf der tatsächlichen Seite.




