106

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.

asked Oct 4, 2008 at 8:46

13 Answers 13

145

Using jQuery you can do this:

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

Quick links to the documentation:

Jonathan Mayhak
12.5k3 gold badges23 silver badges17 bronze badges
answered Oct 4, 2008 at 9:37
Sign up to request clarification or add additional context in comments.

7 Comments

Wish I realized (err.. found) this 3 hours ago ... simple and elegant - awesome!
what is the significance of 'cnt'?
'cnt' is just a variable name that holds "contents"
I'm not sure why, but this didn't work for me when using contents(). However, when I used html() in place of contents(), it worked like a charm!
just 1 line version: $('.remove-just-this').replaceWith(function() { return $(this).html(); });
|
40

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.

answered Oct 4, 2008 at 12:11

2 Comments

Modern JS supports this: node.replaceWith(...node.childNodes);
@Gibolt It does not work: Type 'NodeListOf<ChildNode>' must have a '[Symbol.iterator]()' method that returns an iterator.(2488)
37

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);
Aliaksandr Sushkevich
12.6k8 gold badges41 silver badges46 bronze badges
answered Oct 6, 2008 at 22:07

Comments

30
 $('.remove-just-this > *').unwrap()
answered Oct 19, 2011 at 13:55

Comments

29

More elegant way is

$('.remove-just-this').contents().unwrap();
answered Apr 1, 2016 at 16:22

Comments

22

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

answered Aug 13, 2017 at 18:56

Comments

8

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>

answered Mar 11, 2019 at 13:54

Comments

3

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.

answered Feb 17, 2017 at 13:14

Comments

2

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.

answered Oct 4, 2008 at 11:06

Comments

2

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

answered Oct 22, 2008 at 21:30

Comments

0

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)
answered Apr 24, 2012 at 11:57

2 Comments

Which language is this?
Looks like python -- which makes sense since the user mentions pyjamas.
0

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);
 });
answered May 15, 2017 at 12:11

Comments

0

The solution with replaceWith only works when there is one matching element. When there are more matching elements use this:

$(".remove-just-this").contents().unwrap();
k.tten
26.8k4 gold badges34 silver badges63 bronze badges
answered Oct 2, 2022 at 21:30

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.