web-dev-qa-db-fra.com

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

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>

Je pensais utiliser Mootools, jQuery et même JavaScript (brut), mais je ne savais pas trop comment faire cela.

80
cheeaun

En utilisant jQuery vous pouvez faire ceci:

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

Liens rapides vers la documentation:

127
jk.

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.

35
Jonny Buchanan

Assurez-vous de le faire avec le DOM, et non pas innerHTML (et si vous utilisez la solution jQuery fournie par jk, assurez-vous qu'il déplace les nœuds DOM plutôt que d'utiliser innerHTML en interne), afin de conserver les mêmes propriétés que les gestionnaires d'événements.

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

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
32
eyelidlessness
 $('.remove-just-this > *').unwrap()
25
campino2k

Manière plus élégante est

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

Utilisez moderne JS!

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 propagation, en passant chaque élément de tableau en tant que paramètre

4
Gibolt

Et, puisque vous avez également essayé dans mootools, voici la solution dans mootools.

var children = $('remove-just-this').getChildren();
children.replaces($('remove-just-this');

Notez que cela n’a absolument pas été testé, mais j’ai déjà travaillé avec mootools et cela devrait fonctionner.

http://mootools.net/docs/Element/Element#Element:getChildren

http://mootools.net/docs/Element/Element#Element:replaces

2
tj111

Quelle que soit la bibliothèque que vous utilisez, vous devez cloner la div interne avant de supprimer la div externe du DOM. Ensuite, vous devez ajouter la division interne clonée à la place du DOM où se trouvait la division externe. Les étapes sont donc les suivantes:

  1. Enregistrer une référence au parent de la division externe dans une variable
  2. Copiez la division interne dans une autre variable. Pour ce faire, vous pouvez enregistrer rapidement la innerHTML de la division interne dans une variable ou copier l’arborescence interne récursivement, noeud par noeud.
  3. Appelez removeChild sur le parent de la division externe avec la division externe comme argument.
  4. Insérez le contenu interne copié dans la position correcte du parent de la div externe.

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.

2
domgblackwell

si vous souhaitez faire la même chose en pyjama, voici comment procéder. cela fonctionne très bien (merci à la paupière). J'ai pu créer un véritable éditeur de texte enrichi qui crée 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)
0
user362834

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

la réponse de eyelidlessness indiquait que l'utilisation de javascript serait préférable.

J'ai effectué 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.

Utilisation de $ .unwrap ()

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

201.237ms

Utilisation de $ .replaceWith ()

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

156.983ms

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,211ms

Conclusion

Au niveau des performances, même sur une structure DOM relativement importante, la différence entre l’utilisation de jQuery et javascript n’est pas énorme. Étonnamment, $.unwrap() est plus coûteux que $.replaceWith(). Les tests ont été réalisés avec jQuery 1.12.4.

0
maxime_039

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
Johannes Buchholz

Si vous avez plusieurs lignes, comme dans mon cas d'utilisation, il vaut probablement mieux utiliser quelque chose dans ce sens:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
0
Iso