¿Cómo eliminar solo el elemento principal y no sus elementos secundarios en JavaScript?

88

Digamos:

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

a esto:

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

He estado descubriendo el uso de Mootools, jQuery e incluso JavaScript (sin formato), pero no podía tener la idea de cómo hacerlo.

cheeaun
fuente

Respuestas:

138

Usando jQuery puedes hacer esto:

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

Enlaces rápidos a la documentación:

jk.
fuente
Ojalá me diera cuenta (err ... encontré ) esto hace 3 horas ... simple y elegante, ¡increíble!
Tathagata
3
¿Cuál es el significado de 'cnt'?
Steven Lu
1
'cnt' es solo un nombre de variable que contiene "contenido"
George Anderson
1
No estoy seguro de por qué, pero esto no funcionó para mí cuando usé contenido (). Sin embargo, cuando usé html () en lugar de contents (), ¡funcionó de maravilla!
vertigoelectric
versión de solo 1 línea:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda
36

El método independiente de la biblioteca consiste en insertar todos los nodos secundarios del elemento que se eliminará antes que él mismo (lo que los elimina implícitamente de su posición anterior), antes de eliminarlo:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Esto moverá todos los nodos secundarios al lugar correcto en el orden correcto.

Jonny Buchanan
fuente
3
JS moderno admite esto:node.replaceWith(...node.childNodes);
Gibolt
34

Debe asegurarse de hacer esto con el DOM, no innerHTML(y si usa la solución jQuery proporcionada por jk, asegúrese de que mueva los nodos DOM en lugar de usarlos innerHTMLinternamente), para preservar cosas como los controladores de eventos.

Mi respuesta es muy parecida a la de insin, pero funcionará mejor para estructuras grandes (agregar cada nodo por separado puede ser gravoso en los redibujos donde CSS debe volver a aplicarse para cada uno appendChild; con a DocumentFragment, esto solo ocurre una vez, ya que no se hace visible hasta después de su los niños se adjuntan y se agregan al documento).

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
falta de párpados
fuente
Gracias; corto y directo.
brunoais
28
 $('.remove-just-this > *').unwrap()
campino2k
fuente
22

Una forma más elegante es

$('.remove-just-this').contents().unwrap();
yunda
fuente
2
La mejor respuesta. Gracias.
user706420
7

¡Utilice JS moderno!

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

oldNode.replaceWith(newNode) es válido ES5

...array es el operador de propagación, pasando cada elemento de la matriz como parámetro

Gibolt
fuente
2

Cualquiera que sea la biblioteca que esté utilizando, debe clonar el div interno antes de eliminar el div externo del DOM. Luego, debe agregar el div interno clonado al lugar en el DOM donde estaba el div externo. Entonces los pasos son:

  1. Guarde una referencia al padre del div externo en una variable
  2. Copie el div interno a otra variable. Esto se puede hacer de una manera rápida y sucia guardando elinnerHTML div interno en una variable o puede copiar el árbol interno recursivamente nodo por nodo.
  3. Llame removeChildal padre del div externo con el div externo como argumento.
  4. Inserte el contenido interno copiado al padre del div externo en la posición correcta.

Algunas bibliotecas harán algo o todo esto por usted, pero algo como lo anterior estará sucediendo bajo el capó.

domgblackwell
fuente
1

Reemplaza div con su contenido:

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>

Johannes Buchholz
fuente
0

Si desea hacer lo mismo en pijama, así es como se hace. funciona muy bien (gracias a los párpados). Gracias a esto, he podido crear un editor de texto enriquecido adecuado que hace estilos correctamente sin estropear.

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)
user362834
fuente
1
¿Que idioma es este?
brunoais
Parece python, lo que tiene sentido ya que el usuario lo menciona pyjamas.
mgilson
0

Estaba buscando la mejor respuesta en términos de rendimiento mientras trabajaba en un DOM importante.

La respuesta de eyelidlessness fue señalar que con javascript el rendimiento sería el mejor.

Hice las siguientes pruebas de tiempo de ejecución en 5,000 líneas y 400,000 caracteres con una composición DOM compleja dentro de la sección para eliminar. Estoy usando una ID en lugar de una clase por una razón conveniente cuando uso javascript.

Usando $ .unwrap ()

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

201.237ms

Usando $ .replaceWith ()

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

156,983 ms

Usando 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

Conclusión

En cuanto al rendimiento, incluso en una estructura DOM relativamente grande, la diferencia entre usar jQuery y javascript no es enorme. Sorprendentemente $.unwrap()es más costoso que $.replaceWith(). Las pruebas se han realizado con jQuery 1.12.4.

maxime_039
fuente
0

Si está tratando con varias filas, como fue en mi caso de uso, probablemente sea mejor con algo como esto:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Yo asi
fuente