/*
Script: Core.js
	MooTools - My Object Oriented JavaScript Tools.

License:
	MIT-style license.

MooTools Copyright:
	Copyright (c) 2007 Valerio Proietti, <http://mad4milk.net/>

MooTools Code & Documentation:
	The MooTools team <http://mootools.net/developers/>.

MooTools Credits:
	- Class is slightly based on Base.js <http://dean.edwards.name/weblog/2006/03/base/> (c) 2006 Dean Edwards, License <http://creativecommons.org/licenses/LGPL/2.1/>
*/

var MooTools = {
	'version': '1.2dev',
	'build': '945'
};

/* Section: Utility Functions */

/*
Function: $A
	Creates a copy of an Array. Useful for applying the Array prototypes to iterable objects such as a DOM Node collection or the arguments object.

Syntax:
	>var copiedArray = $A(iterable);

Arguments:
	iterable - (array) The iterable to copy.

Returns:
	(array) The new copied array.

Examples:
	Apply Array to arguments:
	[javascript]
		function myFunction(){
			$A(arguments).each(function(argument, index){
				alert(argument);
			});
		}; //will alert all the arguments passed to the function myFunction.
	[/javascript]

	Copy an Array:
	[javascript]
		var anArray = [0, 1, 2, 3, 4];
		var copiedArray = $A(anArray); //returns [0, 1, 2, 3, 4]
	[/javascript]
*/

function $A(iterable){
	if (Client.Engine.ie && $type(iterable) == 'collection'){
		var array = [];
		for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];
		return array;
	}
	return Array.prototype.slice.call(iterable);
};

/*
Function: $augment
	Augments the first object with all the properties of the second object that are not already defined.
	Similar to extend except that it does not overwrite properties that are already defined.

Syntax:
	>$augment(original, augumentation);

Arguments:
	original     - (object) The object to copy properties to.
	augmentation - (object) The object to copy properties from.

Returns:
	(object) The augmented object.

Example:
	[javascript]
		var firstObj = {
			'name': 'John',
			'lastName': 'Doe'
		};
		var secondObj = {
			'age': '20',
			'sex': 'male',
			'lastName': 'Dorian'
		};
		$augment(firstObj, secondObj);
		//firstObj is now { 'name': 'John', 'lastName': 'Doe', 'age': '20', 'sex': 'male' };
	[/javascript]
*/

function $augment(original, augmentation){
	for (var property in augmentation){
		var old = original[property];
		if (!$defined(old)) original[property] = augmentation[property];
	}
	return original;
};

/*
Function: $chk
	Checks to see if a value exists or is 0. Useful for allowing 0.

Syntax:
	>$chk(obj);

Arguments:
	obj - (mixed) The object to inspect.

Returns:
	(boolean) If the object passed in exists or is 0, returns true. Otherwise, returns false.

Example:
	[javascript]
		function myFunction(arg){
			if($chk(arg)) alert('The object exists or is 0.');
			else alert('The object is either null, undefined, false, or ""');
		}
	[/javascript]
*/

function $chk(obj){
	return !!(obj || obj === 0);
};

/*
Function: $clear
	Clears a Timeout or an Interval.

Syntax:
	>$clear(timer);

Arguments:
	timer - (number) The identifier of the setInterval (periodical) or setTimeout (delay) to clear.

Returns:
	null

Example:
	[javascript]
		var myTimer = myFunction.delay(5000); //Wait 5 seconds and execute myFunction.
		myTimer = $clear(myTimer); //Nevermind.
	[/javascript]

See also:
	<Function.delay>, <Function.periodical>
*/

function $clear(timer){
	clearTimeout(timer);
	clearInterval(timer);
	return null;
};

/*
Function: $defined
	Checks to see if a value is defined.

Syntax:
	>$defined(obj);

Arguments:
	obj - (mixed) The object to inspect.

Returns:
	(boolean) If the object passed is not null or undefined, returns true. Otherwise, returns false.

Example:
	[javascript]
		function myFunction(arg){
			if($defined(arg)) alert('The object is defined.');
			else alert('The object is null or undefined.');
		}
	[/javascript]
*/

function $defined(obj){
	return (obj != undefined);
};

/*
Function: $empty
	An empty function, that's it. Typically used for as a placeholder inside classes event methods.

Syntax:
	>var emptyFn = $empty;

Example:
	[javascript]
		var myFunc = $empty;
	[/javascript]
*/

function $empty(){};

/*
Function: $extend
	Copies all the properties from the second object passed in to the first object passed in.
	In myWhatever.extend = $extend, the first parameter will become myWhatever, and the extend function will only need one parameter.

Syntax:
	>$extend(original[, extended]);

Arguments:
	original - (object) The object to be extended.
	extended - (object, optional) The object whose properties will be copied to src.

Returns:
	(object) The extended object.

Examples:
	Normal Extension:
	[javascript]
		var firstObj = {
			'name': 'John',
			'lastName': 'Doe'
		};
		var secondObj = {
			'age': '20',
			'sex': 'male',
			'lastName': 'Dorian'
		};
		$extend(firstObj, secondObj);
		//firstObj is now: { 'name': 'John', 'lastName': 'Dorian', 'age': '20', 'sex': 'male' };
	[/javascript]

	Without the Second Parameter:
	[javascript]
		var myFunction = function(){ ... };
		myFunction.extend = $extend;
		myFunction.extend(secondObj);
		//myFunction now has the properties: 'age', 'sex', and 'lastName', each with its respected values.
	[/javascript]
*/

function $extend(original, extended){
	if (!extended){
		extended = original;
		original = this;
	}
	for (var property in extended) original[property] = extended[property];
	return original;
};

/*
Function: $merge
	Merges any number of objects recursively without referencing them or their sub-objects.

Syntax:
	>var merged = $merge(obj1, obj2[, obj3[, ...]]);

Arguments:
	(objects) Any number of objects.

Returns:
	(object) The object that is created as a result of merging all the objects passed in.

Example:
	[javascript]
		var obj1 = {a: 0, b: 1};
		var obj2 = {c: 2, d: 3};
		var obj3 = {a: 4, d: 5};
		var merged = $merge(obj1, obj2, obj3); //returns {a: 4, b: 1, c: 2, d: 5}, (obj1, obj2, and obj3 are unaltered)

		var nestedObj1 = {a: {b: 1, c: 1}};
		var nestedObj2 = {a: {b: 2}};
		var nested = $merge(nestedObj1, nestedObj2); //returns: {a: {b: 2, c: 1}}
	[/javascript]
*/

function $merge(){
	var mix = {};
	for (var i = 0; i < arguments.length; i++){
		for (var property in arguments[i]){
			var ap = arguments[i][property];
			var mp = mix[property];
			if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap);
			else mix[property] = ap;
		}
	}
	return mix;
};

/*
Function: $pick
	Returns the first defined argument passed in, or null.

Syntax:
	>var picked = $pick(var1[, var2[, var3[, ...]]]);

Arguments:
	(mixed) Any number of variables.

Returns:
	(mixed) The first variable that is defined. If all variables passed in are null or undefined, returns null.

Example:
	[javascript]
		function say(infoMessage, errorMessage){
			alert($pick(errorMessage, infoMessage, 'There was no message supplied.'));
		}
	[/javascript]
*/


function $pick(){
	for (var i = 0, l = arguments.length; i < l; i++){
		if ($defined(arguments[i])) return arguments[i];
	}
	return null;
};

/*
Function: $random
	Returns a random integer number between the two passed in values.

Syntax:
	>var random = $random(min, max);

Arguments:
	min - (number) The minimum value (inclusive).
	max - (number) The maximum value (inclusive).

Returns:
	(number) A random number between min and max.

Example:
	[javascript]
		alert($random(5, 20)); //alerts a random number between 5 and 20
	[/javascript]
*/

function $random(min, max){
	return Math.floor(Math.random() * (max - min + 1) + min);
};

/*
Function: $splat
	Array-ifies the argument passed in if it is defined and not already an array.

Syntax:
	>var splatted = $splat(obj);

Arguments:
	obj - (mixed) Any type of variable.

Returns:
	(array) If the variable passed in is an array, returns the array. Otherwise, returns an array with the only element being the variable passed in.

Examples:
	[javascript]
		var obj = 'hello';
		$splat(obj); //returns ['hello']

		var obj2 = ['a', 'b', 'c'];
		$splat(obj2); //returns ['a', 'b', 'c']
	[/javascript]
*/

function $splat(obj){
	var type = $type(obj);
	return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
};

/*
Function: $time
	Returns the current time as a timestamp.

Syntax:
	>var time = $time();

Returns:
	(number) - Current timestamp.
*/

var $time = Date.now || function(){
	return new Date().getTime();
};

/*
Function: $try
	Tries to execute a function. Returns false if it fails.

Syntax:
	>$try(fn[, bind[, args]]);

Arguments:
	fn   - (function) The function to execute.
	bind - (object, optional: defaults to the function passed in) The object to use as 'this' in the function. For more information see <Function.bind>.
	args - (mixed, optional) Single item or array of items as arguments to be passed to the function.

Returns:
	(mixed) Standard return of the called function, or false on failure.

Example:
	[javascript]
		var result = $try(eval, window, 'some invalid javascript'); //false
	[/javascript]

Note:
	Warning: if the function passed can return false, there will be no way to know if it has been successfully executed or not.
*/

function $try(fn, bind, args){
	try {
		return fn.apply(bind || null, $splat(args));
	} catch(e){
		return false;
	}
};

/*
Function: $type
	Returns the type of object that matches the element passed in.

Syntax:
	>$type(obj);

Arguments:
	obj - (object) The object to inspect.

Returns:
	'element'    - (string) If object is a DOM element node.
	'textnode'   - (string) If object is a DOM text node.
	'whitespace' - (string) If object is a DOM whitespace node.
	'arguments'  - (string) If object is an arguments object.
	'array'      - (string) If object is an array.
	'object'     - (string) If object is an object.
	'string'     - (string) If object is a string.
	'number'     - (string) If object is a number.
	'boolean'    - (string) If object is a boolean.
	'function'   - (string) If object is a function.
	'regexp'     - (string) If object is a regular expression.
	'class'      - (string) If object is a Class (created with new Class, or the extend of another class).
	'collection' - (string) If object is a native htmlelements collection, such as childNodes, getElementsByTagName, etc.
	'window'     - (string) If object passed is the window object.
	'document'   - (string) If passed object is the document object.
	false        - (boolean) If passed object is undefined, null, NaN or none of the above.

Example:
	[javascript]
		var myString = 'hello';
		$type(myString); //returns "string"
	[/javascript]
*/

function $type(obj){
	if (obj == undefined) return false;
	if (obj.htmlElement) return 'element';
	if (obj.$family) return (obj.$family == 'number' && !isFinite(obj)) ? false : obj.$family;
	var type = typeof obj;
	if (obj.nodeName){
		switch (obj.nodeType){
			case 1: return 'element';
			case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
		}
	} else if (typeof obj.length == 'number'){
		if (obj.item) return 'collection';
		if (obj.callee) return 'arguments';
	}
	return type;
};

var Native = function(options){
	options = $extend({name: false, generics: true, browser: false, initialize: $empty, implement: $empty}, options || {});
	var name = options.name, generics = options.generics, initialize = options.initialize, implement = options.implement, browser = options.browser;
	initialize.prototype.constructor = initialize;
	var self = this;
	initialize.implement = function(properties){
		((browser) ? $augment : $extend)(this.prototype, properties);
		if (generics) self.genericize(this, properties);
		implement.call(this, properties);
		return this;
	};
	if (name) initialize.prototype.$family = name.toLowerCase();
	initialize.$family = 'native';
	initialize.constructor = Native;
	return initialize;
};

//Native.Methods = {};

Native.generic = function(object, property){
	return function(){
		var args = Array.prototype.slice.call(arguments);
		return object.prototype[property].apply(args.shift(), args);
	};
};

Native.prototype = {
	
	genericize: function(object, properties){
		for (var property in properties){
			if (object[property] || typeof object.prototype[property] != 'function') continue;
			object[property] = Native.generic(object, property);
		}
	}

};

Native.implement = function(objects, properties){
	for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
};

/*
Object: Client
	Some browser properties are attached to the Client Object for browser and platform detection.

Features:
	Client.Features.xpath - (boolean) Browser supports dom queries using xpath.
	Client.Features.xhr   - (boolean) Browser supports native XMLHTTP object.

Engine:
	Client.Engine.ie        - (boolean) True if the current browser is Internet Explorer (any).
	Client.Engine.ie6       - (boolean) True if the current browser is Internet Explorer 6.
	Client.Engine.ie7       - (boolean) True if the current browser is Internet Explorer 7.
	Client.Engine.gecko     - (boolean) True if the current browser is Mozilla/Gecko.
	Client.Engine.webkit    - (boolean) True if the current browser is Safari/Konqueror.
	Client.Engine.webkit419 - (boolean) True if the current browser is Safari2 / webkit till version 419.
	Client.Engine.webkit420 - (boolean) True if the current browser is Safari3 (Webkit SVN Build) / webkit over version 419.
	Client.Engine.opera     - (boolean) True if the current browser is opera.
	Client.Engine.name      - (string) The name of the engine.

Platform:
	Client.Platform.mac     - (boolean) True if the platform is mac.
	Client.Platform.windows - (boolean) True if the platform is windows.
	Client.Platform.linux   - (boolean) True if the platform is linux.
	Client.Platform.other   - (boolean) True if the platform is neither mac, windows or linux.
	Client.Platform.name    - (string) The name of the platform.

Note:
	Engine detection is entirely feature-based.
*/

var Client = {
	Engine: {'name': 'unknown', 'version': ''},
	Platform: {'name': (navigator.platform.match(/(mac)|(win)|(linux)|(nix)/i) || ['Other'])[0].toLowerCase()},
	Features: {'xhr': !!(window.XMLHttpRequest), 'xpath': !!(document.evaluate)}
};

if (window.opera) Client.Engine.name = 'opera';
else if (window.ActiveXObject) Client.Engine = {'name': 'ie', 'version': (Client.Features.xhr) ? 7 : 6};
else if (!navigator.taintEnabled) Client.Engine = {'name': 'webkit', 'version': (Client.Features.xpath) ? 420 : 419};
else if (document.getBoxObjectFor != null) Client.Engine.name = 'gecko';
Client.Engine[Client.Engine.name] = Client.Engine[Client.Engine.name + Client.Engine.version] = true;

Client.Platform[Client.Platform.name] = true;

/* Native: Document */

var Document = new Native({
	
	name: 'Document',
	
	initialize: function(doc){
		if ($type(doc) == 'document') return doc;
		Document.instances.push(doc);
		doc.head = doc.getElementsByTagName('head')[0];
		doc.window = doc.defaultView || doc.parentWindow;
		return $extend(doc, this);
	},
	
	implement: function(properties){
		for (var i = 0, l = Document.instances.length; i < l; i++) $extend(Document.instances[i], properties);
	}

});

Document.instances = [];

new Document(document);

/* Native: Window */

