﻿/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* $LastChangedDate: 2007-12-20 08:46:55 -0600 (Thu, 20 Dec 2007) $
* $Rev: 4259 $
*
* Version: 1.2
*
* Requires: jQuery 1.2+
*/

(function($) {

	$.dimensions = {
		version: '1.2'
	};

	// Create innerHeight, innerWidth, outerHeight and outerWidth methods
	$.each(['Height', 'Width'], function(i, name) {

		// innerHeight and innerWidth
		$.fn['inner' + name] = function() {
			if (!this[0]) return;

			var torl = name == 'Height' ? 'Top' : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right

			return this.is(':visible') ? this[0]['client' + name] : num(this, name.toLowerCase()) + num(this, 'padding' + torl) + num(this, 'padding' + borr);
		};

		// outerHeight and outerWidth
		$.fn['outer' + name] = function(options) {
			if (!this[0]) return;

			var torl = name == 'Height' ? 'Top' : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right

			options = $.extend({ margin: false }, options || {});

			var val = this.is(':visible') ?
				this[0]['offset' + name] :
				num(this, name.toLowerCase())
					+ num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
					+ num(this, 'padding' + torl) + num(this, 'padding' + borr);

			return val + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
		};
	});

	// Create scrollLeft and scrollTop methods
	$.each(['Left', 'Top'], function(i, name) {
		$.fn['scroll' + name] = function(val) {
			if (!this[0]) return;

			return val != undefined ?

			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo(
						name == 'Left' ? val : $(window)['scrollLeft'](),
						name == 'Top' ? val : $(window)['scrollTop']()
					) :
					this['scroll' + name] = val;
			}) :

			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] ||
					$.boxModel && document.documentElement['scroll' + name] ||
					document.body['scroll' + name] :
				this[0]['scroll' + name];
		};
	});

	$.fn.extend({
		position: function() {
			var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;

			if (elem) {
				// Get *real* offsetParent
				offsetParent = this.offsetParent();

				// Get correct offsets
				offset = this.offset();
				parentOffset = offsetParent.offset();

				// Subtract element margins
				offset.top -= num(elem, 'marginTop');
				offset.left -= num(elem, 'marginLeft');

				// Add offsetParent borders
				parentOffset.top += num(offsetParent, 'borderTopWidth');
				parentOffset.left += num(offsetParent, 'borderLeftWidth');

				// Subtract the two offsets
				results = {
					top: offset.top - parentOffset.top,
					left: offset.left - parentOffset.left
				};
			}

			return results;
		},

		offsetParent: function() {
			var offsetParent = this[0].offsetParent;
			while (offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static'))
				offsetParent = offsetParent.offsetParent;
			return $(offsetParent);
		}
	});

	function num(el, prop) {
		return parseInt($.curCSS(el.jquery ? el[0] : el, prop, true)) || 0;
	};

})(jQuery);