/*
	Filename: moo.rd - A lightweight Mootools extension
	
	Author: Riccardo Degni, <http://www.riccardodegni.it/> and the moo.rd Team
	
	License: GNU GPL License
	
	Copyright: copyright 2007 Riccardo Degni
	
	[Credits]
		[li] moo.rd is based on the MooTools framework <http://mootools.net/>, and uses the MooTools syntax
		[li] moo.rd constructors extends some of the MooTools Classes
		[li] moo.rd Documentation is written by Riccardo Degni
	[/Credits]
*/

var Moo = {};

Moo.Rd = {
	version: '1.3.2',
	author: 'Riccardo Degni',
	members: [
		'Cristiano Fino',
		'Moocha'
	]
};

/*
	Filename: constructors.js
	
	[Description] 
		Contains some of the moo.rd native Constructors based on the MooTools Class. It permits a major modularity.
	[/Description]
	
	Contains: Class Table, Class Make
*/
/*
	Class: Table
	Description: Allows you to customize tables, tables rows, cells and columns 
*/
var Table = new Class({	
	initialize: function(element) {
		this.element = $(element);
		this.rows = this.element.getElements('tr');
		this.cells = this.element.getElements('tr').getElements('td');
	}
});

/*
	Class: Make
	Description: Wrapper to create Classes that make dinamically Elements.  
*/
var Make = new Class({
	Implements: [Options],
	options: {
		content: 'text'
	}
});

