Comment supprimer uniquement l'élément parent et non ses éléments enfants en JavaScript?


88

Disons:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

pour ça:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

J'ai compris en utilisant Mootools, jQuery et même JavaScript (brut), mais je n'ai pas pu comprendre comment faire cela.

Réponses:


138

En utilisant jQuery, vous pouvez le faire:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

Liens rapides vers la documentation:


J'aimerais avoir réalisé (euh .. trouvé ) il y a 3 heures ... simple et élégant - génial!
Tathagata le

3
quelle est la signification de «cnt»?
Steven Lu

1
'cnt' est juste un nom de variable contenant le "contenu"
George Anderson

1
Je ne sais pas pourquoi, mais cela n'a pas fonctionné pour moi lors de l'utilisation de contents (). Cependant, quand j'ai utilisé html () à la place de contents (), cela a fonctionné comme un charme!
vertigoelectric

version 1 ligne seulement:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda

36

La méthode indépendante de la bibliothèque consiste à insérer tous les nœuds enfants de l'élément à supprimer avant lui-même (ce qui les supprime implicitement de leur ancienne position), avant de le supprimer:

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Cela déplacera tous les nœuds enfants au bon endroit dans le bon ordre.


3
Modern JS prend en charge ceci:node.replaceWith(...node.childNodes);
Gibolt

34

Vous devez vous assurer de le faire avec le DOM, non innerHTML(et si vous utilisez la solution jQuery fournie par jk, assurez-vous qu'elle déplace les nœuds DOM plutôt que de l'utiliser en innerHTMLinterne), afin de préserver des choses comme les gestionnaires d'événements.

Ma réponse ressemble beaucoup à celle des insin, mais fonctionnera mieux pour les grandes structures (l'ajout de chaque nœud séparément peut être pénible pour les redessins où CSS doit être réappliqué pour chacun appendChild; avec un DocumentFragment, cela ne se produit qu'une fois car il n'est rendu visible qu'après son les enfants sont tous ajoutés et il est ajouté au document).

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

Je vous remercie; court et direct.
brunoais


22

Une manière plus élégante est

$('.remove-just-this').contents().unwrap();

2
Meilleure réponse. Merci.
user706420

7

Utilisez JS moderne!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode) est valide ES5

...array est l'opérateur de diffusion, passant chaque élément du tableau en tant que paramètre


2

Quelle que soit la bibliothèque que vous utilisez, vous devez cloner le div interne avant de supprimer le div externe du DOM. Ensuite, vous devez ajouter le div interne cloné à l'endroit dans le DOM où se trouvait le div externe. Les étapes sont donc:

  1. Enregistrer une référence au parent du div externe dans une variable
  2. Copiez le div interne dans une autre variable. Cela peut être fait de manière rapide et sale en sauvegardant leinnerHTML de la div interne dans une variable ou vous pouvez copier l'arborescence interne de manière récursive nœud par nœud.
  3. Appelez removeChildle parent du div externe avec le div externe comme argument.
  4. Insérez le contenu interne copié dans le parent du div externe dans la bonne position.

Certaines bibliothèques feront tout ou partie de cela pour vous, mais quelque chose comme ce qui précède se passera sous le capot.



1

Remplacez div par son contenu:

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>


0

si vous souhaitez faire la même chose en pyjama, voici comment procéder. ça marche très bien (merci à la paupière). J'ai pu créer un éditeur de texte riche approprié qui fait correctement les styles sans gâcher, grâce à cela.

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)

1
Quelle langue est-ce?
brunoais

Ressemble à python - ce qui a du sens puisque l'utilisateur le mentionne pyjamas.
mgilson

0

Je cherchais la meilleure réponse en termes de performances tout en travaillant sur un DOM important.

La réponse de eyelidness soulignait qu'en utilisant javascript les performances seraient les meilleures.

J'ai fait les tests de temps d'exécution suivants sur 5 000 lignes et 400 000 caractères avec une composition DOM complexe dans la section à supprimer. J'utilise un identifiant au lieu d'une classe pour des raisons pratiques lorsque j'utilise javascript.

Utiliser $ .unwrap ()

$('#remove-just-this').contents().unwrap();

201,237 ms

Utiliser $ .replaceWith ()

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);

156,983 ms

Utilisation de DocumentFragment en javascript

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

147,211 ms

Conclusion

Sur le plan des performances, même sur une structure DOM relativement grande, la différence entre l'utilisation de jQuery et de javascript n'est pas énorme. Étonnamment, $.unwrap()c'est plus cher que $.replaceWith(). Les tests ont été effectués avec jQuery 1.12.4.


0

Si vous avez affaire à plusieurs lignes, comme c'était le cas dans mon cas d'utilisation, vous êtes probablement mieux avec quelque chose du genre:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.