Trouble finding left/top offset position of a DIV when parent DIVhas a border

S

Stevo

I have a DIV that's inside another DIV, I'll call them inner and outer.
To find the X (left) position on the page of the inner DIV, I do the
standard method of accumulating the offsetLeft values while chaining up
the offsetParent hierarchy until I reach the top (offsetParent==null).
If the outer DIV has no border/margin/padding CSS, then this usually
works just fine.

If however the outer DIV has border set by CSS, then my position
calculation function is off by that many pixels. I wanted to try and
compensate for this by adding the value of the border (or margin or
padding) of the outer DIV but when I interrogate any of the inner DIv's
..style.border properties, I get an empty string back.

I've interrogated all of the properties inside .style in Visual Studio,
and none of them held the "3px" that I was looking for. The only place I
could find them, was in the alternate .currentStyle. The border
properties in there do present me with my elusive "3px". So I could
fashion a solution for IE like this:

document.getElementById("outerdiv").currentStyle.borderWidth

Whenever I would want to get the position of innerDiv, I call my
position function and add the pixels found in this currentStyle
property. It's non-standard and IE only and therefore not much use to
me. It's also hacky.

Even if I wanted to have a branch to test if currentStyle exists, there
is no equivalent property in Gecko browsers for my else statement. I see
in Firebug (in Firefox) that it has only .style and again all the border
values are "". There are a lot of special Moz properties but none of
them have the border value I'm looking for.

I'm sure I can't be the only person suffering from this. So far I've
never found that I've needed to worry about border/margin/padding
because 99.9% of the outerdiv's that my innerdiv might find itself
inside, have had no such values to worry about.

Here's the CSS that was applied to the outer DIV:

#outer {
border:3px solid #2B5E88;
height:400px;
left:262px;
position:absolute;
top:440px;
width:400px;
}

My position function returns the same value for inner as for outer, even
though the inner DIV is 3 pixels down and right compared to outer.
 
S

Stevo

VK said:
<snip>

Finding the exact position of each element on the page is a very
technically difficult task heavily dependent on actual browser and
browser version. The most robust out of known to me scripts to solve
it - yet still not covering 100% of cases - is Matt Kruse's "Object
Position" script
http://www.javascripttoolbox.com/lib/objectposition/

Thanks VK. I had found that while googling the subject earlier, but it
also doesn't account for border/margin/padding in the way my post
describes. His pos.get function
(http://www.javascripttoolbox.com/lib/objectposition/source.php )
basically does the same mine does except he's also taking account of
scrolling and something about tables. I believe he'd experience the same
miscalculation. I better try it to be sure, but it seems like it.
 
V

VK

Thanks VK. I had found that while googling the subject earlier, but it
also doesn't account for border/margin/padding in the way my post
describes. His pos.get function
(http://www.javascripttoolbox.com/lib/objectposition/source.php)
basically does the same mine does except he's also taking account of
scrolling and something about tables. I believe he'd experience the same
miscalculation. I better try it to be sure, but it seems like it.

Maybe. I should read your OP to the end. You are making a standard
mistake by assuming that DOMElement.style reflects all run-time
styling of an element. It is not at all: DOMElement.style reflects
only styling set over "style" attribute of HTML element and styling
set over scripting: that's it. So even if you have say CSS sheet with
a rule
DIV#MyDIV {
position: absolute;
left: 10px;
}
then for document.getElementById('MyDIV').style.left is not set. So
there is nothing "hacky" in what your are doing: it is the only proper
way. You just have to use either .currentStyle (IE) or
getCalculatedStyle (others). I had posted the above explanation and
the relevant cross-browser script several times in this NG but just
right now I cannot find the link. Maybe you'll be luckier.
 
D

dhtml

That is true!

Other browsers are now implementing getBoundingClientRect, which is
specified in a way that is different than what IE does (it's an oddity
of IE). The offsetTop/Parent properties are not very intuive and the
MS docs are vague. Worse, there's now a spec for these offset*
properties, but it's loosely based on quirks mode offset* in IE, which
Mozilla copied and other browsers copied. The spec also has a
peculiarity that only Opera implements, and one that causes problems.
It basically makes every other browser non-compliant by introducing
another quirk.

The issue is addressed by CSSOM Views and has been discussed on the
www-style list. The CSSOM Views WD is slated to go official soon. The
more people who are proactive in providing valid, unbiased criticism /
feedback for the spec, the better. It's easy to ignore one or two
voices. Personally, I think the spec could be much better and should
be rewritten. Unfortunately, I'm not getting paid to write a spec. I'm
not a pay-to-play member of the w3c.

Coincidentally (or not), the author of the spec works for Opera.


The example page works fine. The arrow always lines up, but there are
cases where the arrow is 1px off -- by the border of the nested
scrolled elements. Margin/position on body. There are some easy cases
where it fails in different browsers. It's not a bad function to
study, but with more thorough testing, you'll find many other cases.

You could try mine out:
example:
http://www.dhtmlkitchen.com/ape/example/dom/getOffsetCoords.html
 
S

Stevo

VK said:
Maybe. I should read your OP to the end. You are making a standard
mistake by assuming that DOMElement.style reflects all run-time
styling of an element. It is not at all: DOMElement.style reflects
only styling set over "style" attribute of HTML element and styling
set over scripting: that's it. So even if you have say CSS sheet with
a rule
DIV#MyDIV {
position: absolute;
left: 10px;
}
then for document.getElementById('MyDIV').style.left is not set. So
there is nothing "hacky" in what your are doing: it is the only proper
way. You just have to use either .currentStyle (IE) or
getCalculatedStyle (others). I had posted the above explanation and
the relevant cross-browser script several times in this NG but just
right now I cannot find the link. Maybe you'll be luckier.