/*
	Filename: effects_cycle.js
	
	[Description] 
		Contains the Fx.Cycle Class and the Fx.Cycle extensions for creating powerful cycle effects, based on different 
		style transitions.
	[/Description]
	
	Contains: Class Fx.Cycle and its extensions, Class Element
	
	[Summary]
		Fx.Cycle ::: A wrapper which allows you to create powerful cycle effects
		Element ::: Contains the cycle method which returns a determinate Fx.Cycle instance
	[/Summary]
*/
/*
	Class: Fx.Cycle
	
	[Description]  
		With the Fx.Cycle extensions, you can create the "cycle effect" which means a slideshow based on a particular
		style transition. This file contains 14 Fx.Cycle extensions, like Fx.Cycle.zoom and Fx.Cycle.fade.
		In addiction, you can create your own cycle effect, either customizing an existing one or creating a new one.
		Below you can find all the Fx.Cycle extensions.
	[/Description]
	
	Extends: Fx.Morph
	
	Constructor: new Fx.Cycle.cycleType (element, options)
	
	[Properties] 
		element - the wrapper which contains your slides
		options - optional. The Fx options plus those described below
	[/Properties]
	
	[Options]
		animeOut : an object whose properties are the styles to alter when the slide gets out.
		animeIn : an object whose properties are the styles to alter when the slide comes in.
		cssBefore : an object whose properties are the styles to alter immediately before the slide comes in.
		animeInType : indicates the method to use with the animeIn object. It can be 'set' (default) or 'start' 
		overflow : the overflow of the wrapper. Depends on the type of cycle effect.
		steps : the timer used by autostart to change periodically the slides. Default is 2000 ms
		handles : an object which attaches events to elements passed in as values. The keywords represent the Fx.Cycle's methods
		autostart : if true the slides will be changed automatically. Deafult is true
		enable : an object containing some keywords to enable extra features. See below.
	[/Options]
	
	>> enable:
	[List]
		[li] keyboard: if true you can navigate with the keyboard too. In addition to the arrows, you can use the following keys. 'a' for autostart, 's' for stop, 'f' to go to the first slide and 'l' to go to the last slide. 
	[/List]
	
	[Events]
		onAnimeIn : function fired immediately before the element is animed in. The current and the next slide will be passed in
		onAnimeOut : function fired immediately before the element is animed out. The current and the next slide will be passed in
	[/Events]
	
	[Methods]
		next -- switches to the next slide
		prev -- switches to the previous slide
		goTo -- swicthes to the given slide
		toFirst -- switches to the first slide
		toLast -- switches to the last slide
		autostart -- enables the cycle slideshow
		stop -- stops the slideshow either if start method has been called or autostart option has been enabled
		animeIn -- sets the animeIn properties
		animeOut -- sets the animeOut properties
		cssBefore -- sets the cssBefore properties
	[/Methods]
	
	[Note]
		You can use the keywords 'this.height' and 'this.width' into the animeIn, animeOut and cssBefore methods,
		to refer respectively to the images' height and width. Using the keyword 'this.parentHeight' and 'this.parentWidth'
		you can refer to the parent element dimensions.
		In addiction, you can use the keywords 'this.currSlide' and 'this.nextSlide' to refer respectively to the current and
		the next slide.
	[/Note]
	
	Method: next
	Description:  switches to the next slide
	[Example]  
		> fx.next();
	[/Example]
	
	Method: prev
	Description:  switches to the previous slide
	[Example]  
		> fx.prev();
	[/Example]
	
	Method: goTo
	Description:  swicthes to the given slide
	[Arguments]
		num :: the position of the needed slide
	[/Arguments]
	[Example]  
		> fx.goTo(2);
	[/Example]
	
	Method: toFirst
	Description:  switches to the first slide
	[Example]  
		> fx.toFirst();
	[/Example]
	
	Method: toLast
	Description:  switches to the last slide
	[Example]  
		> fx.toLast();
	[/Example]
	
	Method: autostart
	Description:  enables the cycle slideshow
	[Example]  
		> fx.autostart();
	[/Example]
	
	Method: stop
	Description:  stops the slideshow either if start method has been called or autostart option has been enabled
	[Example]  
		> fx.stop();
	[/Example]
	
	Method: animeIn
	Description:  sets the animeIn properties
	[Arguments]
		styles :: an object which contains the animeIn css styles
	[/Arguments]
	[Example]  
		> fx.animeIn({top: 200, left: 200});
	[/Example]
	
	Method: animeOut
	Description:  sets the animeOut properties
	[Arguments]
		styles :: an object which contains the animeOut css styles
	[/Arguments]
	[Example]  
		> fx.animeOut({top: -200, opacity: 0});
	[/Example]
	
	Method: cssBefore
	Description:  sets the cssBefore properties
	[Arguments]
		styles :: an object which contains the cssBefore css styles
	[/Arguments]
	[Example]  
		> fx.cssBefore({left: 200, opacity: 1, height: 0, width: 0});
	[/Example]
*/
Fx.Cycle = new Class({
	
	Extends: Fx.Morph,
	
	options: {
		animeOut: {},
		animeIn: {},
		cssBefore: {},
		//cssAfter: {},
		animeInType: 'set',
		overflow: 'visible',
		autostart: true,
		steps: 2000,
		handles: {
			next: false,
			prev: false,
			toFirst: false,
			toLast: false,
			autostart: false,
			stop: false
		},
		enable: {
			keyboard: false	
		},
		onAnimeIn: $empty,
		onAnimeOut: $empty
	},
	
	initialize: function(element, options) {
		
		this.parent(element, options);
		this.imgs = this.element.getChildren();
		this.uimgs = this.element.getChildren().reverse();
		this.element.setStyles({'position': 'relative', 'overflow': this.options.overflow});
		this.first = this.element.getFirst();
		
		this.height = this.first.getStyle('height').toInt();
		this.width = this.first.getStyle('width').toInt();
		this.parentHeight = this.element.getStyle('height').toInt();
		this.parentWidth = this.element.getStyle('width').toInt();
		
		
		this.uimgs.each(function(img, i) { // rino
			img.setStyles({'position': 'absolute', 'top': '0px', 'left': '0px', 'z-index': i});
		}, this);
		this.count = 0;
		this.length = this.imgs.length-1;
		this.fullLength = this.imgs.length;
		if(this.options.autostart) this._autostart = this.next.periodical(this.options.steps, this);
		this.attachHandles();
		if(this.options.enable.keyboard) this.attachKeys.bindWithEvent(this)();
	},
	
	next: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count != this.length) ? this.count++ : this.count = 0;
			this.main();
		}
	},
	
	prev: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count == 0) ? this.count = this.length : this.count--;
			this.main();
		}
	},
	
	goTo: function(to) {
		if(!this.timer && to != this.count) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = to;
			this.main();
		}
	},
	
	toFirst: function() {
		if(!this.timer && this.count != 0) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = 0;
			this.main();
		}
	},
	
	toLast: function() {
		if(!this.timer && this.count != this.length) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.count = this.length;
			this.main();
		}
	},
	
	autostart: function() {
		this._autostart = this.next.periodical(this.options.steps, this);
	},
	
	stop: function() {
		this._autostart = $clear(this._autostart);	
	},
	
	checkAutostart: function() {
		if(this._autostart) {
			this._autostart = $clear(this._autostart);
			this._autostart = this.next.periodical(this.options.steps, this);
		}
	},
	
	attachHandles: function() {
		for(var mtd in this.options.handles) {
			var method = mtd.toString();
			if(this.options.handles[mtd] && $function(this[method])) {
				$(this.options.handles[mtd]).addEvent('click', function(event, method) {
					event.preventDefault();	
					this[method]();
				}.bindWithEvent(this, method));	
			}
		}
	},
	
	attachKeys: function(event) {
		$(document).addEvent('keydown', function(event) {
			switch(event.key) {
				case 'left': this.prev();
					break;
				case 'right': this.next();
					break;
				case 'a': this.autostart();
					break;
				case 's': this.stop();
					break;
				case 'f': this.toFirst();
					break;
				case 'l': this.toLast();
					break;
			}
		}.bind(this));
	},
	
	main: function() {
		this.element.setStyle('z-index', this.fullLength);
		//this.imgs[this.count].setStyle('z-index', 1);
		this.imgs[this.count].setStyle('z-index', this.fullLength-1); //rino
		
		this.currSlide = this.element;
		this.nextSlide = this.imgs[this.count];
		
		this.fireEvent('onAnimeOut', [this.currSlide, this.nextSlide]);
		this.start(this.options.animeOut).chain(
			function() {
				var type = this.options.animeInType;
				if(type == 'set') this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]);
				this.element.setStyle('z-index', 0);
				this.imgs.each(function(img, i) {
					if(i != this.count) img.setStyle('z-index', 0).setStyles(this.options.cssBefore);
				}, this);
				if(type == 'set') this[type](this.options.animeIn); // set instead of start
				if(type == 'start') this[type](this.options.animeIn).chain(function() { this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]); });
			}
		);
	}
					 
});

