/*
	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: type.js
	
	[Description]
		Contains shortcut functions to detect the type of an object using the $type function and the $dump function to detect the value and the type of every objects
	[/Description]
	
	Contains: A collection of functions based on the $type function plus the $dump function
	
	[Functions]
		$dump --- returns the value and the type of the object passed in
		$string --- returns true if the object is a string
		$int --- returns true if the object is a number
		$array --- returns true if the object is an array
		$object --- returns true if the object is an object
		$function --- returns true if the object is a function
		$date --- returns true if the object is a date
		$class --- returns true if the object is a class
		$element --- returns true if the object is an element
		$collection --- returns true if the object is a collection
		$arguments --- returns true if the object is the arguments object
		$textnode --- returns true if the object is a textnode
		$whitespace --- returns true if the object is a whitespace
		$window --- returns true if the object is the window object
		$document --- returns true if the object is the document object
	[/Functions]
*/
/*
	Function: $dump
	Description: returns the value and the type of the object passed in
	[Arguments]
		obj :: the object to analize
		results :: optional. the element to put the results to. If false returns the result string.
	[/Arguments]
	[Example] 
		> var s = 'some data';
		>
		> $dump(s, 'box');
		> // returns
		> '(
		>   Value: some data
		>   Type: string
		> )'
		>
		> var a = ['a', 'b', 'c', 'd'];
		>
		> $dump(a, 'box');
		> // returns
		> '(
		>   Value: a, b, c, d
		>   Type: array
		> )'
	[/Example]
*/
function $dump(obj, result) {
	var r = '(' + '<br />';
	var tinyspaces = '&nbsp;&nbsp;';
	r += tinyspaces + 'Value: ' + obj.toString() + '<br />';
	r += tinyspaces + 'Type: ' + $type(obj) + '<br />';
	r += ')';
	return (result) ? $(result).set('html', r) : r;
}

/*
	Function: $string
	Description: returns true if the object is a string
*/
function $string(obj) {
	return $type(obj) == 'string';
}

/*
	Function: $int
	Description: returns true if the object is a number
*/
function $int(obj) {
	return $type(obj) == 'number';
}

/*
	Function: $array
	Description: returns true if the object is an array
*/
function $array(obj) {
	return $type(obj) == 'array';
}

/*
	Function: $object
	Description: returns true if the object is an object
*/
function $object(obj) {
	return $type(obj) == 'object';
}

/*
	Function: $function
	Description: returns true if the object is a function
*/
function $function(obj) {
	return $type(obj) == 'function';
}

/*
	Function: $date
	Description: returns true if the object is a date
*/
function $date(obj) {
	return $type(obj) == 'date';
}

/*
	Function: $class
	Description: returns true if the object is a class
*/
function $class(obj) {
	return $type(obj) == 'class';
}

/*
	Function: $element
	Description: returns true if the object is an element
*/
function $element(obj) {
	return $type(obj) == 'element';
}

/*
	Function: $collection
	Description: returns true if the object is a collection
*/
function $collection(obj) {
	return $type(obj) == 'collection';
}

/*
	Function: $arguments
	Description: returns true if the object is the arguments object
*/
function $arguments(obj) {
	return $type(obj) == 'arguments';
}

/*
	Function: $textnode
	Description: returns true if the object is a textnode
*/
function $textnode(obj) {
	return $type(obj) == 'textnode';
}

/*
	Function: $whitespace
	Description: returns true if the object is a whitespace
*/
function $whitespace(obj) {
	return $type(obj) == 'whitespace';
}

/*
	Function: $window
	Description: returns true if the object is the window object
*/
function $window(obj) {
	return $type(obj) == 'window';
}

/*
	Function: $document
	Description: returns true if the object is the document object
*/
function $document(obj) {
	return $type(obj) == 'document';
}

/*
	Filename: browser.js
	
	[Description]
		Contains some Browser properties to ease the detection of the browser which is working
	[/Description]
	
	Contains: Hash Browser
	
	[Summary]
		Browser ::: Extends the Browser Hash with new properties 
	[/Summary]
*/
/*
	Hash: Browser
	
	[Description]  
		Extends the Browser Hash with new properties, to speed up and ease the detection of the browser which is working.
	[/Description]
	
	[Hash]
		 Browser.ie : alias of Browser.Engine.trident
		 Browser.ie6 : alias of Browser.Engine.trident4
		 Browser.ie7 : alias of Browser.Engine.trident5
		 Browser.firefox : alias of Browser.Engine.gecko
		 Browser.safari : alias of Browser.Engine.webkit
		 Browser.safari2 : alias of Browser.Engine.webkit419
		 Browser.safari3 : alias of Browser.Engine.webkit420
		 Browser.opera : alias of Browser.Engine.presto
		 Browser.opera925 : alias of Browser.Engine.presto925
		 Browser.opera950 : alias of Browser.Engine.presto950
	[/Hash]
*/
Browser.ie = Browser.Engine.trident;
Browser.ie6 = Browser.Engine.trident4;
Browser.ie7 = Browser.Engine.trident5;
Browser.firefox = Browser.Engine.gecko;
Browser.safari = Browser.Engine.webkit;
Browser.safari2 = Browser.Engine.webkit419;
Browser.safari3 = Browser.Engine.webkit420;
Browser.opera = Browser.Engine.presto;
Browser.opera925 = Browser.Engine.presto925;
Browser.opera950 = Browser.Engine.presto950;