var Window = new Native({
	
	name: 'Window',
	
	initialize: function(win){
		if ($type(win) == 'window') return win;
		Window.instances.push(win);
		
		if (typeof win.HTMLElement == 'undefined'){
			win.HTMLElement = $empty;
			if (Client.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2
			win.HTMLElement.prototype = (Client.Engine.webkit) ? win["[[DOMElement.prototype]]"] : {};
		}
		
		win.HTMLElement.prototype.htmlElement = $empty;
		
		new Native({
			name: 'HTMLElement',
			initialize: win.HTMLElement,
			browser: false,
			generics: false
		});
		
		return $extend(win, this);
	},
	
	implement: function(properties){
		for (var i = 0, l = Window.instances.length; i < l; i++) $extend(Window.instances[i], properties);
	}
	
});

Window.instances = [];

new Window(window);

(function(){
	
	function natives(){
		for (var i = 0, l = arguments.length; i < l; i++){
			new Native({
				name: arguments[i],
				initialize: window[arguments[i]],
				browser: true
			});
		}
	};
	
	natives('String', 'Function', 'Number', 'Array', 'RegExp');
	
	function generic(object, methods){
		for (var i = 0, l = methods.length; i < l; i++){
			if (!object[methods[i]]) object[methods[i]] = Native.generic(object, methods[i]);
		}
	};
	
	generic(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf']);
	generic(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']);

})();


/*
Script: Array.js
	Contains Array prototypes, <$each>.

License:
	MIT-style license.
*/

/*
Native: Array
	A collection of the Array Object prototype methods.

See Also:
	<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array>
*/


Array.implement({

	/*
	Method: every
		Returns true if every element in the array satisfies the provided testing function.

		This method is provided only for browsers without native <Array.every> support.

	Syntax:
		>var allPassed = myArray.every(fn[, bind]);

	Arguments:
		fn   - (function) The function to test for each element.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(item, index, array)

			Arguments:
				item   - (mixed) The current item in the array.
				index  - (number) The current item's index in the array.
				array  - (array) The actual array.

	Returns:
		(boolean) If every element in the array satisfies the provided testing function, returns true. Otherwise, returns false.

	Example:
		[javascript]
			var areAllBigEnough = [10, 4, 25, 100].every(function(item, index){
				return item > 20;
			}); //areAllBigEnough = false
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every>
	*/

	every: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if (!fn.call(bind, this[i], i, this)) return false;
		}
		return true;
	},

	/*
	Method: filter
		Creates a new array with all of the elements of the array for which the provided filtering function returns true.

		This method is provided only for browsers without native <Array.filter> support.

	Syntax:
		>var filteredArray = myArray.filter(fn[, bind]);

	Arguments:
		fn   - (function) The function to test each element of the array. This function is passed the item and its index in the array.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(item, index, array)

			Arguments:
				item   - (mixed) The current item in the array.
				index  - (number) The current item's index in the array.
				array  - (array) The actual array.

	Returns:
		(array) The new filtered array.

	Example:
		[javascript]
			var biggerThanTwenty = [10, 3, 25, 100].filter(function(item, index){
				return item > 20;
			}); //biggerThanTwenty = [25, 100]
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter>
	*/

	filter: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++){
			if (fn.call(bind, this[i], i, this)) results.push(this[i]);
		}
		return results;
	},

	/*
	Method: forEach
		Calls a function for each element in the array.

		This method is only available for browsers without native <Array.forEach> support.

	Syntax:
		>myArray.forEach(fn[, bind]);

	Arguments:
		fn   - (function) The function which should be executed on each item in the array. This function is passed the item and its index in the array.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(item, index, array)

			Arguments:
				item   - (mixed) The current item in the array.
				index  - (number) The current item's index in the array.
				array  - (array) The actual array.

	Example:
		[javascript]
			['apple', 'banana', 'lemon'].forEach(function(item, index){
				alert(index + " = " + item); //alerts "0 = apple" etc.
			}, bind); //optional second argument for binding, not used here
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
	*/

	forEach: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);
	},

	/*
	Method: indexOf
		Returns the index of the first element within the array equal to the specified value, or -1 if the value is not found.

		This method is provided only for browsers without native <Array.indexOf> support.

	Syntax:
		>var index = myArray.indexOf(item[, from]);

	Returns:
		(number) The index of the first element within the array equal to the specified value. If not found, returns -1.

	Arguments:
		item - (object) The item to search for in the array.
		from - (number, optional: defaults to 0) The index of the array at which to begin the search.

	Example:
		[javascript]
			['apple', 'lemon', 'banana'].indexOf('lemon'); //returns 1
			['apple', 'lemon'].indexOf('banana'); //returns -1
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf>
	*/

	indexOf: function(item, from){
		var len = this.length;
		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
			if (this[i] === item) return i;
		}
		return -1;
	},

	/*
	Method: map
		Creates a new array with the results of calling a provided function on every element in the array.

		This method is provided only for browsers without native <Array.map> support.

	Syntax:
		>var mappedArray = myArray.map(fn[, bind]);

	Arguments:
		fn   - (function) The function to produce an element of the new Array from an element of the current one.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(item, index, array)

			Arguments:
				item   - (mixed) The current item in the array.
				index  - (number) The current item's index in the array.
				array  - (array) The actual array.

	Returns:
		(array) The new mapped array.

	Example:
		[javascript]
			var timesTwo = [1, 2, 3].map(function(item, index){
				return item * 2;
			}); //timesTwo = [2, 4, 6];
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map>
	*/

	map: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
		return results;
	},

	/*
	Method: some
		Returns true if at least one element in the array satisfies the provided testing function.

		This method is provided only for browsers without native <Array.some> support.

	Syntax:
		>var somePassed = myArray.some(fn[, bind]);

	Returns:
		(boolean) If at least one element in the array satisfies the provided testing function returns true. Otherwise, returns false.

	Arguments:
		fn   - (function) The function to test for each element. This function is passed the item and its index in the array.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(item, index, array)

			Arguments:
				item   - (mixed) The current item in the array.
				index  - (number) The current item's index in the array.
				array  - (array) The actual array.

	Example:
		[javascript]
			var isAnyBigEnough = [10, 4, 25, 100].some(function(item, index){
				return item > 20;
			}); //isAnyBigEnough = true
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some>
	*/

	some: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if (fn.call(bind, this[i], i, this)) return true;
		}
		return false;
	},

	/*
	Method: reduce
		Apply a function simultaneously against two values of the array (from left-to-right) as to reduce it to a single value.

		This method is provided only for browsers without native <Array.reduce> support.

	Syntax:
		>var reduced = myArray.reduce(fn[, value]);

	Arguments:
		fn    - (function) Function to execute on each value in the array.
		value - (object, optional) Object to use as the initial argument to the first call of the callback.

		fn (continued):
			Signature:
				>fn(previous, current, index, array)

			Arguments:
				previous - (mixed) The item prior to the current item in the array.
				current  - (mixed) The current item in the array.
				index    - (number) The current item's index in the array.
				array    - (array) The actual array.

	Returns:
		(mixed) The result of reducing this array according to fn.

	Examples:
		Sum Up Numbers:
		[javascript]
			var sum = [1, 2, 3, 4, 6].reduce(function(previousItem, currentItem){
				return previousItem + currentItem;
			}, 10); //sum is 26
		[/javascript]

		Collect Elements of Many Arrays Into a Single Array:
		[javascript]
			var collected = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g']].reduce(function(previousItem, currentItem) {
				return previousItem.concat(currentItem);
			}, []); //collected is ['a', 'b', 'c', 'd', 'e', 'f', 'g']
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:reduce>
	*/

	reduce: function(fn, value){
		var i = 0;
		if (arguments.length < 2 && this.length) value = this[i++];
		for (var l = this.length; i < l; i++) value = fn.call(null, value, this[i], i, this);
		return value;
	},

	/*
	Method: associate
		Creates an object with key-value pairs based on the array of keywords passed in and the current content of the array.
		Can also accept an object of key / type pairs to assign values.

	Syntax:
		>var associated = myArray.associate(obj);

	Arguments:
		obj - (mixed) If an array is passed, its items will be used as the keys of the object that will be created.
			Alternatively, an object containing key / type pairs may be passed and used as a template for associating values with the different keys.

	Returns:
		(object) The new associated object.

	Examples:
		Array Example:
		[javascript]
			var animals = ['Cow', 'Pig', 'Dog', 'Cat'];
			var sounds = ['Moo', 'Oink', 'Woof', 'Miao'];
			animals.associate(sounds);
			//returns {'Cow': 'Moo', 'Pig': 'Oink', 'Dog': 'Woof', 'Cat': 'Miao'}
		[/javascript]

		Object Example:
		[javascript]
			var values = [100, 'Hello', {foo: 'bar'}, $('myelement')];
			values.associate({myNumber: 'number', myElement: 'element', myObject: 'object', myString: 'string'});
			//returns {myNumber: 100, myElement: <div id="myelement">, myObject: {foo: bar}, myString: Hello}
		[/javascript]
	*/

	associate: function(obj){
		var routed = {};
		var objtype = $type(obj);
		if (objtype == 'array'){
			var temp = {};
			for (var i = 0, j = obj.length; i < j; i++) temp[obj[i]] = true;
			obj = temp;
		}
		for (var oname in obj) routed[oname] = null;
		for (var k = 0, l = this.length; k < l; k++){
			var res = (objtype == 'array') ? $defined(this[k]) : $type(this[k]);
			for (var name in obj){
				if (!$defined(routed[name]) && ((res && obj[name] === true) || obj[name].contains(res))){
					routed[name] = this[k];
					break;
				}
			}
		}
		return routed;
	},

	/*
	Method: contains
		Tests an array for the presence of an item.

	Syntax:
		>var inArray = myArray.contains(item[, from]);

	Arguments:
		item - (object) The item to search for in the array.
		from - (number, optional: defaults to 0) The index of the array at which to begin the search.

	Returns:
		(boolean) If the array contains the item specified, returns true. Otherwise, returns false.

	Example:
		[javascript]
			["a","b","c"].contains("a"); //returns true
			["a","b","c"].contains("d"); //returns false
		[/javascript]

	See Also:
		<Array.indexOf>
	*/

	contains: function(item, from){
		return this.indexOf(item, from) != -1;
	},

	/*
	Method: extend
		Extends an array with all the items of another.

	Syntax:
		>myArray.extend(array);

	Arguments:
		array - (array) The array whose items should be extended into this array.

	Returns:
		(array) This array, extended.

	Example:
		[javascript]
			var animals = ['Cow', 'Pig', 'Dog'];
			animals.extend(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat', 'Dog'];
		[/javascript]
	*/

	extend: function(array){
		for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
		return this;
	},

	/*
	Method: getLast
		Returns the last item from the array.

	Syntax:
		>myArray.getLast();

	Returns:
		(mixed) The last item in this array. If this array is empty, returns null.

	Example:
		[javascript]
			['Cow', 'Pig', 'Dog', 'Cat'].getLast(); //returns 'Cat'
		[/javascript]
	*/

	getLast: function(){
		return (this.length) ? this[this.length - 1] : null;
	},

	/*
	Method: getRandom
		Returns a random item from the array.

	Syntax:
		>myArray.getRandom();

	Returns:
		(mixed) A random item from this array. If this array is empty, returns null.

	Example:
		[javascript]
			['Cow', 'Pig', 'Dog', 'Cat'].getRandom(); //returns one of the items
		[/javascript]
	*/

	getRandom: function(){
		return (this.length) ? this[$random(0, this.length - 1)] : null;
	},

	/*
	Method: include
		Pushes the passed element into the array if it's not already present (case and type sensitive).

	Syntax:
		>myArray.include(item);

	Arguments:
		item - (object) The item that should be added to this array.

	Returns:
		(array) This array with the new item included.

	Example:
		[javascript]
			['Cow', 'Pig', 'Dog'].include('Cat'); //returns ['Cow', 'Pig', 'Dog', 'Cat']
			['Cow', 'Pig', 'Dog'].include('Dog'); //returns ['Cow', 'Pig', 'Dog']
		[/javascript]
	*/

	include: function(item){
		if (!this.contains(item)) this.push(item);
		return this;
	},

	/*
	Method: merge
		Merges an array with all the items of another. Does not allow duplicates and is case and type sensitive.

	Syntax:
		>myArray.merge(array);

	Arguments:
		array - (array) The array whose items should be merged into this array.

	Returns:
		(array) This array merged with the new items.

	Example:
		[javascript]
			var animals = ['Cow', 'Pig', 'Dog'];
			animals.merge(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat'];
		[/javascript]
	*/

	merge: function(array){
		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
		return this;
	},

	/*
	Method: remove
		Removes all occurrences of an item from the array.

	Syntax:
		>myArray.remove(item);

	Arguments:
		item - (object) The item to search for in the array.

	Returns:
		(array) This array with all occurrences of the item removed.

	Example:
		[javascript]
			['Cow', 'Pig', 'Dog', 'Cat', 'Dog'].remove('Dog') //returns ['Cow', 'Pig', 'Cat']
			['Cow', 'Pig', 'Dog'].remove('Cat') //returns ['Cow', 'Pig', 'Dog']
		[/javascript]
	*/

	remove: function(item){
		for (var i = this.length; i--;){
			if (this[i] === item) this.splice(i, 1);
		}
		return this;
	},

	/*
	Method: empty
		Empties an array.

	Syntax:
		>myArray.empty();

	Returns:
		(array) This array, emptied.

	Example:
		[javascript]
			var myArray = ['old', 'data'];
			myArray.empty(); //myArray is now []
		[/javascript]
	*/

	empty: function(){
		this.length = 0;
		return this;
	}

});

/*
Method: each
	Same as <Array.forEach>.

Syntax:
	>myArray.each(fn[, bind]);

Arguments:
	fn   - (function) The function which should be executed on each item in the array. This function is passed the item and its index in the array.
	bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

	fn (continued):
		Signature:
			>fn(item, index, array)

		Arguments:
			item   - (mixed) The current item in the array.
			index  - (number) The current item's index in the array.
			array  - (array) The actual array.

Example:
	[javascript]
		['apple','banana','lemon'].each(function(item, index){
			alert(index + " = " + item); //alerts "0 = apple" etc.
		}, bind); //optional second argument for binding, not used here
	[/javascript]
*/


Array.prototype.each = Array.prototype.forEach;
Array.each = Array.forEach;

/* Section: Utility Functions */

/*
Function: $each
	Use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, arguments of a function, or an object.

Syntax:
	>$each(iterable, fn[, bind]);

Arguments:
	iterable - (object or array) The object or array to iterate through.
	fn       - (function) The function to test for each element.
	bind     - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

	fn (continued):
		Signature:
			>fn(item, index, object)

		Arguments:
			item   - (mixed) The current item in the array.
			index  - (number) The current item's index in the array. In the case of an object, it is passed the key of that item rather than the index.
			object - (mixed) The actual array/object.

Examples:
	Array example:
	[javascript]
		$each(['Sun','Mon','Tue'], function(day, index){
			alert('name:' + day + ', index: ' + index);
		}); //alerts "name: Sun, index: 0", "name: Mon, index: 1", etc.
	[/javascript]

	Object example:
	[javascript]
		$each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
			alert("the " + key + " day of the week is " + value);
		}); //alerts "the first day of the week is Sunday", "the second day of the week is Monday", etc.
	[/javascript]
*/