(function() {
var methods = {};

['animeOut', 'animeIn', 'cssBefore'].each(function(method) {
	methods[method] = function(styles) {
		for(var style in styles)
			if($defined(styles[style])) this.options[method][style] = styles[style]; 
	}					
});

Fx.Cycle.implement(methods);
})();

/* 
Class: Fx.Cycle.shuffle 
*/
Fx.Cycle.shuffle = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeInType: 'start',
		animeIn: {
			top: 0,
			left: 0
		},
		sizes: [20, -110]
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.options.sizes[0], left: this.options.sizes[1]});
	}
});

/* 
Class: Fx.Cycle.fade 
*/
Fx.Cycle.fade = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			opacity: 0
		},
		cssBefore: {
			opacity: 1	
		}
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
	}
});

/* 
Class: Fx.Cycle.slideUp 
*/
Fx.Cycle.slideUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: -this.parentHeight});
	}
});

/* 
Class: Fx.Cycle.slideDown 
*/
Fx.Cycle.slideDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.parentHeight});
	}
});

/* 
Class: Fx.Cycle.slideRight 
*/
Fx.Cycle.slideRight = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({left: this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.slideLeft 
*/
Fx.Cycle.slideLeft = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left:0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({left: -this.parentWidth});
		alert("ecoolo");
	}
});

/* 
Class: Fx.Cycle.foldUp 
*/
Fx.Cycle.foldUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			height: 0
		},
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.cssBefore({top: 0, height: this.height});
	}
});

/* 
Class: Fx.Cycle.foldDown 
*/
Fx.Cycle.foldDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({height: 0, top: this.height});
		this.cssBefore({top: 0, height: this.height});
	}
});

/* 
Class: Fx.Cycle.foldRight 
*/
Fx.Cycle.foldRight = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			width: 0
		},
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.cssBefore({top: 0, width: this.width});
	}
});

