tags:

views:

4724

answers:

5

Let's say:

<div>
some text
  <div class="remove-just-this">
  <p>foo</p>
  <p>bar</p>
  some text node here
  </div>
some text
</div>

to this:

<div>
some text
  <p>foo</p>
  <p>bar</p>
  some text node here
some text
</div>

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

+13  A: 

Using jQuery you can do this:

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

Quick links to the documentation:

jk
Much cleaner solution than mine!
ConroyP
+1 for the use of 'cnt'
scraimer
A: 

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.

domgblackwell
+8  A: 

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.

insin
A: 

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.insertBefore(fragment, element);
element.parentNode.removeChild(element);
eyelidlessness
+1  A: 

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

tj111