function $each(iterable, fn, bind){
	var type = $type(iterable);
	if (!type) return;
	((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
};

/*
Script: String.js
	Contains String prototypes.

License:
	MIT-style license.
*/

/*
Native: String
	A collection of the String Object prototype methods.

See Also:
	<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:String>
*/

String.implement({

	/*
	Method: test
		Searches for a match between the string and a regular expression.
		For more information see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test>.

	Syntax:
		>myString.test(regex[,params]);

	Arguments:
		regex  - (mixed) The string or regular expression you want to match the string with.
		params - (string, optional) If first parameter is a string, any parameters you want to pass to the regular expression ('g' has no effect).

	Returns:
		(boolean) If a match for the regular expression is found in this string returns true. Otherwise, returns false.

	Example:
		[javascript]
			"I like cookies".test("cookie"); //returns true
			"I like cookies".test("COOKIE", "i"); //returns true (ignore case)
			"I like cookies".test("cake"); //returns false
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions>
	*/

	test: function(regex, params){
		return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
	},

	/*
	Method: contains
		Checks to see if the string passed in is contained in this string.
		If the separator parameter is passed, will check to see if the string is contained in the list of values separated by that parameter.

	Syntax:
		>myString.contains(string[, separator]);

	Arguments:
		string    - (string) The string to search for.
		separator - (string, optional) The string that separates the values in this string (eg. Element classNames are separated by a ' ').

	Returns:
		(boolean) If the string is contained in this string, returns true. Otherwise, returns false.

	Example:
		[javascript]
			'a bc'.contains('bc'); //returns true
			'a b c'.contains('c', ' '); //returns true
			'a bc'.contains('b', ' '); //returns false
		[/javascript]
	*/

	contains: function(string, separator){
		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
	},

	/*
	Method: trim
		Trims the leading and trailing spaces off a string.

	Syntax:
		>myString.trim();

	Returns:
		(string) The trimmed string.

	Example:
		[javascript]
			"    i like cookies     ".trim(); //"i like cookies"
		[/javascript]
	*/

	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	/*
	Method: clean
		Removes all extraneous whitespace from a string and trims (<String.trim>) it.

	Syntax:
		>myString.clean();

	Returns:
		(string) The cleaned string.

	Example:
		[javascript]
			" i      like     cookies      \n\n".clean(); //returns "i like cookies"
		[/javascript]
	*/

	clean: function(){
		return this.replace(/\s{2,}/g, ' ').trim();
	},

	/*
	Method: camelCase
		Converts a hyphenated string to a camelcased string.

	Syntax:
		>myString.camelCase();

	Returns:
		(string) The camelcased string.

	Example:
		[javascript]
			"I-like-cookies".camelCase(); //returns "ILikeCookies"
		[/javascript]
	*/

	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	/*
	Method: hyphenate
		Converts a camelcased string to a hyphenated string.

	Syntax:
		>myString.hyphenate();

	Returns:
		(string) The hyphenated string.

	Example:
		[javascript]
			"ILikeCookies".hyphenate(); //returns "I-like-cookies"
		[/javascript]
	*/

	hyphenate: function(){
		return this.replace(/[A-Z]/g, function(match){
			return ('-' + match.charAt(0).toLowerCase());
		});
	},

	/*
	Method: capitalize
		Converts the first letter of each word in a string to uppercase.

	Syntax:
		>myString.capitalize();

	Returns:
		(string) The capitalized string.

	Example:
		[javascript]
			"i like cookies".capitalize(); //returns "I Like Cookies"
		[/javascript]
	*/

	capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	/*
	Method: escapeRegExp
		Escapes all regular expression characters from the string.

	Syntax:
		>myString.escapeRegExp();

	Returns:
		(string) The escaped string.

	Example:
		[javascript]
			'animals.sheep[1]'.escapeRegExp(); //returns 'animals\.sheep\[1\]'
		[/javascript]
	*/

	escapeRegExp: function(){
		return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
	},

	/*
	Method: toInt
		Parses this string and returns a number of the specified radix or base.

	Syntax:
		>myString.toInt([base]);

	Arguments:
		base - (number, optional) The base to use (defaults to 10).

	Returns:
		(mixed) The number. If the string is not numeric, returns NaN.

	Example:
		[javascript]
			"4em".toInt(); //returns 4
			"10px".toInt(); //returns 10
		[/javascript]

	See Also:
		 <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:parseInt>
	*/

	toInt: function(base){
		return parseInt(this, base || 10);
	},

	/*
	Method: toFloat
		Parses this string and returns a floating point number.

	Syntax:
		>myString.toFloat();

	Returns:
		(mixed) The float. If the string is not numeric, returns NaN.

	Example:
		[javascript]
			"95.25%".toFloat(); //returns 95.25
			"10.848".toFloat(); //returns 10.848
		[/javascript]

		See Also:
			<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:parseFloat>
	*/

	toFloat: function(){
		return parseFloat(this);
	},

	/*
	Method: hexToRgb
		Converts a hexidecimal color value to RGB. Input string must be in one of the following hexidecimal color formats (with or without the hash).
		>'#ffffff', #fff', 'ffffff', or 'fff'

	Syntax:
		>myString.hexToRgb([array]);

	Arguments:
		array - (boolean, optional) If true is passed, will output an array (eg. ['ff','33','00']) instead of a string (eg. "#ff3300").

	Returns:
		(mixed) A string representing the color in RGB. If the array flag is set, an array will be returned instead.

	Example:
		[javascript]
			"#123".hexToRgb(); //returns "rgb(17,34,51)"
			"112233".hexToRgb(); //returns "rgb(17,34,51)"
			"#112233".hexToRgb(true); //returns [17,34,51]
		[/javascript]

	See Also:
		 <Array.hexToRgb>
	*/

	hexToRgb: function(array){
		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		return (hex) ? hex.slice(1).hexToRgb(array) : null;
	},

	/*
	Method: rgbToHex
		Converts an RGB color value to hexidecimal. Input string must be in one of the following RGB color formats.
		>"rgb(255,255,255)", or "rgba(255,255,255,1)"

	Syntax:
		>myString.rgbToHex([array]);

	Arguments:
		array - (boolean, optional) If true is passed, will output an array (eg. ['ff','33','00']) instead of a string (eg. "#ff3300").

	Returns:
		(mixed) A string representing the color in hexadecimal,
		or transparent if the fourth value of rgba in the input string is 0. If the array flag is set, an array will be returned instead.

	Example:
		[javascript]
			"rgb(17,34,51)".rgbToHex(); //returns "#112233"
			"rgb(17,34,51)".rgbToHex(true); //returns ['11','22','33']
			"rgba(17,34,51,0)".rgbToHex(); //returns "transparent"
		[/javascript]

	See Also:
		 <Array.rgbToHex>
	*/

	rgbToHex: function(array){
		var rgb = this.match(/\d{1,3}/g);
		return (rgb) ? rgb.rgbToHex(array) : null;
	}

});

/*
Native: Array
	Contains Array prototypes.

See Also:
	<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array>
*/

Array.implement({

	/*
	Method: hexToRgb
		Converts a hexidecimal color value to RGB. Input array must be in one of the following hexidecimal color formats.
		>['ff', 'ff', 'ff'], or ['f', 'f', 'f']

	Syntax:
		myArray.hexToRgb([array]);

	Arguments:
		array - (boolean, optional) If true is passed, will output an array (eg. ['ff','33','00']) instead of a string (eg. "#ff3300").

	Returns:
		(mixed) A string representing the color in RGB. If the array flag is set, an array will be returned instead.

	Example:
		[javascript]
			["1", "2", "3"].hexToRgb(); //returns "rgb(17,34,51)"
			["11", "22", "33"].hexToRgb(); //returns "rgb(17,34,51)"
			["11", "22", "33"].hexToRgb(true); //returns [17,34,51]
		[/javascript]

	See Also:
		 <String.hexToRgb>
	*/

	hexToRgb: function(array){
		if (this.length != 3) return null;
		var rgb = [];
		for (var i = 0; i < 3; i++){
			rgb.push(((this[i].length == 1) ? this[i] + this[i] : this[i]).toInt(16));
		}
		return array ? rgb : 'rgb(' + String(rgb) + ')';
	},

	/*
	Method: rgbToHex
		Converts an RGB color value to hexidecimal. Input array must be in one of the following RGB color formats.
		>[255,255,255], or [255,255,255,1]

	Syntax:
		>myArray.rgbToHex([array]);

	Arguments:
		array - (boolean, optional) If true is passed, will output an array (eg. ['ff','33','00']) instead of a string (eg. "#ff3300").

	Returns:
		(mixed) A string representing the color in hexadecimal, or transparent if the fourth value of rgba in the input array is 0.
		If the array flag is set, an array will be returned instead.

	Example:
		[javascript]
			[17,34,51].rgbToHex(); //returns "#112233"
			[17,34,51].rgbToHex(true); //returns ['11','22','33']
			[17,34,51,0].rgbToHex(); //returns "transparent"
		[/javascript]

	See Also:
		 <String.rgbToHex>
	*/

	rgbToHex: function(array){
		if (this.length < 3) return null;
		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (this[i] - 0).toString(16);
			hex.push((bit.length == 1) ? '0' + bit : bit);
		}
		return array ? hex : '#' + hex.join('');
	}

});

/*
Script: Function.js
	Contains Function prototypes and utility functions.

License:
	MIT-style license.
*/

/*
Native: Function
	A collection of The Function Object prototype methods.

See Also:
	 <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Function>
*/

Function.implement({

	extend: $extend,

	/*
	Method: create
		Base function for creating functional closures which is used by all other Function prototypes.

	Syntax:
		>var createdFunction = myFunction.create([options]);

	Arguments:
		options - (object, optional) The options from which the function will be created. If options is not provided, then creates a copy of the function.

		options (continued):
			bind       - (object: defaults to this function) The object that the "this" of the function will refer to.
			event      - (mixed: defaults to false) If set to true, the function will act as an event listener and receive an event as its first argument. If set to a class name, the function will receive a new instance of this class (with the event passed as argument's constructor) as first argument.
			arguments  - (mixed: defaults to standard arguments) A single argument or an array of arguments that will be passed as arguments to the function. If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow.
			delay      - (number: defaults to no delay) If set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called.
			periodical - (number: defaults to no periodical execution) If set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called.
			attempt    - (boolean: false) If set to true, the returned function will try to execute and return either the results or false on error.

	Returns:
		(function) The function that was created as a result of the options passed in.

	Example:
		[javascript]
			var myFunction = function(){
				alert("I'm a function :)");
			};

			var mySimpleFunction = myFunction.create(); //just a simple copy

			var myAdvancedFunction = myFunction.create({ //when called, this function will attempt
				arguments: [0,1,2,3],
				attempt: true,
				delay: 1000,
				bind: myElement
			});
		[/javascript]
	*/

	create: function(options){
		var self = this;
		options = options || {};
		return function(event){
			var args = $splat($pick(options.arguments, arguments));
			if (options.event) args = [event || window.event].extend(args);
			var returns = function(){
				return self.apply($pick(options.bind, self), args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt) return $try(returns);
			return returns();
		};
	},

	/*
	Method: pass
		Returns a closure with arguments and bind.

	Syntax:
		>var newFunction = myFunction.pass([args[, bind]]);

	Arguments:
		args - (mixed, optional) The arguments to pass to the function (must be an array if passing more than one argument).
		bind - (object, optional) The object that the "this" of the function will refer to.

	Returns:
		(function) The function whose arguments are passed when called.

	Example:
		[javascript]
			var myFunction = function(){
				var result = 'Passed: ';
				for(var i = 0, l = arguments.length; i < l; i++){
					result += (arguments[i] + ' ');
				}
				return result;
			}
			var myHello = myFunction.pass('hello');
			var myItems = myFunction.pass(['peach', 'apple', 'orange']);

			//when ready I can execute the functions.
			alert(myHello());
			alert(myItems());
		[/javascript]
	*/

	pass: function(args, bind){
		return this.create({'arguments': args, 'bind': bind});
	},

	/*
	Method: attempt
		Tries to execute the function.

	Syntax:
		>var result = myFunction.attempt([args[, bind]]);

	Arguments:
		args - (mixed, optional) The arguments to pass to the function (must be an array if passing more than one argument).
		bind - (object, optional) The object that the "this" of the function will refer to.

	Returns:
		(mixed) False if an exception is thrown, else the function's return.

	Example:
		[javascript]
			var myObject = {
				'cow': 'moo!'
			};

			var myFunction = function(){
				for(var i = 0; i < arguments.length; i++){
					if(!this[arguments[i]]) throw('doh!');
				}
			};
			var result = myFunction.attempt(['pig', 'cow'], myObject); // false
		[/javascript]
	*/

	attempt: function(args, bind){
		return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
	},

	/*
	Method: bind
		Returns a function whose "this" is altered.

	Syntax:
		>myFunction.bind([bind[, args[, evt]]]);

	Arguments:
		bind - (object, optional) The object that the "this" of the function will refer to.
		args - (mixed, optional) The arguments to pass to the function (must be an array if passing more than one argument).
		evt  - (mixed, optional) Used to signifiy that the function is an Event Listener. See <Function.create> Options section for more information.

	Returns:
		(function) The binded function.

	Example:
		[javascript]
			function myFunction(){
				this.setStyle('color', 'red');
				// note that 'this' here refers to myFunction, not an element
				// we'll need to bind this function to the element we want to alter
			};
			var myBoundFunction = myFunction.bind(myElement);
			myBoundFunction(); // this will make the element myElement red.
		[/javascript]
	*/

	bind: function(bind, args, evt){
		return this.create({'bind': bind, 'arguments': args, 'event': evt});
	},

	/*
	Method: delay
		Delays the execution of a function by a specified duration.

	Syntax:
		>var timeoutID = myFunction.delay([delay[, bind[, args]]]);

	Arguments:
		delay - (number, optional) The duration to wait (in milliseconds).
		bind  - (object, optional) The object that the "this" of the function will refer to.
		args  - (mixed, optional) The arguments passed (must be an array if the arguments are greater than one).

	Returns:
		(number) The JavaScript Timeout ID (useful for clearing delays).

	Example:
		[javascript]
			var myFunction = function(){ alert('moo! Element id is: ' + this.id); };
			//wait 50 milliseconds, then call myFunction and bind myElement to it
			myFunction.delay(50, myElement); // alerts: 'moo! Element id is: ... '

			// An anonymous function, example
			(function(){ alert('one second later...'); }).delay(1000); //wait a second and alert
		[/javascript]

	See Also:
		<$clear>, <http://developer.mozilla.org/en/docs/DOM:window.setTimeout>
	*/

	delay: function(delay, bind, args){
		return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
	},

	/*
	Method: periodical
		Executes a function in the specified intervals of time

	Syntax:
		>var intervalID = myFunction.periodical([period[, bind[, args]]]);

	Arguments:
		period - (number, optional) The duration of the intervals between executions.
		bind   - (object, optional) The object that the "this" of the function will refer to.
		args   - (mixed, optional) The arguments passed (must be an array if the arguments are greater than one).

	Returns:
		(number) The Interval ID (useful for clearing a periodical).

	Example:
		[javascript]
			var Site = { counter: 0 };
			var addCount = function(){ this.counter++; };
			addCount.periodical(1000, Site); // will add the number of seconds at the Site
		[/javascript]

	See Also:
		<$clear>, <http://developer.mozilla.org/en/docs/DOM:window.setInterval>
	*/

	periodical: function(interval, bind, args){
		return this.create({'periodical': interval, 'bind': bind, 'arguments': args})();
	},

	/*
	Method: run
		Runs the Function with specified arguments and binding. Kinda like .apply but reversed and with support for single argument.

	Syntax:
		>var myFunctionResult = myFunction.run(args[, bind]);

	Arguments:
		args - (mixed) An argument, or array of arguments to run the function with.
		bind - (object, optional) The object that the "this" of the function will refer to.

	Returns:
		(mixed) This Function's return.

	Examples:
		Simple run:
		[javascript]
			var myFn = function(a, b, c){
				return a + b + c;
			}
			var myArgs = [1,2,3];
			myFn.run(args); //returns 6
		[/javascript]

		Run with binding:
		[javascript]
			var myFn = function(a, b, c){
				return a + b + c + this;
			}
			var myArgs = [1,2,3];
			myFn.run(args, 6); //returns 12
		[/javascript]
	*/

	run: function(args, bind){
		return this.apply(bind, $splat(args));
	}

});

Function.empty = $empty;

/*
Script: Number.js
	Contains the Number prototypes.

License:
	MIT-style license.
*/

/*
Native: Number
	A collection of the Number Object prototype methods.

See Also:
	<http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Number>
*/

Number.implement({

	/*
	Method: limit
		Limits this number between two bounds.

	Syntax:
		>myNumber.limit(min, max);

	Arguments:
		min - (number) The minimum possible value.
		max - (number) The maximum possible value.

	Returns:
		(number) The number bounded between the given limits.

	Example:
		[javascript]
			(12).limit(2, 6.5); //returns 6.5
			(-4).limit(2, 6.5); //returns 2
			(4.3).limit(2, 6.5); //returns 4.3
		[/javascript]
	*/

	limit: function(min, max){
		return Math.min(max, Math.max(min, this));
	},

	/*
	Method: round
		Returns this number rounded to the specified precision.

	Syntax:
		>myNumber.round([precision]);

	Arguments:
		precision - (number, optional: defaults to 0) The number of digits after the decimal place.

	Returns:
		(number) The number, rounded.

	Note:
		Argument may also be negative.

	Example:
		[javascript]
			(12.45).round() //returns 12
			(12.45).round(1) //returns 12.5
			(12.45).round(-1) //returns 10
		[/javascript]
	*/

	round: function(precision){
		precision = Math.pow(10, precision || 0);
		return Math.round(this * precision) / precision;
	},

	/*
	Method: times
		Executes the function passed in the specified number of times.

	Syntax:
		>myNumber.times(fn[, bind]);

	Arguments:
		fn   - (function) The function which should be executed on each iteration of the loop. This function is passed the current iteration's index.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

	Example:
		[javascript]
			(4).times(alert); //alerts 0, 1, 2, 3
		[/javascript]
	*/

	times: function(fn, bind){
		for (var i = 0; i < this; i++) fn.call(bind, i, this);
	},

	/*
	Method: toFloat
		Returns this number as a float. Useful because toFloat must work on both Strings and Numbers.

	Syntax:
		>myNumber.toFloat();

	Returns:
		(number) The number as a float.

	Example:
		[javascript]
			(111).toFloat(); //returns 111
			(111.1).toFloat(); //returns 111.1
		[/javascript]
	*/

	toFloat: function(){
		return parseFloat(this);
	},

	/*
	Method: toInt
		Returns this number as another number with the passed in base. Useful because toInt must work on both Strings and Numbers.

	Syntax:
		>myNumber.toInt([base]);

	Arguments:
		base - (number, optional: defaults to 10) The base to use.

	Returns:
		(number) A number with the base provided.

	Example:
		[javascript]
			(111).toInt(); //returns 111
			(111.1).toInt(); //returns 111
			(111).toInt(2); //returns 7
		[/javascript]
	*/

	toInt: function(base){
		return parseInt(this, base || 10);
	}

});

/*
Script: Hash.js
	Contains the Hash implementation for custom Object prototypes.

License:
	MIT-style license.
*/

/*
Native: Hash
	A Custom "Object" ({}) implementation which does not account for prototypes when setting, getting, iterating.
*/

var Hash = new Native({

	name: 'Hash',

	initialize: function(object){
		if (object){
			if ($type(object) == 'hash') return object;
			this.extend(object);
		}
		return this;
	}

});

function $H(object){
	return new Hash(object);
};

Hash.implement({

	/*
	Method: each
		Calls a function for each key-value pair in the object.

	Syntax:
		>myArray.forEach(fn[, bind]);

	Arguments:
		fn   - (function) The function which should be executed on each item in the array. This function is passed the item and its index in the array.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(value, key, hash)

			Arguments:
				value - (mixed) The current value in the hash.
				key   - (string) The current value's key in the hash.
				hash  - (hash) The actual hash.

	Example:
		[javascript]
			var hash = new Hash({first: "Sunday", second: "Monday", third: "Tuesday"});
			hash.each(function(value, key){
				alert("the " + key + " day of the week is " + value);
			}); //alerts "the first day of the week is Sunday", "the second day of the week is Monday", etc.
		[/javascript]
	*/

	each: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
		}
	},

	/*
	Method: contains
		Tests for the presence of a specified key in the Hash.

	Syntax:
		>var inHash = myHash.contains(item);

	Arguments:
		key - (string) The key to search for in the Hash.

	Returns:
		(boolean) If the Hash has a defined value for the specified key, returns true. Otherwise, returns false.

	Example:
		[javascript]
			var hash = new Hash({'a': 'one', 'b': 'two', 'c': 'three'});
			hash.contains('a'); //returns true
			hash.contains('d'); //returns false
		[/javascript]

	Notes:
		Testing for a Hash prototype will never return true. Only testing the actual properties of the Hash will return true.
	*/

	contains: function(key){
		return this.hasOwnProperty(key);
	},

	/*
	Method: extend
		Extends this Hash with the key-value pairs from the object passed in.

	Syntax:
		>myHash.extend(properties);

	Arguments:
		properties - (object) The object whose items should be extended into this Hash.

	Returns:
		(hash) This Hash, extended.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			var properties = {
				'age': '20',
				'sex': 'male',
				'lastName': 'Dorian'
			};
			hash.extend(properties);
			//hash now holds an object containing: { 'name': 'John', 'lastName': 'Dorian', 'age': '20', 'sex': 'male' };
		[/javascript]
	*/

	extend: function(properties){
		Hash.each(properties, function(value, key){
			this[key] = value;
		}, this);
		return this;
	},

	/*
	Method: merge
		Merges this Hash with the key-value pairs of the object passed in. Does not allow duplicates and is case and type sensitive.

	Syntax:
		>myHash.merge(properties);

	Arguments:
		properties - (object) The object whose items should be merged into this Hash.

	Returns:
		(hash) This Hash, merged with the new key-value pairs.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			var properties = {
				'age': '20',
				'sex': 'male',
				'lastName': 'Dorian'
			};
			hash.merge(properties);
			//hash now holds an object containing: { 'name': 'John', 'lastName': 'Doe', 'age': '20', 'sex': 'male' };
		[/javascript]
	*/

	merge: function(properties){
		Hash.each(properties, function(value, key){
			this.include(key, value);
		}, this);
		return this;
	},

	/*
	Method: remove
		Removes the specified key from the Hash.

	Syntax:
		>myHash.remove(key);

	Arguments:
		key - (string) The key to search for in the Hash.

	Returns:
		(hash) This Hash with the specified key and its value removed.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			hash.remove('lastName');
			//hash now holds an object containing: { 'name': 'John' };
		[/javascript]
	*/

	remove: function(key){
		if (this.contains(key)) delete this[key];
		return this;
	},

	/*
	Method: get
		Retrieves a value from the hash, or if no key is specified, returns a clean copy of the object that this Hash holds.

	Syntax:
		>myHash.get([key]);

	Arguments:
		key - (string, optional) The key to search for in the Hash.

	Returns:
		(mixed) If a key is specified, returns the value that corresponds to the key if found, or null if the key doesn't exist.
			If no argument is passed, a clean copy of the object this Hash holds is returned.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			hash.get('name'); //returns 'John'
			hash.get(); //returns { 'name': 'John', 'lastName': 'Doe' }
		[/javascript]
	*/

	get: function(key){
		if (key) return (this.contains(key)) ? this[key] : null;
		var clean = {};
		this.each(function(value, key){
			clean[key] = value;
		});
		return clean;
	},

	/*
	Property: getKeys
		Returns an array containing all the keys, in the same order as the values returned by <Hash.getValues>.

	Syntax:
		>var keys = myHash.getKeys();

	Returns:
		(array) An array containing all the keys of the hash.
	*/

	getKeys: function(){
		var keys = [];
		Hash.each(this, function(value, key){
			keys.push(key);
		});
		return keys;
	},

	/*
	Property: getValues
		Returns an array containing all the values, in the same order as the keys returned by <Hash.getKeys>.

	Syntax:
		>var values = myHash.getValues();

	Returns:
		(array) An array containing all the values of the hash.
	*/

	getValues: function(){
		var values = [];
		Hash.each(this, function(value, key){
			values.push(value);
		});
		return values;
	},

	/*
	Method: set
		Adds a key-value pair to the hash or replaces a previous value associated with the specified key.

	Syntax:
		>myHash.set(key, value);

	Arguments:
		key   - (string) The key to insert or modify in the Hash.
		value - (mixed) The value to associate with the specified key in the Hash.

	Returns:
		(hash) This Hash with the specified key set to the specified value.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			hash.set('name', 'Michelle'); //hash.name is now 'Michelle'
		[/javascript]
	*/

	set: function(key, value){
		if (!this[key] || this.contains(key)) this[key] = value;
		return this;
	},

	/*
	Method: empty
		Empties the hash.

	Syntax:
		>myHash.empty();

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			hash.empty();
			//hash now holds an empty object: {}
		[/javascript]
	*/

	empty: function(){
		Hash.each(this, function(value, key){
			delete this[key];
		}, this);
	},

	/*
	Method: include
		Includes the specified key-value pair in the Hash if the key doesn't already exist.

	Syntax:
		>myHash.include(key, value);

	Arguments:
		key   - (string) The key to insert into the Hash.
		value - (mixed) The value to associate with the specified key in the Hash.

	Returns:
		(hash) This Hash with the specified key included if it did not previously exist.

	Example:
		[javascript]
			var hash = new Hash({
				'name': 'John',
				'lastName': 'Doe'
			});
			hash.include('name', 'Michelle'); //hash is unchanged
			hash.include('age', 25); //hash.age is now 25
		[/javascript]
	*/

	include: function(key, value){
		if (!this[key]) this[key] = value;
		return this;
	},

	/*
	Method: map
		Creates a new map with the results of calling a provided function on every value in the map.

	Syntax:
		>var mappedHash = myHash.map(fn[, bind]);

	Arguments:
		fn   - (function) The function to produce an element of the new Array from an element of the current one.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(value, key, hash)

			Arguments:
				value - (mixed) The current value in the hash.
				key   - (string) The current value's key in the hash.
				hash  - (hash) The actual hash.

	Returns:
		(array) The new mapped hash.

	Example:
		[javascript]
			var timesTwo = new Hash({a: 1, b: 2, c: 3}).map(function(item, index){
				return item * 2;
			}); //timesTwo now holds an object containing: {a: 2, b: 4, c: 6};
		[/javascript]
	*/

	map: function(fn, bind){
		var results = new Hash;
		Hash.each(this, function(value, key){
			results.set(key, fn.call(bind, value, key, this));
		}, this);
		return results;
	},

	/*
	Method: filter
		Creates a new Hash with all of the elements of the Hash for which the provided filtering function returns true.

	Syntax:
		>var filteredHash = myHash.filter(fn[, bind]);

	Arguments:
		fn   - (function) The function to test each element of the Hash. This function is passed the value and its key in the Hash.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(value, key, hash)

			Arguments:
				value - (mixed) The current value in the hash.
				key   - (string) The current value's key in the hash.
				hash  - (hash) The actual hash.

	Returns:
		(hash) The new filtered hash.

	Example:
		[javascript]
		var biggerThanTwenty = new Hash({a: 10, b: 20, c: 30}).filter(function(value, key){
			return value > 20;
		}); //biggerThanTwenty now holds an object containing: {c: 30}
		[/javascript]
	*/

	filter: function(fn, bind){
		var results = new Hash;
		Hash.each(this, function(value, key){
			if (fn.call(bind, value, key, this)) results.set(key, value);
		}, this);
		return results;
	},

	/*
	Method: every
		Returns true if every value in the object satisfies the provided testing function.

	Syntax:
		>var allPassed = myHash.every(fn[, bind]);

	Arguments:
		fn   - (function) The function to test each element of the Hash. This function is passed the value and its key in the Hash.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(value, key, hash)

			Arguments:
				value - (mixed) The current value in the hash.
				key   - (string) The current value's key in the hash.
				hash  - (hash) The actual hash.

	Returns:
		(boolean) If every value in the Hash satisfies the provided testing function, returns true. Otherwise, returns false.

	Example:
		[javascript]
			var areAllBigEnough = ({a: 10, b: 4, c: 25, d: 100}).every(function(value, key){
				return value > 20;
			}); //areAllBigEnough = false
		[/javascript]
	*/

	every: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
		}
		return true;
	},

	/*
	Method: some
		Returns true if at least one value in the object satisfies the provided testing function.

	Syntax:
		>var anyPassed = myHash.any(fn[, bind]);

	Arguments:
		fn   - (function) The function to test each element of the Hash. This function is passed the value and its key in the Hash.
		bind - (object, optional) The object to use as 'this' in the function. For more information see <Function.bind>.

		fn (continued):
			Signature:
				>fn(value, key, hash)

			Arguments:
				value - (mixed) The current value in the hash.
				key   - (string) The current value's key in the hash.
				hash  - (hash) The actual hash.

	Returns:
		(boolean) If any value in the Hash satisfies the provided testing function, returns true. Otherwise, returns false.

	Example:
		[javascript]
			var areAllBigEnough = ({a: 10, b: 4, c: 25, d: 100}).some(function(value, key){
				return value > 20;
			}); //isAnyBigEnough = true
		[/javascript]
	*/

	some: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
		}
		return false;
	}

});