/* 
Class: Fx.Cycle.foldLeft 
*/
Fx.Cycle.foldLeft = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			left: 0, top: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({width: 0, left: this.width});
		this.cssBefore({top: 0, width: this.width});
	}
});

/* 
Class: Fx.Cycle.zoom 
*/
Fx.Cycle.zoom = new Class({

	Extends: Fx.Cycle,
	
	options: {
		cssBefore: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({width: 0, height: 0, top: this.height/2, left: this.width/2});
		this.animeIn({top: 0, left: 0, width: this.height, height: this.width});
	}
});

/* 
Class: Fx.Cycle.diagonalUp
*/
Fx.Cycle.diagonalUp = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: -this.parentHeight, left: -this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.diagonalDown
*/
Fx.Cycle.diagonalDown = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeIn: {
			top: 0, left: 0
		},
		overflow: 'hidden'
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
		this.animeOut({top: this.parentHeight, left: this.parentWidth});
	}
});

/* 
Class: Fx.Cycle.linear 
*/
Fx.Cycle.linear = new Class({

	Extends: Fx.Cycle,
	
	options: {
		animeOut: {
			display: 'none'
		},
		cssBefore: {
			display: 'block'
		}
	},
	
	initialize: function(element, options) {
		this.parent(element, options);
	}
});

/*
	Class: Element
	
	[Description] 
		Contains the cycle method which returns a determinate Fx.Cycle instance
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		cycle -- returns an Fx.Cycle instance of the given type
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: cycle
	Description:  returns an Fx.Cycle instance of the given type
	[Arguments]
		type :: the Fx.Cycle transition
		options :: the Fx.Cycle options
	[/Arguments]
	[Example]  
		> // slideUp instance
		> var slideUp = $('myElement').cycle('slideUp');
		> // diagonalUp instance
		> var diagonalUp = $('myElement').cycle('diagonalUp', {duration: 4000, steps: 4000});
	[/Example]
	*/
	cycle: function(type, options) {
		return new Fx.Cycle[type](this, options);
	}				  

});

