Getting Coordinates Relative To The Viewport In JavaScript

When you are doing certain calculations, sometimes it’s nice to work with DOM elements using one coordinate system. Those familiar with Adobe Flash can think of this as the (global) Stage coordinates of a Display object. Anyway, one of the features I miss in ActionScript is the localToGlobal() and globalToLocal() methods available on Display objects. So, I set out to find comparable functionality in JavaScript. Unfortunately, the features that’ll get you there are not supported widely enough to be of much use to me yet. The features I am writing about are getClientRects() and getBoundingClientRect(). When ( and if ) they are implemented widely, this little utility script I’ve written will be happily deprecated.

So how’s it work? Well, you pass it a DOM element and it will return to you an object ( representing a rectangle: top, right, bottom, left ) containing coordinates where that element is positioned relative to the top left corner of the view-port. Those familiar to the ActionScript equivalent will notice that the arguments and return values are not exactly the same. I prefer passing in the element that you want converted as opposed to the Points representing the local coordinates. I also chose to return the coordinates of in rectangle format rather than the converted (x,y) Point since I thought it would be more useful to return all the corner values. Be mindful though about how often/successively you execute this function since it contains recursion.

Demo: Example

Tested:
OS X: FireFox 3.5, Safari 4, Opera 9.64
Windows: IE8, FireFox 3.5, Safari 3.1.1, Chrome 2

Source:
local-to-global.js

localToGlobal: function( _el ) {
					var    
					   target = _el, 
					   target_width = target.offsetWidth, 
					   target_height = target.offsetHeight,
					   target_left = target.offsetLeft,
					   target_top = target.offsetTop,
					   gleft = 0, 
					   gtop = 0,
					   rect = {};
					  
					var moonwalk = function( _parent ) {
						if (!!_parent) {
							gleft += _parent.offsetLeft;
							gtop += _parent.offsetTop;
							moonwalk( _parent.offsetParent );
						} else {
							return rect = { 
							     top: target.offsetTop + gtop, 
								 left: target.offsetLeft + gleft, 
								 bottom: (target.offsetTop + gtop) + target_height, 
								 right: (target.offsetLeft + gleft) + target_width 
						    };
						}
					};
				    moonwalk( target.offsetParent );
					return rect;
				}