Thanks, getCalculatedStyle sounds like just what I need :)

Interesting, I just did a test with Matt's pos.get function compared to
my own function. First I did a screen capture and measured exactly how
many pixels it was (150). My func returned 150 for the outer div
(correct), but also returned 150 for the inner div (incorrect - the
outer div had a 10pixel border so the inner div should have returned
160). This is nothing new. What is new and interesting is that Matt's
function returned 152 and 162. So this is both good and bad. It's good
that he somehow notices the 10 pixel border, but bad that he's out by 2
pixels on both somehow.

Here's the entire html page I tested with (if anyone's interested in
playing around with it):

<html><body leftmargin=0 topmargin=0 marginwidth=0 marginheight=0>
<script language="javascript">
function myleft(n){
var o=document.getElementById(n),r=o.offsetLeft;
while(o=o.offsetParent)r+=o.offsetLeft;
return r;
}
function mytop(n){
var o=document.getElementById(n),r=o.offsetTop;
while(o=o.offsetParent)r+=o.offsetTop;
return r;
}

function updateOutput()
{
//crude but quick to code
var my=document.getElementById("myresult");
var str=""+
"My Result: Div 3 Left="+myleft("div3")+", Top="+mytop("div3")+"<br>"+
"My Result: Div 4 Left="+myleft("div4")+", Top="+mytop("div4")+"<br>"+
"<br>Notice how div 3 and 4 have the same calculated position yet
as you<br>"+
"can see, div 4 is 10 pixels right/down from div 3 due to div 3's
border<br><br><br>";

str+="Result from Matt's function:<br><br>"+
"Div 3 Left="+posget("div3").left+",Top="+posget("div3").top+"<br>"+
"Div 4 Left="+posget("div4").left+",Top="+posget("div4").top+"<br>"

my.innerHTML=str;
}
setTimeout(updateOutput,1000);
</script>