/*
	Filename: overlay.js
	
	[Description]
		Contains the Overlay Utility Class, that can be implemented with Implements property into any Class
	[/Description]
	
	Contains: Class Overlay
	
	Requires: browser.js
	
	[Summary]
		Overlay ::: Utility Class for creating customized and advanced overlays
	[/Summary]
*/
/*
	Class: Overlay
	
	[Description]  
		Utility Class for creating customized and advanced overlays. Adds the Overlay properties to the Classes
	[/Description]
	
	Constructor: new Overlay()
	
	[Methods]
		createOverlay -- creates the overlay property which represents the overlay
		createFullPage -- creates the full page overlay which represents the upper level
		setLight -- sets the light of the overlay. Can be 'draken', 'lighten', false or a color
		injectOverlay -- injects the overlay and indicates that the overlay is active
		removeOverlay -- removes the overlay with additional controls for IE 6
	[/Methods]
*/
var Overlay = new Class({
						
	/*
	Method: createOverlay
	Description:  creates the overlay property which represents the overlay
	[Arguments]
		id :: the overlay id
		light :: the overlay light. It can be 'darken' 'lighten', false or a color
	[/Arguments]
	*/
	createOverlay: function(id, light) {
		this.overlay = new Element('div', {
			'id': id || 'overlay',
			'styles': {
				'position': (Browser.ie6) ? 'absolute' : 'fixed',
				'top': '0px',
				'left': '0px',
				'width': (Browser.ie6) ? window.getWidth() : '100%',
				'height': '100%',
				'background-image':'url(g.gif)',
				'z-index': 800
			}
		});
		
		if(Browser.Engine.presto) this.overlay.setStyle('overflow', 'hidden');  
	
		this.setLight(light);
		
		return this;
	},
	
	/*
	Method: createFullPage
	Description:  creates the full page overlay which represents the upper level
	[Arguments]
		id :: the fullpage id
	[/Arguments]
	*/
	createFullPage: function(id) {
		this.fullpage = new Element('div', {
			'id': id || 'fullpage',
			'styles': {
				'position': (Browser.ie6) ? 'absolute' : 'fixed',
				'top': '0px',
				'left': '0px',
				'width': (Browser.ie6) ? window.getWidth() : '100%',
				'height': '100%',
				'background-image':'url(g.gif)',
				'z-index': 900
			}
		});
		
		if(Browser.Engine.presto) this.fullpage.setStyle('overflow', 'hidden');  
		
		return this;
	},
	
	/*
	Method: setLight
	Description:  sets the light of the overlay. Can be 'darken', 'lighten', false or a color
	[Arguments]
		light :: the light of the overlay 
		opacity :: optional. the opacity value of the overlay
	[/Arguments]
	*/
	setLight: function(light, opacity) {
		switch(light) {
			case 'darken': 
				var color = '#333333';
				break;
			case 'lighten':
				var color = '#FFFFFF';
				break;
			case false:
				var color = 'transparent';
				break;
			default: 
				var color = light;
				break;
		};
		this.overlay.setStyles({
			'background-color': color,
			'opacity': opacity || '0.8'			   
		});
		
		return this;
	},
	
	/*
	Method: injectOverlay
	Description:  injects the overlay and indicates that the overlay is active
	[Arguments]
		fullpage :: if true the fullpage will be injected too
	[/Arguments]
	*/
	injectOverlay: function(fullpage) {
		this.overlay.inject(document.body);
		if(fullpage) this.fullpage.inject(document.body);
		this.overlayActive = true;
		this.fixOverlay();
		return this;
	},
	
	/*
	Method: removeOverlay
	Description:  removes the overlay with additional controls for IE 6
	*/
	removeOverlay: function() {
		this.overlay.dispose();
		this.fullpage.dispose();
		if(Browser.ie6) {
			document.body.setStyles({'height': this.bodyHeightTrident4, 'overflow': this.bodyOverflowTrident4});
		}
		this.overlayActive = false;
		return this;
	},
	
	fixOverlay: function() {
		if(Browser.ie6) {
			if(!this.bodyHeightTrident4) this.bodyHeightTrident4 = $(document.body).getStyle('height');
			this.bodyOverflowTrident4 = $(document.body).getStyle('overflow');
			
			$$(this.overlay, this.fullpage).setStyle('overflow', 'hidden');
			
			$$(window, document.body).setStyles({
				'height': '100%',
				'overflow': 'auto',
				'margin': 0,
				'padding': 0
			});
		}
		return this;
	}
});

