1

I need to calculate the position, height and width of every anchored link in my page. I know how to find the x,y coords, but I have a problem with the height and width. The problem appears when the link has children inside (images, divs etc), so heightOffset and widthOffset won't work. Is there a way to do this without going on all the children and calculating their sizes?

EDIT:

Here is some code to demonstrate what I mean (the press function is called whenever the mouse is being pressed):

function findPos(obj) {
    var curleft = curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    return [curleft,curtop];
}

function getHeight(elem) {

          if (elem.style.pixelHeight) {
             return elem.style.pixelHeight;
          } else {
             return elem.offsetHeight;
          }
    }
function getWidth(elem) {

    if (elem.style.pixelWidth) {
       return elem.style.pixelWidth;
    } else {
       return elem.offsetWidth;
    }
}

function press(e)
{


      x= e.pageX;
      y= e.pageY;

    window.alert(x+","+y);


            var links = document.getElementsByTagName('a');
            for (i = 0; i < links.length; i++){
                var pos = findPos(links[i]);
                window.alert(x+","+y+" "+pos[0]+" " + pos[1] + " "+links[i].offsetWidth+ " "+links[i].offsetHeight);
                if (x >= pos[0] && x <= pos[0] + getWidth(links[i]) && y >= pos[1] && y <= pos[1] + getHeight(links[i])){
                    window.alert(links[i].href);
                    i = links.length;
                }
            }


}

When I encounter a link with an image for instance it doesn't return me the right size.

Thanks

Alex1987
  • 9,397
  • 14
  • 70
  • 92

3 Answers3

1

offsetWidth/Height do very much work on links that contain images, as long as you haven't done anything weird like overflowing or positioning the images or other child content so that they fall out of the content area of their parent.

Your code isn't using offsetHeight on IE, it's using pixelHeight, which doesn't do what perhaps you think it does. Stick with offsetHeight.

Conversely, you are using event.pageX/Y, which is a non-standard extension IE doesn't have. Sadly the only reliable way to get page-relative co-ordinates from an event is to use clientX/Y and adjust for viewport scrolling.

I don't really know why you are going to the effort of enumerating link positions when for a mouse click/down event you can quite reliably get the element that was clicked on using event.target/srcElement. In fact this is the only reliable way to do it. Consider a link that has split over two text lines. Now what you've got is a non-rectangular region; you can't test whether a particular mouse position lies within that area using a simple x and y range test.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • actually I don't care much about IE, since I'm writing an iphone app. I am attempting to detect a tap on a link (I don't want to use the touchstart event) by the coordinates. – Alex1987 Jan 12 '10 at 14:44
  • @bobince, I tested his code with a very simple line of html `` and it returns 15 as the offsetHeight - could this be a buggy implementation of offsetHeight in WebKit? – Andy E Jan 12 '10 at 14:48
  • 1
    @Andy E: that will be the correct value for the line-height; remember that both `a` and `img` are inline elements by default. If the image is taller than the line, it will overflow in the visual rendering, but the `a` element itself doesn't stretch to accommodate it. Adding `overflow:hidden;` to the `a` element will show you what I mean. – NickFitz Jan 12 '10 at 15:35
  • You could always make the `a` a block or inline-block if you want it to encompass its inline content. However, again, all this should be completely unnecessary; just look at the `event.target` element. – bobince Jan 12 '10 at 16:29
  • @NickFitz: I figured it was probably the line-height of the `a` element. What was weird was that putting the img in a span tag fixed the problem, so the a element would stretch to the size of a span tag but not to the size of an img tag. – Andy E Jan 14 '10 at 10:06
0

The correct properties are offsetHeight (not heightOffset) and offsetWidth (not widthOffset).
Those properties should correctly return the sizes you're after, because the children would expand the elements to fit, assuming overflow is set to visible. There's no need to calculate the sizes of the children in any situation.

offsetHeight and offsetWidth aren't part of any standard but most browsers seem to have them implemented anyway.

Since you're having problems with Safari and offsetHeight, maybe you could try the getClientRects() method:

http://www.quirksmode.org/dom/tests/rectangles.html

var dims   = links[i].getClientRects()[0];
var width  = dims.right - dims.left;
var height = dims.bottom - dims.top;

Can't say I've ever used getClientRects(), however. It sounds like the results may be closer to clientWidth and clientHeight.

FURTHER EDIT
I figured out a workaround. The following does not work:

<a href="#">
  <img onclick="press(event);" src="http://sstatic.net/so/img/logo.png" alt="" />
  <!-- onclick handler alerts with size 250x15 -->
</a>

But wrapping a <span> tag around the <img> tag, like so:

<a href="#"><span>
  <img onclick="press(event);" src="http://sstatic.net/so/img/logo.png" />
  <!-- onclick handler alerts with size 250x61 -->
</span></a>

Fixes the problem. At least, it does in Chrome but like I said before Chrome and Safari share the WebKit rendering engine, so it should work for Safari too.

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • I ran some tests and I don't think what you say is true. I also attached some code - maybe there is something wrong with it. – Alex1987 Jan 12 '10 at 14:10
  • @Alex1987: Which browsers have you tested it in? It works fine in IE6-8 but Chrome returns an incorrect value for offsetHeight. I don't have Firefox or Opera installed on this machine though so I can't test in those. I suspect this is a bug in Chrome, though. Read https://developer.mozilla.org/en/Determining_the_dimensions_of_elements for a detailed explanation of offset dimensions. – Andy E Jan 12 '10 at 14:41
  • Safari and mobileSafari (on the iphone) - also return incorrect values for offsetHeight!! – Alex1987 Jan 12 '10 at 14:46
  • Safari uses the same rendering engine as Chrome (WebKit) – Andy E Jan 12 '10 at 14:50
  • @Alex1987: I figured out a workaround. Wrap a `` tag around the `` tag and it works - see my updated answer. – Andy E Jan 12 '10 at 18:51
0

You should not use the values in elem.style.* to determine the size of an element. These values are CSS styles and aren't reliable. Use only offsetWidth and offsetHeight.

To get the position of an element, use the answers to this question: Retrieve the position (X,Y) of an HTML element

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820