Como remover apenas o elemento pai e não seus elementos filhos em JavaScript?

Digamos:

pre text

child foo

child bar

nested text
post text

para isso:

 
pre text

child foo

child bar

nested text post text

Eu tenho descoberto o uso do Mootools, jQuery e até JavaScript (raw), mas não consegui entender como fazer isso.

Usando jQuery você pode fazer isso:

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

Links rápidos para a documentação:

  • conteúdo (): jQuery
  • replaceWith ( conteúdo : [ String | Element | jQuery ]): jQuery

O método independente de biblioteca é inserir todos os nós filhos do elemento a ser removido antes deles mesmos (o que implicitamente os remove da posição anterior), antes de removê-lo:

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

Isso moverá todos os nós filhos para o local correto na ordem correta.

Você deve certificar-se de fazer isso com o DOM, não innerHTML (e se estiver usando a solução jQuery fornecida pelo jk, certifique-se de mover os nós DOM em vez de usar innerHTML internamente) para preservar coisas como manipuladores de events.

Minha resposta é muito parecida com a de insin, mas terá melhor desempenho para estruturas grandes (append cada nó separadamente pode estar sobrecarregando redesenhos onde o CSS precisa ser reaplicado para cada appendChild ; com um DocumentFragment , isso só ocorre uma vez, pois não fica visível até que depois que seus filhos são todos acrescentados e é adicionado ao documento).

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

Maneira mais elegante é

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

Qualquer que seja a biblioteca que você esteja usando, você precisa clonar a div interna antes de remover a div externa do DOM. Então você tem que adicionar o div interno clonado ao lugar no DOM onde o div externo estava. Então os passos são:

  1. Salvar uma referência ao pai da div externa em uma variável
  2. Copie o div interno para outra variável. Isso pode ser feito de maneira rápida e suja salvando o innerHTML do div interno em uma variável ou você pode copiar a tree interna recursivamente nó por nó.
  3. Chame removeChild no pai do div externo com o div externo como o argumento.
  4. Insira o conteúdo interno copiado no pai do div externo na posição correta.

Algumas bibliotecas farão parte ou tudo isso para você, mas algo como o descrito acima estará acontecendo sob o capô.

E, desde que você também tentou em mootools, aqui está a solução em mootools.

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

Note que isso é totalmente não testado, mas eu trabalhei com mootools antes e deveria funcionar.

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

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

Use o 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) é válido no ES5

...array é o operador spread, passando cada elemento da matriz como um parâmetro

Se você gostaria de fazer a mesma coisa de pijama, aqui está como é feito. funciona muito bem (obrigado a palpitar). Eu fui capaz de fazer um editor de texto rico adequado que faz corretamente estilos sem bagunçar, graças a isso.

 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) 

Eu estava procurando a melhor resposta em termos de desempenho enquanto trabalhava em um DOM importante.

A resposta da ausência de pálpebra estava apontando que usar o javascript seria melhor.

Fiz os seguintes testes de tempo de execução em 5.000 linhas e 400.000 caracteres com uma composição DOM do complemento dentro da seção a ser removida. Eu estou usando uma identificação em vez de uma class por motivo conveniente ao usar o javascript.

Usando $ .unwrap ()

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

201,237ms

Usando $ .replaceWith ()

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

156,983ms

Usando DocumentFragment em 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

Conclusão

Em termos de desempenho, mesmo em uma estrutura DOM relativamente grande, a diferença entre o uso de jQuery e javascript não é enorme. Surpreendentemente $.unwrap() é mais caro que $.replaceWith() . Os testes foram feitos com o jQuery 1.12.4.

Se você está lidando com várias linhas, como era no meu caso de uso, você provavelmente está melhor com algo ao longo destas linhas:

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