/*
Script: Class.js
	Contains the Class implementations.

License:
	MIT-style license.
*/

/*
Function: Class
	The base Class object of the <http://mootools.net/> framework. Creates a new Class. The Class's initialize method will fire upon class instantiation unless <$empty> is passed to the Class constructor.

Syntax:
	>var MyClass = new Class(properties);

Arguments:
	properties - (object) The collection of properties that apply to the Class. Also accepts some special properties such as Extends, Implements, and initialize (see below).

	properties (continued):
		Extends - (class) That this class will extend.
		Implements - (mixed) An object or an array of objects that the Class implements. Similar to Extends, but it simply overrides the properties. Useful when implementing a Class properties in multiple classes.
		initialize - (function) The initialize function will be the constructor for this class when new instances are created.

Returns:
	(class) The Class created.

Examples:
	Class Example:
	[javascript]
		var Cat = new Class({
			initialize: function(name){
				this.name = name;
			}
		});
		var myCat = new Cat('Micia');
		alert(myCat.name); //alerts 'Micia'

		var Cow = new Class({
			initialize: function(){
				alert('moooo');
			});
		});
		var Effie = new Cow($empty); //will not alert 'moooo'
	[/javascript]

	Extends Example:
	[javascript]
		var Animal = new Class({
			initialize: function(age){
				this.age = age;
			}
		});
		var Cat = new Class({Extends: Animal
			initialize: function(name, age){
				this.parent(age); //will call initalize of Animal
				this.name = name;
			}
		});
		var myCat = new Cat('Micia', 20);
		alert(myCat.name); //alerts 'Micia'
		alert(myCat.age); //alerts 20
	[/javascript]

	Implements Example:
	[javascript]
		var Animal = new Class({
			initialize: function(age){
				this.age = age;
			}
		});
		var Cat = new Class({
			Implements: Animal,
			setName: function(name){
				this.name = name
			}
		});
		var myCat = new Cat(20);
		myAnimal.setName('Micia');
		alert(myAnimal.name); //alerts 'Micia'
	[/javascript]
*/

