jQuery / Méthode / .detach() - Retirer des éléments pour les réutiliser
Dans jQuery, .detach() retire les éléments sélectionnés du modèle objet du document, DOM, tout en conservant leurs données et événements jQuery. Gardez l'objet jQuery renvoyé ou une référence existante dans une variable pour les réinsérer. Ce n'est pas un stockage permanent dans le navigateur ou sur un serveur.
Choisir entre detach, remove et empty
.detach() convient pour retirer provisoirement un élément puis le réutiliser. L'élément et ses enfants quittent ensemble le document ; une référence aux nœuds permet de les réinsérer. Contrairement au masquage CSS, ils ne sont plus dans le document et une nouvelle sélection ne les trouve pas.
| Méthode | Ce qui quitte le document | Données/événements jQuery des parties retirées | Usage |
|---|---|---|---|
| .detach() | Éléments sélectionnés et contenu | Conservés | Retrait temporaire et réutilisation |
| .remove() | Éléments sélectionnés et contenu | Nettoyés | Éliminer des éléments |
| .empty() | Enfants et texte des éléments sélectionnés | Nettoyés pour les enfants retirés | Vider sans supprimer le conteneur |
.remove() ne détruit pas forcément immédiatement un objet nœud encore référencé par une variable JavaScript. Le réinsérer ne restaure pas automatiquement les données et événements jQuery nettoyés. .empty() laisse le conteneur en place. Ne choisissez pas uniquement selon la disparition visuelle commune.
Exemple complet conservant saisie et événements
Enregistrez tout le code en UTF-8 dans detach-demo.html puis ouvrez-le dans un navigateur. Internet est nécessaire pour charger le fichier officiel jQuery 4.0.0 depuis son réseau de diffusion de contenu, CDN, sans installation de paquet. Conservation de la saisie, même nœud et position, retraits/réinitialisations répétés et comparaisons Console ont été exécutés avec 3.7.1 et 4.0.0.
Un nœud de commentaire avant la carte marque sa position. Il reste pendant le retrait, permettant à Restore de retrouver la place initiale. La carte stocke count avec .data() et son bouton enfant a un gestionnaire directement enregistré.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Detach and restore an editable card</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
button, input { font: inherit; margin: 4px; max-width: 100%; }
.card { border: 2px solid teal; padding: 16px; margin: 12px 0; }
</style>
</head>
<body>
<h1>Detach and restore a card</h1>
<button type="button" id="detach">Detach</button>
<button type="button" id="restore">Restore</button>
<button type="button" id="reset">Reset</button>
<div id="slot">
<p>Before the card</p>
<p id="after">After the card</p>
</div>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
const anchor = document.createComment("card position");
$("#after").before(anchor);
let $saved = null;
function makeCard() {
const $card = $('<section class="card"><label>Note <input value="Keep me"></label><p>Count: <span class="count">0</span></p><button type="button" class="increment">Increment</button></section>');
$card.data("count", 0);
$card.find(".increment").on("click", function () {
const count = $card.data("count") + 1;
$card.data("count", count).find(".count").text(count);
report();
});
return $card;
}
let $card = makeCard().insertAfter(anchor);
function report() {
const attached = document.contains($card[0]);
$("#result").text(`attached=${attached} | saved=${$saved !== null} | count=${$card.data("count")}`);
}
$("#detach").on("click", function () {
if ($saved !== null) return;
$saved = $card.detach();
report();
});
$("#restore").on("click", function () {
if ($saved === null) return;
$saved.insertAfter(anchor);
$saved = null;
report();
});
$("#reset").on("click", function () {
$card.remove();
$saved = null;
$card = makeCard().insertAfter(anchor);
report();
});
report();
});
</script>
</body>
</html>
Initialement, la carte est présente dans le document et n'est pas conservée séparément à l'état détaché :
attached=true | saved=false | count=0
- Remplacez Note par Edited note et appuyez une fois sur Increment dans la carte. Count devient 1.
- Appuyez sur Detach. La carte disparaît et le résultat devient
attached=false | saved=true | count=1. Les données restent, mais une nouvelle recherche de .card dans le document trouve zéro élément. - Restore la remet entre les paragraphes Before et After, avec Edited note et Count 1.
- Increment fait alors passer Count à 2 : le gestionnaire enfant est conservé.
- Répéter Detach ou Restore ne perd ni ne duplique la carte, car le code vérifie l'état conservé.
- Reset fonctionne aussi pendant le retrait. Il nettoie l'ancienne carte avec .remove() et en crée une nouvelle avec Keep me et Count 0.
Conserver la valeur actuelle d'un même nœud diffère de recréer un nœud depuis une chaîne HTML. Restore réinsère le nœud conservé ; Reset en crée volontairement un autre. Chaque nouvelle carte reçoit le gestionnaire une seule fois, donc les Reset répétés ne multiplient pas les incréments par clic.
Comparer données et événements avec remove
Exécutez ce fragment complet dans la Console des outils de développement. Il crée deux boutons dans un conteneur temporaire, en détache un, retire l'autre avec remove, puis réinsère les deux. La dernière ligne nettoie le conteneur de test.
const $host = $("<div>").appendTo("body");
let keptClicks = 0;
let removedClicks = 0;
const $keep = $("<button>Keep</button>").data("token", "kept")
.on("click", () => keptClicks++).appendTo($host);
const $gone = $("<button>Remove</button>").data("token", "gone")
.on("click", () => removedClicks++).appendTo($host);
const originalNode = $keep[0];
const $saved = $keep.detach();
console.log(`detached=${!document.contains($saved[0])} | data=${$saved.data("token")}`);
$saved.appendTo($host).trigger("click");
const $removed = $gone.remove();
$removed.appendTo($host).trigger("click");
console.log(`same node=${$saved[0] === originalNode} | kept clicks=${keptClicks}`);
console.log(`removed data=${typeof $removed.data("token")} | removed clicks=${removedClicks}`);
$host.remove();
detached=true | data=kept
same node=true | kept clicks=1
removed data=undefined | removed clicks=0
Le bouton détaché est le même nœud et garde token et son gestionnaire : kept clicks vaut 1. Celui retiré par remove peut aussi être réinséré grâce à sa référence, mais ses données jQuery valent undefined et son ancien gestionnaire direct a été nettoyé : removed clicks vaut 0. Ce constat concerne les données et événements gérés par jQuery, sans garantir le nettoyage de minuteurs externes ou de l'état d'autres bibliothèques.
Filtre de sélection et précautions de restauration
Le sélecteur de .detach(selector) filtre les éléments déjà sélectionnés. Il ne cherche pas de nouveaux enfants à l'intérieur. Cet exemple Console sélectionne A et B mais ne détache que B avec .take ; A reste dans le conteneur. Les deux dernières lignes nettoient les nœuds référencés et le conteneur temporaire.
const $list = $('<div><p class="keep">A</p><p class="take">B</p></div>').appendTo("body");
const $items = $list.children("p");
$items.detach(".take");
console.log(`remaining=${$list.children("p").text()}`);
$items.remove();
$list.remove();
remaining=A
Après retrait, une nouvelle recherche $(".card") ne récupère pas la carte. Utilisez sa référence et gérez séparément l'ancienne position, par exemple avec le commentaire. .appendTo() insère à la fin de la cible, sans mémoriser la position précédente. Une cible déplace le nœud existant, plusieurs peuvent créer des copies : vérifiez leur nombre.
Un événement délégué avec .on() sur un parent dépend de la propagation à travers ce parent. Un élément déplacé ailleurs n'emporte pas les gestionnaires délégués de son ancien parent. Le gestionnaire direct du bouton enfant rend ici la conservation explicite.
Si la restauration échoue, vérifiez que la variable n'a pas été écrasée et que le repère ou la cible est encore dans le document. Une référence durable garde l'objet détaché accessible. À la fin de sa réutilisation, nettoyez l'état jQuery avec .remove() et libérez les références. Annulez minuteurs et abonnements externes par leurs propres API.




