How to remove only the parent element and not its child elements in JavaScript?

JavascriptDom

Javascript Problem Overview


Let's say:

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

to this:

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

I've been figuring out using Mootools, jQuery and even (raw) JavaScript, but couldn't get the idea how to do this.

Javascript Solutions


Solution 1 - Javascript

Using jQuery you can do this:

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

Quick links to the documentation:

Solution 2 - Javascript

The library-independent method is to insert all child nodes of the element to be removed before itself (which implicitly removes them from their old position), before you remove it:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

This will move all child nodes to the correct place in the right order.

Solution 3 - Javascript

You should make sure to do this with the DOM, not innerHTML (and if using the jQuery solution provided by jk, make sure that it moves the DOM nodes rather than using innerHTML internally), in order to preserve things like event handlers.

My answer is a lot like insin's, but will perform better for large structures (appending each node separately can be taxing on redraws where CSS has to be reapplied for each appendChild; with a DocumentFragment, this only occurs once as it is not made visible until after its children are all appended and it is added to the document).

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

Solution 4 - Javascript

 $('.remove-just-this > *').unwrap()

Solution 5 - Javascript

More elegant way is

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

Solution 6 - Javascript

Use modern 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) is valid ES5

...array is the spread operator, passing each array element as a parameter

Solution 7 - Javascript

Replace div with its contents:

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>

Solution 8 - Javascript

Whichever library you are using you have to clone the inner div before removing the outer div from the DOM. Then you have to add the cloned inner div to the place in the DOM where the outer div was. So the steps are:

  1. Save a reference to the outer div's parent in a variable
  2. Copy the inner div to another variable. This can be done in a quick and dirty way by saving the innerHTML of the inner div to a variable or you can copy the inner tree recursively node by node.
  3. Call removeChild on the outer div's parent with the outer div as the argument.
  4. Insert the copied inner content to the outer div's parent in the correct position.

Some libraries will do some or all of this for you but something like the above will be going on under the hood.

Solution 9 - Javascript

And, since you tried in mootools as well, here's the solution in mootools.

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

Note that's totally untested, but I have worked with mootools before and it should work.

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

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

Solution 10 - Javascript

I was looking for the best answer performance-wise while working on an important DOM.

eyelidlessness's answer was pointing out that using javascript the performances would be best.

I've made the following execution time tests on 5,000 lines and 400,000 characters with a complexe DOM composition inside the section to remove. I'm using an ID instead of a class for convenient reason when using javascript.

Using $.unwrap()

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

> 201.237ms

Using $.replaceWith()

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

> 156.983ms

Using DocumentFragment in 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

Performance-wise, even on a relatively big DOM structure, the difference between using jQuery and javascript is not huge. Surprisingly $.unwrap() is most costly than $.replaceWith(). The tests have been done with jQuery 1.12.4.

Solution 11 - Javascript

if you'd like to do this same thing in pyjamas, here's how it's done. it works great (thank you to eyelidness). i've been able to make a proper rich text editor which properly does styles without messing up, thanks to this.

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)

Solution 12 - Javascript

If you are dealing with multiple rows, as it was in my use case you are probably better off with something along these lines:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncheeaunView Question on Stackoverflow
Solution 1 - Javascriptjk.View Answer on Stackoverflow
Solution 2 - JavascriptJonny BuchananView Answer on Stackoverflow
Solution 3 - JavascripteyelidlessnessView Answer on Stackoverflow
Solution 4 - Javascriptcampino2kView Answer on Stackoverflow
Solution 5 - JavascriptyundaView Answer on Stackoverflow
Solution 6 - JavascriptGiboltView Answer on Stackoverflow
Solution 7 - JavascriptJohannes BuchholzView Answer on Stackoverflow
Solution 8 - JavascriptdomgblackwellView Answer on Stackoverflow
Solution 9 - JavascriptTJ LView Answer on Stackoverflow
Solution 10 - Javascriptmaxime_039View Answer on Stackoverflow
Solution 11 - Javascriptuser362834View Answer on Stackoverflow
Solution 12 - JavascriptLaurensVijnckView Answer on Stackoverflow