var Class = function(properties){
	properties = properties || {};
	var klass = function(){
		for (var property in this){
			if ($type(this[property]) == 'object') this[property] = $merge(this[property]);
		}
		var self = (arguments[0] !== $empty && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;
		if (this.options && this.options.initialize) this.options.initialize.call(this);
		return self;
	};

	if (properties.Implements){
		$extend(properties, Class.Implements.run(properties.Implements));
		delete properties.Implements;
	}

	if (properties.Extends){
		properties = Class.Extends(properties.Extends, properties);
		delete properties.Extends;
	}

	$extend(klass, this);
	klass.prototype = properties;
	klass.prototype.constructor = klass;
	klass.$family = 'class';
	return klass;
};

Class.empty = $empty;

Class.prototype = {

	constructor: Class,

	/*
	Method: implement
		Implements the passed in properties into the base Class prototypes, altering the base Class, unlike <Class.extend>.

	Syntax:
		>MyClass.implement(properties);

	Arguments:
		properties - (object) The properties to add to the base Class.

	Example:
		[javascript]
			var Animal = new Class({
				initialize: function(age){
					this.age = age;
				}
			});
			Animal.implement({
				setName: function(name){
					this.name = name
				}
			});
			var myAnimal = new Animal(20);
			myAnimal.setName('Micia');
			alert(myAnimal.name); //alerts 'Micia'
		[/javascript]
	*/

	implement: function(){
		$extend(this.prototype, Class.Implements.run(arguments));
		return this;
	}

};

Class.Implements = function(){
	var all = {};
	Array.each(arguments, function(set){
		$extend(all, ($type(set) == 'class') ? new set($empty) : set);
	});
	return all;
};

Class.Extends = function(klass, properties){
	var proto = new klass($empty);
	for (var property in properties){
		var pp = proto[property];
		proto[property] = Class.merge(pp, properties[property]);
	}
	return proto;
};

Class.merge = function(previous, current){
	if ($defined(previous) && previous != current){
		var type = $type(current);
		if (type != $type(previous)) return current;
		switch (type){
			case 'function':
				return function(){
					current.parent = this.parent = previous.bind(this);
					return current.apply(this, arguments);
				};
			case 'object': return $merge(previous, current);
		}
	}
	return current;
};

/*
Script: Class.Extras.js
	Contains common implementations for custom classes.
	In MooTools these Utilities are implemented in <Ajax>, <XHR>, <Fx> and many other Classes to provide rich functionality.

License:
	MIT-style license.
*/

/*
Class: Chain
	A "Utility" Class which executes functions one after another, with each function firing after completion of the previous.
	Its methods can be implemented with <Class.implement> into any <Class>, and it is currently implemented in <Fx>, <XHR> and <Ajax>.
	In <Fx>, for example, it is used to create custom, complex animations.

Syntax:
	For new classes:
	>var MyClass = new Class({ Implements: Chain });

	For existing classes:
	>MyClass.implement(new Chain);

Example:
	[javascript]
		var Todo = new Class({
			Implements: Chain,
			initialize: function(){
				this.chain.apply(this, arguments);
			}
		});

		var myTodoList = new Todo(
			function(){ alert('get groceries');	},
			function(){ alert('go workout'); },
			function(){ alert('code mootools documentation until eyes close involuntarily'); },
			function(){ alert('sleep');	}
		);
	[/javascript]

See Also:
	<Class>
*/

var Chain = new Class({

	/*
	Method: chain
		Adds functions to the end of the call stack of the Chain instance.

	Syntax:
		>myClass.chain(fn[, fn2[, fn3[, ...]]]);

	Arguments:
		Any number of functions.

	Returns:
		(class) This Class instance. Calls to chain can also be chained.

	Example:
		[javascript]
			//will fade the element in and out three times
			var myFx = new Fx.Style('myElement', 'opacity'); //Fx.Style has implemented class Chain because of inheritance.
			myFx.start(1,0).chain(
				function(){ this.start(0,1); }, //notice that "this" refers to the calling object. In this case: myFx object.
				function(){ this.start(1,0); },
				function(){ this.start(0,1); }
			);
		[/javascript]

	See Also:
		<Fx>, <Fx.Style>
	*/

	chain: function(){
		this.$chain = (this.$chain || []).extend(arguments);
		return this;
	},

	/*
	Method: callChain
		Removes the first function of the Chain instance stack and executes it. The next function will then become first in the array.

	Syntax:
		>myClass.callChain();

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var Queue = new Class({
				Implements: Chain,
				initialize: function(){
					this.chain.apply(this, arguments);
				}
			});
			var myQueue = new Queue();
			myQueue.chain(
				function(){ alert('do dishes'); },
				function(){ alert('put away clean dishes'); }
			);
			myQueue.callChain(); //alerts 'do dishes'
			myQueue.callChain(); //alerts 'put away clean dishes'
		[/javascript]
	*/

	callChain: function(){
		if (this.$chain && this.$chain.length) this.$chain.shift().delay(10, this);
		return this;
	},

	/*
	Method: clearChain
		Clears the stack of a Chain instance.

	Syntax:
		>myClass.clearChain();

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var myFx = Fx.Style('myElement', 'color'); //Fx.Style inherited Fx's implementation of Chain see <Fx>
			myFx.chain(function(){ while(true) alert('doh!'); }); //don't try this at home, kids.
			myFx.clearChain(); // .. that was a close one ...
		[/javascript]

	See Also:
		<Fx>, <Fx.Style>
	*/

	clearChain: function(){
		if (this.$chain) this.$chain.empty();
		return this;
	}

});

/*
Class: Events
	A "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
	In <Fx>, for example, this Class is used to allow any number of functions to be added to the Fx events, like onComplete, onStart, and onCancel.
	Events in a Class that implements <Events> must be either added as an option or with addEvent, not directly through .options.onEventName.

Syntax:
	For new classes:
	>var MyClass = new Class({ Implements: Events });

	For existing classes:
	>MyClass.implement(new Events);

Implementing:
	This class can be implemented into other classes to add its functionality to them.
	It has been designed to work well with the <Options> class.

Example:
	[javascript]
		var Widget = new Class({
			Implements: Events,
			initialize: function(element){
				...
			},
			complete: function(){
				this.fireEvent('onComplete');
			}
		});

		var myWidget = new Widget();
		myWidget.addEvent('onComplete', myFunction);
	[/javascript]

See Also:
	<Class>, <Options>
*/

var Events = new Class({

	/*
	Method: addEvent
		Adds an event to the Class instance's event stack.

	Syntax:
		>myClass.addEvent(type, fn[, internal]);

	Arguments:
		type     - (string) The type of event (e.g. 'onComplete').
		fn       - (function) The function to execute.
		internal - (boolean, optional) Sets the function property: internal to true. Internal property is used to prevent removal.

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var myFx = new Fx.Style('element', 'opacity');
			myFx.addEvent('onStart', myStartFunction);
		[/javascript]
	*/

	addEvent: function(type, fn, internal){
		if (fn != $empty){
			this.$events = this.$events || {};
			this.$events[type] = this.$events[type] || [];
			this.$events[type].include(fn);
			if (internal) fn.internal = true;
		}
		return this;
	},

	/*
	Method: addEvents
		Works as <addEvent>, but accepts an object to add multiple events at once.

	Syntax:
		>myClass.addEvents(events);

	Arguments:
		events - (object) An object containing a collection of event type / function pairs.

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var myFx = new Fx.Style('element', 'opacity');
			myFx.addEvents({
				'onStart': myStartFunction,
				'onComplete': myCompleteFunction
			});
		[/javascript]
	*/

	addEvents: function(events){
		for (var type in events) this.addEvent(type, events[type]);
		return this;
	},

	/*
	Method: fireEvent
		Fires all events of the specified type in the Class instance.

	Syntax:
		>myClass.fireEvent(type[, args[, delay]]);

	Arguments:
		type  - (string) The type of event (e.g. 'onComplete').
		args  - (mixed, optional) The argument(s) to pass to the function. To pass more than one argument, the arguments must be in an array.
		delay - (number, optional) Delay in miliseconds to wait before executing the event (defaults to 0).

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var Widget = new Class({
				Implements: Events,
				initialize: function(arg1, arg2){
					...
					this.fireEvent("onInitialize", [arg1, arg2], 50);
				}
			});
		[/javascript]
	*/

	fireEvent: function(type, args, delay){
		if (this.$events && this.$events[type]){
			this.$events[type].each(function(fn){
				fn.create({'bind': this, 'delay': delay, 'arguments': args})();
			}, this);
		}
		return this;
	},

	/*
	Method: removeEvent
		Removes an event from the stack of events of the Class instance.

	Syntax:
		>myClass.removeEvent(type, fn);

	Arguments:
		type - (string) The type of event (e.g. 'onComplete').
		fn   - (function) The function to remove. Note: this argument is not optional. You must pass the exact function that was added as an event in order to remove it.

	Returns:
		(class) This Class instance.

	Note:
		If the function has the property internal and is set to true, then the event will not be removed.
	*/

	removeEvent: function(type, fn){
		if (!this.$events) return this; 
		if (this.$events && this.$events[type]){
			if (!fn.internal) this.$events[type].remove(fn);
		}
		return this;
	},

	/*
	Method: removeEvents
		Removes all events of the given type from the stack of events of a Class instance. If no type is specified, removes all events of all types.

	Syntax:
		>myClass.removeEvents([type]);

	Arguments:
		type - (string, optional) The type of event to remove (e.g. 'onComplete'). If no type is specified, removes all events of all types.

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var myFx = new Fx.Style('element', 'opacity');
			myFx.removeEvents('onComplete');
		[/javascript]

	Note:
		Will not remove internal events. See <Events.removeEvent>.
	*/

	removeEvents: function(type){
		for (var e in this.$events){
			if (!type || type == e){
				var fns = this.$events[e];
				for (var i = fns.length; i--;) this.removeEvent(e, fns[i]);
			}
		}
		return this;
	}

});

/*
Class: Options
	A "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
	Used to automate the setting of a Class instance's options.
	Will also add Class <Events> when the option property begins with on, followed by a capital letter (e.g. 'onComplete').

Syntax:
	For new classes:
	>var MyClass = new Class({Implements: Options});

	For existing classes:
	>MyClass.implement(Options);
*/

var Options = new Class({

	/*
	Method: setOptions
		Merges the default options of the Class with the options passed in.

	Syntax:
		>myClass.setOptions([options]);

	Arguments:
		options - (object, optional) The user defined options to merge with the defaults.

	Returns:
		(class) This Class instance.

	Example:
		[javascript]
			var Widget = new Class({
				Implements: Options,
				options: {
					color: '#fff',
					size: {
						width: 100,
						height: 100
					}
				},
				initialize: function(options){
					this.setOptions(options);
				}
			});

			var myWidget = new Widget({
				color: '#f00',
				size: {
					width: 200
				}
			});
			//myWidget.options is now {color: #f00, size: {width: 200, height: 100}}
		[/javascript]

	Note:
		Relies on the default options of a Class defined in its options object.
		If a Class has <Events> implemented, every option beginning with 'on' and followed by a capital letter (e.g. 'onComplete') becomes a Class instance event, assuming the value of the option is a function.
	*/

	setOptions: function(options){
		this.options = $merge(this.options, options);
		if (this.addEvent){
			for (var option in this.options){
				if ((/^on[A-Z]/).test(option) && $type(this.options[option]) == 'function') this.addEvent(option, this.options[option]);
			}
		}
		return this;
	}

});


/*
Script: Element.js
	One of the most important items of MooTools, contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.

License:
	MIT-style license.

Credits:
	- Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license.
*/

/*
Native: Element
	Custom Native to allow all of its methods to be used with any DOM element via the dollar function <$>.
*/

/*
Method: constructor 
 	Creates a new Element of the type passed in. 
Syntax:
	>var myEl = new Element(el[, props]);

Arguments:
	el    - (mixed) The tag name for the Element to be created. It's also possible to add an Element for reference, in which case it will be extended.
	props - (object, optional) The properties to be applied to the new Element.

	props (continued):
		Assumes that all keys are properties that the <Element.setProperties receives, there are special keys, however: the 'styles' key whos value is passed to <Element.setStyles> and the 'events' key whos value is passed to <Element.addEvents>.

Example:
	[javascript]
		var myAnchor = new Element('a', {
			'styles': {
				'display': 'block',
				'border': '1px solid black'
			},
			'events': {
				'click': function(){
					alert('omg u clicked');
				},
				'mousedown': function(){
					alert('omg ur gonna click');
				}
			},
			'class': 'myClassSuperClass',
			'href': 'http://mad4milk.net'
		});
	[/javascript]

See Also:
	<$>, <Element.set>
*/

var Element = new Native({

	initialize: function(){
		var params = Array.associate(arguments, {'document': 'document', 'properties': 'object', 'element': true});
		var props = params.properties || {}, el = params.element, doc = params.document || document;
		if (el == 'iframe') return new IFrame(props, doc);
		if ($type(el) == 'string'){
			if (Client.Engine.ie && props && (props.name || props.type)){
				var name = (props.name) ? ' name="' + props.name + '"' : '';
				var type = (props.type) ? ' type="' + props.type + '"' : '';
				delete props.name;
				delete props.type;
				el = '<' + el + name + type + '>';
			}
			el = doc.createElement(el);
		}
		el = $(el);
		return (!props || !el) ? el : el.set(props);
	},
	
	implement: function(properties){
		HTMLElement.implement(properties);
		for (var key in properties) Elements.prototype[(Array.prototype[key]) ? key + 'Elements' : key] = Elements.$multiply(key);
	}

});

/*
Native: IFrame
	Custom Native to create and easily work with IFrames.
*/

/*
Method: constructor
	Creates an iframe and extends its window and document.
	returns the raw element, if you want to work with the iframe use the "this" in the onload method you pass in.
*/

var IFrame = new Native({
	
	name: 'IFrame',

	initialize: function(){
		var params = Array.associate(arguments, {'document': 'document', 'properties': 'object'});
		var props = params.properties || {}, doc = params.document || document;
		var iframe = $(document.createElement('iframe'));
		iframe.name = props.name || 'iframe-' + iframe.$attributes.uid;
		delete props.name;
		var onload = props.onload || $empty;
		delete props.onload;
		iframe.onload = function(){
			var frame = this.ownerDocument.window.frames[this.name];
			new Window(frame);
			new Document(frame.document);
			onload.call(frame);
		};
		return $extend(iframe, this).set(props);
	},
	
	generics: false

});

/*
Native: Elements
	The Elements class allows <Element> methods to work also on an <Elements> array. In MooTools, every DOM function, such as <$$> (and every other function that returns a collection of nodes) returns them as an Elements class.

Syntax:
	>var myElements = new Elements(elements[, nocheck]);

Arguments:
	elements - (array) A mixed array with items of Elements or an string ID reference.
	nocheck  - (boolean: defaults to false) Optionally bypasses the extending of Elements.

Returns:
	(array) An extended array with the <Element> methods.

Example:
	[javascript];
		//The following code would set the color of every paragraph to 'red'.
		$$('p').each(function(el){
		  el.setStyle('color', 'red');
		});

		//However, because $$('myselector') also accepts <Element> methods, the below example would have the same effect as the one above.
		$$('p').setStyle('color', 'red');

		//Create myElements from
		var myElements = new Elements(['myElementID', $('myElement'), 'myElementID2', document.getElementById('myElementID3')]);
		myElements.removeElements('found'); //notice how 'remove' is an <Array> method and therefore the correct usage is: <Element.removeEvents>
	[/javascript]

Note:
	- Because Elements is an Array, it accepts all the <Array> methods.
	- Array methods have priority, so overlapping Element methods (remove, getLast) are changed to "method + Elements" (removeElements, getLastElements).
	- Every node of the Elements instance is already extended with <$>.

See Also:
	<$$>
*/

var Elements = new Native({
	
	initialize: function(elements, nocheck){
		elements = elements || [];
		var length = elements.length;
		if (nocheck || !length) return $extend(elements, this);
		var uniques = {};
		var returned = [];
		for (var i = 0; i < length; i++){
			var el = $(elements[i]);
			if (!el || uniques[el.$attributes.uid]) continue;
			uniques[el.$attributes.uid] = true;
			returned.push(el);
		}
		return $extend(returned, this);
	}

});

Elements.$multiply = function(property){
	return function(){
		var items = [];
		var elements = true;
		for (var i = 0, j = this.length; i < j; i++){
			var returns = this[i][property].apply(this[i], arguments);
			items.push(returns);
			if (elements) elements = ($type(returns) == 'element');
		}
		return (elements) ? new Elements(items) : items;
	};
};

/*
Native: Window
	these methods are attached to the window[s] object.
*/

Window.implement({
	
	/*
	Function: $
		Returns the element passed in with all the Element prototypes applied.

	Arguments:
		el - (mixed) A string containing the id of the DOM element desired or a reference to an actual DOM element.

	Example:
		>$('myElement') // gets a DOM element by id with all the Element prototypes applied.
		>var div = document.getElementById('myElement');
		>$(div) //returns an Element also with all the mootools extensions applied.

		You'll use this when you aren't sure if a variable is an actual element or an id, as
		well as just shorthand for document.getElementById().

	Returns:
		a DOM element or false (if no id was found).

	Note:
		While the $ function needs to be called only once on an element in order to get all the prototypes,
		extended Elements can be passed to this function multiple times without ill effects.
	*/

	$: function(el){
		if (!el) return null;
		if (el.htmlElement) return Garbage.collect(el);
		var type = $type(el);
		if (type == 'string'){
			el = this.document.getElementById(el);
			type = (el) ? 'element' : false;
		}
		if (type != 'element') return (['window', 'document'].contains(type)) ? el : null;
		if (el.htmlElement) return Garbage.collect(el);
		if (Element.$badTags.contains(el.tagName.toLowerCase())) return el;
		$extend(el, Element.prototype);
		el.htmlElement = $empty;
		return Garbage.collect(el);
	},

	/*
	Function: $$
		Selects, and extends DOM elements. Elements arrays returned with $$ will also accept all the <Element> methods.
		The return type of element methods run through $$ is always an array. If the return array is only made by elements,
		$$ will be applied automatically.

	Arguments:
		HTML Collections, arrays of elements, arrays of strings as element ids, elements, strings as selectors.
		Any number of the above as arguments are accepted.

	Note:
		if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names.

	Example:
	>$$('a'); 
	Returns an array of all anchor tags on the page.

	>$$('a', 'b');
	Returns an array of all anchor and bold tags on the page.

	>$$('#myElement');
	Returns an array containing only the element with id = myElement (requires Element.Selectors.js).

	>$$('#myElement a.myClass');
	Returns an array of all anchor tags with the class "myClass" within the DOM element with id "myElement" (requires Element.Selectors.js).

	>$$(myelement, myelement2, 'a', ['myid', myid2, 'myid3'], document.getElementsByTagName('div'));
	Returns a collection of the element referenced as myelement, the element referenced as myelement2, all of the link tags on the page,
	the element with the id 'myid', followed by the elements with the ids of 'myid2' and 'myid3', and finally all the div elements on the page.
	NOTE: If an element is not found, nothing will be included into the array (not even *null*).

	Returns:
		array - array of all the dom elements matched, extended with <$>.  Returns as <Elements>.
	*/

	$$: function(){
		var elements = [];
		for (var i = 0, j = arguments.length; i < j; i++){
			var selector = arguments[i];
			switch ($type(selector)){
				case 'element': elements.push(selector); break;
				case false: case null: break;
				case 'string': selector = this.document.getElements(selector, true);
				default: elements.extend(selector);
			}
		}
		return new Elements(elements);
	}

});

/*
Native: Element
	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
*/

Native.implement([Element, Document], {
	
	/*
	Method: getElement
		Searches all descendents for the first Element whose tag matches the tag provided. getElement method will also automatically extend the Element.

	Syntax:
		>var myElement = myElement.getElement(tag);

	Arguments:
		tag - (string) String of the tag to match.

	Returns:
		(mixed) If found returns an extended Element, else returns null.

	Example:
		[javascript]
			var body = $(document.body);
			var firstDiv = body.getElement('div');
			// or
			var firstDiv = $(document.body).getElement('div');
		[/javascript]

	Note:
		This method is also available for the Document instances.
		This method gets replaced when <Selector.js> is included. <Selector.js> enhances getElement so that it maches with CSS selectors.
	*/
	
	getElement: function(tag, nocash){
		var element = this.getElementsByTagName(tag)[0] || null;
		return (nocash) ? element : $(element);
	},
	
	/*
	Method: getElements
		Searches and returns all descendant Elements that match the tag provided.

	Syntax:
		>var myElements = myElement.getElements(tag);

	Arguments:
		tag - (string) String of the tag to match.

	Returns:
		(array) An array of all matched Elements. If none of the descendants matched the tag, will return an empty array.

	Example:
		[javascript]
			var body = $(document.body);
			var allAnchors = body.getElements('a');
			// or
			var allAnchors = $(document.body).getElement('a');
		[/javascript]

	Note:
		This method gets replaced when <Selector.js> is included. <Selector.js> enhances getElements so that it maches with CSS selectors.
		This method is also available for the Document instances.
	*/

	getElements: function(tag, nocash){
		var elements = this.getElementsByTagName(tag);
		return (nocash) ? elements : $$(elements);
	}

});

Element.Setters = new Hash({

	attributes: function(properties){
		this.setProperties(properties);
	}

});

Element.Setters.properties = Element.Setters.attributes;

Element.implement({
	
	/*
	Method: getElementById
		Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById.

	Arguments:
		id - (string) the id of the element to find.
		
	Returns:
		(mixed) The element you find or null if none found.
	*/

	getElementById: function(id, nocash){
		var el = this.ownerDocument.getElementById(id);
		if (!el) return null;
		for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
			if (!parent) return null;
		}
		return (nocash) ? el : $(el);
	},

	/*
	Method: set
		With this method you can set events, styles, and properties to the Element (same as calling new Element with the second paramater).

	Syntax:
		>myElement.set(props);

	Arguments:
		props - (object) An object with various properties used to modify the current Element. Keyword properties are: 'styles' and 'events' all other are considered properties. See also: new <Element>

	Returns:
		(element) This Element.

	Example:
		[javascript]
			var body = $(document.body).set({
				'styles': { // property styles passes the object to <Element.setStyles>
					'font': '12px Arial',
					'color': 'blue'
				},
				'events': { // property events passes the object to <Element.addEvents>
					'click': function(){ alert('click'); },
					'scroll': function(){
				},
				'id': 'documentBody' //any other property uses setProperty
			});
		[/javascript]

	See Also:
		<Element>, <Element.setStyles>, <Element.addEvents>, <Element.setProperty>
	*/

	set: function(props){
		for (var prop in props){
			if (Element.Setters[prop]) Element.Setters[prop].call(this, props[prop]);
			else this.setProperty(prop, props[prop]);
		}
		return this;
	},
	
	/*
	Method: inject
		Injects, or inserts, the Element at a particular place relative to the Element's children (specified by the second the paramter).

	Syntax:
		>myElement.inject(el[, where]);

	Arguments:
		el    - (mixed) el can be: the string of the id of the Element or an Element.
		where - (string, optional) The place to inject this Element to (defaults to the bottom of the el's child nodes).

	Returns:
		(element) This Element.

	Example:
		[javascript]
			var myDiv = new Element('div', {id: 'mydiv'});
			myDiv.inject(document.body);
			// or inline
			var myDiv = new Element('div', {id: 'mydiv'}).inject(document.body);

			new Element('a').inject('mydiv'); // is also valid since myDiv is now inside the body
		[/javascript]

	See Also:
		<Element.adopt>
	*/

	inject: function(el, where){
		el = $(el);
		switch (where){
			case 'before': el.parentNode.insertBefore(this, el); break;
			case 'after':
				var next = el.getNext();
				if (!next) el.parentNode.appendChild(this);
				else el.parentNode.insertBefore(this, next);
				break;
			case 'top':
				var first = el.firstChild;
				if (first){
					el.insertBefore(this, first);
					break;
				}
			default: el.appendChild(this);
		}
		return this;
	},

	/*
	Method: injectBefore
		Inserts the Element before the passed Element.

	Syntax:
		>myElement.injectBefore(el);

	Arguments:
		el - (mixed) An Element reference or the id of the Element to be injected before.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

		[javascript]
			$('mySecondElement').injectBefore('myElement');
		[/javascript]

		Result:
		[html]
			<div id="mySecondElement"></div>
			<div id="myElement"></div>
		[/html]

	See Also:
		<Element.inject>
	*/

	injectBefore: function(el){
		return this.inject(el, 'before');
	},

	/*
	Method: injectAfter
		Inserts the Element after the passed Element.

	Syntax:
		>myElement.injectAfter(el);

	Arguments:
		el - (mixed) An Element reference or the id of the Element to be injected after.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="mySecondElement"></div>
			<div id="myElement"></div>
		[/html]

		[javascript]
			$('mySecondElement').injectBefore('myElement');
		[/javascript]

		Result:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

	See Also:
		<Element.inject>, <Element.injectBefore>
	*/

	injectAfter: function(el){
		return this.inject(el, 'after');
	},

	/*
	Method: injectInside
		Injects the Element inside and at the end of the child nodes of the passed in Element.

	Syntax:
		>myElement.injectInside(el);

	Arguments:
		el - (mixed) An Element reference or the id of the Element to be injected inside.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

		[javascript]
			$('mySecondElement').injectInside('myElement');
		[/javascript]

		Result:
		[html]
			<div id="myElement">
				<div id="mySecondElement"></div>
			</div>
		[/html]

	See Also:
		<Element.inject>
	*/

	injectInside: function(el){
		return this.inject(el, 'bottom');
	},

	/*
	Method: injectTop
		Same as <Element.injectInside>, but inserts the Element inside, at the top.

	Syntax:
		>myElement.injectTop(el);

	Arguments:
		el - (mixed) An Element reference or the id of the Element to be injected top.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement">
				<div id="mySecondElement"></div>
				<div id="myThirdElement"></div>
			</div>
			<div id="myFourthElement"></div>
		[/html]

		[javascript]
			$('myFourthElement').injectTop('myElement');
		[/javascript]

		Result:
		[html]
			<div id="myElement">
				<div id="myFourthElement"></div>
				<div id="mySecondElement"></div>
				<div id="myThirdElement"></div>
			</div>
		[/html]

	See Also:
		<Element.inject>
	*/

	injectTop: function(el){
		return this.inject(el, 'top');
	},

	/*
	Method: adopt
		Inserts the passed Elements inside the Element.

	Syntax:
		>myElement.adopt(el[, el2[, ...]]);

	Arguments:
		Accepts Elements references, Element ids as string, selectors ($$('stuff')) / array of Elements, array of ids as strings and collections.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
			<div id="myThirdElement"></div>
			<div id="myFourthElement"></div>
		[/html]

		[javascript]
			$('myElement').adopt('mySecondElement', 'myThirdElement', 'myFourthElement');
		[/javascript]

		Result:
		[html]
			<div id="myElement">
				<div id="myFourthElement"></div>
				<div id="mySecondElement"></div>
				<div id="myThirdElement"></div>
			</div>
		[/html]

	See Also:
		<Element.inject>
	*/

	adopt: function(){
		var elements = [];
		Array.each(arguments, function(argument){
			elements = elements.concat(argument);
		});
		$$(elements).inject(this);
		return this;
	},

	/*
	Method: remove
		Removes the Element from the DOM.

	Syntax:
		>var removedElement = myElement.remove();

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

		[javascript]
			$('myElement').remove() //bye bye
		[/javascript]

		Results:
		[html]
			<div id="mySecondElement"></div>
		[/html]

	Note:
		For <Elements> this method is named removeElements, because <Array.remove> has priority.

	See Also:
		<http://developer.mozilla.org/en/docs/DOM:element.removeChild>
	*/

	remove: function(){
		return this.parentNode.removeChild(this);
	},

	/*
	Method: clone
		Clones the Element and returns the cloned one.

	Syntax:
		>var copy = myElement.clone([contents]);

	Arguments:
		contents - (boolean, optional) When true the Element is cloned with childNodes, default true

	Returns:
		(element) The cloned Element without Events.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
		[/html]

		[javascript]
			var clone = $('myElement').clone().injectAfter('myElement'); //clones the Element and append the clone after the Element.
		[/javascript]

		Results:
		[html]
			<div id="myElement"></div>
			<div id=""></div>
		[/html]

	Note:
		The returned Element does not have an attached events. To clone the events use <Element.cloneEvents>.

	See Also:
		<Element.cloneEvents>
	*/

	clone: function(contents){
		var el = $(this.cloneNode(contents !== false));
		if (!el.$events) return el;
		el.$events = {};
		for (var type in this.$events) el.$events[type] = {
			'keys': $A(this.$events[type].keys),
			'values': $A(this.$events[type].values)
		};
		return el.removeEvents();
	},

	/*
	Method: replaceWith
		Replaces the Element with an Element passed.

	Syntax:
		>var replacingElement = myElement.replaceWidth(el);

	Arguments:
		el - (mixed) A string id representing the Element to be injected in, or an Element reference. In addition, if you pass div or another tag, the Element will be created.

	Returns:
		(element) The passed in Element.

	Example:
		[javascript]
			$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place.
		[/javascript]]

	See Also:
		<http://developer.mozilla.org/en/docs/DOM:element.replaceChild>
	*/

	replaceWith: function(el){
		el = $(el);
		this.parentNode.replaceChild(el, this);
		return el;
	},

	/*
	Method: appendText
		Appends text node to a DOM Element.

	Syntax:
		>myElement.appendText(text);

	Arguments:
		text - (string) The text to append.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement">hey</div>
		[/html]

		[javascript]
			$('myElement').appendText('. howdy'); //myElement innerHTML is now "hey howdy"
		[/javascript]

		Result:
		[html]
			<div id="myElement">hey. howdy</div>
		[/html]
	*/

	appendText: function(text){
		this.appendChild(this.ownerDocument.createTextNode(text));
		return this;
	},

	/*
	Method: hasClass
		Tests the Element to see if it has the passed in className.

	Syntax:
		>var result = myElement.hasClass(className);

	Arguments:
		className - (string) The class name to test.

	Returns:
		(boolean) Returns true if the Element has the class, otherwise false.

	Example:
		[html]
			<div id="myElement" class="testClass"></div>
		[/html]

		[javascript]
			$('myElement').hasClass('testClass'); //returns true
		[/javascript]
	*/

	hasClass: function(className){
		return this.className.contains(className, ' ');
	},

	/*
	Method: addClass
		Adds the passed in class to the Element, if the Element doesnt already have it.

	Syntax:
		>myElement.addClass(className);

	Arguments:
		className - (string) The class name to add.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement" class="testClass"></div>
		[/html]

		[javascript]
			$('myElement').addClass('newClass');
		[/javascript]

		Result:
		[html]
			<div id="myElement" class="testClass newClass"></div>
		[/html]
	*/

	addClass: function(className){
		if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
		return this;
	},

	/*
	Method: removeClass
		Works like <Element.addClass>, but removes the class from the Element.

	Syntax:
		>myElement.removeClass(className);

	Arguments:
		className - (string) The class name to remove.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement" class="testClass newClass"></div>
		[/html]

		[javascript]
			$('myElement').removeClass('newClass');
		[/javascript]

		Result:
		[html]
			<div id="myElement" class="testClass"></div>
		[/html]
	*/

	removeClass: function(className){
		this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
		return this;
	},

	/*
	Method: toggleClass
		Adds or removes the passed in class name to the Element, depending on if it's present or not.

	Syntax:
		>myElement.toggleClass(className);

	Arguments:
		className - (string) The class to add or remove.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement" class="myClass"></div>
		[/html]

		[javascript]
			$('myElement').toggleClass('myClass');
		[/javascript]

		Result:
		[html]
			<div id="myElement" class=""></div>
		[/html]

		[javascript]
			$('myElement').toggleClass('myClass');
		[/javascript]

		Result:
		[html]
			<div id="myElement" class="myClass"></div>
		[/html]
	*/

	toggleClass: function(className){
		return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
	},

	walk: function(brother, start){
		brother += 'Sibling';
		var el = (start) ? this[start] : this[brother];
		while (el && $type(el) != 'element') el = el[brother];
		return $(el);
	},

	/*
	Method: getPrevious
		Returns the previousSibling of the Element (excluding text nodes).

	Syntax:
		>var previousSibling = myElement.getPrevious();

	Returns:
		(mixed) The previous sibling Element, or returns null if none found.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

		[javascript]
			$('mySecondElement').getPrevious().remove(); //get the previous DOM Element from mySecondElement and removes.
		[/javascript]

		Result:
		[html]
			<div id="mySecondElement"></div>
		[/html]

		See Also:
			<Element.remove>
	*/

	getPrevious: function(){
		return this.walk('previous');
	},

	/*
	Method: getNext
		Works as Element.getPrevious, but tries to find the nextSibling (excluding text nodes).

	Syntax:
		>var nextSibling = myElement.getNext();

	Returns:
		(mixed) The next sibling Element, or returns null if none found.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
		[/html]

		[javascript]
			$('myElement').getNext().addClass('found'); //get the next DOM Element from myElement and adds class 'found'.
		[/javascript]

		Result:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement" class="found"></div>
		[/html]

	See Also:
		<Element.addClass>
	*/

	getNext: function(){
		return this.walk('next');
	},

	/*
	Method: getFirst
		Works as <Element.getPrevious>, but tries to find the firstChild (excluding text nodes).

	Syntax:
		>var firstElement = myElement.getFirst();

	Returns:
		(mixed) The first sibling Element, or returns null if none found.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
			<div id="myThirdElement"></div>
		[/html]

		[javascript]
			$('myThirdElement').getFirst().inject('mySecondElement'); //gets the first DOM Element from myThirdElement and injects inside mySecondElement.
		[/javascript]

		Result:
		[html]
			<div id="mySecondElement">
				<div id="myElement"></div>
			</div>
			<div id="myThirdElement"></div>
		[/html]

	See Also:
		<Element.inject>
	*/

	getFirst: function(){
		return this.walk('next', 'firstChild');
	},

	/*
	Method: getLast
		Works as <Element.getPrevious>, but tries to find the lastChild.

	Syntax:
		>var lastElement = myElement.getLast();

	Returns:
		(mixed) The first sibling Element, or returns null if none found.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
			<div id="mySecondElement"></div>
			<div id="myThirdElement"></div>
		[/html]

		[javascript]
			$('myElement').getLast().adopt('mySecondElement'); //gets the last DOM Element from myElement and adopts mySecondElement.
		[/javascript]

		Result:
		[html]
			<div id="myElement"></div>
			<div id="myThirdElement">
				<div id="mySecondElement"></div>
			</div>
		[/html]

	Note:
		For <Elements> this method is named getLastElements, because <Array.getLast> has priority.

	See Also:
		<Element.adopt>
	*/

	getLast: function(){
		return this.walk('previous', 'lastChild');
	},

	/*
	Method: getParent
		Returns the parent node extended.

	Syntax:
		>var parent = myElement.getParent();

	Returns:
		(element) This Element's parent.

	Example:
		HTML:
		[html]
			<div id="myElement">
				<div id="mySecondElement"></div>
			</div>
		[/html]

		[javascript]
			$('mySecondElement').getParent().addClass('papa');
		[/javascript]

		Result:
		[html]
			<div id="myElement" class="papa">
				<div id="mySecondElement"></div>
			</div>
		[/html]

	See Also:
		<http://developer.mozilla.org/en/docs/DOM:element.parentNode>
	*/

	getParent: function(){
		return $(this.parentNode);
	},

	/*
	Method: getChildren
		Returns all the Element's children (excluding text nodes). Returns as <Elements>.

	Syntax:
		>var children = myElement.getChildren();

	Returns:
		(array) A <Elements> array with all of the Element's children except the text nodes.

	Example:
		HTML:
		[html]
			<div id="myElement">
				<div id="mySecondElement"></div>
				<div id="myThirdElement"></div>
			</div>
		[/html]

		[javascript]
			$('myElement').getChildren().removeElements(); // notice how <Element.remove> is renamed removeElements due to Array precedence.
		[/javascript]

		Result:
		[/html]
			<div id="myElement"></div>
		[/javascript]

	See Also:
		<Elements>, <Elements.remove>
	*/

	getChildren: function(){
		return $$(this.childNodes);
	},

	/*
	Method: hasChild
		Checks all children (including text nodes) for a match.

	Syntax:
		>var result = myElement.hasChild(el);

	Arguments:
		el - (mixed) Can be a Element reference or string id.

	Returns:
		(boolean) Returns true if the passed in Element is a child of the Element, otherwise false.

	Example:
		HTML:
		[html]
			<div id="Darth_Vader">
				<div id="Luke"></div>
			</div>
		[/html]

		[javascript]
			if($('Darth_Vader').hasChild('Luke')) alert('Luke, I am your father.'); // tan tan tannn.....
		[/javascript]
	*/

	hasChild: function(el){
		return !!$A(this.getElementsByTagName('*')).contains(el);
	},

	/*
	Method: getProperty
		Gets the an attribute of the Element.

	Syntax:
		>myElement.getProperty(property);

	Arguments:
		property - (string) The attribute to retrieve.

	Returns:
		(mixed) The value of the property, or an empty string.

	Example:
		HTML:
		[html]
			<img id="myImage" src="mootools.png" />
		[/html]

		[javascript]
			$('myImage').getProperty('src') // returns mootools.png
		[/javascript]
	*/

	getProperty: function(property){
		var index = Element.$attributes[property];
		if (index) return this[index];
		var flag = Element.$attributesIFlag[property] || 0;
		if (!Client.Engine.ie || flag) return this.getAttribute(property, flag);
		var node = (this.attributes) ? this.attributes[property] : null;
		return (node) ? node.nodeValue : null;
	},

	/*
	Method: removeProperty
		Removes an attribute from the Element.

	Syntax:
		>myElement.removeProperty(property);

	Arguments:
		property - (string) The attribute to remove.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<a id="myAnchor" href="#" onmousedown="alert('click');"></a>
		[/html]

		[javascript]
			$('myAnchor').removeProperty('onmousedown'); //eww inline javascript is bad! Let's get rid of it.
		[/javascript]

		Result:
		[html]
			<a id="myAnchor" href="#"></a>
		[/html]
	*/

	removeProperty: function(property){
		var index = Element.$attributes[property];
		if (index) this[index] = '';
		else this.removeAttribute(property);
		return this;
	},

	/*
	Method: getProperties
		Same as <Element.getStyles>, but for properties.

	Syntax:
		>var myProps = myElement.getProperties();

	Returns:
		(object) An object containing all of the Element's properties.

	Example:
		HTML:
		[html]
			<img id="myImage" src="mootools.png" title="MooTools, the compact JavaScript framework" alt="" />
		[/html]

		[javascript]
			var imgProps = $('myImage').getProperties(); // returns: { id: 'myImage', src: 'mootools.png', title: 'MooTools, the compact JavaScript framework', alt: '' }
		[/javascript]

	See Also:
		<Element.getProperty>
	*/

	getProperties: function(){
		var result = {};
		Array.each(arguments, function(key){
			result[key] = this.getProperty(key);
		}, this);
		return result;
	},

	/*
	Method: setProperty
		Sets an attribute for the Element.

	Arguments:
		property - (string) The property to assign the value passed in.
		value - (mixed) The value to assign to the property passed in.

	Return:
		(element) - This Element.

	Example:
		HTML:
		[html]
			<img id="myImage" />
		[/html]

		[javascript]
			$('myImage').setProperty('src', 'mootools.png');
		[/javascript]

		Result:
		[html]
			<img id="myImage" src="mootools.png" />
		[/html]
	*/

	setProperty: function(property, value){
		var index = Element.$attributes[property];
		if (index) this[index] = value;
		else this.setAttribute(property, value);
		return this;
	},

	/*
	Method: setProperties
		Sets numerous attributes for the Element.

	Arguments:
		properties - (object) An object with key/value pairs.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<img id="myImage" />
		[/html]

		[javascript]
			$('myImage').setProperties({
				src: 'whatever.gif',
				alt: 'whatever dude'
			});
		[/javascript]

		Result:
		[html]
			<img id="myImage" src="whatever.gif" alt="whatever dude" />
		[/html]
	*/

	setProperties: function(properties){
		for (var property in properties) this.setProperty(property, properties[property]);
		return this;
	},

	/*
	Method: setHTML
		Sets the innerHTML of the Element.

	Syntax:
		>myElement.setHTML([htmlString[, htmlString2[, htmlString3[, ..]]]);

	Arguments:
		Any number of string paramters with html.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
		[/html]

		[javascript]
			$('myElement').setHTML('<div></div>', '<p></p>');
		[/javascript]

		Result:
		[html]
			<div id="myElement">
				<div></div>
				<p></p>
			</div>
		[/html]

	Note:
		Any Elements added with setHTML will not be <Garbage> collected. This may be a source of memory leak.

	See Also:
		<http://developer.mozilla.org/en/docs/DOM:element.innerHTML>
	*/

	setHTML: function(){
		this.innerHTML = Array.join(arguments, '');
		return this;
	},

	/*
	Method: setText
		Sets the inner text of the Element.

	Syntax:
		>myElement.setText(text);

	Arguments:
		text - (string) The new text content for the Element.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
		[/html]

		[javascript]
			$('myElement').setText('some text') //the text of myElement is now = 'some text'
		[/javascript]

		Result:
		[html]
			<div id="myElement">some text</div>
		[/html]
	*/

	setText: function(text){
		var tag = this.getTag();
		if (['style', 'script'].contains(tag)){
			if (Client.Engine.ie){
				if (tag == 'style') this.styleSheet.cssText = text;
				else if (tag ==  'script') this.setProperty('text', text);
				return this;
			} else {
				if (this.firstChild) this.removeChild(this.firstChild);
				return this.appendText(text);
			}
		}
		this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text;
		return this;
	},

	/*
	Method: getText
		Gets the inner text of the Element.

	Syntax:
		>var myText = myElement.getText();

	Returns:
		(string) The text of the Element.

	Example:
		HTML:
		[html]
			<div id="myElement">my text</div>
		[/html]

		[javascript]
			var myText = $('myElement').getText(); //myText = 'my text';
		[/javascript]
	*/

	getText: function(){
		var tag = this.getTag();
		if (['style', 'script'].contains(tag)){
			if (Client.Engine.ie){
				if (tag == 'style') return this.styleSheet.cssText;
				else if (tag ==  'script') return this.getProperty('text');
			} else {
				return this.innerHTML;
			}
		}
		return ($pick(this.innerText, this.textContent));
	},

	/*
	Method: getTag
		Returns the tagName of the Element in lower case.

	Syntax:
		>var myTag = myElement.getTag();

	Returns:
		(string) The tag name in lower case

	Example:
		HTML:
		[html]
			<img id="myImage" />
		[/html]

		[javascript]
			var myTag = $('myImage').getTag() // myTag = 'img';
		[/javascript]

	See Also:
		<http://developer.mozilla.org/en/docs/DOM:element.tagName>
	*/

	getTag: function(){
		return this.tagName.toLowerCase();
	},

	/*
	Method: empty
		Empties an Element of all its children.

	Syntax:
		>myElement.empty();

	Returns:
		(element) This Element..

	Example:
		HTML:
		[html]
			<div id="myElement">
				<p></p>
				<span></span>
			</div>
		[/html]

		[javascript]
			$('myElement').empty() // empties the Div and returns it
		[/javascript]

		Result:
		[html]
			<div id="myElement"></div>
		[/html]
	*/

	empty: function(){
		Garbage.trash(this.getElementsByTagName('*'));
		return this.setHTML('');
	},

	/*
	Method: destroy
		Empties an Element of all its children, removes and garbages the Element.

	Syntax:
		>myElement.destroy();

	Returns:
		(null)

	Example:
		HTML:
		[html]
			<div id="myElement"></div>
		[/html]

		[javascript]
			$('myElement').destroy() // the Element is no more.
		[/javascript]

	See Also:
		<Element.empty>
	*/

	destroy: function(){
		Garbage.kill(this.empty().remove());
		return null;
	}

});

