1

I've been coding a bit of Javascript to place a ducky randomly on this page.

I wanted to make it hide on the side of objects (like the posts), but I ended up having to hardcode quite a bit of it, since I couldn't get a way to properly retrieve the real position of relative objects with Chrome. I read quite a few things about it, and used the recursive offsetParent way, but didn't get any good results.

The last bit of code I tried was this:

 var getPost = function (obj) {
    var pos = {'x':0,'y':0};
    if(obj.offsetParent) {
        while(1) {
          pos.x += obj.offsetLeft;
          pos.y += obj.offsetTop;
          if(!obj.offsetParent) {
            break;
          }
          obj = obj.offsetParent;
        }
    } else if(obj.x) {
        pos.x += obj.x;
        pos.y += obj.y;
    }
    return pos;
  }

This code doesn't work on Chrome, except on objects with an absolute position (set with CSS).

Is there a good, cross-browser way to achieve this?

3
  • Have you considered using jQuery? Commented Sep 18, 2010 at 9:18
  • I have not because I want to keep it simple and it's on a blogger blog. That said, it might be an option. Commented Sep 18, 2010 at 9:20
  • Hyperlink supplied in the question is un-available. You might want to edit it. Commented Aug 12, 2013 at 11:03

3 Answers 3

1

I had a case where I was working with mouse positions and objects as well not so long ago because I needed some drag and drop. So these are the two methods I came up with:

/**
 * Calculates the mouse x and y position from the mouse move event fired by the document
 * 
 * @param event
 *            the mouse move event fired by the document
 * 
 * @return the mouse coordinates object with two variables x and y
 */
function mouseCoords(ev) {
  var event = ev;

  // IE does not pass the event object
  if (event == null)
    event = window.event;

  try {

    // normal style
    if (event.pageX) {
      return {
          x : event.pageX,
          y : event.pageY
      };
    }
    // IE style
    else {
      return {
          x : event.clientX + document.body.scrollLeft - document.body.clientLeft,
          y : event.clientY + document.body.scrollTop - document.body.clientTop
      };
    }

  } catch(ex) {

    // IE style
    return {
        x : event.clientX + document.body.scrollLeft - document.body.clientLeft,
        y : event.clientY + document.body.scrollTop - document.body.clientTop
    };
  }
}

/**
 * Calculates an object with the x and y coordinates of the given object
 * 
 * @param object
 *            the object of which the coordinates to be calculated
 * 
 * @return an object with x and y coordinates
 */
function getObjectPosition(object) {
  var left = 0;
  var top = 0;

  while (object.offsetParent) {

    left += object.offsetLeft;
    top += object.offsetTop;

    object = object.offsetParent;
  }

  left += object.offsetLeft;
  top += object.offsetTop;

  return {
      x : left,
      y : top
  };
}

I hope this can help you. This works for me in IE, Firefox and Chrome.

Sign up to request clarification or add additional context in comments.

1 Comment

This is pretty much the same I'm currently doing. My problem seems to be that offsetParent fails at some point, so this function (or the one I was using before) returns NaN for the elements I'm using it on.
1

Alright, my problem was somewhere else. This is what I was doing to call the function:

var allPosts = document.getElementsByClassName('post-outer');

for (post in allPosts) {
   console.log('Post has position '+getPos(post));
}

You can tell I'm not so used to Javascript's recursive behavior in the for loop, so the following code actually fixes my issue:

var allPosts = document.getElementsByClassName('post-outer');

for (var i=0, len=allPosts.length; i<len; ++i ){
  console.log('Post position is '+getPos(allPosts[i]).y);
}

Thanks all for your help :-)

1 Comment

The Javascript 'in' keyword doesn't work like you used it in your first example. Change console.log('Post has position '+getPos(post)); to console.log('Post has position '+getPos(allPosts[post]));. The 'in' keyword iterates through each key on the object, rather than the values. That is why the second loop works and the first doesn't. Yep, it's pretty silly. Check out Underscore JS for a lightweight solution to Javascript silliness in general.
0

That does not work with absolute positioning because it does not factor in top and left (among other things).

I was going to rip out that part of code from jQuery and post it here, but it is too rooted. So I just have to recommend using jQuery! To do so, just have this in the markup (before any other script tags)...

<script type="text/javascript"
 src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

Once you have that referenced, you can get the position of an element so easily...

$(function() {
  var pos = $(".className").position();
  alert(pos.top + "\n" + pos.left);
});

1 Comment

This looks like a nice solution, unfortunately, I need to work with several elements that match a class, so I use getElementsByClassName and the elements returned do not heriate the position() method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.