28

I would like to remove the parent without removing the child - is this possible?

HTML structure:

<div class="wrapper">
  <img src"">
</div>
<div class="button">Remove wrapper</div>

After clicking on the button I would like to have:

<img src"">
<div class="button">Remove wrapper</div>
Web_Designer
  • 72,308
  • 93
  • 206
  • 262
lipenco
  • 1,358
  • 5
  • 16
  • 30

7 Answers7

59

Pure JS (ES2015) solution, in my opinion easier to read than jQuery-solutions.

node.replaceWith(...node.childNodes)

Node has to be an ElementNode

const wrapperNode = document.querySelector('h1')
wrapperNode.replaceWith(...wrapperNode.childNodes)
<h1>
  <a>1</a>
  <b>2</b>
  <em>3</em>
</h1>
vsync
  • 118,978
  • 58
  • 307
  • 400
Tom Oeser
  • 632
  • 1
  • 5
  • 8
34

Pure JS solution that doesn't use innerHTML:

function unwrap(wrapper) {
    // place childNodes in document fragment
    var docFrag = document.createDocumentFragment();
    while (wrapper.firstChild) {
        var child = wrapper.removeChild(wrapper.firstChild);
        docFrag.appendChild(child);
    }

    // replace wrapper with document fragment
    wrapper.parentNode.replaceChild(docFrag, wrapper);
}

Try it:

unwrap(document.querySelector('.wrapper'));
Web_Designer
  • 72,308
  • 93
  • 206
  • 262
  • 1
    why is avoiding innerHTML preferable? – ajbeaven Sep 01 '16 at 03:43
  • 12
    @ajbeaven Keeping the existing DOM objects (rather than recreating them using innerHTML) means any event listeners attached to them are maintained. – HeyHeyJC Sep 12 '16 at 21:45
  • 2
    Nice solution, but there is no need to remove the children from the wrapper since `docFrag.appendChild(wrapper.firstChild);` will automatically move a node from its current position to its new position. [Read more about appendChild on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild) – Robbendebiene Jul 17 '18 at 12:44
19

Surprised that nobody's posting the simplest answer:

// Find your wrapper HTMLElement
var wrapper = document.querySelector('.wrapper');

// Replace the whole wrapper with its own contents
wrapper.outerHTML = wrapper.innerHTML;
ChaseMoskal
  • 7,151
  • 5
  • 37
  • 50
11

Could use this API: http://api.jquery.com/unwrap/

Demo http://jsfiddle.net/7GrbM/

.unwrap

Code will look something on these lines:

Sample Code

$('.button').click(function(){
    $('.wrapper img').unwrap();
});
Tats_innit
  • 33,991
  • 10
  • 71
  • 77
6

Pure javascript solution, i'm sure someone can simplify it more but this is an alternative for pure javascript guys.

HTML

<div class="button" onclick="unwrap(this)">Remove wrapper</div>

Javascript (pure)

function unwrap(i) {
    var wrapper = i.parentNode.getElementsByClassName('wrapper')[0];
    // return if wrapper already been unwrapped
    if (typeof wrapper === 'undefined') return false;
    // remmove the wrapper from img
    i.parentNode.innerHTML = wrapper.innerHTML + i.outerHTML;
    return true;
}

JSFIDDLE

Jay Harris
  • 4,201
  • 17
  • 21
  • 1
    check you working [fiddle](http://jsfiddle.net/7GrbM/2/) some problem after unwrapping. Fix it . – Tushar Gupta - curioustushar Oct 09 '13 at 01:26
  • Using `innerHTML` is evil, it will delete all your events inside the HTML. – dude Apr 22 '16 at 16:07
  • @julmot clearly... (: if you want a solution that does that, scroll up or down and you'll find it. I'm not here to create duplicate answers especially when the question didn't ask to keep the event handlers. (; – Jay Harris Apr 22 '16 at 21:01
1

if you're using jQuery:

$(".wrapper").replaceWith($(".wrapper").html());
szaman
  • 2,159
  • 1
  • 14
  • 30
-2

If the wrapper element contains text, the text remains with child nodes.

Jonathan Argentiero
  • 5,687
  • 8
  • 29
  • 34