Element.$badTags = ['object', 'embed'];

Element.$attributes = {
	'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan',
	'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength',
	'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value',
	'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected'
};

Element.$attributesIFlag = {
	'href': 2, 'src': 2
};

Native.implement([Element, Window, Document], {

	addListener: function(type, fn){
		if (this.addEventListener) this.addEventListener(type, fn, false);
		else this.attachEvent('on' + type, fn);
		return this;
	},

	removeListener: function(type, fn){
		if (this.removeEventListener) this.removeEventListener(type, fn, false);
		else this.detachEvent('on' + type, fn);
		return this;
	}

});

Element.UID = 0;

var Garbage = {

	elements: {},

	collect: function(el){
		if (!el.$attributes){
			el.$attributes = {'opacity': 1, 'uid': Element.UID++};
			Garbage.elements[el.$attributes.uid] = el;
		}
		return el;
	},

	trash: function(elements){
		for (var i = elements.length, el; i--;){
			if (!(el = elements[i]) || !el.$attributes) continue;
			if (el.tagName && !Element.$badTags.contains(el.tagName.toLowerCase())) Garbage.kill(el);
		}
	},

	kill: function(el, unload){
		delete Garbage.elements[String(el.$attributes.uid)];
		if (el.$events) el.fireEvent('trash', unload).removeEvents();
		for (var p in el.$attributes) el.$attributes[p] = null;
		if (Client.Engine.ie){
			for (var d in Element.prototype) el[d] = null;
		}
		el.htmlElement = el.$attributes = el = null;
	},

	empty: function(){
		Garbage.collect(window);
		Garbage.collect(document);
		for (var uid in Garbage.elements) Garbage.kill(Garbage.elements[uid], true);
	}

};

window.addListener('beforeunload', function(){
	window.addListener('unload', Garbage.empty);
	if (Client.Engine.ie) window.addListener('unload', CollectGarbage);
});


/*
Script: Element.Style.js
	Contains useful Element methods to get/set styles in a fashionable way.

License:
	MIT-style license.
*/

/*
Native: Element
	Custom Native to allow all of its methods to be used with any DOM element via the dollar function <$>.
*/

Element.Setters.styles = function(styles){
	this.setStyles(styles);
};

Element.implement({

	/*
	Method: setStyle
		Sets a CSS property to the Element.

	Syntax:
		>myElement.setStyle(property, value);

	Arguments:
		property - (string) The property to set.
		value    - (mixed) The value to which to set it. For numeric values that require "px" you can pass an number.

	Returns:
		(element) This element.

	Example:
		[javascript]
			$('myElement').setStyle('width', '300px'); //the width is now 300px
			//or
			$('myElement').setStyle('width', 300); //the width is now 300px
		[/javascript]

	Note:
		All number values will automatically be rounded to the nearest whole number.
	*/

	setStyle: function(property, value){
		switch (property){
			case 'opacity': return this.setOpacity(parseFloat(value));
			case 'float': property = (Client.Engine.ie) ? 'styleFloat' : 'cssFloat';
		}
		property = property.camelCase();
		if ($type(value) != 'string'){
			var map = (Element.Styles.All[property] || '@').split(' ');
			value = $splat(value).map(function(val, i){
				if (!map[i]) return '';
				return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
			}).join(' ');
		} else if (value == Number(value) + ''){
			value = Math.round(value);
		}
		this.style[property] = value;
		return this;
	},

	/*
	Method: setStyles
		Applies a collection of styles to the Element.

	Syntax:
		>myElement.setStyles(styles);

	Arguments:
		styles - (mixed) An object, or string, containing all the styles to apply.

	Returns:
		(element) This element.

	Example:
		[javascript]
			$('myElement').setStyles({
				border: '1px solid #000',
				width: 300,
				height: 400
			});
			//or
			$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;'); // See the Note
		[/javascript]

	Note:
		When styles is a CSS string, all the CSS styles are overridden.

	See Also:
		<Element.setStyle>
	*/

	setStyles: function(styles){
		switch ($type(styles)){
			case 'object': for (var style in styles) this.setStyle(style, styles[style]); break;
			case 'string': this.style.cssText = styles;
		}
		return this;
	},

	/*
	Method: setOpacity
		Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0.

	Syntax:
		>Element.setOpacity(opacity);

	Arguments:
		opacity - (float) A values from 0.0 to 1.0, where 1.0 is visible and 0.0 is hidden.

	Returns:
		(element) This element.

	Example:
		[javascript]
			$('myElement').setOpacity(0.5) //make it 50% transparent
		[/javascript]
	*/

	setOpacity: function(opacity){
		if (opacity == 0){
			if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
		} else {
			if (this.style.visibility != 'visible') this.style.visibility = 'visible';
		}
		if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
		if (Client.Engine.ie) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
		this.style.opacity = this.$attributes.opacity = opacity;
		return this;
	},

	/*
	Method: getStyle
		Returns the style of the Element given the property passed in.

	Syntax:
		>var style = myElement.getStyle(property);

	Arguments:
		property - (string) The css style property you want to retrieve.

	Returns:
		(string) The style value.

	Example:
		[javascript]
			$('myElement').getStyle('width'); //returns "400px"
			//but you can also use
			$('myElement').getStyle('width').toInt(); //returns 400
		[/javascript]
	*/

	getStyle: function(property){
		property = property.camelCase();
		if (property == 'opacity') return this.$attributes.opacity;
		var result = this.style[property];
		if (!$chk(result)){
			result = [];
			for (var style in Element.Styles.Short){
				if (property != style) continue;
				for (var s in Element.Styles.Short[style]) result.push(this.getStyle(s));
				return (result.every(function(item){
					return item == result[0];
				})) ? result[0] : result.join(' ');
			}
			result = (this.currentStyle) ? this.currentStyle[property] : this.ownerDocument.window.getComputedStyle(this, null).getPropertyValue([property.hyphenate()]);
		}
		if (result){
			result = String(result);
			var color = result.match(/rgba?\([\d\s,]+\)/);
			if (color) result = result.replace(color[0], color[0].rgbToHex());
		}
		return (Client.Engine.ie) ? Element.$fixStyle(property, result, this) : result;
	},

	/*
	Method: getStyles
		Returns an object of styles of the Element for each argument passed in.

	Syntax:
		>var styles = myElement.getStyles(property[, property2[, property3[, ...]]]);

	Arguments:
		properties - (strings) Any number of style properties.

	Returns:
		(object) An key/value object with the CSS styles as computed by the browser.

	Example:
		[javascript]
			$('myElement').getStyles('width', 'height', 'padding'); //returns {width: "10px", height: "10px", padding: "10px 0px 10px 0px"}
		[/javascript]

	See Also:
		<Element.getStyle>
	*/

	getStyles: function(){
		var result = {};
		Array.each(arguments, function(key){
			result[key] = this.getStyle(key);
		}, this);
		return result;
	}

});

Element.$fixStyle = function(property, result, element){
	if ($chk(parseInt(result))) return result;
	if (['height', 'width'].contains(property)){
		var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'];
		var size = 0;
		values.each(function(value){
			size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt();
		});
		return element['offset' + property.capitalize()] - size + 'px';
	} else if (property.test(/border(.+)Width|margin|padding/)){
		return '0px';
	}
	return result;
};

Element.Styles = {

	All: {
		'width': '@px', 'height': '@px', 'left': '@px', 'top': '@px', 'bottom': '@px', 'right': '@px',
		'backgroundColor': 'rgb(@, @, @)', 'backgroundPosition': '@px @px', 'color': 'rgb(@, @, @)',
		'fontSize': '@px', 'letterSpacing': '@px', 'lineHeight': '@px',
		'margin': '@px @px @px @px', 'padding': '@px @px @px @px', 'border': '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
		'borderWidth': '@px @px @px @px', 'borderStyle': '@ @ @ @', 'borderColor': 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
		'zIndex' : '@', 'zoom': '@', 'fontWeight': '@',
		'textIndent': '@px', 'opacity': '@'
	},

	Short: {'margin': {}, 'padding': {}, 'border': {}, 'borderWidth': {}, 'borderStyle': {}, 'borderColor': {}}

};

['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
	var Short = Element.Styles.Short;
	var All = Element.Styles.All;
	['margin', 'padding'].each(function(style){
		var sd = style + direction;
		Short[style][sd] = All[sd] = '@px';
	});
	var bd = 'border' + direction;
	Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
	var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
	Short[bd] = {};
	Short.borderWidth[bdw] = Short[bd][bdw] = '@px';
	Short.borderStyle[bds] = Short[bd][bds] = '@';
	Short.borderColor[bdc] = Short[bd][bdc] = 'rgb(@, @, @)';
});

/*
Script: Element.Event.js
	Contains the Event Class, Element methods to deal with Element events, and custom Events.

License:
	MIT-style license.
*/

