jQuery / Méthode / .clone() - Copier les éléments sélectionnés
Dans jQuery, .clone() crée un nouvel objet jQuery contenant les copies des éléments sélectionnés, de leurs descendants et de leur texte. La copie n'est pas encore dans la page : insérez-la avec .appendTo(), par exemple. Les événements et données jQuery sont exclus par défaut et contrôlés séparément par les arguments.
Structure, déplacement et options d'événements
Dans la documentation de .clone(), une copie structurelle profonde comprend les enfants. Elle ne garantit pas une indépendance complète de tous les événements, objets .data() et valeurs imbriquées. Le second argument deepWithDataAndEvents contrôle événements/données des descendants, pas la copie des enfants DOM eux-mêmes.
| Expression | Élément et descendants | Événements/données de la racine | Événements/données des descendants |
|---|---|---|---|
| .clone() | Copiés | Non copiés | Non copiés |
| .clone(true, false) | Copiés | Copiés | Non copiés |
| .clone(true, true) | Copiés | Copiés | Copiés |
| .clone(true) | Copiés | Copiés | Copiés ; le second argument suit le premier |
Insérer un élément existant dans une seule cible avec .appendTo() le déplace. Pour garder l'original, clonez avant d'insérer. Ce sont des éléments distincts du modèle objet du document, DOM : modifier le titre de la copie ne change pas l'original.
Exemple complet de données et clics sur des cartes
Enregistrez tout le code en UTF-8 dans clone-demo.html et ouvrez-le dans un navigateur. jQuery 4.0.0 vient du réseau officiel de diffusion de contenu, CDN ; internet est nécessaire, sans installation. Les trois modes, les clics, le partage des données et Reset ont été exécutés avec 3.7.1 et 4.0.0.
La racine originale stocke count et kind ; son bouton Increment possède un gestionnaire direct. Le code remet explicitement le compteur et le nombre visible des copies à zéro. Cloner ne réinitialise pas automatiquement un compteur.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Clone structure, data and events</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
.card { padding: 14px; margin: 12px 0; border: 1px solid #8aa; }
.card p { margin: 4px 0; }
button { margin: 4px; padding: 8px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Clone structure, data and events</h1>
<div class="card" id="source">
<p class="label">Original</p>
<p>Count: <span class="count">0</span></p>
<p>Data: <span class="data">stored</span></p>
<button type="button" class="increment">Increment</button>
</div>
<button type="button" id="plain">Clone structure</button>
<button type="button" id="parent">Clone parent data</button>
<button type="button" id="full">Clone events</button>
<button type="button" id="reset">Reset</button>
<div id="copies"></div>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
const $source = $("#source").data({ count: 0, kind: "stored" });
let serial = 1;
function report() {
$("#result").text(`source=${$source.data("count")} | copies=${$("#copies > .card").length}`);
}
$source.find(".increment").on("click", function () {
const $card = $(this).closest(".card");
const count = $card.data("count") + 1;
$card.data("count", count).find(".count").text(count);
report();
});
function copy(withData, deep) {
const $copy = $source.clone(withData, deep);
$copy.attr("id", "copy-" + serial);
$copy.find(".label").text("Copy " + serial++);
$copy.data("count", 0).find(".count").text(0);
$copy.find(".data").text($copy.data("kind") || "none");
$copy.appendTo("#copies");
report();
}
$("#plain").on("click", () => copy(false, false));
$("#parent").on("click", () => copy(true, false));
$("#full").on("click", () => copy(true, true));
$("#reset").on("click", function () {
$("#copies").empty();
serial = 1;
$source.data("count", 0).find(".count").text(0);
report();
});
report();
});
</script>
</body>
</html>
Au départ, seul l'original existe :
source=0 | copies=0
- Appuyez une fois sur Increment dans l'original pour obtenir Count 1.
- Clone structure copie la structure sans kind ni gestionnaire. Copy 1 affiche Data none et son bouton laisse le compteur à zéro.
- Clone parent data copie kind et affiche stored, sans copier le gestionnaire du bouton descendant ; il n'incrémente pas.
- Clone events inclut les gestionnaires descendants. Copy 3 passe à 1 ; l'original reste aussi à 1.
- Reset retire les copies et réinitialise compteur original et numérotation. Il ne réenregistre pas le gestionnaire original, donc un clic reste un incrément après plusieurs Reset.
Avant insertion, la racine reçoit un identifiant unique, tel que copy-1 ; les parties internes utilisent des classes. Si des descendants ont des identifiants ou des références label for et aria-controls, modifiez les identifiants et leurs références ensemble.
Copier explicitement objets et tableaux imbriqués
Les objets et tableaux dans .data() copiés par .clone(true) peuvent rester partagés. Exécutez ce fragment complet dans la console de développement : il utilise des éléments temporaires non insérés.
const $original = $("<div>").data("options", { tags: ["a"] });
const $shared = $original.clone(true);
$shared.data("options").tags.push("b");
console.log($original.data("options").tags.join(", "));
const $independent = $original.clone(true).data("options", {
tags: [...$original.data("options").tags]
});
$independent.data("options").tags.push("c");
console.log($original.data("options").tags.join(", "));
console.log($independent.data("options").tags.join(", "));
a, b
a, b
a, b, c
Ajouter b par la première copie modifie aussi l'original en a, b, car options est le même objet. La copie indépendante reçoit un nouvel options et un nouveau tableau tags ; son c laisse l'original à a, b. Cela copie une structure connue de chaînes, pas n'importe quel objet profondément imbriqué.
État des formulaires, événements et dépannage
Ne supposez pas que tous les champs copient identiquement leur état actuel. La documentation distingue input de textarea/select. Vérifiez les valeurs nécessaires et envisagez de fixer explicitement sélections et notes avec .val() après clonage.
Copier tous les gestionnaires n'est pas la seule manière d'activer les nouvelles cartes. La délégation avec .on() sur un parent conservé peut traiter les nouveaux descendants. Gestionnaires directs copiés et délégation peuvent doubler une action ; choisissez l'approche utile et vérifiez le résultat.
Sans copie visible, vérifiez insertion et cible. Si les boutons restent inactifs, examinez racine ou descendants pour l'enregistrement, puis les deux arguments. Une sélection vide produit une copie vide ; les identifiants dupliqués peuvent détourner sélecteurs et étiquettes. Vérifiez aussi Network et Console.




