var fx = new Object();

fx.Base = function(){};

fx.Base.prototype = {

	setOptions: function(options) {

	this.options = {

		duration: 500,

		onComplete: '',

		transition: fx.sinoidal

	}

	Object.extend(this.options, options || {});

	},



	step: function() {

		var time  = (new Date).getTime();

		if (time >= this.options.duration+this.startTime) {

			this.now = this.to;

			clearInterval (this.timer);

			this.timer = null;

			if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);

		}

		else {

			var Tpos = (time - this.startTime) / (this.options.duration);

			this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;

		}

		this.increase();

	},



	custom: function(from, to) {

		if (this.timer != null) return;

		this.from = from;

		this.to = to;

		this.startTime = (new Date).getTime();

		this.timer = setInterval (this.step.bind(this), 13);

	},



	hide: function() {

		this.now = 0;

		this.increase();

	},



	clearTimer: function() {

		clearInterval(this.timer);

		this.timer = null;

	}

}



fx.Layout = Class.create();

fx.Layout.prototype = Object.extend(new fx.Base(), {

	initialize: function(el, options) {

		this.el = $(el);

		this.el.style.overflow = "hidden";

		this.iniWidth = this.el.offsetWidth;

		this.iniHeight = this.el.offsetHeight;

		this.setOptions(options);

	}

});



fx.Height = Class.create();

Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {	

	increase: function() {

		this.el.style.height = this.now + "px";

	},



	toggle: function() {

		if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);

		else this.custom(0, this.el.scrollHeight);

	}

});



fx.Width = Class.create();

Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {	

	increase: function() {

		this.el.style.width = this.now + "px";

	},



	toggle: function(){

		if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);

		else this.custom(0, this.iniWidth);

	}

});



fx.Opacity = Class.create();

fx.Opacity.prototype = Object.extend(new fx.Base(), {

	initialize: function(el, options) {

		this.el = $(el);

		this.now = 1;

		this.increase();

		this.setOptions(options);

	},



	increase: function() {

		if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;

		this.setOpacity(this.now);

	},

	

	setOpacity: function(opacity) {

		if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";

		else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";

		if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";

		this.el.style.opacity = opacity;

	},



	toggle: function() {

		if (this.now > 0) this.custom(1, 0);

		else this.custom(0, 1);

	}

});



fx.sinoidal = function(pos){

	return ((-Math.cos(pos*Math.PI)/2) + 0.5);

}

fx.linear = function(pos){

	return pos;

}

fx.cubic = function(pos){

	return Math.pow(pos, 3);

}

fx.circ = function(pos){

	return Math.sqrt(pos);

}



fx.Scroll = Class.create();

fx.Scroll.prototype = Object.extend(new fx.Base(), {

	initialize: function(options) {

		this.setOptions(options);

	},



	scrollTo: function(el){

		var dest = Position.cumulativeOffset($(el))[1];

		var client = window.innerHeight || document.documentElement.clientHeight;

		var full = document.documentElement.scrollHeight;

		var top = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;

		if (dest+client > full) this.custom(top, dest - client + (full-dest));

		else this.custom(top, dest);

	},



	increase: function(){

		window.scrollTo(0, this.now);

	}

});



fx.Text = Class.create();

fx.Text.prototype = Object.extend(new fx.Base(), {

	initialize: function(el, options) {

		this.el = $(el);

		this.setOptions(options);

		if (!this.options.unit) this.options.unit = "em";

	},



	increase: function() {

		this.el.style.fontSize = this.now + this.options.unit;

	}

});



fx.Combo = Class.create();

fx.Combo.prototype = {

	setOptions: function(options) {

		this.options = {

			opacity: true,

			height: true,

			width: false

		}

		Object.extend(this.options, options || {});

	},



	initialize: function(el, options) {

		this.el = $(el);

		this.setOptions(options);

		if (this.options.opacity) {

			this.el.o = new fx.Opacity(el, options);

			options.onComplete = null;

		}

		if (this.options.height) {

			this.el.h = new fx.Height(el, options);

			options.onComplete = null;	

		}

		if (this.options.width) this.el.w = new fx.Width(el, options);

	},

	

	toggle: function() { this.checkExec('toggle'); },



	hide: function(){ this.checkExec('hide'); },

	

	clearTimer: function(){ this.checkExec('clearTimer'); },

	

	checkExec: function(func){

		if (this.el.o) this.el.o[func]();

		if (this.el.h) this.el.h[func]();

		if (this.el.w) this.el.w[func]();

	},

	

	resizeTo: function(hto, wto) {

		if (this.el.h && this.el.w) {

			this.el.h.custom(this.el.offsetHeight, this.el.offsetHeight + hto);

			this.el.w.custom(this.el.offsetWidth, this.el.offsetWidth + wto);

		}

	},



	customSize: function(hto, wto) {

		if (this.el.h && this.el.w) {

			this.el.h.custom(this.el.offsetHeight, hto);

			this.el.w.custom(this.el.offsetWidth, wto);

		}

	}

}



fx.Accordion = Class.create();

fx.Accordion.prototype = {

	setOptions: function(options) {

		this.options = {

			delay: 100,

			opacity: false

		}

		Object.extend(this.options, options || {});

	},



	initialize: function(togglers, elements, options) {

		this.elements = elements;

		this.setOptions(options);

		var options = options || '';

		elements.each(function(el, i){

			options.onComplete = function(){

				if (el.offsetHeight > 0) el.style.height = '1%';

			}

			el.fx = new fx.Combo(el, options);

			el.fx.hide();

		});



		togglers.each(function(tog, i){

			tog.onclick = function(){

				this.showThisHideOpen(elements[i]);

			}.bind(this);

		}.bind(this));

	},



	showThisHideOpen: function(toShow){

		if (toShow.offsetHeight == 0) setTimeout(function(){this.clearAndToggle(toShow);}.bind(this), this.options.delay);

		this.elements.each(function(el, i){

			if (el.offsetHeight > 0 ) this.clearAndToggle(el);



		}.bind(this));

	},



	clearAndToggle: function(el){

		el.fx.clearTimer();

		el.fx.toggle();

	}

}