/*************************************************************************************
************************************             *************************************
************************************ ClassFinder *************************************
************************************             *************************************
**************************************************************************************/


var classFinder = new Class({

	//implements
	Implements: [Options],

	//options
	options: {
		cf_height: '370px',
		cf_tab_height: '35px',
		deployState: false,
		speed: 700,
		delay: 0,
		xPos: 0
	},
	
	//initialization
	initialize: function(container, options) {
		//set options
		this.setOptions(options);
		cfFx = new Fx.Morph($('classfinder'), {duration: this.options.speed, transition: Fx.Transitions.Expo.easeOut, wait: false });	
		containerFx = new Fx.Morph(container, {duration:10, wait:false});
			
	},


	deploy: function() {
		$('cf_container').setStyle('height', this.options.cf_height);
		$('cf_submit').setStyle('display','block');
		$('cf_cancel').setStyle('display','block');
		$('cf_prompt').setStyle('display','none');
		cfFx.start.delay(this.options.delay, cfFx, {'margin-top':this.options.xPos } );
		this.slideBlocks();
		this.options.deployState = true;
	},
	

	retract: function() {
		$('cf_submit').setStyle('display','none');
		$('cf_cancel').setStyle('display','none');
		$('cf_prompt').setStyle('display','block');
		var cf_margin = -(this.options.cf_height.toInt() - this.options.cf_tab_height.toInt());
		containerFx.start.delay(650, containerFx, {'height': this.options.cf_tab_height });
		cfFx.start.delay(this.options.delay, cfFx, {'margin-top':cf_margin } );
		this.options.deployState = false;
	},
	
	toggle: function() {
		if (this.options.deployState) {
			this.retract();
		} else {
			this.deploy();
		}	
	},	
	
		
	slideBlocks: function () 
		
	{
	
		var timer = 0;
		var sliders = $$('#classfinder dl');		
		var slidersfxs = [];
		
		
		sliders.each(function(el, i)
								 
		{
		
			timer += 200;
			slidersfxs[i] = new Fx.Morph(el, {duration: 450, transition: Fx.Transitions.Quart.easeOut, wait: false });		
			slidersfxs[i].start.delay(timer, slidersfxs[i], {'margin-top':['8px'] } );

		}, this);


	}
	
	

/*
		var contentFade = new Fx.Morph('rightdouble', {duration:600, wait:false});
		container.start.delay(1000, contentFade, {'opacity': rdOp });
*/

			
	});
											




/*************************************************************************************
*************************************          ***************************************
************************************* MooBlend ***************************************
*************************************          ***************************************
**************************************************************************************/

/* 
	@example $('li').colorize('#ff1313', '#000000', [1,1,1],"color");
 	@desc sets the css tag "color" for all li elements, changing the 
 	color from #ff1313 to #000000 in alinear way
	colorizes all matching elements, using type-specification for each color:
			1: linear
			2: trigonometrical 
			3: accidentally
			4: ordered accident
	* @param startColor: starting Color in hex or as a rgb-array
	* @param endColor: ending Color in hex or as a rgb-array	
	* @param type: array for each color (=> length: 3) to specify the color-algorithm
	* @param cssTag: specifies, which css tag should be changed
*/

