
jQuery.scrollFixed = {
	remove: function( item )
	{
		// remove placeholder if present
		var placeholder = item.data( 'scrollFixedPlaceholder' );
		if( placeholder )
		{
			placeholder.remove();
			item.data( 'scrollFixedPlaceholder', null );
		}

		item.css( { 
			top: '',
			left: '',
			position: ''
		} );
	},
	
	scrollHandler: function()
	{
		jQuery('.scrollFixed').each( function( i, o )
		{
			var item = jQuery(o),
				position = item.data('scrollFixedOriginalPosition');
		
			if( typeof( position ) == 'undefined' )
			{
				position = item.position();;
				item.data( 'scrollFixedOriginalPosition', position );
			}
		
			var fixed = item.css( 'position' ) != 'static', // "fixed" or "absolute"
				// scrolling position
				scroll = {
					top: jQuery( document ).scrollTop(),
					left: jQuery( document ).scrollLeft()
				},
				// test if boundaries were hit
				bound = {
					top: scroll.top >= position.top,
					left: scroll.left >= position.left					
				},
				// test if any boundary was hit
				bounds = bound.top || bound.left;

			
			// item is fixed but within bounds
			if( fixed && !bounds )
			{
				jQuery.scrollFixed.remove( item );
				return true; // continue;
			}

			// item is out of bounds but not fixed yet, so create placeholde
			if( !fixed && bounds )
			{
				item.data( 'scrollFixedPlaceholder', item.clone().removeClass('scrollFixed').css( 'visibility', 'hidden' ).insertBefore( item ) );
			}
		
			// abort if bounds have not been hit
			else if( !fixed )
			{
				return true; // continue;
			}

			// offset to bounds
			var offset = {
				top: position.top - scroll.top,
				left: position.left - scroll.left
			};
		
			// ensure position on boundary
			offset.top = offset.top >= 0 ? offset.top : 0;
			offset.left = offset.left >= 0 ? offset.left : 0;
		
			// reposition
			item.css( {
				top:  offset.top + 'px',
				left: offset.left + 'px',
				position: 'fixed'
			} );
	
		} );
	}
};

jQuery( function()
{
	// bind scrollFixed's scrollHandler to document's scroll-event
	jQuery( window ).bind( 'scroll', jQuery.scrollFixed.scrollHandler );
	jQuery.scrollFixed.scrollHandler();
} );

// toggle elements to scrollFix or behave normally
jQuery.fn.scrollFixed = function()
{
	this.each( function( i, o ){
		jQuery.scrollFixed.remove( $(o) );
		$(o).toggleClass( 'scrollFixed' );
		jQuery.scrollFixed.scrollHandler();
	} );
};