/*	Class: FloatingContainer		Revision $Id: FloatingContainer.js 10590 2009-12-16 21:13:53Z evan $		Floats an element between the upper and lower bounds of a container element as the page scrolls.		Note that the floating element does not actually have to be a child of the container, as it will		simply float vertically between the horizontal coordinates of the container.	Mootools Dependencies (v1.2dev):		Core		Class.Extras		DomReady		Element.Event		Element.Dimensions		Fx.Tween*/var FloatingContainer = new Class({	Implements: [Options, Events],	/*		Group: Options			container - An element, or a string id of an element, within which to restrict movement of the floater element.			floater - An element, or a string id of an element, that will be floated within the bounds of the container element.			margin - Optional number of pixels to pad between the floater and the bounds of the container.  Defaults to 0.			paddingTop - Optional number of pixels to pad floater from top of container.  Defaults to 0.			floatOnInit - Optional boolean indicating whether to start floating on class instantiation if true, or wait for the user to scroll if false.  Defaults to true.	*/	options: {		container:   null,		floater:     null,		margin:      0,		paddingTop:   0,		floatOnInit: true	},	/* Group: Events */	/*		Event: onFloat			Fires immediately after floating action is triggered (on page scroll, for example).  Passes a			single parameter, the vertical offset to which the element is floating.		(start example)		floater.addEvent('onFloat', function(offset){ alert('Floating to ' + offset); });		(end example)	*/	onFloat: $empty,	/* Group: Functions */	/*		Constructor: initialize			Initializes a new instance of the FloatingContainer class, and attaches to the browser's scroll event.		(start example)		// add a FloatingContainer as soon as dom tree is constructed		window.addEvent('domready', function(){			new FloatingContainer({				container: $('page-frame'),				floater: 'floating-frame',				margin: 20,				onFloat: function(offset){ alert('Floating to ' + offset); }			});		});		(end example)		Parameters:			An object containing the <Options> for the new class instance.		Returns:			An instance of this class.	*/	initialize: function(options) {		// accept given options		this.setOptions(options);		// if stringified ids given, retrieve their elements		if(this.options.container != null)			if($type(this.options.container) != 'element')				this.options.container = $(this.options.container);		if(this.options.floater != null)			if($type(this.options.floater) != 'element')				this.options.floater = $(this.options.floater);		// automatically attach to window.scroll event		window.addEvent('scroll', this.delayed.bind(this));		// initialize floating on initialization		if(this.options.floatOnInit == true)			this.float();	},	/* on scroll, delay a float by however many milliseconds, to avoid jumpiness */	delayed: function() {		$clear(this.timer);		this.timer = this.float.delay(200, this);	},	timer: null,	/* we'll attach this to the scroll event to reposition the floater */	float: function() {		// determine relative or absolute offsets of any parents, grandparents, etc		var ancestorOffset = 0;		this.options.floater.getParents().each(function(ancestor){			var ancestorType = ancestor.getStyle('position');			if(ancestorType.match( /(absolute|relative)/i )) {				if(ancestorOffset == 0)					ancestorOffset = ancestor.getCoordinates().top;			}		});				// get top and bottom bounds of the container		var containerCoords = this.options.container.getCoordinates();		var topBound = parseInt(containerCoords.top) + parseInt(this.options.paddingTop);		var bottomBound = containerCoords.bottom			? parseInt(containerCoords.bottom)			: parseInt(containerCoords.top) + parseInt(containerCoords.height)		;		// get height of the floater		var floaterCoords = this.options.floater.getCoordinates();		var floaterHeight = parseInt(floaterCoords.height);		// get scrolled position of the page		var pageOffset = parseInt( window.getScroll().y );		// correct for offset of any positioned ancestors		if(ancestorOffset > 0) {			topBound -= ancestorOffset;			bottomBound -= ancestorOffset;			pageOffset -= ancestorOffset;		}		// get padding margin		var margin = parseInt(this.options.margin);		// initialize a null offset		var floatOffset = null;		// if top of page is not past upper bound, float to upper bound		if(pageOffset <= topBound + margin)			floatOffset = topBound + margin;		// if top of page is past lower bound + floater height, float to lower bound		else if(pageOffset > (bottomBound - margin - floaterHeight))			// but only if floating to lower bound doesnt float past upper bound			floatOffset = (topBound + floaterHeight + margin <= bottomBound)				? (bottomBound - margin - floaterHeight)				: null			;		// otherwise float to top of page		else			floatOffset = pageOffset + margin;		// float to our calculated offset		if(!isNaN(floatOffset))			this.options.floater.tween('top', floatOffset);		// or set null offset		else			floatOffset = null;		// fire event, passing offset		this.fireEvent("onFloat", floatOffset);	}});