/*
	Filename: effects_cycles.js
	
	[Description] 
		Contains the Fx.Cycles Class and the Fx.Cycles extensions to create powerful cycle slideshows which alter 
		two slides at once
	[/Description]
	
	Contains: Class Fx.Cycles and its extensions, Class Element
	
	[Summary]
		Fx.Cycles ::: A wrapper which allows you to create powerful cycle effects
		Element ::: Contains the cycles method which returns a determinate Fx.Cycles instance
	[/Summary]
*/
/*
	Class: Fx.Cycles
	
	[Description]  
		The Fx.Cycles Class provides a similar functionality to the Fx.Cycle Class. With the Fx.Cycles Class however,
		you can "cycle" two slides at once, to create more complex transitions. There are 13 transitions created by default,
		but you can create your own as with the Fx.Cycle Class.
	[/Description]
	
	Extends: Fx.Elements
	
	Constructor: new Fx.Cycles.cycleType (element, options)
	
	[Properties] 
		element - the wrapper which contains your slides
		options - optional. The Fx options
	[/Properties]
	
	[Options]
		animeOut : an object whose properties are the styles to alter when the slide gets out.
		animeIn : an object whose properties are the styles to alter when the slide comes in.
		cssBefore : an object whose properties are the styles to alter immediately before the slide comes in.
		cssAfter : an object whose properties are the styles to alter immediately after the slide has come in.
		reset : an object whose properties are the styles to reset to the next slide.
		overflow : the overflow of the wrapper. Depends on the type of cycle effect.
		steps : the timer used by autostart to change periodically the slides. Default is 2000 ms
		handles : an object which attaches events to elements passed in as values. The keywords represent the Fx.Cycles's methods
		autostart : if true the slides will be changed automatically. Deafult is true
		enable : an object containing some keywords to enable extra features. See below.
	[/Options]
	
	>> enable:
	[List]
		[li] keyboard: if true you can navigate with the keyboard too. In addition to the arrows, you can use the following keys. 'a' for autostart, 's' for stop, 'f' to go to the first slide and 'l' to go to the last slide. 
	[/List]
	
	[Events]
		onAnimeIn : function fired immediately before the element is animed in. The current and the next slide will be passed in
		onAnimeOut : function fired immediately before the element is animed out. The current and the next slide will be passed in
	[/Events]
	
	[Methods]
		next -- switches to the next slide
		prev -- switches to the previous slide
		goTo -- swicthes to the given slide
		toFirst -- switches to the first slide
		toLast -- switches to the last slide
		autostart -- enables the cycle slideshow
		stop -- stops the slideshow either if start method has been called or autostart option has been enabled
		animeIn -- sets the animeIn properties
		animeOut -- sets the animeOut properties
		cssBefore -- sets the cssBefore properties
		cssAfter -- sets the cssAfter properties
		reset -- sets the reset properties
	[/Methods]
	
	[Note]
		You can use the keywords 'this.height' and 'this.width' into the animeIn, animeOut, cssBefore, cssAfter and reset methods,
		to refer respectively to the images' height and width. Using the keyword 'this.parentHeight' and 'this.parentWidth'
		you can refer to the parent element dimensions.
		In addiction, you can use the keywords 'this.currSlide' and 'this.nextSlide' to refer respectively to the current and
		the next slide.
	[/Note]
	
	Method: next
	Description:  switches to the next slide
	[Example]  
		> fx.next();
	[/Example]
	
	Method: prev
	Description:  switches to the previous slide
	[Example]  
		> fx.prev();
	[/Example]
	
	Method: goTo
	Description:  swicthes to the given slide
	[Arguments]
		num :: the position of the needed slide
	[/Arguments]
	[Example]  
		> fx.goTo(2);
	[/Example]
	
	Method: toFirst
	Description:  switches to the first slide
	[Example]  
		> fx.toFirst();
	[/Example]
	
	Method: toLast
	Description:  switches to the last slide
	[Example]  
		> fx.toLast();
	[/Example]
	
	Method: autostart
	Description:  enables the cycle slideshow
	[Example]  
		> fx.autostart();
	[/Example]
	
	Method: stop
	Description:  stops the slideshow either if start method has been called or autostart option has been enabled
	[Example]  
		> fx.stop();
	[/Example]
	
	Method: animeIn
	Description:  sets the animeIn properties
	[Arguments]
		styles :: an object which contains the animeIn css styles
	[/Arguments]
	[Example]  
		> fx.animeIn({top: 200, left: 200});
	[/Example]
	
	Method: animeOut
	Description:  sets the animeOut properties
	[Arguments]
		styles :: an object which contains the animeOut css styles
	[/Arguments]
	[Example]  
		> fx.animeOut({top: -200, opacity: 0});
	[/Example]
	
	Method: cssBefore
	Description:  sets the cssBefore properties
	[Arguments]
		styles :: an object which contains the cssBefore css styles
	[/Arguments]
	[Example]  
		> fx.cssBefore({left: 200, opacity: 1, height: 0, width: 0});
	[/Example]
	
	Method: cssAfter
	Description:  sets the cssAfter properties
	[Arguments]
		styles :: an object which contains the cssAfter css styles
	[/Arguments]
	[Example]  
		> fx.cssAfter({left: 0, opacity: 0, height: 200});
	[/Example]
	
	Method: reset
	Description:  sets the reset properties
	[Arguments]
		styles :: an object which contains the reset css styles
	[/Arguments]
	[Example]  
		> fx.reset({top: 200, opacity: 1, width: 0});
	[/Example]
*/
Fx.Cycles = new Class({
	
	Extends: Fx.Elements,
	
	options: {
		animeOut: {},
		animeIn: {},
		cssBefore: {},
		cssAfter: {},
		reset: {},
		overflow: 'visible',
		autostart: true,
		steps: 2000,
		duration: 3000,
		handles: {
			next: false,
			prev: false,
			toFirst: false,
			toLast: false,
			autostart: false,
			stop: false
		},
		enable: {
			keyboard: false	
		},
		onAnimeIn: $empty,
		onAnimeOut: $empty
	},
	
	initialize: function(element, options) {
		this.element = $(element);
		this.elements = this.element.getChildren();
		this.parent($$(this.elements), options);
		this.imgs = this.element.getChildren();
		this.uimgs = this.element.getChildren().reverse();
		this.element.setStyles({'position': 'relative', 'overflow': this.options.overflow});
		this.first = this.element.getFirst();
		
		this.height = this.first.getStyle('height').toInt();
		this.width = this.first.getStyle('width').toInt();
		this.parentHeight = this.element.getStyle('height').toInt();
		this.parentWidth = this.element.getStyle('width').toInt();
		
		/*this.uimgs.each(function(img, i) {
			img.setStyles({'position': 'absolute', 'top': '0px', 'left': '0px', 'z-index': i});
			//img.setStyles({'position': 'absolute', 'top': '0px', 'left': '-288px', 'z-index': i});
		}, this);*/
		this.count = 0;
		this.where = -1;
		this.length = this.imgs.length-1;
		this.fullLength = this.imgs.length;
		if(this.options.autostart) this._autostart = this.next.periodical(this.options.steps, this);
		this.attachHandles();
		if(!this.options.enable.keyboard) this.attachKeys.bindWithEvent(this)();
	},
	
	next: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count != this.length) ? this.count++ : this.count = 0;
			(this.where == -1) ? this.where = 0 : (this.count == 0) ? this.where = this.length : this.where = this.count-1;
			this.main();
		}
	},
	
	prev: function() {
		if(!this.timer) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			(this.count == 0) ? this.count = this.length : this.count--;
			(this.where == -1) ? this.where = 0 : (this.count == this.length) ? this.where = 0 : this.where = this.count+1;
			this.main();
		}
	},
	
	goTo: function(to) {
		if(!this.timer && to != this.count) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = to;
			this.main();
		}
	},
	
	toFirst: function() {
		if(!this.timer && this.count != 0) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = 0;
			this.main();
		}
	},
	
	toLast: function() {
		if(!this.timer && this.count != this.length) {
			this.checkAutostart();
			this.element = this.imgs[this.count];
			this.where = this.count;
			this.count = this.length;
			this.main();
		}
	},
	
	autostart: function() {
		this._autostart = this.next.periodical(this.options.steps, this);
	},
	
	stop: function() {
		this._autostart = $clear(this._autostart);	
	},
	
	checkAutostart: function() {
		if(this._autostart) {
			this._autostart = $clear(this._autostart);
			this._autostart = this.next.periodical(this.options.steps, this);
		}
	},
	
	attachHandles: function() {
		for(var mtd in this.options.handles) {
			var method = mtd.toString();
			if(this.options.handles[mtd] && $function(this[method])) {
				$(this.options.handles[mtd]).addEvent('click', function(event, method) {
					event.preventDefault();	
					this[method]();
				}.bindWithEvent(this, method));	
			}
		}
	},
	
	attachKeys: function(event) {
		$(document).addEvent('keydown', function(event) {
			switch(event.key) {
				case 'left': this.prev();
					break;
				case 'right': this.next();
					break;
				case 'a': this.autostart();
					break;
				case 's': this.stop();
					break;
				case 'f': this.toFirst();
					break;
				case 'l': this.toLast();
					break;
			}
		}.bind(this));
	},
	
	main: function() {
		this.element.setStyle('z-index', this.fullLength);
		this.imgs[this.count].setStyle('z-index', 1).setStyles(this.options.current);
		
		this.imgs.each(function(img, i) {
				if(i!=this.where)
					img.setStyles(this.options.cssBefore);
		}, this);
		
		var o = {};

		var curr = this.where;
		var next = this.count;
		
		this.currSlide = this.imgs[curr];
		this.nextSlide = this.imgs[next];
			
		o[curr] = this.options.animeOut;
		o[next] = this.options.animeIn;
		
		this.fireEvent('onAnimeOut', [this.currSlide, this.nextSlide]);
		this.imgs[next].setStyles(this.options.reset);
		this.start(o).chain(function() {
			this.imgs[curr].setStyles(this.options.cssAfter); 
			this.fireEvent('onAnimeIn', [this.currSlide, this.nextSlide]);	
		});
	}
					 
});