/*
Class: Event
	Cross browser Class to manage Events.

Syntax:
	>var myEvent = new Event([event[, win]]);

Arguments:
	event - (event, optional) An Event that needs to be extended.
	win   - (win, optional) The context of the event.

Properties:
	shift         - (boolean) True if the user pressed the shift
	control       - (boolean) True if the user pressed the control
	alt           - (boolean) True if the user pressed the alt
	meta          - (boolean) True if the user pressed the meta key
	wheel         - (number) The amount of third button scrolling
	code          - (number) The keycode of the key pressed
	page.x        - (number) The x position of the mouse, relative to the full window
	page.y        - (number) The y position of the mouse, relative to the full window
	client.x      - (number) The x position of the mouse, relative to the viewport
	client.y      - (number) The y position of the mouse, relative to the viewport
	key           - (string) The key pressed as a lowercase string. key also returns 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', 'esc'.
	target        - (element) The event target, not extended with <$> for performance reasons.
	relatedTarget - (element) The event related target, not extended with <$> for performance reasons.

Example:
	[javascript]
		$('myLink').addEvent('keydown', function(event){
		 	// event is already the Event class, if you use el.onkeydown you have to write e = new Event(e);
			alert(event.key); //returns the lowercase letter pressed
			alert(event.shift); //returns true if the key pressed is shift
			if (event.key == 's' && event.control) alert('document saved');
		});
	[/javascript]

Note:
	Accessing event.page / event.client requires an XHTML doctype.
*/

var Event = new Class({

	initialize: function(event, win){
		if (event && event.$extended) return event;
		this.$extended = true;
		event = event || (win || window).event;
		this.event = event;
		this.type = event.type;
		this.target = event.target || event.srcElement;
		if (this.target.nodeType == 3) this.target = this.target.parentNode;

		this.shift = event.shiftKey;
		this.control = event.ctrlKey;
		this.alt = event.altKey;
		this.meta = event.metaKey;

		if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){
			this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
		} else if (this.type.contains('key')){
			this.code = event.which || event.keyCode;
			for (var name in Event.Keys){
				if (Event.Keys[name] == this.code){
					this.key = name;
					break;
				}
			}
			if (this.type == 'keydown'){
				var fKey = this.code - 111;
				if (fKey > 0 && fKey < 13) this.key = 'f' + fKey;
			}
			this.key = this.key || String.fromCharCode(this.code).toLowerCase();
		} else if (this.type.test(/(click|mouse|menu)/)){
			this.page = {
				'x': event.pageX || event.clientX + win.document.documentElement.scrollLeft,
				'y': event.pageY || event.clientY + win.document.documentElement.scrollTop
			};
			this.client = {
				'x': event.pageX ? event.pageX - win.pageXOffset : event.clientX,
				'y': event.pageY ? event.pageY - win.pageYOffset : event.clientY
			};
			this.rightClick = (event.which == 3) || (event.button == 2);
			switch (this.type){
				case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break;
				case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement;
			}
			if (this.fixRelatedTarget.create({'bind': this, 'attempt': Client.Engine.gecko})() === false) this.relatedTarget = this.target;
		}
		return this;
	},

	/*
	Method: stop
		Stop an Event from propagating and also executes preventDefault.

	Syntax:
		>myEvent.stop();

	Returns:
		(class) This Event instance.

	Example:
		HTML:
		[html]
			<a id="myAnchor" href="http://google.com/">Visit Google.com</a>
		[/html]

		[javascript]
			$('myAnchor').addEvent('click', function(event){
				event.stop(); // prevent the user from leaving the site.
				this.setText("Where do you think you're going?"); //'this' is Element that fire's the Event.

				(function(){
					this.setText("Instead visit the Blog.").setProperty('href', 'http://blog.mootools.net');
				}).delay(500, this);
			});
		[/javascript]

	Note:
		Returning false within the function can also stop the propagation of the Event.

	See Also:
		<Element.addEvent>, <Event.stopPropagation>, <Event.preventDefault>, <Function.delay>
	*/

	stop: function(){
		return this.stopPropagation().preventDefault();
	},

	/*
	Method: stopPropagation
		Cross browser method to stop the propagation of an event (will not allow the event to bubble up through the DOM).

	Syntax:
		>myEvent.stopPropagation();

	Returns:
		(class) This Event object.

	Example:
		HTML:
		[html]
			<!-- #myChild does not cover the same area as myElement. Therefore, the 'click' differs from parent and child depending on the click location. -->
			<div id="myElement">
				<div id="myChild"></div>
			</div>
		[/html]

		[javascript]
			$('myElement').addEvent('click', function(){
				alert('click');
				return false; // equivalent to stopPropagation.
			});

			$('myChild').addEvent('click', function(event){
				event.stopPropagation(); // this will prevent the event to bubble up, and fire the parent's click event.
			});
		[/javascript]

	See Also:
		<Element.addEvent>, <http://developer.mozilla.org/en/docs/DOM:event.stopPropagation>
	*/

	stopPropagation: function(){
		if (this.event.stopPropagation) this.event.stopPropagation();
		else this.event.cancelBubble = true;
		return this;
	},

	/*
	Method: preventDefault
		Cross browser method to prevent the default action of the event.

	Syntax:
		>myEvent.preventDefault();

	Returns:
		(class) This Event object.

	Example:
		HTML:
		[html]
			<!-- credits: mozilla.org/en/docs/DOM:event.preventDefault -->
			<form>
				<input id="myCheckbox" type="checkbox" />
			</form>
		[/html]

		[javascript]
			$('myCheckbox').addEvent('click', function(event){
				event.preventDefault(); // will not allow the checkbox to be "checked"
			});
		[/javascript]

	See Also:
		<Element.addEvent>, <http://developer.mozilla.org/en/docs/DOM:event.preventDefault>
	*/

	preventDefault: function(){
		if (this.event.preventDefault) this.event.preventDefault();
		else this.event.returnValue = false;
		return this;
	},

	fixRelatedTarget: function(){
		var rel = this.relatedTarget;
		if (rel && rel.nodeType == 3) this.relatedTarget = rel.parentNode;
	}

});

/*
Property: Keys
	You can add additional Event keys codes this way:

Example:
	[javascript]
		Event.Keys.whatever = 80;
		$('myInput').addEvent('keydown', function(event){
			if (event.key == 'whatever') alert('whatever key clicked');
		});
	[/javascript]
*/

Event.Keys = new Hash({
	'enter': 13,
	'up': 38,
	'down': 40,
	'left': 37,
	'right': 39,
	'esc': 27,
	'space': 32,
	'backspace': 8,
	'tab': 9,
	'delete': 46
});

/*
Native: Element
	Custom Native to allow all of its methods to be used with any DOM element via the dollar function <$>.
	These methods are also available on window and document.
*/

Element.Setters.events = function(events){
	this.addEvents(events);
};

Native.implement([Element, Window, Document], {

	/*
	Method: addEvent
		Attaches an event listener to a DOM element.

	Syntax:
		>myElement.addEvent(type, fn[, nativeType]);

	Arguments:
		type       - (string) The event name to monitor ('click', 'load', etc) without the prefix 'on'.
		fn         - (funtion) The function to execute.

	Returns:
		(element) This Element.

	Example:
		HTML:
		[html]
			<div id="myElement">Click me.</div>
		[/html]

		[javascript]
			$('myElement').addEvent('click', function(){ alert('clicked!'); });
		[/javascript]

	Note:
		You can stop the Event by returning false in the listener or calling <Event.stop>.

	See Also:
		<http://www.w3schools.com/html/html_eventattributes.asp>
	*/

	addEvent: function(type, fn){
		this.$events = this.$events || {};
		if (!this.$events[type]) this.$events[type] = {'keys': [], 'values': []};
		if (this.$events[type].keys.contains(fn)) return this;
		this.$events[type].keys.push(fn);
		var realType = type;
		var custom = Element.Events[type];
		var map = fn;
		if (custom){
			if (custom.add) custom.add.call(this, fn);
			if (custom.map){
				map = function(event){
					if (custom.map.call(this, event)) return fn.call(this, event);
					return false;
				};
			}
			if (custom.type) realType = custom.type;
		}
		var defn = fn;
		var nativeEvent = Element.$events[realType] || 0;
		if (nativeEvent){
			if (nativeEvent == 2){
				var self = this;
				var doc = this.ownerDocument || this;
				defn = function(event){
					event = new Event(event, doc.window);
					if (map.call(self, event) === false) event.stop();
				};
			}
			this.addListener(realType, defn);
		}
		this.$events[type].values.push(defn);
		return this;
	},

	/*
	Method: removeEvent
		Works as Element.addEvent, but instead removes the previously added event listener.

	Syntax:
		>myElement.removeEvent(type, fn);

	Arguments:
		type - (string) The event name.
		fn   - (funtion) The function to remove.

	Returns:
		(element) This Element.

	Examples:
		Standard usage:
		[javascript]
			var destroy = function(){ alert('Boom: ' + this.id); } // this is the Element
			$('myElement').addEvent('click', destroy);
			// later in the code
			$('myElement').removeEvent('click', destroy);
		[/javascript]

		Example with bind:
		[javascript]
			var destroy = function(){ alert('Boom: ' + this.id); } // this is the Element
			var destroy2 = destroy.bind($('anotherElement'));
			$('myElement').addEvent('click', destroy2); // this is now another Element
			// later in the code
			$('myElement').removeEvent('click', destroy); // DOES NOT WORK
			$('myElement').removeEvent('click', destroy.bind($('anotherElement')); // DOES ALSO NOT WORK
			$('myElement').removeEvent('click', destroy2); // Finally, this works
		[/javascript]

	Note:
		When the function was added using <Function.bind> or <Function.pass> a new reference
		was created and you can not use removeEvent with the original function.
	*/

	removeEvent: function(type, fn){
		if (!this.$events || !this.$events[type]) return this;
		var pos = this.$events[type].keys.indexOf(fn);
		if (pos == -1) return this;
		var key = this.$events[type].keys.splice(pos, 1)[0];
		var value = this.$events[type].values.splice(pos, 1)[0];
		var custom = Element.Events[type];
		if (custom){
			if (custom.remove) custom.remove.call(this, fn);
			if (custom.type) type = custom.type;
		}
		return (Element.$events[type]) ? this.removeListener(type, value) : this;
	},

	/*
	Method: addEvents
		As <addEvent>, but accepts an object and add multiple events at once.

	Syntax:
		>myElement.addEvents(events);

	Arguments:
		events - (object) An object with key/value representing: key the event name, and value the function that is called when the Event occurs.

	Returns:
		(element) This Element.

	Example:
		[javascript]
			$('myElement').addEvents({
				'mouseover': function(){
					alert('mouse over');
				},
				'click': function(){
					alert('clicked');
				}
			});
		[/javascript]

	See Also:
		<Element.addEvent>
	*/

	addEvents: function(events){
		for (var event in events) this.addEvent(event, events[event]);
		return this;
	},

	/*
	Method: removeEvents
		Removes all events of a certain type from an Element. If no argument is passed in, removes all events.

	Syntax:
		>myElements.removeEvents([type]);

	Arguments:
		type - (string, optional) The event name (e.g. 'click'). If null, removes all events.

	Returns:
		(element) This Element.

	Example:
		[javascript]
			var myElement = $('myElement');
			myElement.addEvents({
				'mouseover': function(){
					alert('mouse over');
				},
				'click': function(){
					alert('clicked');
				}
			});

			myElement.addEvent('click': function(){ alert('clicked again'); });
			myElement.addEvent('click': function(){ alert('clicked and again :('); });
			// addEvent will keep appending each function. Unfortunately for the visitors, that'll be three alerts they'll receive.

			myElement.removeEvents('click'); //ahhh saved the visitor's finger.
		[/javascript]

	See Also:
		<Element.removeEvent>
	*/

	removeEvents: function(type){
		if (!this.$events) return this;
		if (!type){
			for (var evType in this.$events) this.removeEvents(evType);
			this.$events = null;
		} else if (this.$events[type]){
			while (this.$events[type].keys[0]) this.removeEvent(type, this.$events[type].keys[0]);
			this.$events[type] = null;
		}
		return this;
	},

	/*
	Method: fireEvent
		Executes all events of the specified type present in the Element.

	Syntax:
		>myElement.fireEvent(type[, args[, delay]]);

	Arguments:
		type  - (string) The event name (e.g. 'click')
		args  - (mixed, optional) Array or single object, arguments to pass to the function. If more than one argument, must be an array.
		delay - (number, optional) Delay (in ms) to wait to execute the event.

	Returns:
		(element) This Element.

	Example:
		[javascript]
			$('myElement').fireEvent('click', $('anElement'), 1000);  // Fires all the added 'click' events and passes the element 'anElement' after 1 sec.
		[/javascript]

	Note:
		This will not fire the DOM Event (this concerns all inline events ie. onmousedown="..").
	*/

	fireEvent: function(type, args, delay){
		if (this.$events && this.$events[type]){
			this.$events[type].keys.each(function(fn){
				fn.create({'bind': this, 'delay': delay, 'arguments': args})();
			}, this);
		}
		return this;
	},

	/*
	Method: cloneEvents
		Clones all events from an Element to this Element.

	Syntax:
		>myElement.cloneEvents(from[, type]);

	Arguments:
		from - (element) Copy all events from this Element.
		type - (string, optional) Copies only events of this type. If null, copies all events.

	Returns:
		(element) This Element.

	Example:
		[javascript]
			var myElement = $('myElement');
			var myClone = myElement.clone().cloneEvents(myElement); //clones the element and its events
		[/javascript]
	*/

	cloneEvents: function(from, type){
		if (!from.$events) return this;
		if (!type){
			for (var evType in from.$events) this.cloneEvents(from, evType);
		} else if (from.$events[type]){
			from.$events[type].keys.each(function(fn){
				this.addEvent(type, fn);
			}, this);
		}
		return this;
	}

});

Element.$events = {
	'click': 2, 'dblclick': 2, 'mouseup': 2, 'mousedown': 2, //mouse buttons
	'mousewheel': 2, 'DOMMouseScroll': 2, //mouse wheel
	'mouseover': 2, 'mouseout': 2, 'mousemove': 2, //mouse movement
	'keydown': 2, 'keypress': 2, 'keyup': 2, //keys
	'contextmenu': 2, 'submit': 2, //misc
	'load': 1, 'unload': 1, 'beforeunload': 1, 'resize': 1, 'move': 1, 'DOMContentLoaded': 1, 'readystatechange': 1, //window
	'focus': 1, 'blur': 1, 'change': 1, 'reset': 1, 'select': 1, //forms elements
	'error': 1, 'abort': 1, 'scroll': 1 //misc
};

/* Section: Custom Events */

Element.Events = new Hash({

	/*
	Event: mouseenter
		In addition to the standard javascript events (load, mouseover, mouseout, click, etc.) <Event.js> contains two custom events this event fires when the mouse enters the area of the dom Element and will not be fired again if the mouse crosses over children of the Element (unlike mouseover).

	Example:
		[javascript]
			$('myElement').addEvent('mouseenter', myFunction);
		[/javascript]

	See Also:
		<Element.addEvent>
	*/

	'mouseenter': {
		type: 'mouseover',
		map: function(event){
			var related = event.relatedTarget;
			return (related && related != this && !this.hasChild(related));
		}
	},

	/*
	Event: mouseleave
		This event fires when the mouse exits the area of the dom Element; will not be fired again if the mouse crosses over children of the Element (unlike mouseout).

	Example:
		[javascript]
			$('myElement').addEvent('mouseleave', myFunction);
		[/javascript]

	See Also:
		<Element.addEvent>
	*/

	'mouseleave': {
		type: 'mouseout',
		map: function(event){
			var related = event.relatedTarget;
			return (related && related != this && !this.hasChild(related));
		}
	},

	'mousewheel': {
		type: (Client.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'
	}

});

/*
Script: Element.Form.js
	Contains Element methods for working with forms and their elements.

License:
	MIT-style license.
*/

/*
Native: Element
	Custom Native to allow all of its methods to be used with any DOM element via the dollar function <$>.
*/

Element.implement({

	/*
	Method: getValue
		Returns the value of the Element, if its tag is textarea, select or input. getValue called on a multiple select will return an array.

	Syntax:
		>var value = myElement.getValue();

	Returns:
		(mixed) Returns false if if tag is not a 'select', 'input', or 'textarea'. Otherwise returns the value of the Element.

	Example:
		HTML:
		[html]
			<form id="myForm">
				<select>
					<option value="volvo">Volvo</option>
					<option value="saab" selected="yes">Saab</option>
					<option value="opel">Opel</option>
					<option value="audi">Audi</option>
				</select>
			</form>
		[/html]

		Result:
		[javascript]
			var result = $('myForm').getElement('select').getValue(); // returns 'Saab'
		[/javascript]
	*/

	getValue: function(){
		switch (this.getTag()){
			case 'select':
				var values = [];
				Array.each(this.options, function(option){
					if (option.selected) values.push(option.value);
				});
				return (this.multiple) ? values : values[0];
			case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['search', 'hidden', 'text', 'password'].contains(this.type)) break;
			case 'textarea': return this.value;
		}
		return false;
	},

	/*
	Method: getFormElements
		Finds, extends, and returns all descendant form Elements: 'input, 'select', and 'textarea'.

	Syntax:
		>var elements = myElement.getFormElements();

	Returns:
		(array) A collection of Elements.

	Example:
		HTML:
		[html]
			<form id="myForm">
				<select>
					<option value="volvo">Volvo</option>
					<option value="saab" selected="yes">Saab</option>
				</select>
				<textarea></textarea>
			</form>
		[/html]

		[javascript]
			$('myForm').getFormElements(); // returns: [<select>, <textarea>];
		[/javascript]

	See Also:
		<$$>
	*/

	getFormElements: function(){
		return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea'));
	},

	/*
	Method: toQueryString
		Reads the children inputs of the Element and generates a query string, based on their values.

	Syntax:
		>var query = myElement.toQueryString();

	Returns:
		(string) A string representation of a Form element and its children.

	Example:
		[html]
			<form id="myForm" action="submit.php">
				<input name="email" value="bob@bob.com">
				<input name="zipCode" value="90210">
			</form>
		[/html]

		[/javascript]
			$('myForm').toQueryString() //email=bob@bob.com&zipCode=90210\
		[/javascript]

	Note:
		Used internally in <Ajax>.
	*/

	toQueryString: function(){
		var queryString = [];
		this.getFormElements().each(function(el){
			var name = el.name;
			var value = el.getValue();
			if (value === false || !name || el.disabled) return;
			var qs = function(val){
				queryString.push(name + '=' + encodeURIComponent(val));
			};
			if ($type(value) == 'array') value.each(qs);
			else qs(value);
		});
		return queryString.join('&');
	}

});

/*
Script: Window.DomReady.js
	Contains the custom event domready, for window.

License:
	MIT-style license.
*/

/*
Event: domready
	Executes a function when the dom tree is loaded, without waiting for images. Only works when called from window.

Arguments:
	fn - (function) The function to execute when the DOM is ready.

Example:
	[javascript]
		window.addEvent('domready', function(){
			alert('the dom is ready');
		});
	[/javascript]

Credits:
	(c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools.
*/

Element.Events.domready = {

	add: function(fn){
		if (Client.loaded){
			fn.call(this);
			return this;
		}
		var self = this;
		var domReady = function(){
			if (!arguments.callee.done){
				arguments.callee.done = true;
				fn.call(self);
			};
			return true;
		};
		var check = function(context){
			if ((Client.Engine.webkit ? ['loaded', 'complete'] : 'complete').contains(context.readyState)) return domReady();
			return false;
		};
		if (this.document.readyState && Client.Engine.webkit){
			(function(){
				if (!check(self.document)) arguments.callee.delay(50);
			})();
		} else if (this.document.readyState && Client.Engine.ie){
			var script = $('ie_domready');
			if (!script){
				var src = (this.location.protocol == 'https:') ? '//:' : 'javascript:void(0)';
				this.document.write('<script id="ie_domready" defer src="' + src + '"><\/script>');
				script = $('ie_domready');
			}
			if (!check(script)) script.addEvent('readystatechange', check.pass(script));
		} else {
			this.addEvent('load', domReady);
			this.document.addEvent('DOMContentLoaded', domReady);
		}
		return this;
	}

};