var mooBlend = new Class({

 

	
	//implements
	Implements: [Options],

	//options
	options: {
		startColor: '#000000',
		endColor:'#ffffff',
		cssProperty:'color',
		colors: [],
		count: 5,
		type: [1,1,1]
	},
	
	//initialization
	initialize: function(options) {
		//set options
		this.setOptions(options);
	},
	

	//The primary method called to activate
	colorize: function(elems) {
		if(this.options.colors.length == 0) this.options.colors = this.calculateColor(this.options.startColor, this.options.endColor, {"count": elems.length, "type":[1,1,1]});
		var i = 0;
		var c = this.options.colors;
		
		elems.each(function(sa){
			sa.setStyle("background-color", c[i]);
			i++;
		});
	},
	

	hexDigits: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"],
	
	/**
	* generates a rgb value, using a hex value
	*/
	hex2rgb: function(hex) {
		
		var rgb = new Array();
		try {
			hex = this.checkHex(hex);
			rgb[0]=parseInt(hex.substr(1, 2), 16);
			rgb[1]=parseInt(hex.substr(3, 2), 16);
			rgb[2]=parseInt(hex.substr(5, 2), 16);
			return rgb;
		} catch (e) {
			throw e;
		}
	},

	//generates the hex-digits for a color.	
	hex: function(x) {
		return isNaN(x) ? "00" : this.hexDigits[(x - x % 16) / 16] + this.hexDigits[x % 16];
	},


	/**
	* generates a hex value, using a rgb value
	* @param array(red, greed, blue);
	*/
	rgb2hex: function(rgb) {
		try {
			this.checkRGB(rgb);
			
			return "#" + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
		} catch (e) {
			throw e;
		}
	},
	
	
	/**
	* checks, if an array of three values is a valid rgb-array
	*/
	checkRGB: function(rgb) {
		if (rgb.length!=3) throw "this is not a valid rgb-array";
		
		if (isNaN(rgb[0]) || isNaN(rgb[1]) || isNaN(rgb[2])) throw "this is not a valid rgb-array";
		
		if (rgb[0]<0 || rgb[0]>255 || rgb[1]<0 || rgb[1]>255 || rgb[2]<0 || rgb[3]>255) throw "this is not a valid rgb-array";
		
		return rgb;
	},
	
	/**
	* checks, if a given number is a hexadezimal number
	*/
	checkHex: function(hex) {
		if (!hex || hex==""  || hex=="#") throw "No valid hexadecimal given.";
		
		hex = hex.toUpperCase();
				
		switch(hex.length) {
			case 6:
				hex	= "#" + hex;
				break;
			case 7:
				break;
			case 3:
				hex	= "#" + hex;
				break;
			case 4:
				hex	= "#" + hex.substr(1, 1) + hex.substr(1, 1) + hex.substr(2, 1) + hex.substr(2, 1) + hex.substr(3, 1) + hex.substr(3, 1);
				break;
		}
		if(hex.substr(0, 1) != "#" || !this.checkHexDigits(hex.substr(1))) {
			throw "No valid hexadecimal given.";
		}
		
		return hex;	
	},
	
	/**
	* checks, if there is any unvalid digit for a hex number
	*/
	checkHexDigits: function(s) {
		var	j, found;
		for(var i = 0; i < s.length; i++) {
			found	= false;
			for(j = 0; j < this.hexDigits.length; j++)
				if(s.substr(i, 1) == this.hexDigits[j])
					found	= true;
			if(!found)
				return false;
		}
		return true;
	},
	
	/**
	* calculates an array with hex values. 
	* @param startColor: starting color (hex-format or rgb)
	* @param endColor: ending color (hex-format or rgb)
	* @param options: defines, how the color should be generated. The options are defined
				by an object with:
				count: specifies, how many colors should be generated
				type: array for each color. Speciefies, how the missing color should be calculated:
										1: linear
										2: trigonometrical 
										3: accidentally
										4: ordered accident
	*/
	calculateColor: function(startColor, endColor, options)	{
		if (!options || !options.type || !options.type[0] || !options.type[1] || !options.type[2] || !options.count)
			options = this.options;
		
		var	color	= new Array();
		try {
			try {
				var	start	= this.hex2rgb(startColor);
				var end 	= this.hex2rgb(endColor);
			} catch (e) {
				//no hex-value => check if rgb
				this.checkRGB(startColor);
				var start = startColor;
				this.checkRGB(endColor);
				var end = endColor;
			}
			
			var rgb = new Array();
			rgb[0]	= this.calculateGradient(start[0], end[0], options.count, options.type[0]);
			rgb[1]	= this.calculateGradient(start[1], end[1], options.count, options.type[1]);
			rgb[2]	= this.calculateGradient(start[2], end[2], options.count, options.type[2]);
		
			for(var i = 0; i < options.count; i++) {
				color[i] = "#" + this.hex(rgb[0][i]) + this.hex(rgb[1][i]) + this.hex(rgb[2][i]);
			}
		} catch (e) {
			throw e;
		}
		return color;
	},
	
	/**
	* calculateGradient for a color
	* @param startVal
	* @param endVal
	* @param count
	* @param type: array for each color. Speciefies, how the missing color should be calculated:
										1: linear
										2: trigonometrical 
										3: accidentally
										4: ordered accident
	*/
	calculateGradient: function(startVal, endVal,count, type) {
		var a = new Array();
		if(!type || !count) {
			return null;
		} else if (1<count && count < 3) {
			a[0] = startVal;
			a[1] = endVal;
			return a;
		} else if (count==1) {
			a[0] = endVal;
			return a;
		}
		
		switch(type) {
			case 1: //"linear"
				var i;
				for(i = 0; i < count; i++)
					a[i] = Math.round(startVal + (endVal - startVal) * i / (count - 1));
				break;
	
			case 2: //trigonometrical 
				var i;
				for(i = 0; i < count; i++)
					a[i] = Math.round(startVal + (endVal - startVal) * ((Math.sin((-Math.PI / 2) + Math.PI * i / (count - 1)) + 1) / 2));
				break;
	
			case 3: //accident
				var i;
				for(i = 1; i < count - 1; i++)
					a[i] = Math.round(startVal + (endVal - startVal) * Math.random());
				a[0]	= startVal;
				a[count - 1]	= endVal;
				break;
	
			case 4: //ordered accident
				var i;
				for(i = 1; i < count - 1; i++)
					a[i] = Math.round(startVal + (endVal - startVal) * Math.random());
				a[0]	= startVal;
				a[count - 1]	= endVal;
				if((typeof(a.sort) == "function") && (typeof(a.reverse) == "function"))
				{
					a.sort(this.cmp);
					if(startVal > endVal)
						a.reverse();
				}
				break;
		}
		return a;
	}, 
	
	//compares two values to sort
	cmp: function(a, b) {
		return a - b;
	}
	
	
	
}); 


