14

Mar

Filed in Code, JavaScript |

I had to fix a strange bug today in the iBegin Share widget. On one of our pages (the readme specifically) it was positioning wrong. The goal was to position it 5px below the bottom of the object it’s attached to. Easily enough I was able to Google and find the same 10 results that said “here is what you do to get the *correct* absolute positions for an object”. None of them actually worked :)

So, too many hours later, and after not having a single person being able to clue me in on the problem, I found the issue. We had a container which had position: relative; and border-width: 25px 0;. To my suprise, the 25px border was what wasnt being counted. This didn’t seem to happen in Internet Explorer, only Firefox (and I believe Opera as well). I now give you a fully* (I guarantee nothing) working version of the getXY function.

Update: After doing a little bit more research this may be related to the hasLayout style property.

(You can also grab this over at PasteThat)

/**
 * Returns the absolute X and Y positions of an object.
 * @param {HTMLObject} obj HTML Object.
 * @return {Object} Returns an accessor with .x and .y values.
 */
function getXY(obj)
{
  var curleft = 0;
  var curtop = obj.offsetHeight + 5;
  var border;
  if (obj.offsetParent)
  {
    do
    {
      // XXX: If the element is position: relative we have to add borderWidth
      if (getStyle(obj, 'position') == 'relative')
      {
        if (border = _pub.getStyle(obj, 'border-top-width')) curtop += parseInt(border);
        if (border = _pub.getStyle(obj, 'border-left-width')) curleft += parseInt(border);
      }
      curleft += obj.offsetLeft;
      curtop += obj.offsetTop;
    }
    while (obj = obj.offsetParent)
  }
  else if (obj.x)
  {
    curleft += obj.x;
    curtop += obj.y;
  }
  return {'x': curleft, 'y': curtop};
}
/**
 * Returns the specified computed style on an object.
 * @param {HTMLObject} obj HTML Object
 * @param {String} styleProp Property name.
 * @return {Mixed} Computed style on object.
 */
function getStyle(obj, styleProp)
{
  if (obj.currentStyle)
    return obj.currentStyle[styleProp];
  else if (window.getComputedStyle)
    return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
}
  • anthony

    Thank you! I thought I was going crazy when the “standard” X/Y javascript functions simply didn’t work.

    There seems to be a bit of debug code left in your sample above, below is a slightly modified version that works for me.

    I’ve also added support for object padding, which also causes the co-ordinates to be off.

    Finally, i found that an object may not be set to position=relative, so I changed the logic to be != absolute.

    /**
    * Returns the absolute X and Y positions of an object.
    * @param {HTMLObject} obj HTML Object.
    * @return {Object} Returns an accessor with .x and .y values.
    */
    function getXY(obj)
    {
    var curleft = 0;
    var curtop = 0;
    var border;
    var padding;
    if (obj.offsetParent)
    {
    do
    {
    // XXX: If the element is position: relative we have to add borderWidth
    if (getStyle(obj, ‘position’) != ‘absolute’)
    {
    if (border = getStyle(obj, ‘border-top-width’)) curtop += parseInt(border);
    if (border = getStyle(obj, ‘border-left-width’)) curleft += parseInt(border);

    if (padding = getStyle(obj, ‘padding-top’)) curtop += parseInt(padding);
    if (padding = getStyle(obj, ‘padding-left’)) curleft += parseInt(padding);
    }
    curleft += obj.offsetLeft;
    curtop += obj.offsetTop;
    }
    while (obj = obj.offsetParent)
    }
    else if (obj.x)
    {
    curleft += obj.x;
    curtop += obj.y;
    }
    return {‘x’: curleft, ‘y’: curtop};
    }

  • http://jscolor.com Honza Odvárko

    Thank you for a very helpful solution. I just don’t undesrtand, why you initialize curtop to this value:

    var curtop = obj.offsetHeight + 5;

  • http://jamesgeraldlgayo.webng.com jamesgayo

    please how do you get firefox to return a value from this:
    document.defaultView.getComputedStyle(elem,”).getPropertyValue(‘border-left-width’) ? It’s always nothing :(
    thanks a lot

  • jamesgayo

    oh sorry… i got it now. thanks again.

  • http://darwinweb.net/ gabe da silveira

    Please add the year to your post dates. It’s a crime against information.

  • http://www.salesbox.co.uk Bim

    ^^

    Don’t know how many years old this is now.

    I’m in the same position you were right now, i keep running into problems with objects with javascript and how to get their x and y values.

    Now i’m beginning to think theres some basic javascript thing to do with form elements that makes them different to other objects and theres some other way you have to get to them properties. I’m gonna skip using it for now but this comes up for me quite often if someone knows how to access form element properties it would be good!

blog comments powered by Disqus