/***********************************
** floatable.js
**
** for motozine, relies on prototype
** may want to add a scriptaculous 
** Effect.move type effect to this
************************************/
var Floatables = {
	floatables: [],
	onScroll: false,
	onResize: false,

	register: function(floatable) {
		if (!this.floatables.length) {
			this.setHandlers();
		}
		this.floatables.push(floatable);
		this.scrollFloatable(floatable);
	},

	unregister: function(floatable) {
		var newFloatables = [];
		for (var i=0;i<this.floatables.length;i++) {
			if (this.floatables[i] != floatable) {
				newFloatables.push(this.floatables[i]);
			}
		}

		this.floatables = newFloatables;
		if (!this.floatables.length) {
			this.unsetHandlers();
		}

		return true;
	},

	scrollHandler: function(event) {
		for (var i=0;i<this.floatables.length;i++) {
			if (this.floatables[i].checkOverlap && !this.checkOverlap(this.floatables[i])) {
				this.scrollFloatable(this.floatables[i]);
			}
		}
	},

	resizeHandler: function(event) {
		this.scrollHandler(event);

		return true;
	},
	
	scrollFloatable: function(floatable) {
		var scrollTop = this.getScrollTop();
		if (!floatable.transition) {
			floatable.element.style.top = Math.max((scrollTop-floatable.threshold+floatable.startPosition), floatable.startPosition) + 'px';
		} else {
			var options = (floatable.transitionEffect) ? {transition: transitionEffect}:{};
			var moveBy = (scrollTop - floatable.threshold) - parseInt(floatable.element.style.top);
			moveBy = (parseInt(floatable.element.style.top) + moveBy > floatable.startPosition) ? moveBy:0;
			new Effect.MoveBy(floatable.element, moveBy, 0, options);
		}
		return true;
	},

	setHandlers: function() {
		this.onScroll = this.scrollHandler.bindAsEventListener(this);
		this.onResize = this.resizeHandler.bindAsEventListener(this);
		Event.observe(window, 'scroll', this.onScroll);
		Event.observe(window, 'resize', this.onResize);

		return true;
	},

	unsetHandlers: function() {
		Event.stopObserving(window, 'scroll', this.onScroll);
		Event.stopObserving(window, 'resize', this.onResize);
		this.onResize = false;
		this.onScroll = false;

		return true;
	},
	
	getScrollTop: function() {
		var scrollTop = (document.documentElement.scrollTop) ? document.documentElement.scrollTop:document.body.scrollTop;
		return scrollTop;
	},

	checkOverlap: function(floatable) {
		if (floatable.element.offsetHeight > this.getWindowInner()) {
			return true;
		} else {
			return false;
		}
	},

	getWindowInner: function() {
		var windowHeight = (document.all) ? document.body.clientHeight:window.innerHeight;
		return windowHeight;
	}
};

var Floatable = Class.create();
Floatable.prototype = {
	element: false,
	threshold: 0,
	startPosition: 0,
	checkOverlap: true,
	transition: false,
	transitionEffect: false,

	initialize: function(element) {
		var defaults = {
			threshold: 0,
			checkOverlap: true,
			transition: false,
			transitionEffect: false
		};
		var options = (arguments[1]) ? arguments[1]:{};
		Object.extend(defaults, options);
		defaults.transition = (defaults.transitionEffect) ? true:defaults.transition;

		//set the floatable element
		this.element = $(element);
		
		if (Element.getStyle(this.element, 'position') != 'absolute') {
			this.relativize(this.element);
		}
		
		//assumes top is set in PX for now
		this.element.style.top = (this.element.style.top) ? this.element.style.top:'0px';
		this.startPosition = parseInt(this.element.style.top);

		//set the threshold in pixels before we start to mess with the positioning
		this.checkOverlap = defaults.checkOverlap;
		this.setThreshold(defaults.threshold);
		this.transition = defaults.transition;
		this.transitionEffect = defaults.transitionEffect;

		//register the object with the helper object
		Floatables.register(this);

		return true;
	},

	destroy: function() {
		this.element.style.top = this.startPosition + 'px';
		if (this.element.style.position != 'absolute') {
			this.unrelativize(this.element);
		}
		this.threshold = 0;
		this.element = false;
		Floatables.unregister(this);

		return true;
	},

	relativize: function(element) {
		$(element).style.position = 'relative';
		return true;
	},

	unrelativize: function(element) {
		$(element).style.position = '';
		return true;
	},

	setThreshold: function(threshold) {
		this.threshold = threshold;
		Floatables.scrollFloatable(this);
	}
};
