ObiHill
ObiHill

Reputation: 11896

Using JQuery to find the widths of all children under the body tag down to a specific generation

I'm trying to find the widths of set of HTML elements on a web page.

Basically, I want to get the widths of:

  1. The html element
  2. The body element
  3. All elements directly under the body element [ancestor]
  4. All children directly under 'ancestor' down to the fourth generation (if at all it goes that far down)

So looking at the HTML code below:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <div>
            <div>
                <div>
                    <div>
                        <div>Test 1</div>
                    </div>
                </div>
            </div>
        </div>
        <div>
            <div>
                <div>
                    <div>
                        <div>Test 2
                            <div>Test 2 - Child</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

I can get the widths of html, body, and the 'ancestors' [(1), (2), and (3)] pretty easily with:

console.log($('html').outerWidth());
console.log($('body').outerWidth());
$('body').children().each(function(){
    console.log(this.outerWidth());
});

However, I'm not sure how to get the descendants of the 'ancestor' down to the 4th generation. So 4th generation would be where you have Test 1 and Test 2, Test 2 - Child would be fifth generation.

FYI I'm doing this on pages that I cannot control so identifiers like id and class will not be available for me to target. Also the descendants may vary tag-wise, they might not always be divs.

Upvotes: 1

Views: 311

Answers (3)

TastySpaceApple
TastySpaceApple

Reputation: 3185

You would have to traverse the tree 3 times down. it's easy with recursion:

EDIT: fiddle contributed by asker: http://jsfiddle.net/WqupP/2/

function traverseDownBy(generations, start){ 
    var children = [],
        generation_num_start = generations+2,
        generation_num,
        counter = 0
        ;    
    function traverseDown(node){
        counter++;
        if(counter <= 1)
        {
            generation_num = generation_num_start;
        }
        else
        {
            generation_num--;
        }

        if(generation_num == 0){
            generation_num = generation_num_start;
            return;
        }        
        children.push(node);
        node.children().each( function () { traverseDown($(this)); } );
    }
    traverseDown(start);
    return children;
}
var children = traverseDownBy(4, $('body'));
$(children).each( function (){
    $('#result').append('<p>'+$(this).attr('id')+': '+$(this).width()+'</p>'); 
});

or even

(function(){ //private. member protection.
    var generations = 4;
    function traverseDown(node){
        generations--;
        if(generations == 0) return;
        console.log(node.outerWidth());
        node.children().each( function () { traverseDown($(this)); } );
    }
    traverseDown($('body'));
})()

Upvotes: 1

Tomanow
Tomanow

Reputation: 7377

Simply:

$('body').find('*').each(function(k,v) {
    console.log($(this).width());
});

Upvotes: 0

ProGM
ProGM

Reputation: 7108

I hope I got the problem...

Well, a bad solutions is to combine multiple instances of .children() function. Example:

var childrens = $('body').children().add(
    $('body').children().children().add(
        $('body').children().children().children().add(
            $('body').children().children().children().children()
        )
    )

childrens.each(blablah);

Source: JQuery's "find()" with depth limit, I can't use .children()

How to combine two jQuery results

Upvotes: 0

Related Questions