/*
moo.fx pack, effects extensions for moo.fx.
by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE
for more info visit (http://moofx.mad4milk.net).
Wednesday, November 16, 2005
v1.0.4
*/

//text size modify, now works with pixels too.
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;
	}
});

//composition effect, calls Width and Height alltogheter
fx.Resize = Class.create();
fx.Resize.prototype = {
	initialize: function(el, options) {
		this.h = new fx.Height(el, options);
		if (options) options.onComplete = null;
		this.w = new fx.Width(el, options);
		this.el = $(el);
	},

	toggle: function(){
		this.h.toggle();
		this.w.toggle();
	},

	modify: function(hto, wto) {
		this.h.custom(this.el.offsetHeight, this.el.offsetHeight + hto);
		this.w.custom(this.el.offsetWidth, this.el.offsetWidth + wto);
	},

	custom: function(hto, wto) {
		this.h.custom(this.el.offsetHeight, hto);
		this.w.custom(this.el.offsetWidth, wto);
	},

	hide: function(){
		this.h.hide();
		this.w.hide();
	}
}

//composition effect, calls Opacity and (Width and/or Height) alltogheter
fx.FadeSize = Class.create();
fx.FadeSize.prototype = {
	initialize: function(el, options) {
		this.el = $(el);
		this.el.o = new fx.Opacity(el, options);
		if (options) options.onComplete = null;
		this.el.h = new fx.Height(el, options);
		this.el.w = new fx.Width(el, options);
	},

	toggle: function() {
		this.el.o.toggle();
		for (var i = 0; i < arguments.length; i++) {
			if (arguments[i] == 'height') this.el.h.toggle();
			if (arguments[i] == 'width') this.el.w.toggle();
		}
	},

	hide: function(){
		this.el.o.hide();
		for (var i = 0; i < arguments.length; i++) {
			if (arguments[i] == 'height') this.el.h.hide();
			if (arguments[i] == 'width') this.el.w.hide();
		}
	}
}

//intended to work with arrays.
var Multi = new Object();
Multi = function(){};
Multi.prototype = {
	initialize: function(elements, options){
		this.options = options;
		this.el = this.getElementsFromArray(elements);
		for (i=0;i<this.el.length;i++){
			this.effect(this.el[i]);
		}
	},

	getElementsFromArray: function(array) {
		var elements = new Array();
		for (i=0;i<array.length;i++) {
			elements.push($(array[i]));
		}
		return elements;
	}
}

//Fadesize with arrays
fx.MultiFadeSize = Class.create();
fx.MultiFadeSize.prototype = Object.extend(new Multi(), {
	effect: function(el){
		el.fs = new fx.FadeSize(el, this.options);
	},

	showThisHideOpen: function(el, delay, mode){
		for (i=0;i<this.el.length;i++){
			if (this.el[i].offsetHeight > 0 && this.el[i] != el && this.el[i].h.timer == null && el.h.timer == null){
				this.el[i].fs.toggle(mode);
				setTimeout(function(){el.fs.toggle(mode);}.bind(el), delay);
			}

		}
	},

	hide: function(el, mode){
		el.fs.hide(mode);
	}
});

var Remember = new Object();
Remember = function(){};
Remember.prototype = {
	initialize: function(el, options){
		this.el = $(el);
		this.days = 365;
		this.options = options;
		this.effect();
		var cookie = this.readCookie();
		if (cookie) {
			this.fx.now = cookie;
			this.fx.increase();
		}
	},

	//cookie functions based on code by Peter-Paul Koch
	setCookie: function(value) {
		var date = new Date();
		date.setTime(date.getTime()+(this.days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
		document.cookie = this.el+this.el.id+this.prefix+"="+value+expires+"; path=/";
	},

	readCookie: function() {
		var nameEQ = this.el+this.el.id+this.prefix + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return false;
	},

	custom: function(from, to){
		if (this.fx.now != to) {
			this.setCookie(to);
			this.fx.custom(from, to);
		}
	}
}

fx.RememberHeight = Class.create();
fx.RememberHeight.prototype = Object.extend(new Remember(), {
	effect: function(){
		this.fx = new fx.Height(this.el, this.options);
		this.prefix = 'height';
	},

	toggle: function(){
		if (this.el.offsetHeight == 0) this.setCookie(this.el.scrollHeight);
		else this.setCookie(0);
		this.fx.toggle();
	},

	resize: function(to){
		this.setCookie(this.el.offsetHeight+to);
		this.fx.custom(this.el.offsetHeight,this.el.offsetHeight+to);
	},

	hide: function(){
		if (!this.readCookie()) {
			this.fx.hide();
		}
	}
});

fx.RememberText = Class.create();
fx.RememberText.prototype = Object.extend(new Remember(), {
	effect: function(){
		this.fx = new fx.Text(this.el, this.options);
		this.prefix = 'text';
	}
});


//use to attach effects without using js code, just classnames and rel attributes.
ParseClassNames = Class.create();
ParseClassNames.prototype = {
	initialize: function(options){
		var babies = document.getElementsByTagName('*') || document.all;
		for (var i = 0; i < babies.length; i++) {
			var el = babies[i];
			//attach the effect, from the classNames;
			var effects = this.getEffects(el);
			for (var j = 0; j < effects.length; j++) {
				if (j == 1 && options) options.onComplete = null;
				el[effects[j]+"fx"] = new fx[effects[j]](el, options);
			}
			//execute methods, from rel
			if (el.rel) {
				el.crel = el.rel.split(' ');
				if (el.crel[0].indexOf("fx_") > -1) {
					var event = el.crel[0].replace('fx_', '');
					var tocompute = this.getEffects($(el.crel[1]));
					el["on"+event] = function(){
						for (var f = 0; f < tocompute.length; f++) {
							$(this.crel[1])[tocompute[f]+"fx"][this.crel[2] || "toggle"](this.crel[3] || null, this.crel[4] || null);
						}
					}
				}
			}
		}
	},

	getEffects: function(el){
		var effects = new Array();
		var css = el.className.split(' ');
		for (var i = 0; i < css.length; i++) {
			if (css[i].indexOf('fx_') > -1) {
				var effect = css[i].replace('fx_', '');
				effects.push(effect);
			}
		}
		return effects;
	}
}