<div id="div1"
style="position:absolute;left:50px;top:50px;width:600px;height:500px;background-color:#DDDDDD;">
<div id="div2"
style="position:absolute;left:50px;top:50px;width:600px;height:500px;background-color:#BBBBBB;">
<div id="div3"
style="position:absolute;left:50px;top:50px;width:600px;height:500px;background-color:#AAAAAA;border:10px
solid #2B5E88;">
<div id="div4"
style="position:absolute;left:00px;top:00px;width:600px;height:500px;background-color:#888888;">
<div id="myresult"></div>
<div id="mattkruseresult"></div>
</div></div></div></div>
<script language="javascript">
//Matt's function only slightly tweaked to extract it from the file it
was in
posget = function(o) {
var fixBrowserQuirks = true;
if (typeof(o)=="string") {
o = document.getElementById(o);
}
if (o==null) {
return null;
}
var left = 0;
var top = 0;
var width = 0;
var height = 0;
var parentNode = null;
var offsetParent = null;
offsetParent = o.offsetParent;
var originalObject = o;
var el = o; // "el" will be nodes as we walk up, "o" will be saved
for offsetParent references
while (el.parentNode!=null) {
el = el.parentNode;
if (el.offsetParent==null) {
}
else {
var considerScroll = true;
/*
In Opera, if parentNode of the first object is scrollable, then
offsetLeft/offsetTop already
take its scroll position into account. If elements further up
the chain are scrollable, their
scroll offsets still need to be added in. And for some reason,
TR nodes have a scrolltop value
which must be ignored.
*/
if (fixBrowserQuirks && window.opera) {
if (el==originalObject.parentNode || el.nodeName=="TR") {
considerScroll = false;
}
}
if (considerScroll) {
if (el.scrollTop && el.scrollTop>0) {
top -= el.scrollTop;
}
if (el.scrollLeft && el.scrollLeft>0) {
left -= el.scrollLeft;
}
}
}
// If this node is also the offsetParent, add on the offsets and
reset to the new offsetParent
if (el == offsetParent) {
left += o.offsetLeft;
if (el.clientLeft && el.nodeName!="TABLE") {
left += el.clientLeft;
}
top += o.offsetTop;
if (el.clientTop && el.nodeName!="TABLE") {
top += el.clientTop;
}
o = el;
if (o.offsetParent==null) {
if (o.offsetLeft) {
left += o.offsetLeft;
}
if (o.offsetTop) {
top += o.offsetTop;
}
}
offsetParent = o.offsetParent;
}
}
if (originalObject.offsetWidth) {
width = originalObject.offsetWidth;
}
if (originalObject.offsetHeight) {
height = originalObject.offsetHeight;
}
return {'left':left, 'top':top, 'width':width, 'height':height};
};
</script>
</body></html>
 
S

Stevo

Stevo said:
Interesting, I just did a test with Matt's pos.get function compared to
my own function. First I did a screen capture and measured exactly how
many pixels it was (150). My func returned 150 for the outer div
(correct), but also returned 150 for the inner div (incorrect - the
outer div had a 10pixel border so the inner div should have returned
160). This is nothing new. What is new and interesting is that Matt's
function returned 152 and 162. So this is both good and bad. It's good
that he somehow notices the 10 pixel border, but bad that he's out by 2
pixels on both somehow.

