1

I need to create a "popup" div over a span element.

I try to determinate its position and size to give correct boundary to place floating div.

    <html>
    <body>
    <p>text a</p>
            <div style="padding-left:200px;padding-top:500px">
                    <table class="message">
                            <tr><td>test <span id="test">hello</span> world</td></tr>
                    </table>
            </div>
    </body>
    </html>

I try to get this information for an element id=test

I tried two methods:

First I get span

var span = document.getElementById('test');

Than I calculate either using approach proposed at Retrieve the position (X,Y) of an HTML element

var x0 = 0;
var y0 = 0;
var el = span;
while(el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
    x0 += el.offsetLeft - el.scrollLeft;
    y0 += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
}
var x1 = x0 + span.offsetWidth;
var y1 = y0 + span.offsetHeight;

And I also try it by using:

var rect = span.getBoundingClientRect();
x0 = rect.left;
x1 = rect.right;
y0 = rect.top;
y1 = rect.bottom;

Than I log:

   console.log(JSON.stringify([x0,x1,y0,y1]));

In both cases I get:

[236,264,381,401]

Which can't be correct as the margin above the table of 500 pixels.

How can I solve this problem correctly?

i.e. how can I put a div with position:ablosute over this element at correct location?

Note: I can't use JQuery or other fat toolkits, I rather need a portable solution in plane JavaScript.

Edit: I noted that it does not work if the page requires scolling, i.e. the head part of page is hidden, how can it be compensated?

Community
  • 1
  • 1
Artyom
  • 31,019
  • 21
  • 127
  • 215
  • You might want to mention what browser(s) you tested in. I took your code as-is and ran it in Firefox 18, Chrome 24 and even IE10 and got the expected results: [237,269,548,567]. In all but Chrome, the second method returned floating point coordinates instead of integers, but they were within half a pixel of each other. Actually, I just realized, the methods you are using don't include the scroll position, so try adding that in as well. – Mark Ormston Feb 12 '13 at 17:27

2 Answers2

0

Your code looks fine — PPK has published an article on a slightly neater way of doing it, but as far as I can work out it's functionally identical. If his solution doesn't work, maybe you can try replicating your issue on jsFiddle?

Barney
  • 16,181
  • 5
  • 62
  • 76
0

Even if you can't use the jQuery offset method or other toolkits have a look at it. This is the way jQuery calculates the position (I just modified the win variable and removed the test if the element is existing):

function getPos(elem) {
    var docElem, win,
        box = { top: 0, left: 0 },
        doc = elem && elem.ownerDocument;
    if ( !doc ) { return; }
    docElem = doc.documentElement;
    if ( typeof elem.getBoundingClientRect !== typeof undefined ) {
        box = elem.getBoundingClientRect();
    }
    win = self;
    return {
        top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
        left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
    };
}

Here is a fiddle, to test (click on the span with the ID#test)

axel.michel
  • 5,764
  • 1
  • 15
  • 25