Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove element nodes in post-order traversal

Say I have the following HTML (condensed):

<div><div><div><ul><li>Text</li></ul></div></div></div>
<div><div><div><ul><li>Text 2</li></ul></div></div></div>
<div><div><div><ul><li>Text 3</li></ul></div></div></div>

I want to remove the lowest child elements first, until ultimately removing the parent, then move on to the next parent element and its children. This can be easily accomplished by a simple loop that goes through each child element, removes it, then removes the next child element (i.e. parent of the previous child):

var children = $("body").find("*");
var i = children.length;
function loop() {
    $(children[i]).remove();
    i--;
    if (i > -1) {
        setTimeout(loop, 20);
    }
}
loop();

The problem with this, however, is that it removes the child elements from the lowest parent element first. If you were to run this code with my test markup, you could see what I mean.

I want to remove the child elements from the top most parent, then work my way down, therefore reversing the order of the above code. I was able to somewhat accomplish this with the following code:

var parents = $("body").children(":not(:empty)");
var i = 0;
var speed = 1000;
function loop() {
    var children = $(parents[i]).find("*");
    var x = children.length;
    function inside() {
        $(children[x]).remove();
        x--;
        if (x > -1) {
            setTimeout(inside, speed);
        } else if (i < parents.length) {
            $(parents[i - 1]).remove();
            loop();
        } else if (i === parents.length) {
            $(parents[i - 1]).remove();
        }
    }
    inside();
    i++;
}
loop();

The problem with this code, however, is that it only reverses the order of deleting with respect to the parent element. If there are multiple child elements within a parent, it will still delete them in the default ascending order (bottom to top).

My question, therefore, is how can I delete all the elements in descending order, regardless of how many child elements there are, in a much cleaner fashion? There has to be a much better approach than what I attempted. jQuery isn't a requirement either. The reason for the setTimeouts is because I need a delay between removing the elements. As usual, I probably overlooked something relatively simple, so bear with me.

To reiterate, if the HTML looks like this:

<div>
    <div>Child 1</div>
    <div>Child 2</div>
    <div>
        <div>Child 3</div>
        <div>Child 4</div>
    </div>
</div>

I would want it to be deleted in the following order:

  1. Child 1
  2. Child 2
  3. Child 3
  4. Child 4
like image 960
Charlie Avatar asked Feb 02 '14 23:02

Charlie


People also ask

How do you remove nodes from a tree?

Starting at the root, find the deepest and rightmost node in the binary tree and the node which we want to delete. Replace the deepest rightmost node's data with the node to be deleted. Then delete the deepest rightmost node.

How do you remove a node?

To delete a node from the linked list, we need to do the following steps: Find the previous node of the node to be deleted. Change the next of the previous node. Free memory for the node to be deleted.

How do you delete an element from a binary search tree?

1) Node to be deleted is the leaf: Simply remove from the tree. 3) Node to be deleted has two children: Find inorder successor of the node. Copy contents of the inorder successor to the node and delete the inorder successor.

How do you delete a node with only one child?

The node to be deleted has only one child. In this case, replace the node with its child and delete the child node, which now contains the value which is to be deleted. Simply replace it with the NULL and free the allocated space.


1 Answers

First build a post-order (aka child first) version of the DOM tree using the following recursive function:

var nodes = [];

function generate()
{
    $(this).children().each(generate);
    nodes.push(this);
}

generate.call($('body'));

Then, iterate as per normal:

var i = 0;

function loop() 
{
    $(nodes[i]).remove();
    if (++i < nodes.length) {
        setTimeout(loop, 1000);
    }
}

loop();

Demo

like image 152
Ja͢ck Avatar answered Nov 09 '22 03:11

Ja͢ck