views:

227

answers:

3

Hi all,

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?

A: 

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"&gt;&lt;/script&gt;

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);
});
Josh Stodola
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.
Raphink
@Raphink See the latest update
Josh Stodola
A: 

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.

eitch
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.
Raphink
A: 

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 :-)

Raphink