Well, I think I have the answer I need (thanks to Matt's func :) I'll
just mention left in my example here (same deal for top of course).

I need to add o.clientLeft in my loop as well as o.offsetLeft. So my
function changes to this (with //<<< indicating the new line):

function myleft(n){
var o=document.getElementById(n),r=o.offsetLeft;
while(o=o.offsetParent)
{
r+=o.offsetLeft;
if(o.offsetParent)r+=o.clientLeft; //<<< new line
}
return r;
}

Does anyone see a problem with that ? It doesn't add the clientLeft when
it reaches the top of the chain. That's what was causing Matt's func to
add the extra 2 pixels. This worries me a bit. I can see an example
existing where there might be something in there (at the top of the
chain) that I want. Right now though, it's passing this test which is
more than my old func did. I'll wait on feedback to see if it's worth
taking away with me though.
 
T

Thomas 'PointedEars' Lahn

dhtml said:
[...]
The issue is addressed by CSSOM Views and has been discussed on the
www-style list. The CSSOM Views WD is slated to go official soon.

Utter nonsense.

,-<http://www.w3.org/TR/2008/WD-cssom-view-20080222/>
|
| Status of this Document
|
| This section describes the status of this document at the time of
| its publication. Other documents may supersede this document.
| A list of current W3C publications and the latest revision of this
| technical report can be found in the W3C technical reports index
| at http://www.w3.org/TR/.
|
| Publication as a Working Draft does not imply endorsement by the
| W3C Membership. This is a draft document and may be updated,
| replaced or obsoleted by other documents at any time. It is
| inappropriate to cite this document as other than work in progress.

It is not even a Last Call Working Draft.


PointedEars
 
D

dhtml

[...]
The issue is addressed by CSSOM Views and has been discussed on the
www-style list. The CSSOM Views WD is slated to go official soon.

Utter nonsense.

,-<http://www.w3.org/TR/2008/WD-cssom-view-20080222/>
|
| Status of this Document
|
| This section describes the status of this document at the time of
| its publication. Other documents may supersede this document.
| A list of current W3C publications and the latest revision of this
| technical report can be found in the W3C technical reports index
| athttp://www.w3.org/TR/.
|
| Publication as a Working Draft does not imply endorsement by the
| W3C Membership. This is a draft document and may be updated,
| replaced or obsoleted by other documents at any time. It is
| inappropriate to cite this document as other than work in progress.

It is not even a Last Call Working Draft.
http://www.w3.org/TR/cssom-view/

Apparently, you haven't been following the www-style list.
"I think it's ready for Last Call."

AVK -- and that's from a few weeks ago.

I'm not really interested in getting into a technical discussion of
'soon'. However, consider that it was an editor's draft for 2 years
(while Opera was implementing these bugs), then it went live, then
three weeks later, AVK said "ready for Last Call." Considering that, I
think the time of last to official is about three weeks. Three weeks
out of what, 100+ weeks (?) is not a lot of time, relatively speaking.

I've tried to point out some of the more obvious problems in the spec,
but again, it's just too much wrong with it to comment on all the
problems. I found communicating with (or attempting to communicate
with) the author to be mostly a waste of time. The last 3 mails
criticizing CSSOM were ignored.

Garrett
 
T

Thomas 'PointedEars' Lahn

dhtml said:
[...] Thomas 'PointedEars' Lahn said:
dhtml said:
VK wrote:
I have a DIV that's inside another DIV
<snip>
Finding the exact position of each element on the page is a very
technically difficult task heavily dependent on actual browser and
browser version.
[...]
The issue is addressed by CSSOM Views and has been discussed on the
www-style list. The CSSOM Views WD is slated to go official soon.
Utter nonsense.

,-<http://www.w3.org/TR/2008/WD-cssom-view-20080222/>
|
| Status of this Document
|
| This section describes the status of this document at the time of
| its publication. Other documents may supersede this document.
| A list of current W3C publications and the latest revision of this
| technical report can be found in the W3C technical reports index
| athttp://www.w3.org/TR/.
|
| Publication as a Working Draft does not imply endorsement by the
| W3C Membership. This is a draft document and may be updated,
| replaced or obsoleted by other documents at any time. It is
| inappropriate to cite this document as other than work in progress.

It is not even a Last Call Working Draft.
http://www.w3.org/TR/cssom-view/

Apparently, you haven't been following the www-style list.
"I think it's ready for Last Call."

The least that would be required for this to become some kind of argument to
consider (although not a valid one; it is result of the red herring
fallacies of Appeal to authority, and of Wishful thinking) is to name the
author of that statement, and probably also to post the URL of the archived
message.

Anyway, not apparently, but definitely, you do not know or understand W3C
procedures, and therefore you are not in a position to properly assess the
relevance of messages posted to the public (not W3C-member- or
Working-Group-member-only) W3C mailing lists regarding the standardization
process, which is near zero. While the discussions there are taken into
account by the responsible Working Group (at least that should be the case,
with the HTML WG it too often was not), it is eventually up to the W3C
Advisory Committee, consisting of W3C Members (organizations, not
individuals) and the W3C Director (currently TBL) to decide what becomes a
Web standard.

Even if a Working Draft becomes a "Last Call" Working Draft, that "may be
updated, replaced or obsoleted by other documents at any time". When a
Technical Report (TR) has reached that maturity level it CAN (not MUST)
become a Candidate Recommendation (CR), then a Proposed Recommendation (PR)
and not before it has then reached the level of Recommendation (REC) it can
reasonably be called a Web standard. In fact, it has happened before that a
Specification that had already reached the level of Candidate Recommendation
fell back to that of a Working Draft; for example, this was the case with
the CSS 2.1 Specification in 2004 CE, which went back again to CR in 2007.
(Those dates should make it clear to you eventually how wrong your
assessment actually has been.)

http://www.w3.org/Consortium/Process/tr.html#Reports


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top