Aras
Aras

Reputation: 5926

Postorder traversal of nested dom elements selected by jQuery

This should be a nice little puzzle, and hopefully solvable by jQuery. Here is a self explanatory jsFiddle. Note that I am looking for a generic solution to traverse the elements of interest in the dom based on where they are in the dom tree. I provide this reduced case as an example, so you can test your solutions against it and it is also easier to understand.

The DOM:

<div class="element" value="Hi5!">
    <div class="element" value="Zero"></div>
    <div class="junk" value="no no!"></div>
    <div class="element" value="Four">
        <div class="element" value="One"></div>
        <div class="element" value="Three">
            <div class="element" value="Two"></div>
        </div>
    </div>
    <div class="element" value="Five"></div>
</div>

The code I'v got which prints elements in an undesired order:

$(document).ready(function(){
    console.log("ready");
    $(".element").each(function(index, item){
       console.log(index + " | ",  item.getAttribute('value'));
    });
});

The current output:

ready
0 | Hi5!
1 | Zero
2 | Two
3 | One
4 | Four
5 | Three
6 | Five

How can I traverse and print the values of the nested div elements above in a postorder fashion?

Edit: thanks to @zshooter for providing a solution and pointing out a mistake in my question. Here is my updated jsFiddle ordered properly in postorder.

Upvotes: 3

Views: 926

Answers (2)

Ja͢ck
Ja͢ck

Reputation: 173552

An answer has already been given, but I wrote a more generic function:

function applyPostOrder(selector, fn, filter)
{
    (function visit() {
        $node = jQuery(this);
        $node.children(filter).each(visit);

        if (!filter || $node.is(filter)) {
            fn(this);
        }
    }).call(jQuery(selector).get(0));
}

This function will call fn for every node found that matches the given filter. This is how you call it:

function visitItem(node)
{
    console.log(node.getAttribute('value'));
}

jQuery(function($) {
    console.log("ready");
    applyPostOrder('body', visitItem, '.element');
});

Upvotes: 0

zbrunson
zbrunson

Reputation: 1757

here you go:

$(document).ready(function(){
    console.log("ready");

    $("body").children('.element').each(function(index, item) {
        visitNode(item);
    });
});

function visitNode(element) {
    $(element).children('.element').each(function(index, item) {
        visitNode(item);
    });
    console.log(element.getAttribute('value'));
}

Upvotes: 2

Related Questions