(function() {
var methods = {};

['animeOut', 'animeIn', 'cssBefore', 'cssAfter', 'reset'].each(function(method) {
	methods[method] = function(styles) {
		for(var style in styles)
			if($defined(styles[style])) this.options[method][style] = styles[style]; 
	}					
});

Fx.Cycles.implement(methods);
})();

/* 
Class: Fx.Cycles.scrollUp 
*/
Fx.Cycles.scrollUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: [0, -this.parentHeight]});
		this.animeIn({top: [this.parentHeight, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollDown 
*/
Fx.Cycles.scrollDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: [0, this.parentHeight]});
		this.animeIn({top: [-this.parentHeight, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollLeft
*/
Fx.Cycles.scrollLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({left: [0, -this.parentWidth]});
		this.animeIn({left: [this.parentWidth, 0]});
	}
});

/* 
Class: Fx.Cycles.scrollRight
*/
Fx.Cycles.scrollRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({left: [0, this.parentWidth]});
		this.animeIn({left: [-this.parentWidth, 0]});
	}
});

/* 
Class: Fx.Cycles.fadeZoom
*/
Fx.Cycles.fadeZoom = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({opacity: [1, 0], display: 'block'});
		this.animeIn({left: [this.width/2, 0], top: [this.height/2, 0], width: [0, this.width], height: [0, this.height], display: 'block'});
		this.cssBefore({height: 0, width: 0, display: 'none'});
		this.reset({height: this.height, width: this.width, opacity: 1, top: this.height/2, left: this.width/2, display: 'none'});
	}
});

