/**
 * Copyright (c)2005-2007 Matt Kruse (javascripttoolbox.com)
 *
 * Dual licensed under the MIT and GPL licenses.
 * This basically means you can use this code however you want for
 * free, but don't claim to have written it yourself!
 * Donations always accepted: http://www.JavascriptToolbox.com/donate/
 *
 * Please do not link to the .js files on javascripttoolbox.com from
 * your site. Copy the files locally to your server instead.
 *
 */
window.kPosition = (function() {
	// Resolve a string identifier to an object
	// ========================================
	function resolveObject(s) {
		if (document.getElementById && document.getElementById(s)!=null) {
			return document.getElementById(s);
		}
		else if (document.all && document.all[s]!=null) {
			return document.all[s];
		}
		else if (document.anchors && document.anchors.length && document.anchors.length>0 && document.anchors[0].x) {
			for (var i=0; i<document.anchors.length; i++) {
				if (document.anchors[i].name==s) {
					return document.anchors[i]
				}
			}
		}
	}

	var pos = {};
	pos.$VERSION = 1.0;

/** @function Position.set (object, left, top) : Boolean
* @purpose :: Set the position of an object to a certain location on the screen. If the object is not already position:absolute, it will be made so in order to be moved. Returns true if successful, else false.
* @param :: Object as Object or String [required] An object whose position should be set. This can be either a reference to the object itself, or a string which will be resolved as an element ID or using document.all or anchor name.
* @param :: left as Object or Number [required] If passed an Object as the second parameter, the method assumes that this object will contain 'left' and 'top' properties and use those coordinates. If a Number is passed, it is the number of pixels from the left side of the screen to position the object.
* @param :: top as Number [not required] If left is a Number, then top should also be a number, specifying the number of pixels from the top of the screen to position the object.
* @return :: Boolean
*/
	pos.set = function(o,left,top) {
		if (typeof(o)=="string") {
			o = resolveObject(o);
		}
		if (o==null || !o.style) {
			return false;
		}

		// If the second parameter is an object, it is assumed to be the result of getPosition()
		if (typeof(left)=="object") {
			var pos = left;
			left = pos.left;
			top = pos.top;
		}

		o.style.left = left + "px";
		o.style.top = top + "px";
		return true;
	};

/** @function Position.get (object) : Object
* @purpose :: Get the top and left position of an object on the page, relative to the root element (HTML or BODY) tag. This can then be used to position another object relative to the first.
* @param :: object as object or string [Required] An object whose position should be calculated. This can be either a reference to the object itself, or a string which will be resolved as an element ID or using document.all or anchor name.
* @return :: Object with properties: 'left' and 'top' to specify position, and 'width' and 'height' to specify the dimensions of the object's full box (including padding and borders)
*/
	pos.get = function(o) {
		var fixBrowserQuirks = true;
			// If a string is passed in instead of an object ref, resolve it
		if (typeof(o)=="string") {
			o = resolveObject(o);
		}

		if (o==null) {
			return null;
		}

		var left = 0;
		var top = 0;
		var width = 0;
		var height = 0;
		var parentNode = null;
		var offsetParent = null;


		offsetParent = o.offsetParent;
		var originalObject = o;
		var el = o; // "el" will be nodes as we walk up, "o" will be saved for offsetParent references
		while (el.parentNode!=null) {
			el = el.parentNode;
			if (el.offsetParent==null) {
			}
			else {
				var considerScroll = true;
				/*
				In Opera, if parentNode of the first object is scrollable, then offsetLeft/offsetTop already
				take its scroll position into account. If elements further up the chain are scrollable, their
				scroll offsets still need to be added in. And for some reason, TR nodes have a scrolltop value
				which must be ignored.
				*/
				if (fixBrowserQuirks && window.opera) {
					if (el==originalObject.parentNode || el.nodeName=="TR") {
						considerScroll = false;
					}
				}
				if (considerScroll) {
					if (el.scrollTop && el.scrollTop>0) {
						top -= el.scrollTop;
					}
					if (el.scrollLeft && el.scrollLeft>0) {
						left -= el.scrollLeft;
					}
				}
			}
			// If this node is also the offsetParent, add on the offsets and reset to the new offsetParent
			if (el == offsetParent) {
				left += o.offsetLeft;
				if (el.clientLeft && el.nodeName!="TABLE") {
					left += el.clientLeft;
				}
				top += o.offsetTop;
				if (el.clientTop && el.nodeName!="TABLE") {
					top += el.clientTop;
				}
				o = el;
				if (o.offsetParent==null) {
					if (o.offsetLeft) {
						left += o.offsetLeft;
					}
					if (o.offsetTop) {
						top += o.offsetTop;
					}
				}
				offsetParent = o.offsetParent;
			}
		}


		if (originalObject.offsetWidth) {
			width = originalObject.offsetWidth;
		}
		if (originalObject.offsetHeight) {
			height = originalObject.offsetHeight;
		}

		return {'left':left, 'top':top, 'width':width, 'height':height,'x':left, 'y':top, 'w':width, 'h':height};
	};

/** @function Position.getCenter (object) : Object
* @purpose :: Similar to Position.get(), but this method returns the coordinates
*		of the center of the object, rather than the upper left corner.
* @param :: object as Object or String [required] An object whose position should
*		be calculated. This can be either a reference to the object itself, or a string which
*		will be resolved as an element ID or using document.all or anchor name.
* @return :: Object with properties: 'left' and 'top' to specify position, and 'width'
*		and 'height' to specify the dimensions of the object's full box (including padding and borders)
*/
	pos.getCenter = function(o) {
		var c = this.get(o);
		if (c==null) { return null; }
		c.left = c.left + (c.width/2);
		c.top = c.top + (c.height/2);
		return c;
	};

	return pos;
})();
window.getAnchorPosition = function(o){
	window.kPosition.get(o);
}
