1

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.

ObiHill
  • 11,448
  • 20
  • 86
  • 135
  • You need to use a recursive function to go as deep as it needs to. – scrowler Dec 22 '13 at 22:56
  • `$.each('div', function(k,v) { console.log('div #' + k + ': ' + $(this).html()) });` – Tomanow Dec 22 '13 at 22:57
  • @Tomanow Thanks. It is not guaranteed that the elements are going to be `div` tags – ObiHill Dec 22 '13 at 22:59
  • @scrowler Looking into that now – ObiHill Dec 22 '13 at 23:01
  • @ObinwanneHill here's a fiddle example: http://jsfiddle.net/5SV9Z/1/ - not sure what you want to do with the data but this is targetting those two deepest elements and logging their widths to the console. You could use something like this, and target a fourth level element if you wanted to. Use a global variable to know how deep you are. – scrowler Dec 22 '13 at 23:03
  • @scrowler Thanks, but it doesn't provide the width of every single descendant down to the 4th Generation, which is what I need. – ObiHill Dec 22 '13 at 23:22

3 Answers3

1

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'));
})()
TastySpaceApple
  • 3,115
  • 1
  • 18
  • 27
  • Thanks. I'm getting inconsistent results. See this http://jsfiddle.net/Yt24J/1/ for more. – ObiHill Dec 22 '13 at 23:19
  • I found the solution. It's on this fiddle: http://jsfiddle.net/WqupP/2/. Can you update the code in your answer so I can accept it?! Cheers. – ObiHill Dec 23 '13 at 01:25
0

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

Community
  • 1
  • 1
ProGM
  • 6,949
  • 4
  • 33
  • 52
0

Simply:

$('body').find('*').each(function(k,v) {
    console.log($(this).width());
});
Tomanow
  • 7,247
  • 3
  • 24
  • 52