window.addEvent('domready', function(){
	Client.loaded = true;
});

/*
Script: XHR.js
	Contains the basic XMLHttpRequest Class Wrapper.

License:
	MIT-style license.
*/

/*
Class: XHR
	An XMLHttpRequest Wrapper.

Implements:
	<Chain>, <Events>, <Options>

Syntax:
	>var myXHR = new XHR([url][, options]);

Arguments:
	url     - (string, optional) The URL pointing to the server-side script.
	options - (object, optional) See below.

	options (continued):
		method     - (string: defaults to 'post') The HTTP method for the request, can be either 'post' or 'get'.
		data       - (string) The default data for <XHR.send>, used when no data is given.
		async      - (boolean: defaults to true) If set to false, the requests will be synchronous and freeze the browser during request.
		encoding   - (string: defaults to "utf-8") The encoding to be set in the request header.
		autoCancel - (boolean: defaults to false) When set to true, automatically cancels the already running request if another one is sent. Otherwise, ignores any new calls while a request is in progress.
		headers    - (object) An object to use in order to set the request headers.
		isSuccess  - (function) Overrides the built-in isSuccess function.

Events:
	onRequest   - (function) Function to execute when the XHR request is fired.
		Signature:
			>onRequest(instance)

		Arguments:
			instance - (XHR) The transport instance.

	onSuccess   - (function) Function to execute when the XHR request completes.
		Signature:
			>onSuccess(reponseText, responseXML)

		Arguments:
			responseText - (string) The returned text from the request.
			responseXML  - (mixed) The response XML from the request.

	onFailure   - (function) Function to execute when the request failes (error status code).
		Signature:
			>onFailure(instance)

		Arguments:
			instance - (XHR) The transport instance.

	onException - (function) Function to execute when setting a request header fails.
		Signature:
			>onException(headerName, value)

		Arguments:
			headerName - (string) The name of the failing header.
			value      - (string) The value of the failing header.

	onCancel    - (function) Function to execute when a request has been cancelled.
		Signature:
			>onCancel()

Properties:
	running  - (boolean) True if the request is running.
	response - (object) Object with text and xml as keys. You can access this property in the onSuccess event.

Returns:
	(class) A new XHR instance.

Example:
	[javascript]
		var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian');
	[/javascript]

See Also:
	<http://en.wikipedia.org/wiki/XMLHttpRequest>
*/

var XHR = new Class({

	Implements: [Chain, Events, Options],

	options: {
		/*onRequest: $empty,
		onSuccess: $empty,
		onFailure: $empty,
		onException: $empty,*/
		method: 'post',
		async: true,
		data: null,
		urlEncoded: true,
		encoding: 'utf-8',
		autoCancel: false,
		headers: {},
		isSuccess: null
	},

	setTransport: function(){
		this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (Client.Engine.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
	},

	initialize: function(){
		var params = Array.associate(arguments, {'url': 'string', 'options': 'object'});
		this.url = params.url;
		this.setTransport();
		this.setOptions(params.options);
		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
		this.headers = $merge(this.options.headers);
		if (this.options.urlEncoded && this.options.method != 'get'){
			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
			this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
		}
		this.setHeader('X-Requested-With', 'XMLHttpRequest');
	},

	onStateChange: function(){
		if (this.transport.readyState != 4 || !this.running) return;
		this.running = false;
		this.status = 0;
		$try(function(){
			this.status = this.transport.status;
		}, this);
		if (this.options.isSuccess.call(this, this.status)) this.onSuccess();
		else this.onFailure();
		this.transport.onreadystatechange = $empty;
	},

	isSuccess: function(){
		return ((this.status >= 200) && (this.status < 300));
	},

	onSuccess: function(){
		this.response = {
			text: this.transport.responseText,
			xml: this.transport.responseXML
		};
		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
		this.callChain();
	},

	onFailure: function(){
		this.fireEvent('onFailure', this.transport);
	},

	/*
	Method: setHeader
		Add or modify a header for the request. It will not override headers from the options.

	Syntax:
		>myXHR.setHeader(name, value);

	Arguments:
		name  - (string) The name for the header.
		value - (string) The value to be assigned.

	Returns:
		(class) This XHR instance.

	Example:
		[javascript]
			var myXHR = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}});
			myXHR.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT');
		[/javascript]
	*/

	setHeader: function(name, value){
		this.headers[name] = value;
		return this;
	},

	/*
	Method: getHeader
		Returns the given response header or null if not found.

	Syntax:
		>myXHR.getHeader(name);

	Arguments:
		name - (string) The name of the header to retrieve the value of.

	Returns:
		(string) The value of the retrieved header.

	Example:
		var myXHR = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}});
		var headers = myXHR.getHeader('X-Request'); // returns 'JSON'
	*/

	getHeader: function(name){
		return $try(function(name){
			return this.getResponseHeader(name);
		}, this.transport, name) || null;
	},

	/*
	Method: send
		Opens the XHR connection and sends the provided data.

	Syntax:
		>myXHR.send(url[, data]);

	Arguments:
		url  - (string) The URL to make the request to.
		data - (string, optional) The request data as query string.

	Examples:
		Simple POST request:
		[javascript]
			var myXHR = new XHR().send(url, "save=username&name=John");
		[/javascript]

		Synchronous Request:
		[javascript]
			var syncXHR = new XHR({async: false});
			syncXHR.send(url, null);
			alert(syncXHR.response.text);
		[/javascript]
	*/

	send: function(url, data){
		if (this.options.autoCancel) this.cancel();
		else if (this.running) return this;
		this.running = true;
		data = data || this.options.data;
		if (data && this.options.method == 'get'){
			url = url + (url.contains('?') ? '&' : '?') + data;
			data = null;
		}
		this.transport.open(this.options.method.toUpperCase(), url, this.options.async);
		this.transport.onreadystatechange = this.onStateChange.bind(this);
		if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');
		for (var type in this.headers){
			try{
				this.transport.setRequestHeader(type, this.headers[type]);
			} catch(e){
				this.fireEvent('onException', [e, type, this.headers[type]]);
			}
		}
		this.fireEvent('onRequest');
		this.transport.send($pick(data, null));
		if (!this.options.async) this.onStateChange();
		return this;
	},

	/*
	Method: request
		Uses the internal url (passed in <XHR>'s instantiation) to send the passed in data.

	Syntax:
		>myXHR.request([data]);

	Arguments:
		data - (string, optional) The request data as query string.

	Returns:
		(class) This XHR instance.

	Example:
		[javascript]
			var myXHR = new XHR(url);
			myXHR.send("save=username&name=John");
		[/javascript]
	*/

	request: function(data){
		return this.send(this.url, data);
	},

	/*
	Method: cancel
		Cancels the currently running request, if any.

	Syntax:
		>myRequest.cancel();

	Returns:
		(class) This XHR instance.

	Example:
		[javascript]
			var myXHR = new XHR({method: 'get'}).send(url);
			myXHR.cancel();
		[/javascript]
	*/

	cancel: function(){
		if (!this.running) return this;
		this.running = false;
		this.transport.abort();
		this.transport.onreadystatechange = $empty;
		this.setTransport();
		this.fireEvent('onCancel');
		return this;
	}

});


/*
Script: Ajax.js
	Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects.

License:
	MIT-style license.
*/

/*
Class: Ajax
	An Ajax class, For all your asynchronous needs.

Extends:
	<XHR>

Syntax:
	>var myAjax = new Ajax(url[, options]);

Arguments:
	url     - (string) The url pointing to the server-side script.
	options - (object, optional) In addition to <XHR>'s options object, see "Options" below.

	options (continued):
		update       - (element: defaults to null) The Element to insert the response text of the XHR into upon completion of the request.
		evalScripts  - (boolean: defaults to false) If set to true, HTMLScript tags inside the response is evaluated.
		evalResponse - (boolean: defaults to false) If set to true, the entire response is evaluated.

Events:
	onComplete - (function) Function to execute when the AJAX request completes.
		Signature:
			>onComplete(responseText, responseXML)

		Arguments:
			responseText - (string) The content of the remote response.
			responseXML  - (string) The XML response of the request.

Returns:
	(class) A new Ajax instance.

Examples:
	Simple GET Request:
	[javascript]
		var myAjax = new Ajax(url, {method: 'get'}).request();
	[/javascript]

	POST Request with Data as String:
	[javascript]
		var myAjax = new Ajax('save/').request("user_id=25&save=true");
	[/javascript]

	Data from Object Passed via GET:
	[javascript]
		var myAjax = new Ajax('load/').request({'user_id': 25}); //loads url "load/?user_id=25"
	[javascript]

	Data from Element via POST:
	[html]
		<form action="save/" method="post" id="user-form">
			<p>
				Search: <input type="text" name="search" />
				Search in description: <input type="checkbox" name="search_description" value="yes" />
				<input type="submit" />
			</p>
		</form>
	[/html]
	[javascript]
		//Needs to be in a submit event or the form handler
		var myAjax = new Ajax('save/').request($('user-form'));
	[/javascript]

Note:
	If the response's content-type is JavaScript or EcmaScript, everything is evaluated.

See Also:
	<XHR>
*/

var Ajax = new Class({

	Extends: XHR,

	options: {
		/*onComplete: $empty,*/
		update: null,
		evalScripts: false,
		evalResponse: false
	},

	initialize: function(url, options){
		this.addEvent('onSuccess', this.onComplete, true);
		arguments.callee.parent(url, options);
		if (!['post', 'get'].contains(this.options.method)){
			this._method = '_method=' + this.options.method;
			this.options.method = 'post';
		}
		this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
	},

	onComplete: function(){
		var scripts;
		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))){
			scripts = this.response.text;
		} else{
			scripts = (this.options.evalScripts) ? '' : null;
			this.response.text = this.response.text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
				if (scripts !== null) scripts += arguments[1] + '\n';
				return '';
			});
		}
		if (this.options.update) $(this.options.update).empty().setHTML(this.response.text);
		if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0);
		this.fireEvent('onComplete', [this.response.text, this.response.xml]);
	},

	/*
	Method: request
		Executes the AJAX request.

	Syntax:
		>myAjax.request([data]);

	Arguments:
		data - (mixed, optional: defaults to options.data) A String, Object (used in <Hash.toQueryString>), or an Element with input elements (used in <Element.toQueryString>) which represents the data to request.

	Returns:
		(class) This Ajax instance.

	Examples:
		Reusable Example:
		[javascript]
			var myAjax = new Ajax(url, {method: 'get'});
			myAjax.request();
		[/javascript]

		One Shot Example:
		[javascript]
			new Ajax(url, {method: 'get'}).request();
		[/javascript]
	*/

	request: function(data){
		data = data || this.options.data;
		switch ($type(data)){
			case 'element': data = $(data).toQueryString(); break;
			case 'hash': case 'object': data = Hash.toQueryString(data);
		}
		if (this._method) data = (data) ? this._method + '&' + data : this._method;
		return arguments.callee.parent(data);
	}

});

/*
Native: Hash
	A Custom "Object" ({}) implementation which does not account for prototypes when setting, getting, iterating.
*/

/*
Method: toQueryString
	Generates a query string from key/pair values in an object and URI encodes the values.

Syntax:
	>var myHash = new Hash({...}); = myHash.toQueryString();

Arguments:
	source - (object) The object to generate the query string from.

Returns:
	(string) The query string.

Examples:
	Using Hash generic:
	[javascript]
		Hash.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow"
	[/javascript]

	Using Hash instance:
	[javascript]
		var myHash = new Hash({apple: "red", lemon: "yellow"});
		myHash.toQueryString(); //returns "apple=red&lemon=yellow"
	[/javascript]
*/

Hash.implement({

	toQueryString: function(){
		var queryString = [];
		Hash.each(this, function(value, key){
			queryString.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
		});
		return queryString.join('&');
	}

});

/*
Native: Element
	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
*/

Element.implement({

	/*
	Method: send
		Sends a form with an Ajax request.

	Syntax:
		>myElement.send([options]);

	Arguments:
		options - (object, optional) Options object for the <Ajax> request.

	Returns:
		(class) An Ajax Class instance.

	Example:
		[html]
			<form id="myForm" action="submit.php">
				<p>
					<input name="email" value="bob@bob.com">
					<input name="zipCode" value="90210">
				</p>
			</form>
		[/html]
		[javascript]
			$('myForm').send();
		[/javascript]

	Note:
		The URL is taken from the action attribute, as well as the method, which defaults to post if not found.
	*/

	send: function(options){
		var send = this.$attributes.send;
		if (!send) send = this.$attributes.send = new Ajax(this.getProperty('action'), {method: this.method || 'post', autoCancel: true});
		if (options) send.setOptions(options);
		return send.request(this);
	},

	/*
	Method: update
		Updates the content of the element with an Ajax get request.

	Syntax:
		>myElement.update(url[, options]);

	Arguments:
		url     - (string) The URL pointing to the server-side document.
		options - (object, optional) Options object for the <Ajax> request.

	Returns:
		(class) An Ajax Class instance.

	Example:
		[html]
			<div id="content">Loading content...</div>
		[/html]
		[javascript]
			$('content').update('page_1.html');
		[/javascript]

	Note:
		It saves the Ajax instance to the Element, so it uses the same instance every update call.
	*/

	update: function(url, options){
		var update = this.$attributes.update;
		if (!update) update = this.$attributes.update = new Ajax({update: this, method: 'get', autoCancel: true});
		if (options) update.setOptions(options);
		update.url = url;
		return update.request();
	}

});

/*
Script: Swiff.js
	Contains <Swiff>, <Swiff.getVersion>, <Swiff.remote>

Credits:
	Flash detection 'borrowed' from SWFObject.

License:
	MIT-style license.
*/

/*
Function: Swiff
	Creates a Flash object with supplied parameters.

Syntax:
	>var mySwiff = Swiff(movie[, options]);

Arguments:
	movie   - (string) The path to the swf movie.
	options - (object) an object with options names as keys. See options below.

	options (continued):
		width      - (number: defaults to 1) The width of the flash object.
		height     - (number: defaults to 1) The height of the flash object.
		id         - (string: defaults to 'Swiff' + UID) The id of the flash object.
		inject     - (element) The target container for the SWF object.
		params     - (object) SWF object parameters (ie. wmode, bgcolor, allowScriptAccess, loop, etc.)
		properties - (object) Additional attributes for the object element.
		vars       - (object) Given to the SWF as querystring in flashVars.
		callBacks  - (object) Functions you want to pass to your Flash movie.

		params (continued):
			allowScriptAccess - (string: defaults to sameDomain) The domain that the SWF object allows access to.

Returns:
	(element) A new HTML object element.

Example:
	[javascript]
		var obj = Swiff('myMovie.swf', {
			inject: $('myElement')
			width: 500,
			height: 400,
			id: 'myBeautifulMovie'
			parameters: {
				wmode: 'opaque',
				bgcolor: '#ff3300',
			},
			vars: {
				myVariable: myJsVar,
				myVariableString: 'hello'
			}
			callBacks: {
				onLoad: myOnloadFunc
			}
		});
	[/javascript]

Note:
	The <$> function on the OBJECT element will not extend. The <$> will just target the movie by its id/reference. Therefore, its not possible to use the <Element> methods on the Element.
*/

var Swiff = function(movie, options){
	if (!Swiff.fixed) Swiff.fix();
	options = $merge({
		width: 1,
		height: 1,
		id: null,
		inject: null,
		params: {
			allowScriptAccess: 'sameDomain'
		},
		properties: {},
		callBacks: {},
		vars: {}
	}, options);

	var instance = Swiff.nextInstance();
	var properties = $merge(options.properties, {
		id: options.id || instance,
		width: options.width,
		height: options.height
	});
	var params = options.params;
	var vars = options.vars;
	Swiff.callBacks[instance] = {};
	for (var prop in options.callBacks){
		Swiff.callBacks[instance][prop] = options.callBacks[prop];
		vars[prop] = 'Swiff.callBacks.' + instance + '.' + prop;
	}
	if ($type(vars) == 'object') vars = Hash.toQueryString(vars);
	if (vars) params.FlashVars = (params.FlashVars) ? (params.FlashVars + '&' + vars) : vars;

	if (Client.Engine.ie){
		properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
		params.movie = movie;
	} else{
		properties.type = 'application/x-shockwave-flash';
		properties.data = movie;
	}

	var build = '<object ';
	for (var attr in properties) build += attr + '="' + properties[attr] + '" ';
	build += '>';
	for (var name in params) build += '<param name="' + name + '" value="' + params[name] + '" />';
	build += '</object>';
	var obj = new Element('div').setHTML(build).firstChild;
	if (options.inject) $(options.inject).appendChild(obj);
	return obj;
};

Swiff.extend({

	UID: 0,

	callBacks: {},

	nextInstance: function(){
		return 'Swiff' + (++Swiff.UID);
	},

	/*
	Function: Swiff.fix
		Fixes bugs in ie+fp9.

	Credits:
		From swfObject, <http://blog.deconcept.com/swfobject/>
	*/

	fix: function(){
		Swiff.fixed = true;
		window.addEvent('beforeunload', function(){
			__flash_unloadHandler = __flash_savedUnloadHandler = $empty;
		});
		if (!Client.Engine.ie) return;
		window.addEvent('unload', function(){
			Array.each(document.getElementsByTagName('object'), function(swf){
				swf.style.display = 'none';
				for (var p in swf){
					if (typeof swf[p] == 'function') swf[p] = $empty;
				}
			});
		});
	},

	/*
	Function: Swiff.getVersion
		Gets the major version of the flash player installed.

	Syntax:
		>var version = Swiff.getVersion();

	Returns:
		(number) A number representing the (major) flash version installed, or 0 if no player is installed.

	Example:
		[javascript]
			alert(Swiff.getVersion());
		[/javascript]
	*/

	getVersion: function(){
		if (!$defined(Swiff.pluginVersion)){
			var version;
			if (navigator.plugins && navigator.mimeTypes.length){
				version = navigator.plugins["Shockwave Flash"];
				if (version && version.description) version = version.description;
			} else if (Client.Engine.ie){
				version = $try(function(){
					return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");
				});
			}
			Swiff.pluginVersion = ($type(version) == 'string') ? parseInt(version.match(/\d+/)[0]) : 0;
		}
		return Swiff.pluginVersion;
	},

	/*
	Function: Swiff.remote
		Calls an ActionScript function from javascript.

	Syntax:
		>var result = Swiff.remote(obj, fn);

	Arguments:
		obj - (element) A Swiff instance (an HTML object Element).
		fn  - (string) The name of the function to execute in the Flash movie.

	Returns:
		(mixed) The ActionScrip function's result.

	Example:
		[javascript]
			var obj = Swiff('myMovie.swf');
			alert(Swiff.remote(obj, 'myFlashFn'));
		[/javascript]

	Note:
		The SWF file should have been compiled with ExternalInterface component.
	*/

	remote: function(obj, fn){
		var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
		return eval(rs);
	}

});