/* 
Class: Fx.Cycles.turnDown
*/
Fx.Cycles.turnDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({height: [this.height, 0], top: [0, this.height]});
		this.animeIn({height: [0, this.height]});
		this.reset({display: 'block', height: this.height, width: this.width, top: 0, left: 0});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnUp
*/
Fx.Cycles.turnUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({height: [this.height, 0], top: 0});
		this.animeIn({height: [0, this.height], top: 0});
		this.reset({display: 'block', top: this.height, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnLeft
*/
Fx.Cycles.turnLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({width: [this.width, 0], left: 0});
		this.animeIn({width: [0, this.width], left: [this.width, 0]});
		this.reset({display: 'block', left: this.width, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.turnRight
*/
Fx.Cycles.turnRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({width: [this.width, 0], left: [0, this.width]});
		this.animeIn({width: [0, this.width], left: 0});
		this.reset({display: 'block', left: 0, width: this.width});
		this.cssAfter({display: 'none', width: 0});
	}
});

/* 
Class: Fx.Cycles.inOutLeft
*/
Fx.Cycles.inOutLeft = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: this.parentHeight, left: this.parentWidth});
		this.animeIn({top:0, left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: -this.parentHeight, left: this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutRight
*/
Fx.Cycles.inOutRight = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: -this.parentHeight, left: -this.parentWidth});
		this.animeIn({top:0, left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: this.parentHeight, left: -this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutUp
*/
Fx.Cycles.inOutUp = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: -this.parentHeight});
		this.animeIn({left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: 0, left: this.parentWidth, display: 'block'});
	}
});

/* 
Class: Fx.Cycles.inOutDown
*/
Fx.Cycles.inOutDown = new Class({

	Extends: Fx.Cycles,
	
	options: {
		overflow: 'hidden'
	},
	
	initialize: function(elements, options) {
		this.parent(elements, options);
		this.animeOut({top: this.parentHeight});
		this.animeIn({left: 0});
		this.cssBefore({display: 'none'});
		this.reset({top: 0, left: this.parentWidth, display: 'block'});
	}
});

/*
	Class: Element
	
	[Description] 
		Contains the cycles method which returns a determinate Fx.Cycles instance
	[/Description]
	
	Extends: Class Element
	
	[Methods]
		cycles -- returns an Fx.Cycles instance of the given type
	[/Methods]
*/	
Element.implement({
	
	/*
	Method: cycles
	Description:  returns an Fx.Cycles instance of the given type
	[Arguments]
		type :: the Fx.Cycles transition
		options :: the Fx.Cycles options
	[/Arguments]
	[Example]  
		> // scrollUp instance
		> var scrollUp = $('myElement').cycles('scrollUp');
		> // turnUp instance
		> var turnUp = $('myElement').cycles('turnUp', {duration: 2000, steps: 4000});
	[/Example]
	*/
	cycles: function(type, options) {
		return new Fx.Cycles[type](this, options);
	}				  

});