/*
	Filename: tabs.js
	
	[Description]
		Contains the Tabs Class to create professional tab-based interfaces.
	[/Description]
	
	Contains: Class Tabs
	
	[Summary]
		Tabs ::: Custom Class for creating tab-based interfaces 
	[/Summary]
*/
/*
	Class: Tabs
	
	[Description] 
		Allows to create professional tab-based interfaces with many additional controls, like the scrolling effect,
		the autoresizing, the opening tab and more. Note that in the Tabs namespacing, the 'tabs' represent
		the contents while the 'sections' represent the handlers (the list items).
	[/Description]
	
	Extends: 
	
	Constructor: new Tabs(element, options)
	
	[Properties] 
		element - the container element
		options - the Tabs options. See below
	[/Properties]
	
	[Options]
		effect : the transition effect used to change the tabs. Can be 'scroll' or 'fix'
		autoresize : if true the tabs will be autoresized. Default is true.
		scrollOptions : the additional Fx.Scroll options
		opening : the tab which will be activated at first. Default is 0.
		openingEffect : the opening effect, 'scroll' or 'fix' (default). Can be different from the 'effect' option.
		names : an object containing the class names of the sections represent the Tabs interface. See below.
	[/Options]
	
	>> names:
	[List]
		[li] wrapper: the class name of the wrapper which contains the tabs. Default is 'tabs'
		[li] sections: the class name of the list element that contains the sections. Deafukt is 'sections'
		[li] tab: the class name of the elements represent the tabs. Default is 'tab'
	[/List]

    [Events]
		onOpen : function fired if the 'opening' option is a number represents a tab. The tab element and its position will be passed as arguments.
		onChange : function fired when an user changes to another tab. The tab element, the section and the tab position will be passed as arguments.
	[/Events]
	
	[Example]
		> var tabs = new Tabs('main', {
		>	autoresize: false,
		>	opening: 2,
		>	openingEffect: 'scroll',
		>	effect: 'fix',
		>	onChange: function(tab, section, i) {
		>		this.sections.removeClass('active');
		>		section.addClass('active');
		>	}
		> });
	[/Example]
*/
var Tabs = new Class({
	
	Implements: [Events, Options],
	
	options: {
		effect: 'scroll',
		autoresize: true,
		names: {
			wrapper: 'tabs',
			sections: 'sections',
			tab: 'tab'
		},
		scrollOptions: {},
		onChange: $empty,
		onOpen: $empty,
		opening: 0,
		openingEffect: 'fix'
	},
	
	initialize: function(element, options) {
		this.main = $(element);
		this.setOptions(options);
		this.wrapper = this.main.getElement('.' + this.options.names.wrapper);
		this.sections = this.main.getElement('ul.' + this.options.names.sections).getElements('li');
		this.tabs = this.wrapper.getElements('.' + this.options.names.tab);
		
		this.wrapper.setStyles({'overflow': 'hidden'});
		
		this.tabs.each(function(tab, i) {
			tab.store('height', tab.getHeight());
		}, this);
		
		this.fx = new Fx.Scroll(this.wrapper, this.options.scrollOptions);
		
		if($int(this.options.opening) && this.sections[this.options.opening]) { 
			this.goTo(this.sections[this.options.opening], this.options.opening, this.options.openingEffect);
			this.fireEvent('onOpen', [this.sections[this.options.opening], this.options.opening]);	
		}
		
		this.sections.each(function(section, i) {
			section.addEvent('click', this.goTo.bind(this, [section, i]));
		}, this);
	},
	
	goTo: function(section, i, effect) {
		var tab = this.tabs[i], height = tab.retrieve('height'), count = i, method = false, eff = this.options.effect;
		
		if(effect) this.options.effect = effect;
		
		if(eff == 'scroll' && !this.fx.timer)
			method = 'start';
		else if(eff == 'fix')
			method = 'set';
		
		if(method) {
			this.fireEvent('onChange', [tab, section, count]);
			if(this.options.autoresize) $$(this.wrapper, tab).setStyle('height', height);
			this.fx[method](0, tab.getPosition(this.wrapper).y.toInt());
		}
		
		if(effect)	this.options.effect = eff;
	}

});