// Loosely based on http://jqueryfordesigners.com/fixed-floating-elements/
(function($){
	$(document).ready(function(){
		// Feature detection for position:fixed, courtesy of http://yura.thinkweb2.com/cft/#IS_POSITION_FIXED_SUPPORTED
		$.support.positionFixed = null;
		if (document.createElement)
		{
			var el = document.createElement("div");
			if (el && el.style)
			{
				el.style.position = "fixed";
				el.style.top = "10px";
				var root = document.body;
				if (root && root.appendChild && root.removeChild)
				{
					root.appendChild(el);
					$.support.positionFixed = (el.offsetTop === 10);
					root.removeChild(el);
				}
			}
		}
	});
	
	$.fn.stickyfloat = function(options)
	{
		return this.each(function(){ 
			// Artificial parent for forcing minimum dimensions
			$(this).wrap('<div>');
				
			init_sticky_float(
				$(this), options
			);
		});
	};
	
	$.fn.stickyfloat_children = function(options)
	{
		return this.each(function(){ 
		
			// We want to sticky all the children as one entity, 
			//	so create a surrogate div containing them all
			$(this).children().wrapAll('<div>');
			var $surrogate = $(this).children();
			
			// the surrogate div will take over the top margin
			var top_margin = $(this).css('margin-top');
			$(this).css('margin-top', 0);
			$surrogate.css('margin-top', top_margin)
			
			// proceed to sticky the surrogate, using the real container
			//	as the parent for size reservation
			init_sticky_float(
				$surrogate, options
			);
			
		});
	};
	
	function init_sticky_float($sticky_element, options)
	{
		var settings = $.extend(
			{
				space_reserved_below: 0
			},
			options
		);
		
		var initial_top = $sticky_element.offset().top
			- parseFloat($sticky_element.css('marginTop').replace(/auto/, 0));
		
		// As soon as we make the element absolutely positioned, it will drop
		//	out of flow, so we need to force the dimensions on its parent
		$sticky_element.parent()
			.height( $sticky_element.outerHeight(true) )
			.width( $sticky_element.outerWidth(true) );         
			
		// Similarly, and variable width elements currently constrained by their parent
		//	will lose that constraint when they drop out of flow
		$sticky_element.css( 'width', $sticky_element.width() );
			  
		$(window).bind(
			'scroll',
			function (event) {
				// how far down is the window scrolled?
				var y = $(window).scrollTop();
				
				var current_base = y + $sticky_element.outerHeight(true); 
				var lowest_base = $(document).height() - settings.space_reserved_below;
				
				if (
					current_base > lowest_base
				)
				{
					// if the object is too big to fit on the screen, 
					//	or is bumping into the reserved footer space
					//	let it scroll
					$sticky_element
						.css('position', 'absolute')
						.css('top', lowest_base - $sticky_element.outerHeight(true));
				}
				else if (y >= initial_top)
				{
					// if above the initial top, set fixed
					if ( $.support.positionFixed )
					{
						$sticky_element
							.css('position', 'fixed')
							.css('top', 0);
					}
					// Give IE6 a jittery approximation of fixed-ness
					else
					{
						$sticky_element
							.css('position', 'absolute')
							.css('top', y);
					}
				}
				else
				{
					// else set absolute
					$sticky_element
						.css('position', 'absolute')
						.css('top', initial_top);
				}
			}
		).trigger('scroll');       
	}
})(jQuery);

