PageSourceSearch

https://www.arzacq.com/wp-content/plugins/smartslider/mootools.js

js arzacq.com collected 2026-10-02 23:51:57 UTC 183,646 bytes, 7,102 lines download raw bytes

1/*
2Script: Core.js
3	Mootools - My Object Oriented javascript.
4
5License:
6	MIT-style license.
7
8MooTools Copyright:
9	copyright (c) 2007 Valerio Proietti, <http://mad4milk.net>
10
11MooTools Credits:
12	- 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/>
13	- 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
14	- Documentation by Aaron Newton (aaron.newton [at] cnet [dot] com) and Valerio Proietti.
15*/
16
17var MooTools = {
18	version: '1.11'
19};
20
21/* Section: Core Functions */
22
23/*
24Function: $defined
25	Returns true if the passed in value/object is defined, that means is not null or undefined.
26
27Arguments:
28	obj - object to inspect
29*/
30
31function $defined(obj){
32	return (obj != undefined);
33};
34
35/*
36Function: $type
37	Returns the type of object that matches the element passed in.
38
39Arguments:
40	obj - the object to inspect.
41
42Example:
43	>var myString = 'hello';
44	>$type(myString); //returns "string"
45
46Returns:
47	'element' - if obj is a DOM element node
48	'textnode' - if obj is a DOM text node
49	'whitespace' - if obj is a DOM whitespace node
50	'arguments' - if obj is an arguments object
51	'object' - if obj is an object
52	'string' - if obj is a string
53	'number' - if obj is a number
54	'boolean' - if obj is a boolean
55	'function' - if obj is a function
56	'regexp' - if obj is a regular expression
57	'class' - if obj is a Class. (created with new Class, or the extend of another class).
58	'collection' - if obj is a native htmlelements collection, such as childNodes, getElementsByTagName .. etc.
59	false - (boolean) if the object is not defined or none of the above.
60*/
61
62function $type(obj){
63	if (!$defined(obj)) return false;
64	if (obj.htmlElement) return 'element';
65	var type = typeof obj;
66	if (type == 'object' && obj.nodeName){
67		switch(obj.nodeType){
68			case 1: return 'element';
69			case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
70		}
71	}
72	if (type == 'object' || type == 'function'){
73		switch(obj.constructor){
74			case Array: return 'array';
75			case RegExp: return 'regexp';
76			case Class: return 'class';
77		}
78		if (typeof obj.length == 'number'){
79			if (obj.item) return 'collection';
80			if (obj.callee) return 'arguments';
81		}
82	}
83	return type;
84};
85
86/*
87Function: $merge
88	merges a number of objects recursively without referencing them or their sub-objects.
89
90Arguments:
91	any number of objects.
92
93Example:
94	>var mergedObj = $merge(obj1, obj2, obj3);
95	>//obj1, obj2, and obj3 are unaltered
96*/
97
98function $merge(){
99	var mix = {};
100	for (var i = 0; i < arguments.length; i++){
101		for (var property in arguments[i]){
102			var ap = arguments[i][property];
103			var mp = mix[property];
104			if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap);
105			else mix[property] = ap;
106		}
107	}
108	return mix;
109};
110
111/*
112Function: $extend
113	Copies all the properties from the second passed object to the first passed Object.
114	If you do myWhatever.extend = $extend the first parameter will become myWhatever, and your extend function will only need one parameter.
115
116Example:
117	(start code)
118	var firstOb = {
119		'name': 'John',
120		'lastName': 'Doe'
121	};
122	var secondOb = {
123		'age': '20',
124		'sex': 'male',
125		'lastName': 'Dorian'
126	};
127	$extend(firstOb, secondOb);
128	//firstOb will become:
129	{
130		'name': 'John',
131		'lastName': 'Dorian',
132		'age': '20',
133		'sex': 'male'
134	};
135	(end)
136
137Returns:
138	The first object, extended.
139*/
140
141var $extend = function(){
142	var args = arguments;
143	if (!args[1]) args = [this, args[0]];
144	for (var property in args[1]) args[0][property] = args[1][property];
145	return args[0];
146};
147
148/*
149Function: $native
150	Will add a .extend method to the objects passed as a parameter, but the property passed in will be copied to the object's prototype only if non previously existent.
151	Its handy if you dont want the .extend method of an object to overwrite existing methods.
152	Used automatically in MooTools to implement Array/String/Function/Number methods to browser that dont support them whitout manual checking.
153
154Arguments:
155	a number of classes/native javascript objects
156
157*/
158
159var $native = function(){
160	for (var i = 0, l = arguments.length; i < l; i++){
161		arguments[i].extend = function(props){
162			for (var prop in props){
163				if (!this.prototype[prop]) this.prototype[prop] = props[prop];
164				if (!this[prop]) this[prop] = $native.generic(prop);
165			}
166		};
167	}
168};
169
170$native.generic = function(prop){
171	return function(bind){
172		return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1));
173	};
174};
175
176$native(Function, Array, String, Number);
177
178/*
179Function: $chk
180	Returns true if the passed in value/object exists or is 0, otherwise returns false.
181	Useful to accept zeroes.
182
183Arguments:
184	obj - object to inspect
185*/
186
187function $chk(obj){
188	return !!(obj || obj === 0);
189};
190
191/*
192Function: $pick
193	Returns the first object if defined, otherwise returns the second.
194
195Arguments:
196	obj - object to test
197	picked - the default to return
198
199Example:
200	(start code)
201		function say(msg){
202			alert($pick(msg, 'no meessage supplied'));
203		}
204	(end)
205*/
206
207function $pick(obj, picked){
208	return $defined(obj) ? obj : picked;
209};
210
211/*
212Function: $random
213	Returns a random integer number between the two passed in values.
214
215Arguments:
216	min - integer, the minimum value (inclusive).
217	max - integer, the maximum value (inclusive).
218
219Returns:
220	a random integer between min and max.
221*/
222
223function $random(min, max){
224	return Math.floor(Math.random() * (max - min + 1) + min);
225};
226
227/*
228Function: $time
229	Returns the current timestamp
230
231Returns:
232	a timestamp integer.
233*/
234
235function $time(){
236	return new Date().getTime();
237};
238
239/*
240Function: $clear
241	clears a timeout or an Interval.
242
243Returns:
244	null
245
246Arguments:
247	timer - the setInterval or setTimeout to clear.
248
249Example:
250	>var myTimer = myFunction.delay(5000); //wait 5 seconds and execute my function.
251	>myTimer = $clear(myTimer); //nevermind
252
253See also:
254	<Function.delay>, <Function.periodical>
255*/
256
257function $clear(timer){
258	clearTimeout(timer);
259	clearInterval(timer);
260	return null;
261};
262
263/*
264Class: Abstract
265	Abstract class, to be used as singleton. Will add .extend to any object
266
267Arguments:
268	an object
269
270Returns:
271	the object with an .extend property, equivalent to <$extend>.
272*/
273
274var Abstract = function(obj){
275	obj = obj || {};
276	obj.extend = $extend;
277	return obj;
278};
279
280//window, document
281
282var Window = new Abstract(window);
283var Document = new Abstract(document);
284document.head = document.getElementsByTagName('head')[0];
285
286/*
287Class: window
288	Some properties are attached to the window object by the browser detection.
289	
290Note:
291	browser detection is entirely object-based. We dont sniff.
292
293Properties:
294	window.ie - will be set to true if the current browser is internet explorer (any).
295	window.ie6 - will be set to true if the current browser is internet explorer 6.
296	window.ie7 - will be set to true if the current browser is internet explorer 7.
297	window.gecko - will be set to true if the current browser is Mozilla/Gecko.
298	window.webkit - will be set to true if the current browser is Safari/Konqueror.
299	window.webkit419 - will be set to true if the current browser is Safari2 / webkit till version 419.
300	window.webkit420 - will be set to true if the current browser is Safari3 (Webkit SVN Build) / webkit over version 419.
301	window.opera - is set to true by opera itself.
302*/
303
304window.xpath = !!(document.evaluate);
305if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
306else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true;
307else if (document.getBoxObjectFor != null) window.gecko = true;
308
309/*compatibility*/
310
311window.khtml = window.webkit;
312
313Object.extend = $extend;
314
315/*end compatibility*/
316
317//htmlelement
318
319if (typeof HTMLElement == 'undefined'){
320	var HTMLElement = function(){};
321	if (window.webkit) document.createElement("iframe"); //fixes safari
322	HTMLElement.prototype = (window.webkit) ? window["[[DOMElement.prototype]]"] : {};
323}
324HTMLElement.prototype.htmlElement = function(){};
325
326//enables background image cache for internet explorer 6
327
328if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){};
329
330/*
331Script: Class.js
332	Contains the Class Function, aims to ease the creation of reusable Classes.
333
334License:
335	MIT-style license.
336*/
337
338/*
339Class: Class
340	The base class object of the <http://mootools.net> framework.
341	Creates a new class, its initialize method will fire upon class instantiation.
342	Initialize wont fire on instantiation when you pass *null*.
343
344Arguments:
345	properties - the collection of properties that apply to the class.
346
347Example:
348	(start code)
349	var Cat = new Class({
350		initialize: function(name){
351			this.name = name;
352		}
353	});
354	var myCat = new Cat('Micia');
355	alert(myCat.name); //alerts 'Micia'
356	(end)
357*/
358
359var Class = function(properties){
360	var klass = function(){
361		return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;
362	};
363	$extend(klass, this);
364	klass.prototype = properties;
365	klass.constructor = Class;
366	return klass;
367};
368
369/*
370Property: empty
371	Returns an empty function
372*/
373
374Class.empty = function(){};
375
376Class.prototype = {
377
378	/*
379	Property: extend
380		Returns the copy of the Class extended with the passed in properties.
381
382	Arguments:
383		properties - the properties to add to the base class in this new Class.
384
385	Example:
386		(start code)
387		var Animal = new Class({
388			initialize: function(age){
389				this.age = age;
390			}
391		});
392		var Cat = Animal.extend({
393			initialize: function(name, age){
394				this.parent(age); //will call the previous initialize;
395				this.name = name;
396			}
397		});
398		var myCat = new Cat('Micia', 20);
399		alert(myCat.name); //alerts 'Micia'
400		alert(myCat.age); //alerts 20
401		(end)
402	*/
403
404	extend: function(properties){
405		var proto = new this(null);
406		for (var property in properties){
407			var pp = proto[property];
408			proto[property] = Class.Merge(pp, properties[property]);
409		}
410		return new Class(proto);
411	},
412
413	/*
414	Property: implement
415		Implements the passed in properties to the base Class prototypes, altering the base class, unlike <Class.extend>.
416
417	Arguments:
418		properties - the properties to add to the base class.
419
420	Example:
421		(start code)
422		var Animal = new Class({
423			initialize: function(age){
424				this.age = age;
425			}
426		});
427		Animal.implement({
428			setName: function(name){
429				this.name = name
430			}
431		});
432		var myAnimal = new Animal(20);
433		myAnimal.setName('Micia');
434		alert(myAnimal.name); //alerts 'Micia'
435		(end)
436	*/
437
438	implement: function(){
439		for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);
440	}
441
442};
443
444//internal
445
446Class.Merge = function(previous, current){
447	if (previous && previous != current){
448		var type = $type(current);
449		if (type != $type(previous)) return current;
450		switch(type){
451			case 'function':
452				var merged = function(){
453					this.parent = arguments.callee.parent;
454					return current.apply(this, arguments);
455				};
456				merged.parent = previous;
457				return merged;
458			case 'object': return $merge(previous, current);
459		}
460	}
461	return current;
462};
463
464/*
465Script: Class.Extras.js
466	Contains common implementations for custom classes. In Mootools is implemented in <Ajax>, <XHR> and <Fx.Base> and many more.
467
468License:
469	MIT-style license.
470*/
471
472/*
473Class: Chain
474	An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
475	Currently implemented in <Fx.Base>, <XHR> and <Ajax>. In <Fx.Base> for example, is used to execute a list of function, one after another, once the effect is completed.
476	The functions will not be fired all togheter, but one every completion, to create custom complex animations.
477
478Example:
479	(start code)
480	var myFx = new Fx.Style('element', 'opacity');
481
482	myFx.start(1,0).chain(function(){
483		myFx.start(0,1);
484	}).chain(function(){
485		myFx.start(1,0);
486	}).chain(function(){
487		myFx.start(0,1);
488	});
489	//the element will appear and disappear three times
490	(end)
491*/
492
493var Chain = new Class({
494
495	/*
496	Property: chain
497		adds a function to the Chain instance stack.
498
499	Arguments:
500		fn - the function to append.
501	*/
502
503	chain: function(fn){
504		this.chains = this.chains || [];
505		this.chains.push(fn);
506		return this;
507	},
508
509	/*
510	Property: callChain
511		Executes the first function of the Chain instance stack, then removes it. The first function will then become the second.
512	*/
513
514	callChain: function(){
515		if (this.chains && this.chains.length) this.chains.shift().delay(10, this);
516	},
517
518	/*
519	Property: clearChain
520		Clears the stack of a Chain instance.
521	*/
522
523	clearChain: function(){
524		this.chains = [];
525	}
526
527});
528
529/*
530Class: Events
531	An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
532	In <Fx.Base> Class, for example, is used to give the possibility add any number of functions to the Effects events, like onComplete, onStart, onCancel.
533	Events in a Class that implements <Events> can be either added as an option, or with addEvent. Never with .options.onEventName.
534
535Example:
536	(start code)
537	var myFx = new Fx.Style('element', 'opacity').addEvent('onComplete', function(){
538		alert('the effect is completed');
539	}).addEvent('onComplete', function(){
540		alert('I told you the effect is completed');
541	});
542
543	myFx.start(0,1);
544	//upon completion it will display the 2 alerts, in order.
545	(end)
546
547Implementing:
548	This class can be implemented into other classes to add the functionality to them.
549	Goes well with the <Options> class.
550
551Example:
552	(start code)
553	var Widget = new Class({
554		initialize: function(){},
555		finish: function(){
556			this.fireEvent('onComplete');
557		}
558	});
559	Widget.implement(new Events);
560	//later...
561	var myWidget = new Widget();
562	myWidget.addEvent('onComplete', myfunction);
563	(end)
564*/
565
566var Events = new Class({
567
568	/*
569	Property: addEvent
570		adds an event to the stack of events of the Class instance.
571
572	Arguments:
573		type - string; the event name (e.g. 'onComplete')
574		fn - function to execute
575	*/
576
577	addEvent: function(type, fn){
578		if (fn != Class.empty){
579			this.$events = this.$events || {};
580			this.$events[type] = this.$events[type] || [];
581			this.$events[type].include(fn);
582		}
583		return this;
584	},
585
586	/*
587	Property: fireEvent
588		fires all events of the specified type in the Class instance.
589
590	Arguments:
591		type - string; the event name (e.g. 'onComplete')
592		args - array or single object; arguments to pass to the function; if more than one argument, must be an array
593		delay - (integer) delay (in ms) to wait to execute the event
594
595	Example:
596	(start code)
597	var Widget = new Class({
598		initialize: function(arg1, arg2){
599			...
600			this.fireEvent("onInitialize", [arg1, arg2], 50);
601		}
602	});
603	Widget.implement(new Events);
604	(end)
605	*/
606
607	fireEvent: function(type, args, delay){
608		if (this.$events && this.$events[type]){
609			this.$events[type].each(function(fn){
610				fn.create({'bind': this, 'delay': delay, 'arguments': args})();
611			}, this);
612		}
613		return this;
614	},
615
616	/*
617	Property: removeEvent
618		removes an event from the stack of events of the Class instance.
619
620	Arguments:
621		type - string; the event name (e.g. 'onComplete')
622		fn - function that was added
623	*/
624
625	removeEvent: function(type, fn){
626		if (this.$events && this.$events[type]) this.$events[type].remove(fn);
627		return this;
628	}
629
630});
631
632/*
633Class: Options
634	An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
635	Used to automate the options settings, also adding Class <Events> when the option begins with on.
636
637	Example:
638		(start code)
639		var Widget = new Class({
640			options: {
641				color: '#fff',
642				size: {
643					width: 100
644					height: 100
645				}
646			},
647			initialize: function(options){
648				this.setOptions(options);
649			}
650		});
651		Widget.implement(new Options);
652		//later...
653		var myWidget = new Widget({
654			color: '#f00',
655			size: {
656				width: 200
657			}
658		});
659		//myWidget.options = {color: #f00, size: {width: 200, height: 100}}
660		(end)
661*/
662
663var Options = new Class({
664
665	/*
666	Property: setOptions
667		sets this.options
668
669	Arguments:
670		defaults - object; the default set of options
671		options - object; the user entered options. can be empty too.
672
673	Note:
674		if your Class has <Events> implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event.
675	*/
676
677	setOptions: function(){
678		this.options = $merge.apply(null, [this.options].extend(arguments));
679		if (this.addEvent){
680			for (var option in this.options){
681				if ($type(this.options[option] == 'function') && (/^on[A-Z]/).test(option)) this.addEvent(option, this.options[option]);
682			}
683		}
684		return this;
685	}
686
687});
688
689/*
690Script: Array.js
691	Contains Array prototypes, <$A>, <$each>
692
693License:
694	MIT-style license.
695*/
696
697/*
698Class: Array
699	A collection of The Array Object prototype methods.
700*/
701
702//custom methods
703
704Array.extend({
705
706	/*
707	Property: forEach
708		Iterates through an array; This method is only available for browsers without native *forEach* support.
709		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
710
711		*forEach* executes the provided function (callback) once for each element present in the array. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
712
713	Arguments:
714		fn - function to execute with each item in the array; passed the item and the index of that item in the array
715		bind - the object to bind "this" to (see <Function.bind>)
716
717	Example:
718		>['apple','banana','lemon'].each(function(item, index){
719		>	alert(index + " = " + item); //alerts "0 = apple" etc.
720		>}, bindObj); //optional second arg for binding, not used here
721	*/
722
723	forEach: function(fn, bind){
724		for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this);
725	},
726
727	/*
728	Property: filter
729		This method is provided only for browsers without native *filter* supp
729ort.
730		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter>
731
732		*filter* calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values. Array elements which do not pass the callback test are simply skipped, and are not included in the new array.
733
734	Arguments:
735		fn - function to execute with each item in the array; passed the item and the index of that item in the array
736		bind - the object to bind "this" to (see <Function.bind>)
737
738	Example:
739		>var biggerThanTwenty = [10,3,25,100].filter(function(item, index){
740		> return item > 20;
741		>});
742		>//biggerThanTwenty = [25,100]
743	*/
744
745	filter: function(fn, bind){
746		var results = [];
747		for (var i = 0, j = this.length; i < j; i++){
748			if (fn.call(bind, this[i], i, this)) results.push(this[i]);
749		}
750		return results;
751	},
752
753	/*
754	Property: map
755		This method is provided only for browsers without native *map* support.
756		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map>
757
758		*map* calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
759
760	Arguments:
761		fn - function to execute with each item in the array; passed the item and the index of that item in the array
762		bind - the object to bind "this" to (see <Function.bind>)
763
764	Example:
765		>var timesTwo = [1,2,3].map(function(item, index){
766		> return item*2;
767		>});
768		>//timesTwo = [2,4,6];
769	*/
770
771	map: function(fn, bind){
772		var results = [];
773		for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this);
774		return results;
775	},
776
777	/*
778	Property: every
779		This method is provided only for browsers without native *every* support.
780		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every>
781
782		*every* executes the provided callback function once for each element present in the array until it finds one where callback returns a false value. If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
783
784	Arguments:
785		fn - function to execute with each item in the array; passed the item and the index of that item in the array
786		bind - the object to bind "this" to (see <Function.bind>)
787
788	Example:
789		>var areAllBigEnough = [10,4,25,100].every(function(item, index){
790		> return item > 20;
791		>});
792		>//areAllBigEnough = false
793	*/
794
795	every: function(fn, bind){
796		for (var i = 0, j = this.length; i < j; i++){
797			if (!fn.call(bind, this[i], i, this)) return false;
798		}
799		return true;
800	},
801
802	/*
803	Property: some
804		This method is provided only for browsers without native *some* support.
805		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some>
806
807		*some* executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, some immediately returns true. Otherwise, some returns false. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
808
809	Arguments:
810		fn - function to execute with each item in the array; passed the item and the index of that item in the array
811		bind - the object to bind "this" to (see <Function.bind>)
812
813	Example:
814		>var isAnyBigEnough = [10,4,25,100].some(function(item, index){
815		> return item > 20;
816		>});
817		>//isAnyBigEnough = true
818	*/
819
820	some: function(fn, bind){
821		for (var i = 0, j = this.length; i < j; i++){
822			if (fn.call(bind, this[i], i, this)) return true;
823		}
824		return false;
825	},
826
827	/*
828	Property: indexOf
829		This method is provided only for browsers without native *indexOf* support.
830		For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf>
831
832		*indexOf* compares a search element to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).
833
834	Arguments:
835		item - any type of object; element to locate in the array
836		from - integer; optional; the index of the array at which to begin the search (defaults to 0)
837
838	Example:
839		>['apple','lemon','banana'].indexOf('lemon'); //returns 1
840		>['apple','lemon'].indexOf('banana'); //returns -1
841	*/
842
843	indexOf: function(item, from){
844		var len = this.length;
845		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
846			if (this[i] === item) return i;
847		}
848		return -1;
849	},
850
851	/*
852	Property: each
853		Same as <Array.forEach>.
854
855	Arguments:
856		fn - function to execute with each item in the array; passed the item and the index of that item in the array
857		bind - optional, the object that the "this" of the function will refer to.
858
859	Example:
860		>var Animals = ['Cat', 'Dog', 'Coala'];
861		>Animals.each(function(animal){
862		>	document.write(animal)
863		>});
864	*/
865
866	/*
867	Property: copy
868		returns a copy of the array.
869
870	Returns:
871		a new array which is a copy of the current one.
872
873	Arguments:
874		start - integer; optional; the index where to start the copy, default is 0. If negative, it is taken as the offset from the end of the array.
875		length - integer; optional; the number of elements to copy. By default, copies all elements from start to the end of the array.
876
877	Example:
878		>var letters = ["a","b","c"];
879		>
879var copy = letters.copy();		// ["a","b","c"] (new instance)
880	*/
881
882	copy: function(start, length){
883		start = start || 0;
884		if (start < 0) start = this.length + start;
885		length = length || (this.length - start);
886		var newArray = [];
887		for (var i = 0; i < length; i++) newArray[i] = this[start++];
888		return newArray;
889	},
890
891	/*
892	Property: remove
893		Removes all occurrences of an item from the array.
894
895	Arguments:
896		item - the item to remove
897
898	Returns:
899		the Array with all occurrences of the item removed.
900
901	Example:
902		>["1","2","3","2"].remove("2") // ["1","3"];
903	*/
904
905	remove: function(item){
906		var i = 0;
907		var len = this.length;
908		while (i < len){
909			if (this[i] === item){
910				this.splice(i, 1);
911				len--;
912			} else {
913				i++;
914			}
915		}
916		return this;
917	},
918
919	/*
920	Property: contains
921		Tests an array for the presence of an item.
922
923	Arguments:
924		item - the item to search for in the array.
925		from - integer; optional; the index at which to begin the search, default is 0. If negative, it is taken as the offset from the end of the array.
926
927	Returns:
928		true - the item was found
929		false - it wasn't
930
931	Example:
932		>["a","b","c"].contains("a"); // true
933		>["a","b","c"].contains("d"); // false
934	*/
935
936	contains: function(item, from){
937		return this.indexOf(item, from) != -1;
938	},
939
940	/*
941	Property: associate
942		Creates an object with key-value pairs based on the array of keywords passed in
943		and the current content of the array.
944
945	Arguments:
946		keys - the array of keywords.
947
948	Example:
949		(start code)
950		var Animals = ['Cat', 'Dog', 'Coala', 'Lizard'];
951		var Speech = ['Miao', 'Bau', 'Fruuu', 'Mute'];
952		var Speeches = Animals.associate(Speech);
953		//Speeches['Miao'] is now Cat.
954		//Speeches['Bau'] is now Dog.
955		//...
956		(end)
957	*/
958
959	associate: function(keys){
960		var obj = {}, length = Math.min(this.length, keys.length);
961		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
962		return obj;
963	},
964
965	/*
966	Property: extend
967		Extends an array with another one.
968
969	Arguments:
970		array - the array to extend ours with
971
972	Example:
973		>var Animals = ['Cat', 'Dog', 'Coala'];
974		>Animals.extend(['Lizard']);
975		>//Animals is now: ['Cat', 'Dog', 'Coala', 'Lizard'];
976	*/
977
978	extend: function(array){
979		for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
980		return this;
981	},
982
983	/*
984	Property: merge
985		merges an array in another array, without duplicates. (case- and type-sensitive)
986
987	Arguments:
988		array - the array to merge from.
989
990	Example:
991		>['Cat','Dog'].merge(['Dog','Coala']); //returns ['Cat','Dog','Coala']
992	*/
993
994	merge: function(array){
995		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
996		return this;
997	},
998
999	/*
1000	Property: include
1001		includes the passed in element in the array, only if its not already present. (case- and type-sensitive)
1002
1003	Arguments:
1004		item - item to add to the array (if not present)
1005
1006	Example:
1007		>['Cat','Dog'].include('Dog'); //returns ['Cat','Dog']
1008		>['Cat','Dog'].include('Coala'); //returns ['Cat','Dog','Coala']
1009	*/
1010
1011	include: function(item){
1012		if (!this.contains(item)) this.push(item);
1013		return this;
1014	},
1015
1016	/*
1017	Property: getRandom
1018		returns a random item in the Array
1019	*/
1020
1021	getRandom: function(){
1022		return this[$random(0, this.length - 1)] || null;
1023	},
1024
1025	/*
1026	Property: getLast
1027		returns the last item in the Array
1028	*/
1029
1030	getLast: function(){
1031		return this[this.length - 1] || null;
1032	}
1033
1034});
1035
1036//copies
1037
1038Array.prototype.each = Array.prototype.forEach;
1039Array.each = Array.forEach;
1040
1041/* Section: Utility Functions */
1042
1043/*
1044Function: $A()
1045	Same as <Array.copy>, but as function.
1046	Useful to apply Array prototypes to iterable objects, as a collection of DOM elements or the arguments object.
1047
1048Example:
1049	(start code)
1050	function myFunction(){
1051		$A(arguments).each(argument, function(){
1052			alert(argument);
1053		});
1054	};
1055	//the above will alert all the arguments passed to the function myFunction.
1056	(end)
1057*/
1058
1059function $A(array){
1060	return Array.copy(array);
1061};
1062
1063/*
1064Function: $each
1065	Use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, arguments of a function, or an object.
1066
1067Arguments:
1068	iterable - an iterable element or an objct.
1069	function - function to apply to the iterable.
1070	bind - optional, the 'this' of the function will refer to this object.
1071
1072Function argument:
1073	The function argument will be passed the following arguments.
1074
1075	item - the current item in the iterator being procesed
1076	index - integer; the index of the item, or key in case of an object.
1077
1078Examples:
1079	(start code)
1080	$each(['Sun','Mon','Tue'], function(day, index){
1081		alert('name:' + day + ', index: ' + index);
1082	});
1083	//alerts "name: Sun, index: 0", "name: Mon, index: 1", etc.
1084	//over an object
1085	$each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
1086		alert("the " + key + " day of the week is " + value);
1087	});
1088	//alerts "the first day of the week is Sunday",
1089	//"the second day of the week is Monday", etc.
1090	(end)
1091*/
1092
1093function $each(iterable, fn, bind){
1094	if (iterable && typeof iterable.length == 'number' && $type(iterable) != 'object'){
1095		Array.forEach(iterable, fn, bind);
1096	} else {
1097		 for (var name in iterable) fn.call(bind || iterable, iterable[name], name);
1098	}
1099};
1100
1101/*compatibility*/
1102
1103Array.prototype.test = Array.prototype.contains;
1104
1105/*end compatibility*/
1106
1107/*
1108Script: String.js
1109	Contains String prototypes.
1110
1111License:
1112	MIT-style license.
1113*/
1114
1115/*
1116Class: String
1117	A collection of The String Object prototype methods.
1118*/
1119
1120String.extend({
1121
1122	/*
1123	Property: test
1124		Tests a string with a regular expression.
1125
1126	Arguments:
1127		regex - a string or regular expression object, the regular expression you want to match the string with
1128		params - optional, if first parameter is a string, any parameters you want to pass to the regex ('g' has no effect)
1129
1130	Returns:
1131		true if a match for the regular expression is found in the string, false if not.
1132		See <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test>
1133
1134	Example:
1135		>"I like cookies".test("cookie"); // returns true
1136		>"I like cookies".test("COOKIE", "i") // ignore case, returns true
1137		>"I like cookies".test("cake"); // returns false
1138	*/
1139
1140	test: function(regex, params){
1141		return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
1142	},
1143
1144	/*
1145	Property: toInt
1146		parses a string to an integer.
1147
1148	Returns:
1149		either an int or "NaN" if the string is not a number.
1150
1151	Example:
1152		>var value = "10px".toInt(); // value is 10
1153	*/
1154
1155	toInt: function(){
1156		return parseInt(this, 10);
1157	},
1158
1159	/*
1160	Property: toFloat
1161		parses a string to an float.
1162
1163	Returns:
1164		either a float or "NaN" if the string is not a number.
1165
1166	Example:
1167		>var value = "10.848".toFloat(); // value is 10.848
1168	*/
1169
1170	toFloat: function(){
1171		return parseFloat(this);
1172	},
1173
1174	/*
1175	Property: camelCase
1176		Converts a hiphenated string to a camelcase string.
1177
1178	Example:
1179		>
1179"I-like-cookies".camelCase(); //"ILikeCookies"
1180
1181	Returns:
1182		the camel cased string
1183	*/
1184
1185	camelCase: function(){
1186		return this.replace(/-\D/g, function(match){
1187			return match.charAt(1).toUpperCase();
1188		});
1189	},
1190
1191	/*
1192	Property: hyphenate
1193		Converts a camelCased string to a hyphen-ated string.
1194
1195	Example:
1196		>"ILikeCookies".hyphenate(); //"I-like-cookies"
1197	*/
1198
1199	hyphenate: function(){
1200		return this.replace(/\w[A-Z]/g, function(match){
1201			return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
1202		});
1203	},
1204
1205	/*
1206	Property: capitalize
1207		Converts the first letter in each word of a string to Uppercase.
1208
1209	Example:
1210		>"i like cookies".capitalize(); //"I Like Cookies"
1211
1212	Returns:
1213		the capitalized string
1214	*/
1215
1216	capitalize: function(){
1217		return this.replace(/\b[a-z]/g, function(match){
1218			return match.toUpperCase();
1219		});
1220	},
1221
1222	/*
1223	Property: trim
1224		Trims the leading and trailing spaces off a string.
1225
1226	Example:
1227		>"    i like cookies     ".trim() //"i like cookies"
1228
1229	Returns:
1230		the trimmed string
1231	*/
1232
1233	trim: function(){
1234		return this.replace(/^\s+|\s+$/g, '');
1235	},
1236
1237	/*
1238	Property: clean
1239		trims (<String.trim>) a string AND removes all the double spaces in a string.
1240
1241	Returns:
1242		the cleaned string
1243
1244	Example:
1245		>" i      like     cookies      \n\n".clean() //"i like cookies"
1246	*/
1247
1248	clean: function(){
1249		return this.replace(/\s{2,}/g, ' ').trim();
1250	},
1251
1252	/*
1253	Property: rgbToHex
1254		Converts an RGB value to hexidecimal. The string must be in the format of "rgb(255,255,255)" or "rgba(255,255,255,1)";
1255
1256	Arguments:
1257		array - boolean value, defaults to false. Use true if you want the array ['FF','33','00'] as output instead of "#FF3300"
1258
1259	Returns:
1260		hex string or array. returns "transparent" if the output is set as string and the fourth value of rgba in input string is 0.
1261
1262	Example:
1263		>"rgb(17,34,51)".rgbToHex(); //"#112233"
1264		>"rgba(17,34,51,0)".rgbToHex(); //"transparent"
1265		>"rgb(17,34,51)".rgbToHex(true); //['11','22','33']
1266	*/
1267
1268	rgbToHex: function(array){
1269		var rgb = this.match(/\d{1,3}/g);
1270		return (rgb) ? rgb.rgbToHex(array) : false;
1271	},
1272
1273	/*
1274	Property: hexToRgb
1275		Converts a hexidecimal color value to RGB. Input string must be the hex color value (with or without the hash). Also accepts triplets ('333');
1276
1277	Arguments:
1278		array - boolean value, defaults to false. Use true if you want the array [255,255,255] as output instead of "rgb(255,255,255)";
1279
1280	Returns:
1281		rgb string or array.
1282
1283	Example:
1284		>"#112233".hexToRgb(); //"rgb(17,34,51)"
1285		>"#112233".hexToRgb(true); //[17,34,51]
1286	*/
1287
1288	hexToRgb: function(array){
1289		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
1290		return (hex) ? hex.slice(1).hexToRgb(array) : false;
1291	},
1292
1293	/*
1294	Property: contains
1295		checks if the passed in string is contained in the String. also accepts an optional second parameter, to check if the string is contained in a list of separated values.
1296
1297	Example:
1298		>'a b c'.contains('c', ' '); //true
1299		>'a bc'.contains('bc'); //true
1300		>'a bc'.contains('b', ' '); //false
1301	*/
1302
1303	contains: function(string, s){
1304		return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1;
1305	},
1306
1307	/*
1308	Property: escapeRegExp
1309		Returns string with escaped regular expression characters
1310
1311	Example:
1312		>var search = 'animals.sheeps[1]'.escapeRegExp(); // search is now 'animals\.sheeps\[1\]'
1313
1314	Returns:
1315		Escaped string
1316	*/
1317
1318	escapeRegExp: function(){
1319		return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
1320	}
1321
1322});
1323
1324Array.extend({
1325
1326	/*
1327	Property: rgbToHex
1328		see <String.rgbToHex>, but as an array method.
1329	*/
1330
1331	rgbToHex: function(array){
1332		if (this.length < 3) return false;
1333		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
1334		var hex = [];
1335		for (var i = 0; i < 3; i++){
1336			var bit = (this[i] - 0).toString(16);
1337			hex.push((bit.length == 1) ? '0' + bit : bit);
1338		}
1339		return array ? hex : '#' + hex.join('');
1340	},
1341
1342	/*
1343	Property: hexToRgb
1344		same as <String.hexToRgb>, but as an array method.
1345	*/
1346
1347	hexToRgb: function(array){
1348		if (this.length != 3) return false;
1349		var rgb = [];
1350		for (var i = 0; i < 3; i++){
1351			rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16));
1352		}
1353		return array ? rgb : 'rgb(' + rgb.join(',') + ')';
1354	}
1355
1356});
1357
1358/* 
1359Script: Function.js
1360	Contains Function prototypes and utility functions .
1361
1362License:
1363	MIT-style license.
1364
1365Credits:
1366	- 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
1367*/
1368
1369/*
1370Class: Function
1371	A collection of The Function Object prototype methods.
1372*/
1373
1374Function.extend({
1375
1376	/*
1377	Property: create
1378		Main function to create closures.
1379
1380	Returns:
1381		a function.
1382
1383	Arguments:
1384		options - An Options object.
1385
1386	Options:
1387		bind - The object that the "this" of the function will refer to. Default is the current function.
1388		event - If set to true, the function will act as an event listener and receive an event as first argument.
1389				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.
1390				Default is false.
1391		arguments - A single argument or array of arguments that will be passed to the function when called.
1392		
1393					If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow.
1394					
1395					Default is no custom arguments, the function will receive the standard arguments when called.
1396					
1397		delay - Numeric value: if set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called.
1398				Default is no delay.
1399		periodical - Numeric value: if set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called.
1400				Default is no periodical execution.
1401		attempt - If set to true, the returned function will try to execute and return either the results or false on error. Default is false.
1402	*/
1403
1404	create: function(options){
1405		var fn = this;
1406		options = $merge({
1407			'bind': fn,
1408			'event': false,
1409			'arguments': null,
1410			'delay': false,
1411			'periodical': false,
1412			'attempt': false
1413		}, options);
1414		if ($chk(options.arguments) && $type(options.arguments) != 'array') o
1414ptions.arguments = [options.arguments];
1415		return function(event){
1416			var args;
1417			if (options.event){
1418				event = event || window.event;
1419				args = [(options.event === true) ? event : new options.event(event)];
1420				if (options.arguments) args.extend(options.arguments);
1421			}
1422			else args = options.arguments || arguments;
1423			var returns = function(){
1424				return fn.apply($pick(options.bind, fn), args);
1425			};
1426			if (options.delay) return setTimeout(returns, options.delay);
1427			if (options.periodical) return setInterval(returns, options.periodical);
1428			if (options.attempt) try {return returns();} catch(err){return false;};
1429			return returns();
1430		};
1431	},
1432
1433	/*
1434	Property: pass
1435		Shortcut to create closures with arguments and bind.
1436
1437	Returns:
1438		a function.
1439
1440	Arguments:
1441		args - the arguments passed. must be an array if arguments > 1
1442		bind - optional, the object that the "this" of the function will refer to.
1443
1444	Example:
1445		>myFunction.pass([arg1, arg2], myElement);
1446	*/
1447
1448	pass: function(args, bind){
1449		return this.create({'arguments': args, 'bind': bind});
1450	},
1451
1452	/*
1453	Property: attempt
1454		Tries to execute the function, returns either the result of the function or false on error.
1455
1456	Arguments:
1457		args - the arguments passed. must be an array if arguments > 1
1458		bind - optional, the object that the "this" of the function will refer to.
1459
1460	Example:
1461		>myFunction.attempt([arg1, arg2], myElement);
1462	*/
1463
1464	attempt: function(args, bind){
1465		return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
1466	},
1467
1468	/*
1469	Property: bind
1470		method to easily create closures with "this" altered.
1471
1472	Arguments:
1473		bind - optional, the object that the "this" of the function will refer to.
1474		args - optional, the arguments passed. must be an array if arguments > 1
1475
1476	Returns:
1477		a function.
1478
1479	Example:
1480		>function myFunction(){
1481		>	this.setStyle('color', 'red');
1482		>	// note that 'this' here refers to myFunction, not an element
1483		>	// we'll need to bind this function to the element we want to alter
1484		>};
1485		>var myBoundFunction = myFunction.bind(myElement);
1486		>myBoundFunction(); // this will make the element myElement red.
1487	*/
1488
1489	bind: function(bind, args){
1490		return this.create({'bind': bind, 'arguments': args});
1491	},
1492
1493	/*
1494	Property: bindAsEventListener
1495		cross browser method to pass event firer
1496
1497	Arguments:
1498		bind - optional, the object that the "this" of the function will refer to.
1499		args - optional, the arguments passed. must be an array if arguments > 1
1500
1501	Returns:
1502		a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
1503
1504	Example:
1505		>function myFunction(event){
1506		>	alert(event.clientx) //returns the coordinates of the mouse..
1507		>};
1508		>myElement.onclick = myFunction.bindAsEventListener(myElement);
1509	*/
1510
1511	bindAsEventListener: function(bind, args){
1512		return this.create({'bind': bind, 'event': true, 'arguments': args});
1513	},
1514
1515	/*
1516	Property: delay
1517		Delays the execution of a function by a specified duration.
1518
1519	Arguments:
1520		delay - the duration to wait in milliseconds.
1521		bind - optional, the object that the "this" of the function will refer to.
1522		args - optional, the arguments passed. must be an array if arguments > 1
1523
1524	Example:
1525		>myFunction.delay(50, myElement) //wait 50 milliseconds, then call myFunction and bind myElement to it
1526		>(function(){alert('one second later...')}).delay(1000); //wait a second and alert
1527	*/
1528
1529	delay: function(delay, bind, args){
1530		return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
1531	},
1532
1533	/*
1534	Property: periodical
1535		Executes a function in the specified intervals of time
1536
1537	Arguments:
1538		interval - the duration of the intervals between executions.
1539		bind - optional, the object that the "this" of the function will refer to.
1540		args - optional, the arguments passed. must be an array if arguments > 1
1541	*/
1542
1543	periodical: function(interval, bind, args){
1544		return this.create({'periodical': interval, 'bind': bind, 'arguments': args})();
1545	}
1546
1547});
1548
1549/*
1550Script: Number.js
1551	Contains the Number prototypes.
1552
1553License:
1554	MIT-style license.
1555*/
1556
1557/*
1558Class: Number
1559	A collection of The Number Object prototype methods.
1560*/
1561
1562Number.extend({
1563
1564	/*
1565	Property: toInt
1566		Returns this number; useful because toInt must work on both Strings and Numbers.
1567	*/
1568
1569	toInt: function(){
1570		return parseInt(this);
1571	},
1572
1573	/*
1574	Property: toFloat
1575		Returns this number as a float; useful because toFloat must work on both Strings and Numbers.
1576	*/
1577
1578	toFloat: function(){
1579		return parseFloat(this);
1580	},
1581
1582	/*
1583	Property: limit
1584		Limits the number.
1585
1586	Arguments:
1587		min - number, minimum value
1588		max - number, maximum value
1589
1590	Returns:
1591		the number in the given limits.
1592
1593	Example:
1594		>(12).limit(2, 6.5)  // returns 6.5
1595		>(-4).limit(2, 6.5)  // returns 2
1596		>(4.3).limit(2, 6.5) // returns 4.3
1597	*/
1598
1599	limit: function(min, max){
1600		return Math.min(max, Math.max(min, this));
1601	},
1602
1603	/*
1604	Property: round
1605		Returns the number rounded to specified precision.
1606
1607	Arguments:
1608		precision - integer, number of digits after the decimal point. Can also be negative or zero (default).
1609
1610	Example:
1611		>12.45.round() // returns 12
1612		>12.45.round(1) // returns 12.5
1613		>12.45.round(-1) // returns 10
1614
1615	Returns:
1616		The rounded number.
1617	*/
1618
1619	round: function(precision){
1620		precision = Math.pow(10, precision || 0);
1621		return Math.round(this * precision) / precision;
1622	},
1623
1624	/*
1625	Property: times
1626		Executes a passed in function the specified number of times
1627
1628	Arguments:
1629		function - the function to be executed on each iteration of the loop
1630
1631	Example:
1632		>(4).times(alert);
1633	*/
1634
1635	times: function(fn){
1636		for (var i = 0; i < this; i++) fn(i);
1637	}
1638
1639});
1640
1641/*
1642Script: Element.js
1643	Contains useful Element prototypes, to be used with the dollar function <$>.
1644
1645License:
1646	MIT-style license.
1647
1648Credits:
1649	- 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
1650*/
1651
1652/*
1653Class: Element
1654	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
1655*/
1656
1657var Element = new Class({
1658
1659	/*
1660	Property: initialize
1661		Creates a new element of the type passed in.
1662
1663	Arguments:
1664		el - string; the tag name for the element you wish to create. you can also pass in an element reference, in which case it will be extended.
1665		props - object; the properties you want to add to your element.
1666		Accepts the same keys as <Element.setProperties>, but also allows events and styles
1667
1668	Props:
1669		the key styles will be used as setStyles, the key events will be used as addEvents. any other key is used as setProperty.
1670
1671	Example:
1672		(start code)
1673		new Element('a', {
1674			'styles': {
1675				'display': 'block',
1676				'border': '1px solid black'
1677			},
1678			'events': {
1679				'click': function(){
1680					//aaa
1681				},
1682				'mousedown': function(){
1683					//aaa
1684				}
1685			},
1686			'class': 'myClassSuperClass',
1687			'href': 'http://mad4milk.net'
1688		});
1689
1690		(end)
1691	*/
1692
1693	initialize: function(el, props){
1694		if ($type(el) == 'string'){
1695			if (window.ie && props && (props.name || props.type)){
1696				var name = (props.name) ? ' name="' + props.name + '"' : '';
1697				var type = (props.type) ? ' type="' + props.type + '"' : '';
1698				delete props.name;
1699				delete props.type;
1700				el = '<' + el + name + type + '>';
1701			}
1702			el = document.createElement(el);
1703		}
1704		el = $(el);
1705		return (!props || !el) ? el : el.set(props);
1706	}
1707
1708});
1709
1710/*
1711Class: Elements
1712	- Every dom function such as <$$>, or in general every function that returns a collection of nodes in mootools, returns them as an Elements class.
1713	- The purpose of the Elements class is to allow <Element> methods to work also on <Elements> array.
1714	- Elements is also an Array, so it accepts all the <Array> methods.
1715	- Every node of the Elements instance is already extended with <$>.
1716
1717Example:
1718	>$$('myselector').each(function(el){
1719	> //...
1720	>});
1721
1722	some iterations here, $$('myselector') is also an array.
1723
1724	>$$('myselector').setStyle('color', 'red');
1725	every element returned by $$('myselector') also accepts <Element> methods, in this example every element will be made red.
1726*/
1727
1728var Elements = new Class({
1729
1730	initialize: function(elements){
1731		return (elements) ? $extend(elements, this) : this;
1732	}
1733
1734});
1735
1736Elements.extend = function(props){
1737	for (var prop in props){
1738		this.prototype[prop] = props[prop];
1739		this[prop] = $native.generic(prop);
1740	}
1741};
1742
1743/*
1744Section: Utility Functions
1745
1746Function: $
1747	returns the element passed in with all the Element prototypes applied.
1748
1749Arguments:
1750	el - a reference to an actual element or a string representing the id of an element
1751
1752Example:
1753	>$('myElement') // gets a DOM element by id with all the Element prototypes applied.
1754	>var div = document.getElementById('myElement');
1755	>$(div) //returns an Element also with all the mootools extentions applied.
1756
1757	You'll use this when you aren't sure if a variable is an actual element or an id, as
1758	well as just shorthand for document.getElementById().
1759
1760Returns:
1761	a DOM element or false (if no id was found).
1762
1763Note:
1764	you need to call $ on an element only once to get all the prototypes.
1765	But its no harm to call it multiple times, as it will detect if it has been already extended.
1766*/
1767
1768function $(el){
1769	if (!el) return null;
1770	if (el.htmlElement) return Garbage.collect(el);
1771	if ([window, document].contains(el)) return el;
1772	var type = $type(el);
1773	if (type == 'string'){
1774		el = document.getElementById(el);
1775		type = (el) ? 'element' : false;
1776	}
1777	if (type != 'element') return null;
1778	if (el.htmlElement) return Garbage.collect(el);
1779	if (['object', 'embed'].contains(el.tagName.toLowerCase())) return el;
1780	$extend(el, Element.prototype);
1781	el.htmlElement = function(){};
1782	return Garbage.collect(el);
1783};
1784
1785/*
1786Function: $$
1787	Selects, and extends DOM elements. Elements arrays returned with $$ will also accept all the <Element> methods.
1788	The return type of element methods run through $$ is always an array. If the return array is only made by elements,
1789	$$ will be applied automatically.
1790
1791Arguments:
1792	HTML Collections, arrays of elements, arrays of strings as element ids, elements, strings as selectors.
1793	Any number of the above as arguments are accepted.
1794
1795Note:
1796	if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names.
1797
1798Example:
1799	>$$('a') //an array of all anchor tags on the page
1800	>$$('a', 'b') //an array of all anchor and bold tags on the page
1801	>$$('#myElement') //array containing only the element with id = myElement. (only with <Element.Selectors.js>)
1802	>$$('#myElement a.myClass') //an array of all anchor tags with the class "myClass"
1803	>//within the DOM element with id "myElement" (only with <Element.Selectors.js>)
1804	>$$(myelement, myelement2, 'a', ['myid', myid2, 'myid3'], document.getElementsByTagName('div')) //an array containing:
1805	>// the element referenced as myelement if existing,
1806	>// the element referenced as myelement2 if existing,
1807	>// all the elements with a as tag in the page,
1808	>// the element with id = myid if existing
1809	>// the element with id = myid2 if existing
1810	>// the element with id = myid3 if existing
1811	>// all the elements with div as tag in the page
1812
1813Returns:
1814	array - array of all the dom elements matched, extended with <$>.  Returns as <Elements>.
1815*/
1816
1817document.getElementsBySelector = document.getElementsByTagName;
1818
1819function $$(){
1820	var elements = [];
1821	for (var i = 0, j = arguments.length; i < j; i++){
1822		var selector = arguments[i];
1823		switch($type(selector)){
1824			case 'element': elements.push(selector);
1825			case 'boolean': break;
1826			case false: break;
1827			case 'string': selector = document.getElementsBySelector(selector, true);
1828			default: elements.extend(selector);
1829		}
1830	}
1831	return $$.unique(elements);
1832};
1833
1834$$.unique = function(array){
1835	var elements = [];
1836	for (var i = 0, l = array.length; i < l; i++){
1837		if (array[i].$included) continue;
1838		var element = $(array[i]);
1839		if (element && !element.$included){
1840			element.$included = true;
1841			elements.push(element);
1842		}
1843	}
1844	for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null;
1845	return new Elements(elements);
1846};
1847
1848Elements.Multi = function(property){
1849	return function(){
1850		var args = arguments;
1851		var items = [];
1852		var elements = true;
1853		for (var i = 0, j = this.length, returns; i < j; i++){
1854			returns = this[i][property].apply(this[i], args);
1855			if ($type(returns) != 'element') elements = false;
1856			items.push(returns);
1857		};
1858		return (elements) ? $$.unique(items) : items;
1859	};
1860};
1861
1862Element.extend = function(properties){
1863	for (var property in properties){
1864		HTMLElement.prototype[property] = properties[property];
1865		Element.prototype[property] = properties[property];
1866		Element[property] = $native.generic(property);
1867		var elementsProperty = (Array.prototype[property]) ? property + 'Elements' : property;
1868		Elements.prototype[elementsProperty] = Elements.Multi(property);
1869	}
1870};
1871
1872/*
1873Class: Element
1874	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
1875*/
1876
1877Element.extend({
1878
1879	/*
1880	Property: set
1881		you can set events, styles and properties with this shortcut. same as calling new Element.
1882	*/
1883
1884	set: function(props){
1885		for (var prop in props){
1886			var val = props[prop];
1887			switch(prop){
1888				case 'styles': this.setStyles(val); break;
1889				case 'events': if (this.addEvents) this.addEvents(val); break;
1890				case 'properties': this.setProperties(val); break;
1891				default: this.setProperty(prop, val);
1892			}
1893		}
1894		return this;
1895	},
1896
1897	inject: function(el, where){
1898		el = $(el);
1899		switch(where){
1900			case 'before': el.parentNode.insertBefore(this, el); break;
1901			case 'after':
1902				var next = el.getNext();
1903				if (!next) el.parentNode.appendChild(this);
1904				else el.parentNode.insertBefore(this, next);
1905				break;
1906			case 'top':
1907				var first = el.firstChild;
1908				if (first){
1909					el.insertBefore(this, first);
1910					break;
1911				}
1912			default: el.appendChild(this);
1913		}
1914		return this;
1915	},
1916
1917	/*
1918	Property: injectBefore
1919		Inserts the Element before the passed element.
1920
1921	Arguments:
1922		el - an element reference or the id of the element to be injected in.
1923
1924	Example:
1925		>html:
1926		><div id="myElement"></div>
1927		><div id="mySecondElement"></div>
1928		>js:
1929		>$('mySecondElement').injectBefore('myElement');
1930		>resulting html:
1931		><div id="mySecondElement"></div>
1932		><div id="myElement"></div>
1933	*/
1934
1935	injectBefore: function(el){
1936		return this.inject(el, 'before');
1937	},
1938
1939	/*
1940	Property: injectAfter
1941		Same as <Element.injectBefore>, but inserts the element after.
1942	*/
1943
1944	injectAfter: function(el){
1945		return this.inject(el, 'after');
1946	},
1947
1948	/*
1949	Property: injectInside
1950		Same as <Element.injectBefore>, but inserts the element inside.
1951	*/
1952
1953	injectInside: function(el){
1954		return this.inject(el, 'bottom');
1955	},
1956
1957	/*
1958	Property: injectTop
1959		Same as <Element.injectInside>, but inserts the element inside, at the top.
1960	*/
1961
1962	injectTop: function(el){
1963		return this.inject(el, 'top');
1964	},
1965
1966	/*
1967	Property: adopt
1968		Inserts the passed elements inside the Element.
1969
1970	Arguments:
1971		accepts elements references, element ids as string, selectors ($$('stuff')) / array of elements, array of ids as strings and collections.
1972	*/
1973
1974	adopt: function(){
1975		var elements = [];
1976		$each(arguments, function(argument){
1977			elements = elements.concat(argument);
1978		});
1979		$$(elements).inject(this);
1980		return this;
1981	},
1982
1983	/*
1984	Property: remove
1985		Removes the Element from the DOM.
1986
1987	Example:
1988		>$('myElement').remove() //bye bye
1989	*/
1990
1991	remove: function(){
1992		return this.parentNode.removeChild(this);
1993	},
1994
1995	/*
1996	Property: clone
1997		Clones the Element and returns the cloned one.
1998
1999	Arguments:
2000		contents - boolean, when true the Element is cloned with childNodes, default true
2001
2002	Returns:
2003		the cloned element
2004
2005	Example:
2006		>var clone = $('myElement').clone().injectAfter('myElement');
2007		>//clones the Element and append the clone after the Element.
2008	*/
2009
2010	clone: function(contents){
2011		var el = $(this.cloneNode(contents !== false));
2012		if (!el.$events) return el;
2013		el.$events = {};
2014		for (var type in this.$events) el.$events[type] = {
2015			'keys': $A(this.$events[type].keys),
2016			'values': $A(this.$events[type].values)
2017		};
2018		return el.removeEvents();
2019	},
2020
2021	/*
2022	Property: replaceWith
2023		Replaces the Element with an element passed.
2024
2025	Arguments:
2026		el - a string representing the element to be injected in (myElementId, or div), or an element reference.
2027		If you pass div or another tag, the element will be created.
2028
2029	Returns:
2030		the passed in element
2031
2032	Example:
2033		>$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place.
2034	*/
2035
2036	replaceWith: function(el){
2037		el = $(el);
2038		this.parentNode.replaceChild(el, this);
2039		return el;
2040	},
2041
2042	/*
2043	Property: appendText
2044		Appends text node to a DOM element.
2045
2046	Arguments:
2047		text - the text to append.
2048
2049	Example:
2050		><div id="myElement">hey</div>
2051		>$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy"
2052	*/
2053
2054	appendText: function(text){
2055		this.appendChild(document.createTextNode(text));
2056		return this;
2057	},
2058
2059	/*
2060	Property: hasClass
2061		Tests the Element to see if it has the passed in className.
2062
2063	Returns:
2064		true - the Element has the class
2065		false - it doesn't
2066
2067	Arguments:
2068		className - string; the class name to test.
2069
2070	Example:
2071		><div id="myElement" class="testClass"></div>
2072		>$('myElement').hasClass('testClass'); //returns true
2073	*/
2074
2075	hasClass: function(className){
2076		return this.className.contains(className, ' ');
2077	},
2078
2079	/*
2080	Property: addClass
2081		Adds the passed in class to the Element, if the element doesnt already have it.
2082
2083	Arguments:
2084		className - string; the class name to add
2085
2086	Example:
2087		><div id="myElement" class="testClass"></div>
2088		>$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div>
2089	*/
2090
2091	addClass: function(className){
2092		if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
2093		return this;
2094	},
2095
2096	/*
2097	Property: removeClass
2098		Works like <Element.addClass>, but removes the class from the element.
2099	*/
2100
2101	removeClass: function(className){
2102		this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
2103		return this;
2104	},
2105
2106	/*
2107	Property: toggleClass
2108		Adds or removes the passed in class name to the element, depending on if it's present or not.
2109
2110	Arguments:
2111		className - the class to add or remove
2112
2113	Example:
2114		>
2114<div id="myElement" class="myClass"></div>
2115		>$('myElement').toggleClass('myClass');
2116		><div id="myElement" class=""></div>
2117		>$('myElement').toggleClass('myClass');
2118		><div id="myElement" class="myClass"></div>
2119	*/
2120
2121	toggleClass: function(className){
2122		return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
2123	},
2124
2125	/*
2126	Property: setStyle
2127		Sets a css property to the Element.
2128
2129		Arguments:
2130			property - the property to set
2131			value - the value to which to set it; for numeric values that require "px" you can pass an integer
2132
2133		Example:
2134			>$('myElement').setStyle('width', '300px'); //the width is now 300px
2135			>$('myElement').setStyle('width', 300); //the width is now 300px
2136	*/
2137
2138	setStyle: function(property, value){
2139		switch(property){
2140			case 'opacity': return this.setOpacity(parseFloat(value));
2141			case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat';
2142		}
2143		property = property.camelCase();
2144		switch($type(value)){
2145			case 'number': if (!['zIndex', 'zoom'].contains(property)) value += 'px'; break;
2146			case 'array': value = 'rgb(' + value.join(',') + ')';
2147		}
2148		this.style[property] = value;
2149		return this;
2150	},
2151
2152	/*
2153	Property: setStyles
2154		Applies a collection of styles to the Element.
2155
2156	Arguments:
2157		source - an object or string containing all the styles to apply. When its a string it overrides old style.
2158
2159	Examples:
2160		>$('myElement').setStyles({
2161		>	border: '1px solid #000',
2162		>	width: 300,
2163		>	height: 400
2164		>});
2165
2166		OR
2167
2168		>$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;');
2169	*/
2170
2171	setStyles: function(source){
2172		switch($type(source)){
2173			case 'object': Element.setMany(this, 'setStyle', source); break;
2174			case 'string': this.style.cssText = source;
2175		}
2176		return this;
2177	},
2178
2179	/*
2180	Property: setOpacity
2181		Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0.
2182
2183	Arguments:
2184		opacity - float; Accepts values from 0 to 1.
2185
2186	Example:
2187		>$('myElement').setOpacity(0.5) //make it 50% transparent
2188	*/
2189
2190	setOpacity: function(opacity){
2191		if (opacity == 0){
2192			if (this.style.visibility != "hidden") this.style.visibility = "hidden";
2193		} else {
2194			if (this.style.visibility != "visible") this.style.visibility = "visible";
2195		}
2196		if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
2197		if (window.ie) this.style.filter = (opacity == 1) ? '' : "alpha(opacity=" + opacity * 100 + ")";
2198		this.style.opacity = this.$tmp.opacity = opacity;
2199		return this;
2200	},
2201
2202	/*
2203	Property: getStyle
2204		Returns the style of the Element given the property passed in.
2205
2206	Arguments:
2207		property - the css style property you want to retrieve
2208
2209	Example:
2210		>$('myElement').getStyle('width'); //returns "400px"
2211		>//but you can also use
2212		>$('myElement').getStyle('width').toInt(); //returns 400
2213
2214	Returns:
2215		the style as a string
2216	*/
2217
2218	getStyle: function(property){
2219		property = property.camelCase();
2220		var result = this.style[property];
2221		if (!$chk(result)){
2222			if (property == 'opacity') return this.$tmp.opacity;
2223			result = [];
2224			for (var style in Element.Styles){
2225				if (property == style){
2226					Element.Styles[style].each(function(s){
2227						var style = this.getStyle(s);
2228						result.push(parseInt(style) ? style : '0px');
2229					}, this);
2230					if (property == 'border'){
2231						var every = result.every(function(bit){
2232							return (bit == result[0]);
2233						});
2234						return (every) ? result[0] : false;
2235					}
2236					return result.join(' ');
2237				}
2238			}
2239			if (property.contains('border')){
2240				if (Element.Styles.border.contains(property)){
2241					return ['Width', 'Style', 'Color'].map(function(p){
2242						return this.getStyle(property + p);
2243					}, this).join(' ');
2244				} else if (Element.borderShort.contains(property)){
2245					return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){
2246						return this.getStyle('border' + p + property.replace('border', ''));
2247					}, this).join(' ');
2248				}
2249			}
2250			if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
2251			else if (this.currentStyle) result = this.currentStyle[property];
2252		}
2253		if (window.ie) result = Element.fixStyle(property, result, this);
2254		if (result && property.test(/color/i) && result.contains('rgb')){
2255			return result.split('rgb').splice(1,4).map(function(color){
2256				return color.rgbToHex();
2257			}).join(' ');
2258		}
2259		return result;
2260	},
2261
2262	/*
2263	Property: getStyles
2264		Returns an object of styles of the Element for each argument passed in.
2265		Arguments:
2266		properties - strings; any number of style properties
2267	Example:
2268		>$('myElement').getStyles('width','height','padding');
2269		>//returns an object like:
2270		>{width: "10px", height: "10px", padding: "10px 0px 10px 0px"}
2271	*/
2272
2273	getStyles: function(){
2274		return Element.getMany(this, 'getStyle', arguments);
2275	},
2276
2277	walk: function(brother, start){
2278		brother += 'Sibling';
2279		var el = (start) ? this[start] : this[brother];
2280		while (el && $type(el) != 'element') el = el[brother];
2281		return $(el);
2282	},
2283
2284	/*
2285	Property: getPrevious
2286		Returns the previousSibling of the Element, excluding text nodes.
2287
2288	Example:
2289		>$('myElement').getPrevious(); //get the previous DOM element from myElement
2290
2291	Returns:
2292		the sibling element or undefined if none found.
2293	*/
2294
2295	getPrevious: function(){
2296		return this.walk('previous');
2297	},
2298
2299	/*
2300	Property: getNext
2301		Works as Element.getPrevious, but tries to find the nextSibling.
2302	*/
2303
2304	getNext: function(){
2305		return this.walk('next');
2306	},
2307
2308	/*
2309	Property: getFirst
2310		Works as <Element.getPrevious>, but tries to find the firstChild.
2311	*/
2312
2313	getFirst: function(){
2314		return this.walk('next', 'firstChild');
2315	},
2316
2317	/*
2318	Property: getLast
2319		Works as <Element.getPrevious>, but tries to find the lastChild.
2320	*/
2321
2322	getLast: function(){
2323		return this.walk('previous', 'lastChild');
2324	},
2325
2326	/*
2327	Property: getParent
2328		returns the $(element.parentNode)
2329	*/
2330
2331	getParent: function(){
2332		return $(this.parentNode);
2333	},
2334
2335	/*
2336	Property: getChildren
2337		returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>.
2338	*/
2339
2340	getChildren: function(){
2341		return $$(this.childNodes);
2342	},
2343
2344	/*
2345	Property: hasChild
2346		returns true if the passed in element is a child of the $(element).
2347	*/
2348
2349	hasChild: function(el){
2350		return !!$A(this.getElementsByTagName('*')).contains(el);
2351	},
2352
2353	/*
2354	Property: getProperty
2355		Gets the an attribute of the Element.
2356
2357	Arguments:
2358		property - string; the attribute to retrieve
2359
2360	Example:
2361		>$('myImage').getProperty('src') // returns whatever.gif
2362
2363	Returns:
2364		the value, or an empty string
2365	*/
2366
2367	getProperty: function(property){
2368		var index = Element.Properties[property];
2369		if (index) return this[index];
2370		var flag = Element.PropertiesIFlag[property] || 0;
2371		if (!window.ie || flag) return this.getAttribute(property, flag);
2372		var node = this.attributes[property];
2373		return (node) ? node.nodeValue : null;
2374	},
2375
2376	/*
2377	Property: removeProperty
2378		Removes an attribute from the Element
2379
2380	Arguments:
2381		property - string; the attribute to remove
2382	*/
2383
2384	removeProperty: function(property){
2385		var index = Element.Properties[property];
2386		if (index) this[index] = '';
2387		else this.removeAttribute(property);
2388		return this;
2389	},
2390
2391	/*
2392	Property: getProperties
2393		same as <Element.getStyles>, but for properties
2394	*/
2395
2396	getProperties: function(){
2397		return Element.getMany(this, 'getProperty', arguments);
2398	},
2399
2400	/*
2401	Property: setProperty
2402		Sets an attribute for the Element.
2403
2404	Arguments:
2405		property - string; the property to assign the value passed in
2406		value - the value to assign to the property passed in
2407
2408	Example:
2409		>$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source
2410	*/
2411
2412	setProperty: function(property, value){
2413		var index = Element.Properties[property];
2414		if (index) this[index] = value;
2415		else this.setAttribute(property, value);
2416		return this;
2417	},
2418
2419	/*
2420	Property: setProperties
2421		Sets numerous attributes for the Element.
2422
2423	Arguments:
2424		source - an object with key/value pairs.
2425
2426	Example:
2427		(start code)
2428		$('myElement').setProperties({
2429			src: 'whatever.gif',
2430			alt: 'whatever dude'
2431		});
2432		<img src="whatever.gif" alt="whatever dude">
2433		(end)
2434	*/
2435
2436	setProperties: function(source){
2437		return Element.setMany(this, 'setProperty', source);
2438	},
2439
2440	/*
2441	Property: setHTML
2442		Sets the innerHTML of the Element.
2443
2444	Arguments:
2445		html - string; the new innerHTML for the element.
2446
2447	Example:
2448		>$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML
2449	*/
2450
2451	setHTML: function(){
2452		this.innerHTML = $A(arguments).join('');
2453		return this;
2454	},
2455
2456	/*
2457	Property: setText
2458		Sets the inner text of the Element.
2459
2460	Arguments:
2461		text - string; the new text content for the element.
2462
2463	Example:
2464		>$('myElement').setText('some text') //the text of myElement is now = 'some text'
2465	*/
2466
2467	setText: function(text){
2468		var tag = this.getTag();
2469		if (['style', 'script'].contains(tag)){
2470			if (window.ie){
2471				if (tag == 'style') this.styleSheet.cssText = text;
2472				else if (tag ==  'script') this.setProperty('text', text);
2473				return this;
2474			} else {
2475				this.removeChild(this.firstChild);
2476				return this.appendText(text);
2477			}
2478		}
2479		this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text;
2480		return this;
2481	},
2482
2483	/*
2484	Property: getText
2485		Gets the inner text of the Element.
2486	*/
2487
2488	getText: function(){
2489		var tag = this.getTag();
2490		if (['style', 'script'].contains(tag)){
2491			if (window.ie){
2492				if (tag == 'style') return this.styleSheet.cssText;
2493				else if (tag ==  'script') return this.getProperty('text');
2494			} else {
2495				return this.innerHTML;
2496			}
2497		}
2498		return ($pick(this.innerText, this.textContent));
2499	},
2500
2501	/*
2502	Property: getTag
2503		Returns the tagName of the element in lower case.
2504
2505	Example:
2506		>$('myImage').getTag() // returns 'img'
2507
2508	Returns:
2509		The tag name in lower case
2510	*/
2511
2512	getTag: function(){
2513		return this.tagName.toLowerCase();
2514	},
2515
2516	/*
2517	Property: empty
2518		Empties an element of all its children.
2519
2520	Example:
2521		>$('myDiv').empty() // empties the Div and returns it
2522
2523	Returns:
2524		The element.
2525	*/
2526
2527	empty: function(){
2528		Garbage.trash(this.getElementsByTagName('*'));
2529		return this.setHTML('');
2530	}
2531
2532});
2533
2534Element.fixStyle = function(property, result, element){
2535	if ($chk(parseInt(result))) return result;
2536	if (['height', 'width'].contains(property)){
2537		var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'];
2538		var size = 0;
2539		values.each(function(value){
2540			size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt();
2541		});
2542		return element['offset' + property.capitalize()] - size + 'px';
2543	} else if (property.test(/border(.+)Width|margin|padding/)){
2544		return '0px';
2545	}
2546	return result;
2547};
2548
2549Element.Styles = {'border': [], 'padding': [], 'margin': []};
2550['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
2551	for (var style in Element.Styles) Element.Styles[style].push(style + direction);
2552});
2553
2554Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor'];
2555
2556Element.getMany = function(el, method, keys){
2557	var result = {};
2558	$each(keys, function(key){
2559		result[key] = el[method](key);
2560	});
2561	return result;
2562};
2563
2564Element.setMany = function(el, method, pairs){
2565	for (var key in pairs) el[method](key, pairs[key]);
2566	return el;
2567};
2568
2569Element.Properties = new Abstract({
2570	'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan',
2571	'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength',
2572	'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value',
2573	'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected'
2574});
2575Element.PropertiesIFlag = {
2576	'href': 2, 'src': 2
2577};
2578
2579Element.Methods = {
2580	Listeners: {
2581		addListener: function(type, fn){
2582			if (this.addEventListener) this.addEventListener(type, fn, false);
2583			else this.attachEvent('on' + type, fn);
2584			return this;
2585		},
2586
2587		removeListener: function(type, fn){
2588			if (this.removeEventListener) this.removeEventListener(type, fn, false);
2589			else this.detachEvent('on' + type, fn);
2590			return this;
2591		}
2592	}
2593};
2594
2595window.extend(Element.Methods.Listeners);
2596document.extend(Element.Methods.Listeners);
2597Element.extend(Element.Methods.Listeners);
2598
2599var Garbage = {
2600
2601	elements: [],
2602
2603	collect: function(el){
2604		if (!el.$tmp){
2605			Garbage.elements.push(el);
2606			el.$tmp = {'opacity': 1};
2607		}
2608		return el;
2609	},
2610
2611	trash: function(elements){
2612		for (var i = 0, j = elements.length, el; i < j; i++){
2613			if (!(el = elements[i]) || !el.$tmp) continue;
2614			if (el.$events) el.fireEvent('trash').removeEvents();
2615			for (var p in el.$tmp) el.$tmp[p] = null;
2616			for (var d in Element.prototype) el[d] = null;
2617			Garbage.elements[Garbage.elements.indexOf(el)] = null;
2618			el.htmlElement = el.$tmp = el = null;
2619		}
2620		Garbage.elements.remove(null);
2621	},
2622
2623	empty: function(){
2624		Garbage.collect(window);
2625		Garbage.collect(document);
2626		Garbage.trash(Garbage.elements);
2627	}
2628
2629};
2630
2631window.addListener('beforeunload', function(){
2632	window.addListener('unload', Garbage.empty);
2633	if (window.ie) window.addListener('unload', CollectGarbage);
2634});
2635
2636/*
2637Script: Element.Event.js
2638	Contains the Event Class, Element methods to deal with Element events, custom Events, and the Function prototype bindWithEvent.
2639
2640License:
2641	MIT-style license.
2642*/
2643
2644/*
2645Class: Event
2646	Cross browser methods to manage events.
2647
2648Arguments:
2649	event - the event
2650
2651Properties:
2652	shift - true if the user pressed the shift
2653	control - true if the user pressed the control
2654	alt - true if the user pressed the alt
2655	meta - true if the user pressed the meta key
2656	wheel - the amount of third button scrolling
2657	code - the keycode of the key pressed
2658	page.x - the x position of the mouse, relative to the full window
2659	page.y - the y position of the mouse, relative to the full window
2660	client.x - the x position of the mouse, relative to the viewport
2661	client.y - the y position of the mouse, relative to the viewport
2662	key - the key pressed as a lowercase string. key also returns 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', 'esc'. Handy for these special keys.
2663	target - the event target
2664	relatedTarget - the event related target
2665
2666Example:
2667	(start code)
2668	$('myLink').onkeydown = function(event){
2669		var event = new Event(event);
2670		//event is now the Event class.
2671		alert(event.key); //returns the lowercase letter pressed
2672		alert(event.shift); //returns true if the key pressed is shift
2673		if (event.key == 's' && event.control) alert('document saved');
2674	};
2675	(end)
2676*/
2677
2678var Event = new Class({
2679
2680	initialize: function(event){
2681		if (event && event.$extended) return event;
2682		this.$extended = true;
2683		event = event || window.event;
2684		this.event = event;
2685		this.type = event.type;
2686		this.target = event.target || event.srcElement;
2687		if (this.target.nodeType == 3) this.target = this.target.parentNode;
2688		this.shift = event.shiftKey;
2689		this.control = event.ctrlKey;
2690		this.alt = event.altKey;
2691		this.meta = event.metaKey;
2692		if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){
2693			this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
2694		} else if (this.type.contains('key')){
2695			this.code = event.which || event.keyCode;
2696			for (var name in Event.keys){
2697				if (Event.keys[name] == this.code){
2698					this.key = name;
2699					break;
2700				}
2701			}
2702			if (this.type == 'keydown'){
2703				var fKey = this.code - 111;
2704				if (fKey > 0 && fKey < 13) this.key = 'f' + fKey;
2705			}
2706			this.key = this.key || String.fromCharCode(this.code).toLowerCase();
2707		} else if (this.type.test(/(click|mouse|menu)/)){
2708			this.page = {
2709				'x': event.pageX || event.clientX + document.documentElement.scrollLeft,
2710				'y': event.pageY || event.clientY + document.documentElement.scrollTop
2711			};
2712			this.client = {
2713				'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX,
2714				'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY
2715			};
2716			this.rightClick = (event.which == 3) || (event.button == 2);
2717			switch(this.type){
2718				case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break;
2719				case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement;
2720			}
2721			this.fixRelatedTarget();
2722		}
2723		return this;
2724	},
2725
2726	/*
2727	Property: stop
2728		cross browser method to stop an event
2729	*/
2730
2731	stop: function(){
2732		return this.stopPropagation().preventDefault();
2733	},
2734
2735	/*
2736	Property: stopPropagation
2737		cross browser method to stop the propagation of an event
2738	*/
2739
2740	stopPropagation: function(){
2741		if (this.event.stopPropagation) this.event.stopPropagation();
2742		else this.event.cancelBubble = true;
2743		return this;
2744	},
2745
2746	/*
2747	Property: preventDefault
2748		cross browser method to prevent the default action of the event
2749	*/
2750
2751	preventDefault: function(){
2752		if (this.event.preventDefault) this.event.preventDefault();
2753		else this.event.returnValue = false;
2754		return this;
2755	}
2756
2757});
2758
2759Event.fix = {
2760
2761	relatedTarget: function(){
2762		if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode;
2763	},
2764
2765	relatedTargetGecko: function(){
2766		try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;}
2767	}
2768
2769};
2770
2771Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget;
2772
2773/*
2774Property: keys
2775	you can add additional Event keys codes this way:
2776
2777Example:
2778	(start code)
2779	Event.keys.whatever = 80;
2780	$(myelement).addEvent(keydown, function(event){
2781		event = new Event(event);
2782		if (event.key == 'whatever') console.log(whatever key clicked).
2783	});
2784	(end)
2785*/
2786
2787Event.keys = new Abstract({
2788	'enter': 13,
2789	'up': 38,
2790	'down': 40,
2791	'left': 37,
2792	'right': 39,
2793	'esc': 27,
2794	'space': 32,
2795	'backspace': 8,
2796	'tab': 9,
2797	'delete': 46
2798});
2799
2800/*
2801Class: Element
2802	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
2803*/
2804
2805Element.Methods.Events = {
2806
2807	/*
2808	Property: addEvent
2809		Attaches an event listener to a DOM element.
2810
2811	Arguments:
2812		type - the event to monitor ('click', 'load', etc) without the prefix 'on'.
2813		fn - the function to execute
2814
2815	Example:
2816		>$('myElement').addEvent('click', function(){alert('clicked!')});
2817	*/
2818
2819	addEvent: function(type, fn){
2820		this.$events = this.$events || {};
2821		this.$events[type] = this.$events[type] || {'keys': [], 'values': []};
2822		if (this.$events[type].keys.contains(fn)) return this;
2823		this.$events[type].keys.push(fn);
2824		var realType = type;
2825		var custom = Element.Events[type];
2826		if (custom){
2827			if (custom.add) custom.add.call(this, fn);
2828			if (custom.map) fn = custom.map;
2829			if (custom.type) realType = custom.type;
2830		}
2831		if (!this.addEventListener) fn = fn.create({'bind': this, 'event': true});
2832		this.$events[type].values.push(fn);
2833		return (Element.NativeEvents.contains(realType)) ? this.addListener(realType, fn) : this;
2834	},
2835
2836	/*
2837	Property: removeEvent
2838		Works as Element.addEvent, but instead removes the previously added event listener.
2839	*/
2840
2841	removeEvent: function(type, fn){
2842		if (!this.$events || !this.$events[type]) return this;
2843		var pos = this.$events[type].keys.indexOf(fn);
2844		if (pos == -1) return this;
2845		var key = this.$events[type].keys.splice(pos,1)[0];
2846		var value = this.$events[type].values.splice(pos,1)[0];
2847		var custom = Element.Events[type];
2848		if (custom){
2849			if (custom.remove) custom.remove.call(this, fn);
2850			if (custom.type) type = custom.type;
2851		}
2852		return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this;
2853	},
2854
2855	/*
2856	Property: addEvents
2857		As <addEvent>, but accepts an object and add multiple events at once.
2858	*/
2859
2860	addEvents: function(source){
2861		return Element.setMany(this, 'addEvent', source);
2862	},
2863
2864	/*
2865	Property: removeEvents
2866		removes all events of a certain type from an element. if no argument is passed in, removes all events.
2867
2868	Arguments:
2869		type - string; the event name (e.g. 'click')
2870	*/
2871
2872	removeEvents: function(type){
2873		if (!this.$events) return this;
2874		if (!type){
2875			for (var evType in this.$events) this.removeEvents(evType);
2876			this.$events = null;
2877		} else if (this.$events[type]){
2878			this.$events[type].keys.each(function(fn){
2879				this.removeEvent(type, fn);
2880			}, this);
2881			this.$events[type] = null;
2882		}
2883		return this;
2884	},
2885
2886	/*
2887	Property: fireEvent
2888		executes all events of the specified type present in the element.
2889
2890	Arguments:
2891		type - string; the event name (e.g. 'click')
2892		args - array or single object; arguments to pass to the function; if more than one argument, must be an array
2893		delay - (integer) delay (in ms) to wait to execute the event
2894	*/
2895
2896	fireEvent: function(type, args, delay){
2897		if (this.$events && this.$events[type]){
2898			this.$events[type].keys.each(function(fn){
2899				fn.create({'bind': this, 'delay': delay, 'arguments': args})();
2900			}, this);
2901		}
2902		return this;
2903	},
2904
2905	/*
2906	Property: cloneEvents
2907		Clones all events from an element to this element.
2908
2909	Arguments:
2910		from - element, copy all events from this element
2911		type - optional, copies only events of this type
2912	*/
2913
2914	cloneEvents: function(from, type){
2915		if (!from.$events) return this;
2916		if (!type){
2917			for (var evType in from.$events) this.cloneEvents(from, evType);
2918		} else if (from.$events[type]){
2919			from.$events[type].keys.each(function(fn){
2920				this.addEvent(type, fn);
2921			}, this);
2922		}
2923		return this;
2924	}
2925
2926};
2927
2928window.extend(Element.Methods.Events);
2929document.extend(Element.Methods.Events);
2930Element.extend(Element.Methods.Events);
2931
2932/* Section: Custom Events */
2933
2934Element.Events = new Abstract({
2935
2936	/*
2937	Event: mouseenter
2938		In addition to the standard javascript events (load, mouseover, mouseout, click, etc.) <Event.js> contains two custom events
2939		this event fires when the mouse enters the area of the dom element; will not be fired again if the mouse crosses over children of the element (unlike mouseover)
2940
2941
2942	Example:
2943		>$(myElement).addEvent('mouseenter', myFunction);
2944	*/
2945
2946	'mouseenter': {
2947		type: 'mouseover',
2948		map: function(event){
2949			event = new Event(event);
2950			if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event);
2951		}
2952	},
2953
2954	/*
2955	Event: mouseleave
2956		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)
2957
2958
2959	Example:
2960		>$(myElement).addEvent('mouseleave', myFunction);
2961	*/
2962
2963	'mouseleave': {
2964		type: 'mouseout',
2965		map: function(event){
2966			event = new Event(event);
2967			if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event);
2968		}
2969	},
2970
2971	'mousewheel': {
2972		type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel'
2973	}
2974
2975});
2976
2977Element.NativeEvents = [
2978	'click', 'dblclick', 'mouseup', 'mousedown', //mouse buttons
2979	'mousewheel', 'DOMMouseScroll', //mouse wheel
2980	'mouseover', 'mouseout', 'mousemove', //mouse movement
2981	'keydown', 'keypress', 'keyup', //keys
2982	'load', 'unload', 'beforeunload', 'resize', 'move', //window
2983	'focus', 'blur', 'change', 'submit', 'reset', 'select', //forms elements
2984	'error', 'abort', 'contextmenu', 'scroll' //misc
2985];
2986
2987/*
2988Class: Function
2989	A collection of The Function Object prototype methods.
2990*/
2991
2992Function.extend({
2993
2994	/*
2995	Property: bindWithEvent
2996		automatically passes MooTools Event Class.
2997
2998	Arguments:
2999		bind - optional, the object that the "this" of the function will refer to.
3000		args - optional, an argument to pass to the function; if more than one argument, it must be an array of arguments.
3001
3002	Returns:
3003		a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
3004
3005	Example:
3006		>function myFunction(event){
3007		>	alert(event.client.x) //returns the coordinates of the mouse..
3008		>};
3009		>myElement.addEvent('click', myFunction.bindWithEvent(myElement));
3010	*/
3011
3012	bindWithEvent: function(bind, args){
3013		return this.create({'bind': bind, 'arguments': args, 'event': Event});
3014	}
3015
3016});
3017
3018
3019/*
3020Script: Element.Filters.js
3021	add Filters capability to <Elements>.
3022
3023License:
3024	MIT-style license.
3025*/
3026
3027/*
3028Class: Elements
3029	A collection of methods to be used with <$$> elements collections.
3030*/
3031
3032Elements.extend({
3033	
3034	/*
3035	Property: filterByTag
3036		Filters the collection by a specified tag name.
3037		Returns a new Elements collection, while the original remains untouched.
3038	*/
3039	
3040	filterByTag: function(tag){
3041		return new Elements(this.filter(function(el){
3042			return (Element.getTag(el) == tag);
3043		}));
3044	},
3045	
3046	/*
3047	Property: filterByClass
3048		Filters the collection by a specified class name.
3049		Returns a new Elements collection, while the original remains untouched.
3050	*/
3051	
3052	filterByClass: function(className, nocash){
3053		var elements = this.filter(function(el){
3054			return (el.className && el.className.contains(className, ' '));
3055		});
3056		return (nocash) ? elements : new Elements(elements);
3057	},
3058	
3059	/*
3060	Property: filterById
3061		Filters the collection by a specified ID.
3062		Returns a new Elements collection, while the original remains untouched.
3063	*/
3064	
3065	filterById: function(id, nocash){
3066		var elements = this.filter(function(el){
3067			return (el.id == id);
3068		});
3069		return (nocash) ? elements : new Elements(elements);
3070	},
3071	
3072	/*
3073	Property: filterByAttribute
3074		Filters the collection by a specified attribute.
3075		Returns a new Elements collection, while the original remains untouched.
3076		
3077	Arguments:
3078		name - the attribute name.
3079		operator - optional, the attribute operator.
3080		value - optional, the attribute value, only valid if the operator is specified.
3081	*/
3082	
3083	filterByAttribute: function(name, operator, value, nocash){
3084		var elements = this.filter(function(el){
3085			var current = Element.getProperty(el, name);
3086			if (!current) return false;
3087			if (!operator) return true;
3088			switch(operator){
3089				case '=': return (current == value);
3090				case '*=': return (current.contains(value));
3091				case '^=': return (current.substr(0, value.length) == value);
3092				case '$=': return (current.substr(current.length - value.length) == value);
3093				case '!=': return (current != value);
3094				case '~=': return current.contains(value, ' ');
3095			}
3096			return false;
3097		});
3098		return (nocash) ? elements : new Elements(elements);
3099	}
3100
3101});
3102
3103/*
3104Script: Element.Selectors.js
3105	Css Query related functions and <Element> extensions
3106
3107License:
3108	MIT-style license.
3109*/
3110
3111/* Section: Utility Functions */
3112
3113/*
3114Function: $E
3115	Selects a single (i.e. the first found) Element based on the selector passed in and an optional filter element.
3116	Returns as <Element>.
3117
3118Arguments:
3119	selector - string; the css selector to match
3120	filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
3121
3122Example:
3123	>$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement'
3124
3125Returns:
3126	a DOM element - the first element that matches the selector
3127*/
3128
3129function $E(selector, filter){
3130	return ($(filter) || document).getElement(selector);
3131};
3132
3133/*
3134Function: $ES
3135	Returns a collection of Elements that match the selector passed in limited to the scope of the optional filter.
3136	See Also: <Element.getElements> for an alternate syntax.
3137	Returns as <Elements>.
3138
3139Returns:
3140	an array of dom elements that match the selector within the filter
3141
3142Arguments:
3143	selector - string; css selector to match
3144	filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
3145
3146Examples:
3147	>$ES("a") //gets all the anchor tags; synonymous with $$("a")
3148	>$ES('a','myElement') //get all the anchor tags within $('myElement')
3149*/
3150
3151function $ES(selector, filter){
3152	return ($(filter) || document).getElementsBySelector(selector);
3153};
3154
3155$$.shared = {
3156
3157	'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/,
3158	
3159	'xpath': {
3160
3161		getParam: function(items, context, param, i){
3162			var temp = [context.namespaceURI ? 'xhtml:' : '', param[1]];
3163			if (param[2]) temp.push('[@id="', param[2], '"]');
3164			if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]');
3165			if (param[4]){
3166				if (param[5] && param[6]){
3167					switch(param[5]){
3168						case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break;
3169						case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break;
3170						case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break;
3171						case '=': temp.push('[@', param[4], '="', param[6], '"]'); break;
3172						case '!=': temp.push('[@', param[4], '!="', param[6], '"]');
3173					}
3174				} else {
3175					temp.push('[@', param[4], ']');
3176				}
3177			}
3178			items.push(temp.join(''));
3179			return items;
3180		},
3181		
3182		getItems: function(items, context, nocash){
3183			var elements = [];
3184			var xpath = document.evaluate('.//' + items.join('//'), context, $$.shared.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
3185			for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements.push(xpath.snapshotItem(i));
3186			return (nocash) ? elements : new Elements(elements.map($));
3187		}
3188
3189	},
3190	
3191	'normal': {
3192		
3193		getParam: function(items, context, param, i){
3194			if (i == 0){
3195				if (param[2]){
3196					var el = context.getElementById(param[2]);
3197					if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false;
3198					items = [el];
3199				} else {
3200					items = $A(context.getElementsByTagName(param[1]));
3201				}
3202			} else {
3203				items = $$.shared.getElementsByTagName(items, param[1]);
3204				if (param[2]) items = Elements.filterById(items, param[2], true);
3205			}
3206			if (param[3]) items = Elements.filterByClass(items, param[3], true);
3207			if (param[4]) items = Elements.filterByAttribute(items, param[4], param[5], param[6], true);
3208			return items;
3209		},
3210
3211		getItems: function(items, context, nocash){
3212			return (nocash) ? items : $$.unique(items);
3213		}
3214
3215	},
3216
3217	resolver: function(prefix){
3218		return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
3219	},
3220
3221	getElementsByTagName: function(context, tagName){
3222		var found = [];
3223		for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName));
3224		return found;
3225	}
3226
3227};
3228
3229$$.shared.method = (window.xpath) ? 'xpath' : 'normal';
3230
3231/*
3232Class: Element
3233	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3234*/
3235
3236Element.Methods.Dom = {
3237
3238	/*
3239	Property: getElements
3240		Gets all the elements within an element that match the given (single) selector.
3241		Returns as <Elements>.
3242
3243	Arguments:
3244		selector - string; the css selector to match
3245
3246	Examples:
3247		>$('myElement').getElements('a'); // get all anchors within myElement
3248		>$('myElement').getElements('input[name=dialog]') //get all input tags with name 'dialog'
3249		>$('myElement').getElements('input[name$=log]') //get all input tags with names ending with 'log'
3250
3251	Notes:
3252		Supports these operators in attribute selectors:
3253
3254		- = : is equal to
3255		- ^= : starts-with
3256		- $= : ends-with
3257		- != : is not equal to
3258
3259		Xpath is used automatically for compliant browsers.
3260	*/
3261
3262	getElements: function(selector, nocash){
3263		var items = [];
3264		selector = selector.trim().split(' ');
3265		for (var i = 0, j = selector.length; i < j; i++){
3266			var sel = selector[i];
3267			var param = sel.match($$.shared.regexp);
3268			if (!param) break;
3269			param[1] = param[1] || '*';
3270			var temp = $$.shared[$$.shared.method].getParam(items, this, param, i);
3271			if (!temp) break;
3272			items = temp;
3273		}
3274		return $$.shared[$$.shared.method].getItems(items, this, nocash);
3275	},
3276
3277	/*
3278	Property: getElement
3279		Same as <Element.getElements>, but returns only the first. Alternate syntax for <$E>, where filter is the Element.
3280		Returns as <Element>.
3281
3282	Arguments:
3283		selector - string; css selector
3284	*/
3285
3286	getElement: function(selector){
3287		return $(this.getElements(selector, true)[0] || false);
3288	},
3289
3290	/*
3291	Property: getElementsBySelector
3292		Same as <Element.getElements>, but allows for comma separated selectors, as in css. Alternate syntax for <$$>, where filter is the Element.
3293		Returns as <Elements>.
3294
3295	Arguments:
3296		selector - string; css selector
3297	*/
3298
3299	getElementsBySelector: function(selector, nocash){
3300		var elements = [];
3301		selector = selector.split(',');
3302		for (var i = 0, j = selector.length; i < j; i++) elements = elements.concat(this.getElements(selector[i], true));
3303		return (nocash) ? elements : $$.unique(elements);
3304	}
3305
3306};
3307
3308Element.extend({
3309
3310	/*
3311	Property: getElementById
3312		Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById.
3313
3314	Arguments:
3315		id - string; the id of the element to find.
3316	*/
3317
3318	getElementById: function(id){
3319		var el = document.getElementById(id);
3320		if (!el) return false;
3321		for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
3322			if (!parent) return false;
3323		}
3324		return el;
3325	}/*compatibility*/,
3326	
3327	getElementsByClassName: function(className){ 
3328		return this.getElements('.' + className); 
3329	}
3330	
3331	/*end compatibility*/
3332
3333});
3334
3335document.extend(Element.Methods.Dom);
3336Element.extend(Element.Methods.Dom);
3337
3338/*
3339Script: Element.Form.js
3340	Contains Element prototypes to deal with Forms and their elements.
3341
3342License:
3343	MIT-style license.
3344*/
3345
3346/*
3347Class: Element
3348	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3349*/
3350
3351Element.extend({
3352
3353	/*
3354	Property: getValue
3355		Returns the value of the Element, if its tag is textarea, select or input. getValue called on a multiple select will return an array.
3356	*/
3357
3358	getValue: function(){
3359		switch(this.getTag()){
3360			case 'select':
3361				var values = [];
3362				$each(this.options, function(option){
3363					if (option.selected) values.push($pick(option.value, option.text));
3364				});
3365				return (this.multiple) ? values : values[0];
3366			case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break;
3367			case 'textarea': return this.value;
3368		}
3369		return false;
3370	},
3371
3372	getFormElements: function(){
3373		return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea'));
3374	},
3375
3376	/*
3377	Property: toQueryString
3378		Reads the children inputs of the Element and generates a query string, based on their values. Used internally in <Ajax>
3379
3380	Example:
3381		(start code)
3382		<form id="myForm" action="submit.php">
3383		<input name="email" value="[email protected]">
3384		<input name="zipCode" value="90210">
3385		</form>
3386
3387		<script>
3388		 $('myForm').toQueryString()
3389		</script>
3390		(end)
3391
3392		Returns:
3393			[email protected]&zipCode=90210
3394	*/
3395
3396	toQueryString: function(){
3397		var queryString = [];
3398		this.getFormElements().each(function(el){
3399			var name = el.name;
3400			var value = el.getValue();
3401			if (value === false || !name || el.disabled) return;
3402			var qs = function(val){
3403				queryString.push(name + '=' + encodeURIComponent(val));
3404			};
3405			if ($type(value) == 'array') value.each(qs);
3406			else qs(value);
3407		});
3408		return queryString.join('&');
3409	}
3410
3411});
3412
3413/*
3414Script: Element.Dimensions.js
3415	Contains Element prototypes to deal with Element size and position in space.
3416
3417Note:
3418	The functions in this script require n XHTML doctype.
3419
3420License:
3421	MIT-style license.
3422*/
3423
3424/*
3425Class: Element
3426	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3427*/
3428
3429Element.extend({
3430
3431	/*
3432	Property: scrollTo
3433		Scrolls the element to the specified coordinated (if the element has an overflow)
3434
3435	Arguments:
3436		x - the x coordinate
3437		y - the y coordinate
3438
3439	Example:
3440		>$('myElement').scrollTo(0, 100)
3441	*/
3442
3443	scrollTo: function(x, y){
3444		this.scrollLeft = x;
3445		this.scrollTop = y;
3446	},
3447
3448	/*
3449	Property: getSize
3450		Return an Object representing the size/scroll values of the element.
3451
3452	Example:
3453		(start code)
3454		$('myElement').getSize();
3455		(end)
3456
3457	Returns:
3458		(start code)
3459		{
3460			'scroll': {'x': 100, 'y': 100},
3461			'size': {'x': 200, 'y': 400},
3462			'scrollSize': {'x': 300, 'y': 500}
3463		}
3464		(end)
3465	*/
3466
3467	getSize: function(){
3468		return {
3469			'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
3470			'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
3471			'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
3472		};
3473	},
3474
3475	/*
3476	Property: getPosition
3477		Returns the real offsets of the element.
3478
3479	Arguments:
3480		overflown - optional, an array of nested scrolling containers for scroll offset calculation, use this if your element is inside any element containing scrollbars
3481
3482	Example:
3483		>$('element').getPosition();
3484
3485	Returns:
3486		>{x: 100, y:500};
3487	*/
3488
3489	getPosition: function(overflown){
3490		overflown = overflown || [];
3491		var el = this, left = 0, top = 0;
3492		do {
3493			left += el.offsetLeft || 0;
3494			top += el.offsetTop || 0;
3495			el = el.offsetParent;
3496		} while (el);
3497		overflown.each(function(element){
3498			left -= element.scrollLeft || 0;
3499			top -= element.scrollTop || 0;
3500		});
3501		return {'x': left, 'y': top};
3502	},
3503
3504	/*
3505	Property: getTop
3506		Returns the distance from the top of the window to the Element.
3507
3508	Arguments:
3509		overflown - optional, an array of nested scrolling containers, see Element::getPosition
3510	*/
3511
3512	getTop: function(overflown){
3513		return this.getPosition(overflown).y;
3514	},
3515
3516	/*
3517	Property: getLeft
3518		Returns the distance from the left of the window to the Element.
3519
3520	Arguments:
3521		overflown - optional, an array of nested scrolling containers, see Element::getPosition
3522	*/
3523
3524	getLeft: function(overflown){
3525		return this.getPosition(overflown).x;
3526	},
3527
3528	/*
3529	Property: getCoordinates
3530		Returns an object with width, height, left, right, top, and bottom, representing the values of the Element
3531
3532	Arguments:
3533		overflown - optional, an array of nested scrolling containers, see Element::getPosition
3534
3535	Example:
3536		(start code)
3537		var myValues = $('myElement').getCoordinates();
3538		(end)
3539
3540	Returns:
3541		(start code)
3542		{
3543			width: 200,
3544			height: 300,
3545			left: 100,
3546			top: 50,
3547			right: 300,
3548			bottom: 350
3549		}
3550		(end)
3551	*/
3552
3553	getCoordinates: function(overflown){
3554		var position = this.getPosition(overflown);
3555		var obj = {
3556			'width': this.offsetWidth,
3557			'height': this.offsetHeight,
3558			'left': position.x,
3559			'top': position.y
3560		};
3561		obj.right = obj.left + obj.width;
3562		obj.bottom = obj.top + obj.height;
3563		return obj;
3564	}
3565
3566});
3567
3568/*
3569Script: Window.DomReady.js
3570	Contains the custom event domready, for window.
3571
3572License:
3573	MIT-style license.
3574*/
3575
3576/* Section: Custom Events */
3577
3578/*
3579Event: domready
3580	executes a function when the dom tree is loaded, without waiting for images. Only works when called from window.
3581
3582Credits:
3583	(c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools.
3584
3585Arguments:
3586	fn - the function to execute when the DOM is ready
3587
3588Example:
3589	> window.addEvent('domready', function(){
3590	>	alert('the dom is ready');
3591	> });
3592*/
3593
3594Element.Events.domready = {
3595
3596	add: function(fn){
3597		if (window.loaded){
3598			fn.call(this);
3599			return;
3600		}
3601		var domReady = function(){
3602			if (window.loaded) return;
3603			window.loaded = true;
3604			window.timer = $clear(window.timer);
3605			this.fireEvent('domready');
3606		}.bind(this);
3607		if (document.readyState && window.webkit){
3608			window.timer = function(){
3609				if (['loaded','complete'].contains(document.readyState)) domReady();
3610			}.periodical(50);
3611		} else if (document.readyState && window.ie){
3612			if (!$('ie_ready')){
3613				var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
3614				document.write('<script id="ie_ready" defer src="' + src + '"><\/script>');
3615				$('ie_ready').onreadystatechange = function(){
3616					if (this.readyState == 'complete') domReady();
3617				};
3618			}
3619		} else {
3620			window.addListener("load", domReady);
3621			document.addListener("DOMContentLoaded", domReady);
3622		}
3623	}
3624
3625};
3626
3627/*compatibility*/
3628
3629window.onDomReady = function(fn){ 
3630	return this.addEvent('domready', fn); 
3631};
3632
3633/*end compatibility*/
3634
3635/*
3636Script: Window.Size.js
3637	Window cross-browser dimensions methods.
3638	
3639Note:
3640	The Functions in this script require an XHTML doctype.
3641
3642License:
3643	MIT-style license.
3644*/
3645
3646/*
3647Class: window
3648	Cross browser methods to get various window dimensions.
3649	Warning: All these methods require that the browser operates in strict mode, not quirks mode.
3650*/
3651
3652window.extend({
3653
3654	/*
3655	Property: getWidth
3656		Returns an integer representing the width of the browser window (without the scrollbar).
3657	*/
3658
3659	getWidth: function(){
3660		if (this.webkit419) return this.innerWidth;
3661		if (this.opera) return document.body.clientWidth;
3662		return document.documentElement.clientWidth;
3663	},
3664
3665	/*
3666	Property: getHeight
3667		Returns an integer representing the height of the browser window (without the scrollbar).
3668	*/
3669
3670	getHeight: function(){
3671		if (this.webkit419) return this.innerHeight;
3672		if (this.opera) return document.body.clientHeight;
3673		return document.documentElement.clientHeight;
3674	},
3675
3676	/*
3677	Property: getScrollWidth
3678		Returns an integer representing the scrollWidth of the window.
3679		This value is equal to or bigger than <getWidth>.
3680
3681	See Also:
3682		<http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
3683	*/
3684
3685	getScrollWidth: function(){
3686		if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth);
3687		if (this.webkit) return document.body.scrollWidth;
3688		return document.documentElement.scrollWidth;
3689	},
3690
3691	/*
3692	Property: getScrollHeight
3693		Returns an integer representing the scrollHeight of the window.
3694		This value is equal to or bigger than <getHeight>.
3695
3696	See Also:
3697		<http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
3698	*/
3699
3700	getScrollHeight: function(){
3701		if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight);
3702		if (this.webkit) return document.body.scrollHeight;
3703		return document.documentElement.scrollHeight;
3704	},
3705
3706	/*
3707	Property: getScrollLeft
3708		Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).
3709
3710	See Also:
3711		<http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
3712	*/
3713
3714	getScrollLeft: function(){
3715		return this.pageXOffset || document.documentElement.scrollLeft;
3716	},
3717
3718	/*
3719	Property: getScrollTop
3720		Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).
3721
3722	See Also:
3723		<http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
3724	*/
3725
3726	getScrollTop: function(){
3727		return this.pageYOffset || document.documentElement.scrollTop;
3728	},
3729
3730	/*
3731	Property: getSize
3732		Same as <Element.getSize>
3733	*/
3734
3735	getSize: function(){
3736		return {
3737			'size': {'x': this.getWidth(), 'y': this.getHeight()},
3738			'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()},
3739			'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()}
3740		};
3741	},
3742
3743	//ignore
3744	getPosition: function(){return {'x': 0, 'y': 0};}
3745
3746});
3747
3748/*
3749Script: Fx.Base.js
3750	Contains <Fx.Base>, the foundamentals of the MooTools Effects.
3751
3752License:
3753	MIT-style license.
3754*/
3755
3756var Fx = {};
3757
3758/*
3759Class: Fx.Base
3760	Base class for the Effects.
3761
3762Options:
3763	transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.Sine.easeInOut>
3764	duration - the duration of the effect in ms; 500 is the default.
3765	unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%').
3766	wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true.
3767	fps - the frames per second for the transition; default is 50
3768	
3769Events:
3770	onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
3771	onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
3772	onCancel - the function to execute when you manually stop the effect.
3773*/
3774
3775Fx.Base = new Class({
3776
3777	options: {
3778		onStart: Class.empty,
3779		onComplete: Class.empty,
3780		onCancel: Class.empty,
3781		transition: function(p){
3782			return -(Math.cos(Math.PI * p) - 1) / 2;
3783		},
3784		duration: 500,
3785		unit: 'px',
3786		wait: true,
3787		fps: 50
3788	},
3789
3790	initialize: function(options){
3791		this.element = this.element || null;
3792		this.setOptions(options);
3793		if (this.options.initialize) this.options.initialize.call(this);
3794	},
3795
3796	step: function(){
3797		var time = $time();
3798		if (time < this.time + this.options.duration){
3799			this.delta = this.options.transition((time - this.time) / this.options.duration);
3800			this.setNow();
3801			this.increase();
3802		} else {
3803			this.stop(true);
3804			this.set(this.to);
3805			this.fireEvent('onComplete', this.element, 10);
3806			this.callChain();
3807		}
3808	},
3809
3810	/*
3811	Property: set
3812		Immediately sets the value with no transition.
3813
3814	Arguments:
3815		to - the point to jump to
3816
3817	Example:
3818		>var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
3819	*/
3820
3821	set: function(to){
3822		this.now = to;
3823		this.increase();
3824		return this;
3825	},
3826
3827	setNow: function(){
3828		this.now = this.compute(this.from, this.to);
3829	},
3830
3831	compute: function(from, to){
3832		return (to - from) * this.delta + from;
3833	},
3834
3835	/*
3836	Property: start
3837		Executes an effect from one position to the other.
3838
3839	Arguments:
3840		from - integer: staring value
3841		to - integer: the ending value
3842
3843	Examples:
3844		>var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque.
3845	*/
3846
3847	start: function(from, to){
3848		if (!this.options.wait) this.stop();
3849		else if (this.timer) return this;
3850		this.from = from;
3851		this.to = to;
3852		this.change = this.to - this.from;
3853		this.time = $time();
3854		this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
3855		this.fireEvent('onStart', this.element);
3856		return this;
3857	},
3858
3859	/*
3860	Property: stop
3861		Stops the transition.
3862	*/
3863
3864	stop: function(end){
3865		if (!this.timer) return this;
3866		this.timer = $clear(this.timer);
3867		if (!end) this.fireEvent('onCancel', this.element);
3868		return this;
3869	}/*compatibility*/,
3870	
3871	custom: function(from, to){
3872		return this.start(from, to);
3873	},
3874
3875	clearTimer: function(end){
3876		return this.stop(end);
3877	}
3878
3879	/*end compatibility*/
3880
3881});
3882
3883Fx.Base.implement(new Chain, new Events, new Options);
3884
3885/*
3886Script: Fx.CSS.js
3887	Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally.
3888
3889License:
3890	MIT-style license.
3891*/
3892
3893Fx.CSS = {
3894
3895	select: function(property, to){
3896		if (property.test(/color/i)) return this.Color;
3897		var type = $type(to);
3898		if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi;
3899		return this.Single;
3900	},
3901
3902	parse: function(el, property, fromTo){
3903		if (!fromTo.push) fromTo = [fromTo];
3904		var from = fromTo[0], to = fromTo[1];
3905		if (!$chk(to)){
3906			to = from;
3907			from = el.getStyle(property);
3908		}
3909		var css = this.select(property, to);
3910		return {'from': css.parse(from), 'to': css.parse(to), 'css': css};
3911	}
3912
3913};
3914
3915Fx.CSS.Single = {
3916
3917	parse: function(value){
3918		return parseFloat(value);
3919	},
3920
3921	getNow: function(from, to, fx){
3922		return fx.compute(from, to);
3923	},
3924
3925	getValue: function(value, unit, property){
3926		if (unit == 'px' && property != 'opacity') value = Math.round(value);
3927		return value + unit;
3928	}
3929
3930};
3931
3932Fx.CSS.Multi = {
3933
3934	parse: function(value){
3935		return value.push ? value : value.split(' ').map(function(v){
3936			return parseFloat(v);
3937		});
3938	},
3939
3940	getNow: function(from, to, fx){
3941		var now = [];
3942		for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
3943		return now;
3944	},
3945
3946	getValue: function(value, unit, property){
3947		if (unit == 'px' && property != 'opacity') value = value.map(Math.round);
3948		return value.join(unit + ' ') + unit;
3949	}
3950
3951};
3952
3953Fx.CSS.Color = {
3954
3955	parse: function(value){
3956		return value.push ? value : value.hexToRgb(true);
3957	},
3958
3959	getNow: function(from, to, fx){
3960		var now = [];
3961		for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
3962		return now;
3963	},
3964
3965	getValue: function(value){
3966		return 'rgb(' + value.join(',') + ')';
3967	}
3968
3969};
3970
3971/*
3972Script: Fx.Style.js
3973	Contains <Fx.Style>
3974
3975License:
3976	MIT-style license.
3977*/
3978
3979/*
3980Class: Fx.Style
3981	The Style effect, used to transition any css property from one value to another. Includes colors.
3982	Colors must be in hex format.
3983	Inherits methods, properties, options and events from <Fx.Base>.
3984
3985Arguments:
3986	el - the $(element) to apply the style transition to
3987	property - the property to transition
3988	options - the Fx.Base options (see: <Fx.Base>)
3989
3990Example:
3991	>var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
3992	>marginChange.start(10, 100);
3993*/
3994
3995Fx.Style = Fx.Base.extend({
3996
3997	initialize: function(el, property, options){
3998		this.element = $(el);
3999		this.property = property;
4000		this.parent(options);
4001	},
4002
4003	/*
4004	Property: hide
4005		Same as <Fx.Base.set> (0); hides the element immediately without transition.
4006	*/
4007
4008	hide: function(){
4009		return this.set(0);
4010	},
4011
4012	setNow: function(){
4013		this.now = this.css.getNow(this.from, this.to, this);
4014	},
4015
4016	/*
4017	Property: set
4018		Sets the element's css property (specified at instantiation) to the specified value immediately.
4019
4020	Example:
4021		(start code)
4022		var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4023		marginChange.set(10); //margin-top is set to 10px immediately
4024		(end)
4025	*/
4026
4027	set: function(to){
4028		this.css = Fx.CSS.select(this.property, to);
4029		return this.parent(this.css.parse(to));
4030	},
4031
4032	/*
4033	Property: start
4034		Displays the transition to the value/values passed in
4035
4036	Arguments:
4037		from - (integer; optional) the starting position for the transition
4038		to - (integer) the ending position for the transition
4039
4040	Note:
4041		If you provide only one argument, the transition will use the current css value for its starting value.
4042
4043	Example:
4044		(start code)
4045		var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4046		marginChange.start(10); //tries to read current margin top value and goes from current to 10
4047		(end)
4048	*/
4049
4050	start: function(from, to){
4051		if (this.timer && this.options.wait) return this;
4052		var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
4053		this.css = parsed.css;
4054		return this.parent(parsed.from, parsed.to);
4055	},
4056
4057	increase: function(){
4058		this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property));
4059	}
4060
4061});
4062
4063/*
4064Class: Element
4065	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4066*/
4067
4068Element.extend({
4069
4070	/*
4071	Property: effect
4072		Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>.
4073
4074	Arguments:
4075		property - (string) the css property to alter
4076		options - (object; optional) key/value set of options (see <Fx.Style>)
4077
4078	Example:
4079		>var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear});
4080		>myEffect.start(10, 100);
4081		>//OR
4082		>$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100);
4083	*/
4084
4085	effect: function(property, options){
4086		return new Fx.Style(this, property, options);
4087	}
4088
4089});
4090
4091/*
4092Script: Fx.Styles.js
4093	Contains <Fx.Styles>
4094
4095License:
4096	MIT-style license.
4097*/
4098
4099/*
4100Class: Fx.Styles
4101	Allows you to animate multiple css properties at once;
4102	Colors must be in hex format.
4103	Inherits methods, properties, options and events from <Fx.Base>.
4104
4105Arguments:
4106	el - the $(element) to apply the styles transition to
4107	options - the fx options (see: <Fx.Base>)
4108
4109Example:
4110	(start code)
4111	var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear});
4112
4113	//height from 10 to 100 and width from 900 to 300
4114	myEffects.start({
4115		'height': [10, 100],
4116		'width': [900, 300]
4117	});
4118
4119	//or height from current height to 100 and width from current width to 300
4120	myEffects.start({
4121		'height': 100,
4122		'width': 300
4123	});
4124	(end)
4125*/
4126
4127Fx.Styles = Fx.Base.extend({
4128
4129	initialize: function(el, options){
4130		this.element = $(el);
4131		this.parent(options);
4132	},
4133
4134	setNow: function(){
4135		for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this);
4136	},
4137
4138	set: function(to){
4139		var parsed = {};
4140		this.css = {};
4141		for (var p in to){
4142			this.css[p] = Fx.CSS.select(p, to[p]);
4143			parsed[p] = this.css[p].parse(to[p]);
4144		}
4145		return this.parent(parsed);
4146	},
4147
4148	/*
4149	Property: start
4150		Executes a transition for any number of css properties in tandem.
4151
4152	Arguments:
4153		obj - an object containing keys that specify css properties to alter and values that specify either the from/to values (as an array) or just the end value (an integer).
4154
4155	Example:
4156		see <Fx.Styles>
4157	*/
4158
4159	start: function(obj){
4160		if (this.timer && this.options.wait) return this;
4161		this.now = {};
4162		this.css = {};
4163		var from = {}, to = {};
4164		for (var p in obj){
4165			var parsed = Fx.CSS.parse(this.element, p, obj[p]);
4166			from[p] = parsed.from;
4167			to[p] = parsed.to;
4168			this.css[p] = parsed.css;
4169		}
4170		return this.parent(from, to);
4171	},
4172
4173	increase: function(){
4174		for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit, p));
4175	}
4176
4177});
4178
4179/*
4180Class: Element
4181	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4182*/
4183
4184Element.extend({
4185
4186	/*
4187	Property: effects
4188		Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>.
4189
4190	Example:
4191		>var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.Sine.easeInOut});
4192 		>myEffects.start({'height': [10, 100], 'width': [900, 300]});
4193	*/
4194
4195	effects: function(options){
4196		return new Fx.Styles(this, options);
4197	}
4198
4199});
4200
4201/*
4202Script: Fx.Elements.js
4203	Contains <Fx.Elements>
4204
4205License:
4206	MIT-style license.
4207*/
4208
4209/*
4210Class: Fx.Elements
4211	Fx.Elements allows you to apply any number of styles transitions to a selection of elements. Includes colors (must be in hex format).
4212	Inherits methods, properties, options and events from <Fx.Base>.
4213
4214Arguments:
4215	elements - a collection of elements the effects will be applied to.
4216	options - same as <Fx.Base> options.
4217*/
4218
4219Fx.Elements = Fx.Base.extend({
4220
4221	initialize: function(elements, options){
4222		this.elements = $$(elements);
4223		this.parent(options);
4224	},
4225
4226	setNow: function(){
4227		for (var i in this.from){
4228			var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {};
4229			for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this);
4230		}
4231	},
4232
4233	set: function(to){
4234		var parsed = {};
4235		this.css = {};
4236		for (var i in to){
4237			var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {};
4238			for (var p in iTo){
4239				iCss[p] = Fx.CSS.select(p, iTo[p]);
4240				iParsed[p] = iCss[p].parse(iTo[p]);
4241			}
4242		}
4243		return this.parent(parsed);
4244	},
4245
4246	/*
4247	Property: start
4248		Applies the passed in style transitions to each object named (see example). Each item in the collection is refered to as a numerical string ("1" for instance). The first item is "0", the second "1", etc.
4249
4250	Example:
4251		(start code)
4252		var myElementsEffects = new Fx.Elements($$('a'));
4253		myElementsEffects.start({
4254			'0': { //let's change the first element's opacity and width
4255				'opacity': [0,1],
4256				'width': [100,200]
4257			},
4258			'4': { //and the fifth one's opacity
4259				'opacity': [0.2, 0.5]
4260			}
4261		});
4262		(end)
4263	*/
4264
4265	start: function(obj){
4266		if (this.timer && this.options.wait) return this;
4267		this.now = {};
4268		this.css = {};
4269		var from = {}, to = {};
4270		for (var i in obj){
4271			var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {};
4272			for (var p in iProps){
4273				var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]);
4274				iFrom[p] = parsed.from;
4275				iTo[p] = parsed.to;
4276				iCss[p] = parsed.css;
4277			}
4278		}
4279		return this.parent(from, to);
4280	},
4281
4282	increase: function(){
4283		for (var i in this.now){
4284			var iNow = this.now[i], iCss = this.css[i];
4285			for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit, p));
4286		}
4287	}
4288
4289});
4290
4291/*
4292Script: Fx.Scroll.js
4293	Contains <Fx.Scroll>
4294
4295License:
4296	MIT-style license.
4297*/
4298
4299/*
4300Class: Fx.Scroll
4301	Scroll any element with an overflow, including the window element.
4302	Inherits methods, properties, options and events from <Fx.Base>.
4303
4304Note:
4305	Fx.Scroll requires an XHTML doctype.
4306
4307Arguments:
4308	element - the element to scroll
4309	options - optional, see Options below.
4310
4311Options:
4312	all the Fx.Base options and events, plus:
4313	offset - the distance for the scrollTo point/element. an Object with x/y properties.
4314	overflown - an array of nested scrolling containers, see <Element.getPosition>
4315*/
4316
4317Fx.Scroll = Fx.Base.extend({
4318
4319	options: {
4320		overflown: [],
4321		offset: {'x': 0, 'y': 0},
4322		wheelStops: true
4323	},
4324
4325	initialize: function(element, options){
4326		this.now = [];
4327		this.element = $(element);
4328		this.bound = {'stop': this.stop.bind(this, false)};
4329		this.parent(options);
4330		if (this.options.wheelStops){
4331			this.addEvent('onStart', function(){
4332				document.addEvent('mousewheel', this.bound.stop);
4333			}.bind(this));
4334			this.addEvent('onComplete', function(){
4335				document.removeEvent('mousewheel', this.bound.stop);
4336			}.bind(this));
4337		}
4338	},
4339
4340	setNow: function(){
4341		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4342	},
4343
4344	/*
4345	Property: scrollTo
4346		Scrolls the chosen element to the x/y coordinates.
4347
4348	Arguments:
4349		x - the x coordinate to scroll the element to
4350		y - the y coordinate to scroll the element to
4351	*/
4352
4353	scrollTo: function(x, y){
4354		if (this.timer && this.options.wait) return this;
4355		var el = this.element.getSize();
4356		var values = {'x': x, 'y': y};
4357		for (var z in el.size){
4358			var max = el.scrollSize[z] - el.size[z];
4359			if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;
4360			else values[z] = el.scroll[z];
4361			values[z] += this.options.offset[z];
4362		}
4363		return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]);
4364	},
4365
4366	/*
4367	Property: toTop
4368		Scrolls the chosen element to its maximum top.
4369	*/
4370
4371	toTop: function(){
4372		return this.scrollTo(false, 0);
4373	},
4374
4375	/*
4376	Property: toBottom
4377		Scrolls the chosen element to its maximum bottom.
4378	*/
4379
4380	toBottom: function(){
4381		return this.scrollTo(false, 'full');
4382	},
4383
4384	/*
4385	Property: toLeft
4386		Scrolls the chosen element to its maximum left.
4387	*/
4388
4389	toLeft: function(){
4390		return this.scrollTo(0, false);
4391	},
4392
4393	/*
4394	Property: toRight
4395		Scrolls the chosen element to its maximum right.
4396	*/
4397
4398	toRight: function(){
4399		return this.scrollTo('full', false);
4400	},
4401
4402	/*
4403	Property: toElement
4404		Scrolls the specified element to the position the passed in element is found.
4405
4406	Arguments:
4407		el - the $(element) to scroll the window to
4408	*/
4409
4410	toElement: function(el){
4411		var parent = this.element.getPosition(this.options.overflown);
4412		var target = $(el).getPosition(this.options.overflown);
4413		return this.scrollTo(target.x - parent.x, target.y - parent.y);
4414	},
4415
4416	increase: function(){
4417		this.element.scrollTo(this.now[0], this.now[1]);
4418	}
4419
4420});
4421
4422/*
4423Script: Fx.Slide.js
4424	Contains <Fx.Slide>
4425
4426License:
4427	MIT-style license.
4428*/
4429
4430/*
4431Class: Fx.Slide
4432	The slide effect; slides an element in horizontally or vertically, the contents will fold inside.
4433	Inherits methods, properties, options and events from <Fx.Base>.
4434	
4435Note:
4436	Fx.Slide requires an XHTML doctype.
4437
4438Options:
4439	mode - set it to vertical or horizontal. Defaults to vertical.
4440	options - all the <Fx.Base> options
4441
4442Example:
4443	(start code)
4444	var mySlider = new Fx.Slide('myElement', {duration: 500});
4445	mySlider.toggle() //toggle the slider up and down.
4446	(end)
4447*/
4448
4449Fx.Slide = Fx.Base.extend({
4450
4451	options: {
4452		mode: 'vertical'
4453	},
4454
4455	initialize: function(el, options){
4456		this.element = $(el);
4457		this.wrapper = new Element('div', {'styles': $extend(this.element.getStyles('margin'), {'overflow': 'hidden'})}).injectAfter(this.element).adopt(this.element);
4458		this.element.setStyle('margin', 0);
4459		this.setOptions(options);
4460		this.now = [];
4461		this.parent(this.options);
4462		this.open = true;
4463		this.addEvent('onComplete', function(){
4464			this.open = (this.now[0] === 0);
4465		});
4466		if (window.webkit419) this.addEvent('onComplete', function(){
4467			if (this.open) this.element.remove().inject(this.wrapper);
4468		});
4469	},
4470
4471	setNow: function(){
4472		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4473	},
4474
4475	vertical: function(){
4476		this.margin = 'margin-top';
4477		this.layout = 'height';
4478		this.offset = this.element.offsetHeight;
4479	},
4480
4481	horizontal: function(){
4482		this.margin = 'margin-left';
4483		this.layout = 'width';
4484		this.offset = this.element.offsetWidth;
4485	},
4486
4487	/*
4488	Property: slideIn
4489		Slides the elements in view horizontally or vertically.
4490
4491	Arguments:
4492		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4493	*/
4494
4495	slideIn: function(mode){
4496		this[mode || this.options.mode]();
4497		return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.offset]);
4498	},
4499
4500	/*
4501	Property: slideOut
4502		Sides the elements out of view horizontally or vertically.
4503
4504	Arguments:
4505		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4506	*/
4507
4508	slideOut: function(mode){
4509		this[mode || this.options.mode]();
4510		return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]);
4511	},
4512
4513	/*
4514	Property: hide
4515		Hides the element without a transition.
4516
4517	Arguments:
4518		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4519	*/
4520
4521	hide: function(mode){
4522		this[mode || this.options.mode]();
4523		this.open = false;
4524		return this.set([-this.offset, 0]);
4525	},
4526
4527	/*
4528	Property: show
4529		Shows the element without a transition.
4530
4531	Arguments:
4532		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4533	*/
4534
4535	show: function(mode){
4536		this[mode || this.options.mode]();
4537		this.open = true;
4538		return this.set([0, this.offset]);
4539	},
4540
4541	/*
4542	Property: toggle
4543		Slides in or Out the element, depending on its state
4544
4545	Arguments:
4546		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4547
4548	*/
4549
4550	toggle: function(mode){
4551		if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode);
4552		return this.slideOut(mode);
4553	},
4554
4555	increase: function(){
4556		this.element.setStyle(this.margin, this.now[0] + this.options.unit);
4557		this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit);
4558	}
4559
4560});
4561
4562/*
4563Script: Fx.Transitions.js
4564	Effects transitions, to be used with all the effects.
4565
4566License:
4567	MIT-style license.
4568
4569Credits:
4570	Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified & optimized to be used with mootools.
4571*/
4572
4573/*
4574Class: Fx.Transitions
4575	A collection of tweening transitions for use with the <Fx.Base> classes.
4576
4577Example:
4578	>//Elastic.easeOut with default values:
4579	>new Fx.Style('margin', {transition: Fx.Transitions.Elastic.easeOut});
4580	>//Elastic.easeOut with user-defined value for elasticity.
4581	> var myTransition = new Fx.Transition(Fx.Transitions.Elastic, 3);
4582	>new Fx.Style('margin', {transition: myTransition.easeOut});
4583
4584See also:
4585	http://www.robertpenner.com/easing/
4586*/
4587
4588Fx.Transition = function(transition, params){
4589	params = params || [];
4590	if ($type(params) != 'array') params = [params];
4591	return $extend(transition, {
4592		easeIn: function(pos){
4593			return transition(pos, params);
4594		},
4595		easeOut: function(pos){
4596			return 1 - transition(1 - pos, params);
4597		},
4598		easeInOut: function(pos){
4599			return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
4600		}
4601	});
4602};
4603
4604Fx.Transitions = new Abstract({
4605
4606	/*
4607	Property: linear
4608		displays a linear transition.
4609
4610	Graph:
4611		(see Linear.png)
4612	*/
4613
4614	linear: function(p){
4615		return p;
4616	}
4617
4618});
4619
4620Fx.Transitions.extend = function(transitions){
4621	for (var transition in transitions){
4622		Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
4623		/*compatibility*/
4624		Fx.Transitions.compat(transition);
4625		/*end compatibility*/
4626	}
4627};
4628
4629/*compatibility*/
4630
4631Fx.Transitions.compat = function(transition){
4632	['In', 'Out', 'InOut'].each(function(easeType){
4633		Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType];
4634	});
4635};
4636
4637/*end compatibility*/
4638
4639Fx.Transitions.extend({
4640
4641	/*
4642	Property: Quad
4643		displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut
4644
4645	Graph:
4646		(see Quad.png)
4647	*/
4648
4649	//auto generated
4650
4651	/*
4652	Property: Cubic
4653		displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut
4654
4655	Graph:
4656		(see Cubic.png)
4657	*/
4658
4659	//auto generated
4660
4661	/*
4662	Property: Quart
4663		displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut
4664
4665	Graph:
4666		(see Quart.png)
4667	*/
4668
4669	//auto generated
4670
4671	/*
4672	Property: Quint
4673		displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut
4674
4675	Graph:
4676		(see Quint.png)
4677	*/
4678
4679	//auto generated
4680
4681	/*
4682	Property: Pow
4683		Used to generate Quad, Cubic, Quart and Quint.
4684		By default is p^6.
4685
4686	Graph:
4687		(see Pow.png)
4688	*/
4689
4690	Pow: function(p, x){
4691		return Math.pow(p, x[0] || 6);
4692	},
4693
4694	/*
4695	Property: Expo
4696		displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut
4697
4698	Graph:
4699		(see Expo.png)
4700	*/
4701
4702	Expo: function(p){
4703		return Math.pow(2, 8 * (p - 1));
4704	},
4705
4706	/*
4707	Property: Circ
4708		displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut
4709
4710	Graph:
4711		(see Circ.png)
4712	*/
4713
4714	Circ: function(p){
4715		return 1 - Math.sin(Math.acos(p));
4716	},
4717
4718
4719	/*
4720	Property: Sine
4721		displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut
4722
4723	Graph:
4724		(see Sine.png)
4725	*/
4726
4727	Sine: function(p){
4728		return 1 - Math.sin((1 - p) * Math.PI / 2);
4729	},
4730
4731	/*
4732	Property: Back
4733		makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut
4734
4735	Graph:
4736		(see Back.png)
4737	*/
4738
4739	Back: function(p, x){
4740		x = x[0] || 1.618;
4741		return Math.pow(p, 2) * ((x + 1) * p - x);
4742	},
4743
4744	/*
4745	Property: Bounce
4746		makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut
4747
4748	Graph:
4749		(see Bounce.png)
4750	*/
4751
4752	Bounce: function(p){
4753		var value;
4754		for (var a = 0, b = 1; 1; a += b, b /= 2){
4755			if (p >= (7 - 4 * a) / 11){
4756				value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;
4757				break;
4758			}
4759		}
4760		return value;
4761	},
4762
4763	/*
4764	Property: Elastic
4765		Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut
4766
4767	Graph:
4768		(see Elastic.png)
4769	*/
4770
4771	Elastic: function(p, x){
4772		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
4773	}
4774
4775});
4776
4777['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
4778	Fx.Transitions[transition] = new Fx.Transition(function(p){
4779		return Math.pow(p, [i + 2]);
4780	});
4781	
4782	/*compatibility*/
4783	Fx.Transitions.compat(transition);
4784	/*end compatibility*/
4785});
4786
4787/*
4788Script: Drag.Base.js
4789	Contains <Drag.Base>, <Element.makeResizable>
4790
4791License:
4792	MIT-style license.
4793*/
4794
4795var Drag = {};
4796
4797/*
4798Class: Drag.Base
4799	Modify two css properties of an element based on the position of the mouse.
4800	
4801Note:
4802	Drag.Base requires an XHTML doctype.
4803
4804Arguments:
4805	el - the $(element) to apply the transformations to.
4806	options - optional. The options object.
4807
4808Options:
4809	handle - the $(element) to act as the handle for the draggable element. defaults to the $(element) itself.
4810	modifiers - an object. see Modifiers Below.
4811	limit - an object, see Limit below.
4812	grid - optional, distance in px for snap-to-grid dragging
4813	snap - optional, the distance you have to drag before the element starts to respond to the drag. defaults to false
4814
4815	modifiers:
4816		x - string, the style you want to modify when the mouse moves in an horizontal direction. defaults to 'left'
4817		y - string, the style you want to modify when the mouse moves in a vertical direction. defaults to 'top'
4818
4819	limit:
4820		x - array with start and end limit relative to modifiers.x
4821		y - array with start and end limit relative to modifiers.y
4822		
4823Events:
4824	onStart - optional, function to execute when the user starts to drag (on mousedown);
4825	onComplete - optional, function to execute when the user completes the drag.
4826	onDrag - optional, function to execute at every step of the drag
4827*/
4828
4829Drag.Base = new Class({
4830
4831	options: {
4832		handle: false,
4833		unit: 'px',
4834		onStart: Class.empty,
4835		onBeforeStart: Class.empty,
4836		onComplete: Class.empty,
4837		onSnap: Class.empty,
4838		onDrag: Class.empty,
4839		limit: false,
4840		modifiers: {x: 'left', y: 'top'},
4841		grid: false,
4842		snap: 6
4843	},
4844
4845	initialize: function(el, options){
4846		this.setOptions(options);
4847		this.element = $(el);
4848		this.handle = $(this.options.handle) || this.element;
4849		this.mouse = {'now': {}, 'pos': {}};
4850		this.value = {'start': {}, 'now': {}};
4851		this.bound = {
4852			'start': this.start.bindWithEvent(this),
4853			'check': this.check.bindWithEvent(this),
4854			'drag': this.drag.bindWithEvent(this),
4855			'stop': this.stop.bind(this)
4856		};
4857		this.attach();
4858		if (this.options.initialize) this.options.initialize.call(this);
4859	},
4860
4861	attach: function(){
4862		this.handle.addEvent('mousedown', this.bound.start);
4863		return this;
4864	},
4865
4866	detach: function(){
4867		this.handle.removeEvent('mousedown', this.bound.start);
4868		return this;
4869	},
4870
4871	start: function(event){
4872		this.fireEvent('onBeforeStart', this.element);
4873		this.mouse.start = event.page;
4874		var limit = this.options.limit;
4875		this.limit = {'x': [], 'y': []};
4876		for (var z in this.options.modifiers){
4877			if (!this.options.modifiers[z]) continue;
4878			this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
4879			this.mouse.pos[z] = event.page[z] - this.value.now[z];
4880			if (limit && limit[z]){
4881				for (var i = 0; i < 2; i++){
4882					if ($chk(limit[z][i])) this.limit[z][i] = ($type(limit[z][i]) == 'function') ? limit[z][i]() : limit[z][i];
4883				}
4884			}
4885		}
4886		if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};
4887		document.addListener('mousemove', this.bound.check);
4888		document.addListener('mouseup', this.bound.stop);
4889		this.fireEvent('onStart', this.element);
4890		event.stop();
4891	},
4892
4893	check: function(event){
4894		var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
4895		if (distance > this.options.snap){
4896			document.removeListener('mousemove', this.bound.check);
4897			document.addListener('mousemove', this.bound.drag);
4898			this.drag(event);
4899			this.fireEvent('onSnap', this.element);
4900		}
4901		event.stop();
4902	},
4903
4904	drag: function(event){
4905		this.out = false;
4906		this.mouse.now = event.page;
4907		for (var z in this.options.modifiers){
4908			if (!this.options.modifiers[z]) continue;
4909			this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
4910			if (this.limit[z]){
4911				if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
4912					this.value.now[z] = this.limit[z][1];
4913					this.out = true;
4914				} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
4915					this.value.now[z] = this.limit[z][0];
4916					this.out = true;
4917				}
4918			}
4919			if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);
4920			this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
4921		}
4922		this.fireEvent('onDrag', this.element);
4923		event.stop();
4924	},
4925
4926	stop: function(){
4927		document.removeListener('mousemove', this.bound.check);
4928		document.removeListener('mousemove', this.bound.drag);
4929		document.removeListener('mouseup', this.bound.stop);
4930		this.fireEvent('onComplete', this.element);
4931	}
4932
4933});
4934
4935Drag.Base.implement(new Events, new Options);
4936
4937/*
4938Class: Element
4939	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4940*/
4941
4942Element.extend({
4943
4944	/*
4945	Property: makeResizable
4946		Makes an element resizable (by dragging) with the supplied options.
4947
4948	Arguments:
4949		options - see <Drag.Base> for acceptable options.
4950	*/
4951
4952	makeResizable: function(options){
4953		return new Drag.Base(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
4954	}
4955
4956});
4957
4958/*
4959Script: Drag.Move.js
4960	Contains <Drag.Move>, <Element.makeDraggable>
4961
4962License:
4963	MIT-style license.
4964*/
4965
4966/*
4967Class: Drag.Move
4968	Extends <Drag.Base>, has additional functionality for dragging an element, support snapping and droppables.
4969	Drag.move supports either position absolute or relative. If no position is found, absolute will be set.
4970	Inherits methods, properties, options and events from <Drag.Base>.
4971
4972Note:
4973	Drag.Move requires an XHTML doctype.
4974
4975Arguments:
4976	el - the $(element) to apply the drag to.
4977	options - optional. see Options below.
4978
4979Options:
4980	all the drag.Base options, plus:
4981	container - an element, will fill automatically limiting options based on the $(element) size and position. defaults to false (no limiting)
4982	droppables - an array of elements you can drop your draggable to.
4983	overflown - an array of nested scrolling containers, see Element::getPosition
4984*/
4985
4986Drag.Move = Drag.Base.extend({
4987
4988	options: {
4989		droppables: [],
4990		container: false,
4991		overflown: []
4992	},
4993
4994	initialize: function(el, options){
4995		this.setOptions(options);
4996		this.element = $(el);
4997		this.droppables = $$(this.options.droppables);
4998		this.container = $(this.options.container);
4999		this.position = {'element': this.element.getStyle('position'), 'container': false};
5000		if (this.container) this.position.container = this.container.getStyle('position');
5001		if (!['relative', 'absolute', 'fixed'].contains(this.position.element)) this.position.element = 'absolute';
5002		var top = this.element.getStyle('top').toInt();
5003		var left = this.element.getStyle('left').toInt();
5004		if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5005			top = $chk(top) ? top : this.element.getTop(this.options.overflown);
5006			left = $chk(left) ? left : this.element.getLeft(this.options.overflown);
5007		} else {
5008			top = $chk(top) ? top : 0;
5009			left = $chk(left) ? left : 0;
5010		}
5011		this.element.setStyles({'top': top, 'left': left, 'position': this.position.element});
5012		this.parent(this.element);
5013	},
5014
5015	start: function(event){
5016		this.overed = null;
5017		if (this.container){
5018			var cont = this.container.getCoordinates();
5019			var el = this.element.getCoordinates();
5020			if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5021				this.options.limit = {
5022					'x': [cont.left, cont.right - el.width],
5023					'y': [cont.top, cont.bottom - el.height]
5024				};
5025			} else {
5026				this.options.limit = {
5027					'y': [0, cont.height - el.height],
5028					'x': [0, cont.width - el.width]
5029				};
5030			}
5031		}
5032		this.parent(event);
5033	},
5034
5035	drag: function(event){
5036		this.parent(event);
5037		var overed = this.out ? false : this.droppables.filter(this.checkAgainst, this).getLast();
5038		if (this.overed != overed){
5039			if (this.overed) this.overed.fireEvent('leave', [this.element, this]);
5040			this.overed = overed ? overed.fireEvent('over', [this.element, this]) : null;
5041		}
5042		return this;
5043	},
5044
5045	checkAgainst: function(el){
5046		el = el.getCoordinates(this.options.overflown);
5047		var now = this.mouse.now;
5048		return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
5049	},
5050
5051	stop: function(){
5052		if (this.overed && !this.out) this.overed.fireEvent('drop', [this.element, this]);
5053		else this.element.fireEvent('emptydrop', this);
5054		this.parent();
5055		return this;
5056	}
5057
5058});
5059
5060/*
5061Class: Element
5062	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5063*/
5064
5065Element.extend({
5066
5067	/*
5068	Property: makeDraggable
5069		Makes an element draggable with the supplied options.
5070
5071	Arguments:
5072		options - see <Drag.Move> and <Drag.Base> for acceptable options.
5073	*/
5074
5075	makeDraggable: function(options){
5076		return new Drag.Move(this, options);
5077	}
5078
5079});
5080
5081/*
5082Script: XHR.js
5083	Contains the basic XMLHttpRequest Class Wrapper.
5084
5085License:
5086	MIT-style license.
5087*/
5088
5089/*
5090Class: XHR
5091	Basic XMLHttpRequest Wrapper.
5092
5093Arguments:
5094	options - an object with options names as keys. See options below.
5095
5096Options:
5097	method - 'post' or 'get' - the protocol for the request; optional, defaults to 'post'.
5098	async - boolean: asynchronous option; true uses asynchronous requests. Defaults to true.
5099	encoding - the encoding, defaults to utf-8.
5100	autoCancel - cancels the already running request if another one is sent. defaults to false.
5101	headers - accepts an object, that will be set to request headers.
5102	
5103Events:
5104	onRequest - function to execute when the XHR request is fired.
5105	onSuccess - function to execute when the XHR request completes.
5106	onStateChange - function to execute when the state of the XMLHttpRequest changes.
5107	onFailure - function to execute when the state of the XMLHttpRequest changes.
5108
5109Properties:
5110	running - true if the request is running.
5111	response - object, text and xml as keys. You can access this property in the onSuccess event.
5112
5113Example:
5114	>var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian');
5115*/
5116
5117var XHR = new Class({
5118
5119	options: {
5120		method: 'post',
5121		async: true,
5122		onRequest: Class.empty,
5123		onSuccess: Class.empty,
5124		onFailure: Class.empty,
5125		urlEncoded: true,
5126		encoding: 'utf-8',
5127		autoCancel: false,
5128		headers: {}
5129	},
5130
5131	setTransport: function(){
5132		this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
5133		return this;
5134	},
5135
5136	initialize: function(options){
5137		this.setTransport().setOptions(options);
5138		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
5139		this.headers = {};
5140		if (this.options.urlEncoded && this.options.method == 'post'){
5141			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
5142			this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
5143		}
5144		if (this.options.initialize) this.options.initialize.call(this);
5145	},
5146
5147	onStateChange: function(){
5148		if (this.transport.readyState != 4 || !this.running) return;
5149		this.running = false;
5150		var status = 0;
5151		try {status = this.transport.status;} catch(e){};
5152		if (this.options.isSuccess.call(this, status)) this.onSuccess();
5153		else this.onFailure();
5154		this.transport.onreadystatechange = Class.empty;
5155	},
5156
5157	isSuccess: function(status){
5158		return ((status >= 200) && (status < 300));
5159	},
5160
5161	onSuccess: function(){
5162		this.response = {
5163			'text': this.transport.responseText,
5164			'xml': this.transport.responseXML
5165		};
5166		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
5167		this.callChain();
5168	},
5169
5170	onFailure: function(){
5171		this.fireEvent('onFailure', this.transport);
5172	},
5173
5174	/*
5175	Property: setHeader
5176		Add/modify an header for the request. It will not override headers from the options.
5177
5178	Example:
5179		>var myXhr = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}});
5180		>myXhr.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT');
5181	*/
5182
5183	setHeader: function(name, value){
5184		this.headers[name] = value;
5185		return this;
5186	},
5187
5188	/*
5189	Property: send
5190		Opens the XHR connection and sends the data. Data has to be null or a string.
5191
5192	Example:
5193		>var myXhr = new XHR({method: 'post'});
5194		>myXhr.send(url, querystring);
5195		>
5196		>var syncXhr = new XHR({async: false, method: 'post'});
5197		>syncXhr.send(url, null);
5198		>
5199	*/
5200
5201	send: function(url, data){
5202		if (this.options.autoCancel) this.cancel();
5203		else if (this.running) return this;
5204		this.running = true;
5205		if (data && this.options.method == 'get'){
5206			url = url + (url.contains('?') ? '&' : '?') + data;
5207			data = null;
5208		}
5209		this.transport.open(this.options.method.toUpperCase(), url, this.options.async);
5210		this.transport.onreadystatechange = this.onStateChange.bind(this);
5211		if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');
5212		$extend(this.headers, this.options.headers);
5213		for (var type in this.headers) try {this.transport.setRequestHeader(type, this.headers[type]);} catch(e){};
5214		this.fireEvent('onRequest');
5215		this.transport.send($pick(data, null));
5216		return this;
5217	},
5218
5219	/*
5220	Property: cancel
5221		Cancels the running request. No effect if the request is not running.
5222
5223	Example:
5224		>var myXhr = new XHR({method: 'get'}).send(url);
5225		>myXhr.cancel();
5226	*/
5227
5228	cancel: function(){
5229		if (!this.running) return this;
5230		this.running = false;
5231		this.transport.abort();
5232		this.transport.onreadystatechange = Class.empty;
5233		this.setTransport();
5234		this.fireEvent('onCancel');
5235		return this;
5236	}
5237
5238});
5239
5240XHR.implement(new Chain, new Events, new Options);
5241
5242/*
5243Script: Ajax.js
5244	Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects.
5245
5246Credits:
5247	Loosely based on the version from prototype.js <http://prototype.conio.net>
5248
5249License:
5250	MIT-style license.
5251*/
5252
5253/*
5254Class: Ajax
5255	An Ajax class, For all your asynchronous needs.
5256	Inherits methods, properties, options and events from <XHR>.
5257
5258Arguments:
5259	url - the url pointing to the server-side script.
5260	options - optional, an object containing options.
5261
5262Options:
5263	data - you can write parameters here. Can be a querystring, an object or a Form element.
5264	update - $(element) to insert the response text of the XHR into, upon completion of the request.
5265	evalScripts - boolean; default is false. Execute scripts in the response text onComplete. When the response is javascript the whole response is evaluated.
5266	evalResponse - boolean; default is false. Force global evalulation of the whole response, no matter what content-type it is.
5267	
5268Events:
5269	onComplete - function to execute when the ajax request completes.
5270
5271Example:
5272	>var myAjax = new Ajax(url, {method: 'get'}).request();
5273*/
5274
5275var Ajax = XHR.extend({
5276
5277	options: {
5278		data: null,
5279		update: null,
5280		onComplete: Class.empty,
5281		evalScripts: false,
5282		evalResponse: false
5283	},
5284
5285	initialize: function(url, options){
5286		this.addEvent('onSuccess', this.onComplete);
5287		this.setOptions(options);
5288		/*compatibility*/
5289		this.options.data = this.options.data || this.options.postBody;
5290		/*end compatibility*/
5291		if (!['post', 'get'].contains(this.options.method)){
5292			this._method = '_method=' + this.options.method;
5293			this.options.method = 'post';
5294		}
5295		this.parent();
5296		this.setHeader('X-Requested-With', 'XMLHttpRequest');
5297		this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
5298		this.url = url;
5299	},
5300
5301	onComplete: function(){
5302		if (this.options.update) $(this.options.update).empty().setHTML(this.response.text);
5303		if (this.options.evalScripts || this.options.evalResponse) this.evalScripts();
5304		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
5305	},
5306
5307	/*
5308	Property: request
5309		Executes the ajax request.
5310
5311	Example:
5312		>var myAjax = new Ajax(url, {method: 'get'});
5313		>myAjax.request();
5314
5315		OR
5316
5317		>new Ajax(url, {method: 'get'}).request();
5318	*/
5319
5320	request: function(data){
5321		data = data || this.options.data;
5322		switch($type(data)){
5323			case 'element': data = $(data).toQueryString(); break;
5324			case 'object': data = Object.toQueryString(data);
5325		}
5326		if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
5327		return this.send(this.url, data);
5328	},
5329
5330	/*
5331	Property: evalScripts
5332		Executes scripts in the response text
5333	*/
5334
5335	evalScripts: function(){
5336		var script, scripts;
5337		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) scripts = this.response.text;
5338		else {
5339			scripts = [];
5340			var regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
5341			while ((script = regexp.exec(this.response.text))) scripts.push(script[1]);
5342			scripts = scripts.join('\n');
5343		}
5344		if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0);
5345	},
5346
5347	/*
5348	Property: getHeader
5349		Returns the given response header or null
5350	*/
5351
5352	getHeader: function(name){
5353		try {return this.transport.getResponseHeader(name);} catch(e){};
5354		return null;
5355	}
5356
5357});
5358
5359/* Section: Object related Functions */
5360
5361/*
5362Function: Object.toQueryString
5363	Generates a querystring from key/pair values in an object
5364
5365Arguments:
5366	source - the object to generate the querystring from.
5367
5368Returns:
5369	the query string.
5370
5371Example:
5372	>Object.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow"
5373*/
5374
5375Object.toQueryString = function(source){
5376	var queryString = [];
5377	for (var property in source) queryString.push(encodeURIComponent(property) + '=' + encodeURIComponent(source[property]));
5378	return queryString.join('&');
5379};
5380
5381/*
5382Class: Element
5383	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5384*/
5385
5386Element.extend({
5387
5388	/*
5389	Property: send
5390		Sends a form with an ajax post request
5391
5392	Arguments:
5393		options - option collection for ajax request. See <Ajax> for the options list.
5394
5395	Returns:
5396		The Ajax Class Instance
5397
5398	Example:
5399		(start code)
5400		<form id="myForm" action="submit.php">
5401		<input name="email" value="[email protected]">
5402		<input name="zipCode" value="90210">
5403		</form>
5404		<script>
5405		$('myForm').send()
5406		</script>
5407		(end)
5408	*/
5409
5410	send: function(options){
5411		return new Ajax(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request();
5412	}
5413
5414});
5415
5416/*
5417Script: Cookie.js
5418	A cookie reader/creator
5419
5420Credits:
5421	based on the functions by Peter-Paul Koch (http://quirksmode.org)
5422*/
5423
5424/*
5425Class: Cookie
5426	Class for creating, getting, and removing cookies.
5427*/
5428
5429var Cookie = new Abstract({
5430
5431	options: {
5432		domain: false,
5433		path: false,
5434		duration: false,
5435		secure: false
5436	},
5437
5438	/*
5439	Property: set
5440		Sets a cookie in the browser.
5441
5442	Arguments:
5443		key - the key (name) for the cookie
5444		value - the value to set, cannot contain semicolons
5445		options - an object representing the Cookie options. See Options below. Default values are stored in Cookie.options.
5446
5447	Options:
5448		domain - the domain the Cookie belongs to. If you want to share the cookie with pages located on a different domain, you have to set this value. Defaults to the current domain.
5449		path - the path the Cookie belongs to. If you want to share the cookie with pages located in a different path, you have to set this value, for example to "/" to share the cookie with all pages on the domain. Defaults to the current path.
5450		duration - the duration of the Cookie before it expires, in days.
5451					If set to false or 0, the cookie will be a session cookie that expires when the browser is closed. This is default.
5452		secure - Stored cookie information can be accessed only from a secure environment.
5453
5454	Returns:
5455		An object with the options, the key and the value. You can give it as first parameter to Cookie.remove.
5456
5457	Example:
5458		>Cookie.set('username', 'Harald'); // session cookie (duration is false), or ...
5459		>Cookie.set('username', 'JackBauer', {duration: 1}); // save this for 1 day
5460
5461	*/
5462
5463	set: function(key, value, options){
5464		options = $merge(this.options, options);
5465		value = encodeURIComponent(value);
5466		if (options.domain) value += '; domain=' + options.domain;
5467		if (options.path) value += '; path=' + options.path;
5468		if (options.duration){
5469			var date = new Date();
5470			date.setTime(date.getTime() + options.duration * 24 * 60 * 60 * 1000);
5471			value += '; expires=' + date.toGMTString();
5472		}
5473		if (options.secure) value += '; secure';
5474		document.cookie = key + '=' + value;
5475		return $extend(options, {'key': key, 'value': value});
5476	},
5477
5478	/*
5479	Property: get
5480		Gets the value of a cookie.
5481
5482	Arguments:
5483		key - the name of the cookie you wish to retrieve.
5484
5485	Returns:
5486		The cookie string value, or false if not found.
5487
5488	Example:
5489		>Cookie.get("username") //returns JackBauer
5490	*/
5491
5492	get: function(key){
5493		var value = document.cookie.match('(?:^|;)\\s*' + key.escapeRegExp() + '=([^;]*)');
5494		return value ? decodeURIComponent(value[1]) : false;
5495	},
5496
5497	/*
5498	Property: remove
5499		Removes a cookie from the browser.
5500
5501	Arguments:
5502		cookie - the name of the cookie to remove or a previous cookie (for domains)
5503		options - optional. you can also pass the domain and path here. Same as options in <Cookie.set>
5504
5505	Examples:
5506		>Cookie.remove('username') //bye-bye JackBauer, cya in 24 hours
5507		>
5508		>var myCookie = Cookie.set('username', 'Aaron', {domain: 'mootools.net'}); // Cookie.set returns an object with all values need to remove the cookie
5509		>Cookie.remove(myCookie);
5510	*/
5511
5512	remove: function(cookie, options){
5513		if ($type(cookie) == 'object') this.set(cookie.key, '', $merge(cookie, {duration: -1}));
5514		else this.set(cookie, '', $merge(options, {duration: -1}));
5515	}
5516
5517});
5518
5519/*
5520Script: Json.js
5521	Simple Json parser and Stringyfier, See: <http://www.json.org/>
5522
5523License:
5524	MIT-style license.
5525*/
5526
5527/*
5528Class: Json
5529	Simple Json parser and Stringyfier, See: <http://www.json.org/>
5530*/
5531
5532var Json = {
5533
5534	/*
5535	Property: toString
5536		Converts an object to a string, to be passed in server-side scripts as a parameter. Although its not normal usage for this class, this method can also be used to convert functions and arrays to strings.
5537
5538	Arguments:
5539		obj - the object to convert to string
5540
5541	Returns:
5542		A json string
5543
5544	Example:
5545		(start code)
5546		Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}'
5547		(end)
5548	*/
5549
5550	toString: function(obj){
5551		switch($type(obj)){
5552			case 'string':
5553				return '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
5554			case 'array':
5555				return '[' + obj.map(Json.toString).join(',') + ']';
5556			case 'object':
5557				var string = [];
5558				for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property]));
5559				return '{' + string.join(',') + '}';
5560			case 'number':
5561				if (isFinite(obj)) break;
5562			case false:
5563				return 'null';
5564		}
5565		return String(obj);
5566	},
5567
5568	/*
5569	Property: evaluate
5570		converts a json string to an javascript Object.
5571
5572	Arguments:
5573		str - the string to evaluate. if its not a string, it returns false.
5574		secure - optionally, performs syntax check on json string. Defaults to false.
5575
5576	Credits:
5577		Json test regexp is by Douglas Crockford <http://crockford.org>.
5578
5579	Example:
5580		>var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}');
5581		>//myObject will become {apple: 'red', lemon: 'yellow'}
5582	*/
5583
5584	evaluate: function(str, secure){
5585		return (($type(str) != 'string') || (secure && !str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/))) ? null : eval('(' + str + ')');
5586	}
5587
5588};
5589
5590/*
5591Script: Json.Remote.js
5592	Contains <Json.Remote>.
5593
5594License:
5595	MIT-style license.
5596*/
5597
5598/*
5599Class: Json.Remote
5600	Wrapped XHR with automated sending and receiving of Javascript Objects in Json Format.
5601	Inherits methods, properties, options and events from <XHR>.
5602
5603Arguments:
5604	url - the url you want to send your object to.
5605	options - see <XHR> options
5606
5607Example:
5608	this code will send user information based on name/last name
5609	(start code)
5610	var jSonRequest = new Json.Remote("http://site.com/tellMeAge.php", {onComplete: function(person){
5611		alert(person.age); //is 25 years
5612		alert(person.height); //is 170 cm
5613		alert(person.weight); //is 120 kg
5614	}}).send({'name': 'John', 'lastName': 'Doe'});
5615	(end)
5616*/
5617
5618Json.Remote = XHR.extend({
5619
5620	initialize: function(url, options){
5621		this.url = url;
5622		this.addEvent('onSuccess', this.onComplete);
5623		this.parent(options);
5624		this.setHeader('X-Request', 'JSON');
5625	},
5626
5627	send: function(obj){
5628		return this.parent(this.url, 'json=' + Json.toString(obj));
5629	},
5630
5631	onComplete: function(){
5632		this.fireEvent('onComplete', [Json.evaluate(this.response.text, this.options.secure)]);
5633	}
5634
5635});
5636
5637/*
5638Script: Assets.js
5639	provides dynamic loading for images, css and javascript files.
5640
5641License:
5642	MIT-style license.
5643*/
5644
5645var Asset = new Abstract({
5646
5647	/*
5648	Property: javascript
5649		Injects a javascript file in the page.
5650
5651	Arguments:
5652		source - the path of the javascript file
5653		properties - some additional attributes you might want to add to the script element
5654
5655	Example:
5656		>
5656 new Asset.javascript('/scripts/myScript.js', {id: 'myScript'});
5657	*/
5658
5659	javascript: function(source, properties){
5660		properties = $merge({
5661			'onload': Class.empty
5662		}, properties);
5663		var script = new Element('script', {'src': source}).addEvents({
5664			'load': properties.onload,
5665			'readystatechange': function(){
5666				if (this.readyState == 'complete') this.fireEvent('load');
5667			}
5668		});
5669		delete properties.onload;
5670		return script.setProperties(properties).inject(document.head);
5671	},
5672
5673	/*
5674	Property: css
5675		Injects a css file in the page.
5676
5677	Arguments:
5678		source - the path of the css file
5679		properties - some additional attributes you might want to add to the link element
5680
5681	Example:
5682		> new Asset.css('/css/myStyle.css', {id: 'myStyle', title: 'myStyle'});
5683	*/
5684
5685	css: function(source, properties){
5686		return new Element('link', $merge({
5687			'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
5688		}, properties)).inject(document.head);
5689	},
5690
5691	/*
5692	Property: image
5693		Preloads an image and returns the img element. does not inject it to the page.
5694
5695	Arguments:
5696		source - the path of the image file
5697		properties - some additional attributes you might want to add to the img element
5698
5699	Example:
5700		> new Asset.image('/images/myImage.png', {id: 'myImage', title: 'myImage', onload: myFunction});
5701
5702	Returns:
5703		the img element. you can inject it anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5704	*/
5705
5706	image: function(source, properties){
5707		properties = $merge({
5708			'onload': Class.empty,
5709			'onabort': Class.empty,
5710			'onerror': Class.empty
5711		}, properties);
5712		var image = new Image();
5713		image.src = source;
5714		var element = new Element('img', {'src': source});
5715		['load', 'abort', 'error'].each(function(type){
5716			var event = properties['on' + type];
5717			delete properties['on' + type];
5718			element.addEvent(type, function(){
5719				this.removeEvent(type, arguments.callee);
5720				event.call(this);
5721			});
5722		});
5723		if (image.width && image.height) element.fireEvent('load', element, 1);
5724		return element.setProperties(properties);
5725	},
5726
5727	/*
5728	Property: images
5729		Preloads an array of images (as strings) and returns an array of img elements. does not inject them to the page.
5730
5731	Arguments:
5732		sources - array, the paths of the image files
5733		options - object, see below
5734
5735	Options:
5736		onComplete - a function to execute when all image files are loaded in the browser's cache
5737		onProgress - a function to execute when one image file is loaded in the browser's cache
5738
5739	Example:
5740		(start code)
5741		new Asset.images(['/images/myImage.png', '/images/myImage2.gif'], {
5742			onComplete: function(){
5743				alert('all images loaded!');
5744			}
5745		});
5746		(end)
5747
5748	Returns:
5749		the img elements as $$. you can inject them anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5750	*/
5751
5752	images: function(sources, options){
5753		options = $merge({
5754			onComplete: Class.empty,
5755			onProgress: Class.empty
5756		}, options);
5757		if (!sources.push) sources = [sources];
5758		var images = [];
5759		var counter = 0;
5760		sources.each(function(source){
5761			var img = new Asset.image(source, {
5762				'onload': function(){
5763					options.onProgress.call(this, counter);
5764					counter++;
5765					if (counter == sources.length) options.onComplete();
5766				}
5767			});
5768			images.push(img);
5769		});
5770		return new Elements(images);
5771	}
5772
5773});
5774
5775/*
5776Script: Hash.js
5777	Contains the class Hash.
5778
5779License:
5780	MIT-style license.
5781*/
5782
5783/*
5784Class: Hash
5785	It wraps an object that it uses internally as a map. The user must use set(), get(), and remove() to add/change, retrieve and remove values, it must not access the internal object directly. null/undefined values are allowed.
5786
5787Note:
5788	Each hash instance has the length property.
5789
5790Arguments:
5791	obj - an object to convert into a Hash instance.
5792
5793Example:
5794	(start code)
5795	var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'});
5796	hash.remove('b'); // b is removed.
5797	hash.set('c', 'hello');
5798	hash.get('c'); // returns 'hello'
5799	hash.length // returns 2 (a and c)
5800	(end)
5801*/
5802
5803var Hash = new Class({
5804
5805	length: 0,
5806
5807	initialize: function(object){
5808		this.obj = object || {};
5809		this.setLength();
5810	},
5811
5812	/*
5813	Property: get
5814		Retrieves a value from the hash.
5815
5816	Arguments:
5817		key - The key
5818
5819	Returns:
5820		The value
5821	*/
5822
5823	get: function(key){
5824		return (this.hasKey(key)) ? this.obj[key] : null;
5825	},
5826
5827	/*
5828	Property: hasKey
5829		Check the presence of a specified key-value pair in the hash.
5830
5831	Arguments:
5832		key - The key
5833
5834	Returns:
5835		True if the Hash contains a value for the specified key, otherwise false
5836	*/
5837
5838	hasKey: function(key){
5839		return (key in this.obj);
5840	},
5841
5842	/*
5843	Property: set
5844		Adds a key-value pair to the hash or replaces a previous value associated with the key.
5845
5846	Arguments:
5847		key - The key
5848		value - The value
5849	*/
5850
5851	set: function(key, value){
5852		if (!this.hasKey(key)) this.length++;
5853		this.obj[key] = value;
5854		return this;
5855	},
5856
5857	setLength: function(){
5858		this.length = 0;
5859		for (var p in this.obj) this.length++;
5860		return this;
5861	},
5862
5863	/*
5864	Property: remove
5865		Removes a key-value pair from the hash.
5866
5867	Arguments:
5868		key - The key
5869	*/
5870
5871	remove: function(key){
5872		if (this.hasKey(key)){
5873			delete this.obj[key];
5874			this.length--;
5875		}
5876		return this;
5877	},
5878
5879	/*
5880	Property: each
5881		Calls a function for each key-value pair. The first argument passed to the function will be the value, the second one will be the key, like $each.
5882
5883	Arguments:
5884		fn - The function to call for each key-value pair
5885		bind - Optional, the object that will be referred to as "this" in the function
5886	*/
5887
5888	each: function(fn, bind){
5889		$each(this.obj, fn, bind);
5890	},
5891
5892	/*
5893	Property: extend
5894		Extends the current hash with an object containing key-value pairs. Values for duplicate keys will be replaced by the new ones.
5895
5896	Arguments:
5897		obj - An object containing key-value pairs
5898	*/
5899
5900	extend: function(obj){
5901		$extend(this.obj, obj);
5902		return this.setLength();
5903	},
5904
5905	/*
5906	Property: merge
5907		Merges the current hash with multiple objects.
5908	*/
5909
5910	merge: function(){
5911		this.obj = $merge.apply(null, [this.obj].extend(arguments));
5912		return this.setLength();
5913	},
5914
5915	/*
5916	Property: empty
5917		Empties all hash values properties and values.
5918	*/
5919
5920	empty: function(){
5921		this.obj = {};
5922		this.length = 0;
5923		return this;
5924	},
5925
5926	/*
5927	Property: keys
5928		Returns an array containing all the keys, in the same order as the values returned by <Hash.values>.
5929
5930	Returns:
5931		An array containing all the keys of the hash
5932	*/
5933
5934	keys: function(){
5935		var keys = [];
5936		for (var property in this.obj) keys.push(property);
5937		return keys;
5938	},
5939
5940	/*
5941	Property: values
5942		Returns an array containing all the values, in the same order as the keys returned by <Hash.keys>.
5943
5944	Returns:
5945		An array containing all the values of the hash
5946	*/
5947
5948	values: function(){
5949		var values = [];
5950		for (var property in this.obj) values.push(this.obj[property]);
5951		return values;
5952	}
5953
5954});
5955
5956/* Section: Utility Functions */
5957
5958/*
5959Function: $H
5960	Shortcut to create a Hash from an Object.
5961*/
5962
5963function $H(obj){
5964	return new Hash(obj);
5965};
5966
5967/*
5968Script: Hash.Cookie.js
5969	Stores and loads an Hash as a cookie using Json format.
5970*/
5971
5972/*
5973Class: Hash.Cookie
5974	Inherits all the methods from <Hash>, additional methods are save and load.
5975	Hash json string has a limit of 4kb (4096byte), so be careful with your Hash size.
5976	Creating a new instance automatically loads the data from the Cookie into the Hash.
5977	If the Hash is emptied, the cookie is also removed.
5978
5979Arguments:
5980	name - the key (name) for the cookie
5981	options - options are identical to <Cookie> and are simply passed along to it.
5982		In addition, it has the autoSave option, to save the cookie at every operation. defaults to true.
5983
5984Example:
5985	(start code)
5986	var fruits = new Hash.Cookie('myCookieName', {duration: 3600});
5987	fruits.extend({
5988		'lemon': 'yellow',
5989		'apple': 'red'
5990	});
5991	fruits.set('melon', 'green');
5992	fruits.get('lemon'); // yellow
5993
5994	// ... on another page ... values load automatically
5995
5996	var fruits = new Hash.Cookie('myCookieName', {duration: 365});
5997	fruits.get('melon'); // green
5998
5999	fruits.erase(); // delete cookie
6000	(end)
6001*/
6002
6003Hash.Cookie = Hash.extend({
6004
6005	initialize: function(name, options){
6006		this.name = name;
6007		this.options = $extend({'autoSave': true}, options || {});
6008		this.load();
6009	},
6010
6011	/*
6012	Property: save
6013		Saves the Hash to the cookie. If the hash is empty, removes the cookie.
6014
6015	Returns:
6016		Returns false when the JSON string cookie is too long (4kb), otherwise true.
6017
6018	Example:
6019		(start code)
6020		var login = new Hash.Cookie('userstatus', {autoSave: false});
6021
6022		login.extend({
6023			'username': 'John',
6024			'credentials': [4, 7, 9]
6025		});
6026		login.set('last_message', 'User logged in!');
6027
6028		login.save(); // finally save the Hash
6029		(end)
6030	*/
6031
6032	save: function(){
6033		if (this.length == 0){
6034			Cookie.remove(this.name, this.options);
6035			return true;
6036		}
6037		var str = Json.toString(this.obj);
6038		if (str.length > 4096) return false; //cookie would be truncated!
6039		Cookie.set(this.name, str, this.options);
6040		return true;
6041	},
6042	
6043	/*
6044	Property: load
6045		Loads the cookie and assigns it to the Hash.
6046	*/
6047
6048	load: function(){
6049		this.obj = Json.evaluate(Cookie.get(this.name), true) || {};
6050		this.setLength();
6051	}
6052
6053});
6054
6055Hash.Cookie.Methods = {};
6056['extend', 'set', 'merge', 'empty', 'remove'].each(function(method){
6057	Hash.Cookie.Methods[method] = function(){
6058		Hash.prototype[method].apply(this, arguments);
6059		if (this.options.autoSave) this.save();
6060		return this;
6061	};
6062});
6063Hash.Cookie.implement(Hash.Cookie.Methods);
6064
6065/*
6066Script: Color.js
6067	Contains the Color class.
6068
6069License:
6070	MIT-style license.
6071*/
6072
6073/*
6074Class: Color
6075	Creates a new Color Object, which is an array with some color specific methods.
6076Arguments:
6077	color - the hex, the RGB array or the HSB array of the color to create. For HSB colors, you need to specify the second argument.
6078	type - a string representing the type of the color to create. needs to be specified if you intend to create the color with HSB values, or an array of HEX values. Can be 'rgb', 'hsb' or 'hex'.
6079
6080Example:
6081	(start code)
6082	var black = new Color('#000');
6083	var purple = new Color([255,0,255]);
6084	// mix black with white and purple, each time at 10% of the new color
6085	var darkpurple = black.mix('#fff', purple, 10);
6086	$('myDiv').setStyle('background-color', darkpurple);
6087	(end)
6088*/
6089
6090var Color = new Class({
6091
6092	initialize: function(color, type){
6093		type = type || (color.push ? 'rgb' : 'hex');
6094		var rgb, hsb;
6095		switch(type){
6096			case 'rgb':
6097				rgb = color;
6098				hsb = rgb.rgbToHsb();
6099				break;
6100			case 'hsb':
6101				rgb = color.hsbToRgb();
6102				hsb = color;
6103				break;
6104			default:
6105				rgb = color.hexToRgb(true);
6106				hsb = rgb.rgbToHsb();
6107		}
6108		rgb.hsb = hsb;
6109		rgb.hex = rgb.rgbToHex();
6110		return $extend(rgb, Color.prototype);
6111	},
6112
6113	/*
6114	Property: mix
6115		Mixes two or more colors with the Color.
6116		
6117	Arguments:
6118		color - a color to mix. you can use as arguments how many colors as you want to mix with the original one.
6119		alpha - if you use a number as the last argument, it will be threated as the amount of the color to mix.
6120	*/
6121
6122	mix: function(){
6123		var colors = $A(arguments);
6124		var alpha = ($type(colors[colors.length - 1]) == 'number') ? colors.pop() : 50;
6125		var rgb = this.copy();
6126		colors.each(function(color){
6127			color = new Color(color);
6128			for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
6129		});
6130		return new Color(rgb, 'rgb');
6131	},
6132
6133	/*
6134	Property: invert
6135		Inverts the Color.
6136	*/
6137
6138	invert: function(){
6139		return new Color(this.map(function(value){
6140			return 255 - value;
6141		}));
6142	},
6143
6144	/*
6145	Property: setHue
6146		Modifies the hue of the Color, and returns a new one.
6147	
6148	Arguments:
6149		value - the hue to set
6150	*/
6151
6152	setHue: function(value){
6153		return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
6154	},
6155
6156	/*
6157	Property: setSaturation
6158		Changes the saturation of the Color, and returns a new one.
6159	
6160	Arguments:
6161		percent - the percentage of the saturation to set
6162	*/
6163
6164	setSaturation: function(percent){
6165		return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
6166	},
6167
6168	/*
6169	Property: setBrightness
6170		Changes the brightness of the Color, and returns a new one.
6171	
6172	Arguments:
6173		percent - the percentage of the brightness to set
6174	*/
6175
6176	setBrightness: function(percent){
6177		return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
6178	}
6179
6180});
6181
6182/* Section: Utility Functions */
6183
6184/*
6185Function: $RGB
6186	Shortcut to create a new color, based on red, green, blue values.
6187
6188Arguments:
6189	r - (integer) red value (0-255)
6190	g - (integer) green value (0-255)
6191	b - (integer) blue value (0-255)
6192
6193*/
6194
6195function $RGB(r, g, b){
6196	return new Color([r, g, b], 'rgb');
6197};
6198
6199/*
6200Function: $HSB
6201	Shortcut to create a new color, based on hue, saturation, brightness values.
6202
6203Arguments:
6204	h - (integer) hue value (0-100)
6205	s - (integer) saturation value (0-100)
6206	b - (integer) brightness value (0-100)
6207*/
6208
6209function $HSB(h, s, b){
6210	return new Color([h, s, b], 'hsb');
6211};
6212
6213/*
6214Class: Array
6215	A collection of The Array Object prototype methods.
6216*/
6217
6218Array.extend({
6219	
6220	/*
6221	Property: rgbToHsb
6222		Converts a RGB array to an HSB array.
6223
6224	Returns:
6225		the HSB array.
6226	*/
6227
6228	rgbToHsb: function(){
6229		var red = this[0], green = this[1], blue = this[2];
6230		var hue, saturation, brightness;
6231		var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
6232		var delta = max - min;
6233		brightness = max / 255;
6234		saturation = (max != 0) ? delta / max : 0;
6235		if (saturation == 0){
6236			hue = 0;
6237		} else {
6238			var rr = (max - red) / delta;
6239			var gr = (max - green) / delta;
6240			var br = (max - blue) / delta;
6241			if (red == max) hue = br - gr;
6242			else if (green == max) hue = 2 + rr - br;
6243			else hue = 4 + gr - rr;
6244			hue /= 6;
6245			if (hue < 0) hue++;
6246		}
6247		return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
6248	},
6249
6250	/*
6251	Property: hsbToRgb
6252		Converts an HSB array to an RGB array.
6253
6254	Returns:
6255		the RGB array.
6256	*/
6257
6258	hsbToRgb: function(){
6259		var br = Math.round(this[2] / 100 * 255);
6260		if (this[1] == 0){
6261			return [br, br, br];
6262		} else {
6263			var hue = this[0] % 360;
6264			var f = hue % 60;
6265			var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
6266			var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
6267			var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
6268			switch(Math.floor(hue / 60)){
6269				case 0: return [br, t, p];
6270				case 1: return [q, br, p];
6271				case 2: return [p, br, t];
6272				case 3: return [p, q, br];
6273				case 4: return [t, p, br];
6274				case 5: return [br, p, q];
6275			}
6276		}
6277		return false;
6278	}
6279
6280});
6281
6282/*
6283Script: Scroller.js
6284	Contains the <Scroller>.
6285
6286License:
6287	MIT-style license.
6288*/
6289
6290/*
6291Class: Scroller
6292	The Scroller is a class to scroll any element with an overflow (including the window) when the mouse 
6292cursor reaches certain buondaries of that element.
6293	You must call its start method to start listening to mouse movements.
6294
6295Note:
6296	The Scroller requires an XHTML doctype.
6297
6298Arguments:
6299	element - required, the element to scroll.
6300	options - optional, see options below, and <Fx.Base> options.
6301
6302Options:
6303	area - integer, the necessary boundaries to make the element scroll.
6304	velocity - integer, velocity ratio, the modifier for the window scrolling speed.
6305
6306Events:
6307	onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets.
6308		Automatically passes as parameters x and y values.
6309*/
6310
6311var Scroller = new Class({
6312
6313	options: {
6314		area: 20,
6315		velocity: 1,
6316		onChange: function(x, y){
6317			this.element.scrollTo(x, y);
6318		}
6319	},
6320
6321	initialize: function(element, options){
6322		this.setOptions(options);
6323		this.element = $(element);
6324		this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element;
6325	},
6326
6327	/*
6328	Property: start
6329		The scroller starts listening to mouse movements.
6330	*/
6331
6332	start: function(){
6333		this.coord = this.getCoords.bindWithEvent(this);
6334		this.mousemover.addListener('mousemove', this.coord);
6335	},
6336
6337	/*
6338	Property: stop
6339		The scroller stops listening to mouse movements.
6340	*/
6341
6342	stop: function(){
6343		this.mousemover.removeListener('mousemove', this.coord);
6344		this.timer = $clear(this.timer);
6345	},
6346
6347	getCoords: function(event){
6348		this.page = (this.element == window) ? event.client : event.page;
6349		if (!this.timer) this.timer = this.scroll.periodical(50, this);
6350	},
6351
6352	scroll: function(){
6353		var el = this.element.getSize();
6354		var pos = this.element.getPosition();
6355
6356		var change = {'x': 0, 'y': 0};
6357		for (var z in this.page){
6358			if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
6359				change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
6360			else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
6361				change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
6362		}
6363		if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
6364	}
6365
6366});
6367
6368Scroller.implement(new Events, new Options);
6369
6370/*
6371Script: Slider.js
6372	Contains <Slider>
6373
6374License:
6375	MIT-style license.
6376*/
6377
6378/*
6379Class: Slider
6380	Creates a slider with two elements: a knob and a container. Returns the values.
6381	
6382Note:
6383	The Slider requires an XHTML doctype.
6384
6385Arguments:
6386	element - the knob container
6387	knob - the handle
6388	options - see Options below
6389
6390Options:
6391	steps - the number of steps for your slider.
6392	mode - either 'horizontal' or 'vertical'. defaults to horizontal.
6393	offset - relative offset for knob position. default to 0.
6394	
6395Events:
6396	onChange - a function to fire when the value changes.
6397	onComplete - a function to fire when you're done dragging.
6398	onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position.
6399		Passes as parameter the new position.
6400*/
6401
6402var Slider = new Class({
6403
6404	options: {
6405		onChange: Class.empty,
6406		onComplete: Class.empty,
6407		onTick: function(pos){
6408			this.knob.setStyle(this.p, pos);
6409		},
6410		mode: 'horizontal',
6411		steps: 100,
6412		offset: 0
6413	},
6414
6415	initialize: function(el, knob, options){
6416		this.element = $(el);
6417		this.knob = $(knob);
6418		this.setOptions(options);
6419		this.previousChange = -1;
6420		this.previousEnd = -1;
6421		this.step = -1;
6422		this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
6423		var mod, offset;
6424		switch(this.options.mode){
6425			case 'horizontal':
6426				this.z = 'x';
6427				this.p = 'left';
6428				mod = {'x': 'left', 'y': false};
6429				offset = 'offsetWidth';
6430				break;
6431			case 'vertical':
6432				this.z = 'y';
6433				this.p = 'top';
6434				mod = {'x': false, 'y': 'top'};
6435				offset = 'offsetHeight';
6436		}
6437		this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
6438		this.half = this.knob[offset]/2;
6439		this.getPos = this.element['get' + this.p.capitalize()].bind(this.element);
6440		this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset);
6441		var lim = {};
6442		lim[this.z] = [- this.options.offset, this.max - this.options.offset];
6443		this.drag = new Drag.Base(this.knob, {
6444			limit: lim,
6445			modifiers: mod,
6446			snap: 0,
6447			onStart: function(){
6448				this.draggedKnob();
6449			}.bind(this),
6450			onDrag: function(){
6451				this.draggedKnob();
6452			}.bind(this),
6453			onComplete: function(){
6454				this.draggedKnob();
6455				this.end();
6456			}.bind(this)
6457		});
6458		if (this.options.initialize) this.options.initialize.call(this);
6459	},
6460
6461	/*
6462	Property: set
6463		The slider will get the step you pass.
6464
6465	Arguments:
6466		step - one integer
6467	*/
6468
6469	set: function(step){
6470		this.step = step.limit(0, this.options.steps);
6471		this.checkStep();
6472		this.end();
6473		this.fireEvent('onTick', this.toPosition(this.step));
6474		return this;
6475	},
6476
6477	clickedElement: function(event){
6478		var position = event.page[this.z] - this.getPos() - this.half;
6479		position = position.limit(-this.options.offset, this.max -this.options.offset);
6480		this.step = this.toStep(position);
6481		this.checkStep();
6482		this.end();
6483		this.fireEvent('onTick', position);
6484	},
6485
6486	draggedKnob: function(){
6487		this.step = this.toStep(this.drag.value.now[this.z]);
6488		this.checkStep();
6489	},
6490
6491	checkStep: function(){
6492		if (this.previousChange != this.step){
6493			this.previousChange = this.step;
6494			this.fireEvent('onChange', this.step);
6495		}
6496	},
6497
6498	end: function(){
6499		if (this.previousEnd !== this.step){
6500			this.previousEnd = this.step;
6501			this.fireEvent('onComplete', this.step + '');
6502		}
6503	},
6504
6505	toStep: function(position){
6506		return Math.round((position + this.options.offset) / this.max * this.options.steps);
6507	},
6508
6509	toPosition: function(step){
6510		return this.max * step / this.options.steps;
6511	}
6512
6513});
6514
6515Slider.implement(new Events);
6516Slider.implement(new Options);
6517
6518/*
6519Script: SmoothScroll.js
6520	Contains <SmoothScroll>
6521
6522License:
6523	MIT-style license.
6524*/
6525
6526/*
6527Class: SmoothScroll
6528	Auto targets all the anchors in a page and display a smooth scrolling effect upon clicking them.
6529	Inherits methods, properties, options and events from <Fx.Scroll>.
6530
6531Note:
6532	SmoothScroll requires an XHTML doctype.
6533
6534Arguments:
6535	options - the Fx.Scroll options (see: <Fx.Scroll>) plus links, a collection of elements you want your smoothscroll on. Defaults to document.links.
6536
6537Example:
6538	>new SmoothScroll();
6539*/
6540
6541var SmoothScroll = Fx.Scroll.extend({
6542
6543	initialize: function(options){
6544		this.parent(window, options);
6545		this.links = (this.options.links) ? $$(this.options.links) : $$(document.links);
6546		var location = window.location.href.match(/^[^#]*/)[0] + '#';
6547		this.links.each(function(link){
6548			if (link.href.indexOf(location) != 0) return;
6549			var anchor = link.href.substr(location.length);
6550			if (anchor && $(anchor)) this.useLink(link, anchor);
6551		}, this);
6552		if (!window.webkit419) this.addEvent('onComplete', function(){
6553			window.location.hash = this.anchor;
6554		});
6555	},
6556
6557	useLink: function(link, anchor){
6558		link.addEvent('click', function(event){
6559			this.anchor = anchor;
6560			this.toElement(anchor);
6561			event.stop();
6562		}.bindWithEvent(this));
6563	}
6564
6565});
6566
6567/*
6568Script: Sortables.js
6569	Contains <Sortables> Class.
6570
6571License:
6572	MIT-style license.
6573*/
6574
6575/*
6576Class: Sortables
6577	Creates an interface for <Drag.Base> and drop, resorting of a list.
6578
6579Note:
6580	The Sortables require an XHTML doctype.
6581
6582Arguments:
6583	list - required, the list that will become sortable.
6584	options - an Object, see options below.
6585
6586Options:
6587	handles - a collection of elements to be used for drag handles. defaults to the elements.
6588	
6589Events:
6590	onStart - function executed when the item starts dragging
6591	onComplete - function executed when the item ends dragging
6592*/
6593
6594var Sortables = new Class({
6595
6596	options: {
6597		handles: false,
6598		onStart: Class.empty,
6599		onComplete: Class.empty,
6600		ghost: true,
6601		snap: 3,
6602		onDragStart: function(element, ghost){
6603			ghost.setStyle('opacity', 0.7);
6604			element.setStyle('opacity', 0.7);
6605		},
6606		onDragComplete: function(element, ghost){
6607			element.setStyle('opacity', 1);
6608			ghost.remove();
6609			this.trash.remove();
6610		}
6611	},
6612
6613	initialize: function(list, options){
6614		this.setOptions(options);
6615		this.list = $(list);
6616		this.elements = this.list.getChildren();
6617		this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements;
6618		this.bound = {
6619			'start': [],
6620			'moveGhost': this.moveGhost.bindWithEvent(this)
6621		};
6622		for (var i = 0, l = this.handles.length; i < l; i++){
6623			this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]);
6624		}
6625		this.attach();
6626		if (this.options.initialize) this.options.initialize.call(this);
6627		this.bound.move = this.move.bindWithEvent(this);
6628		this.bound.end = this.end.bind(this);
6629	},
6630
6631	attach: function(){
6632		this.handles.each(function(handle, i){
6633			handle.addEvent('mousedown', this.bound.start[i]);
6634		}, this);
6635	},
6636
6637	detach: function(){
6638		this.handles.each(function(handle, i){
6639			handle.removeEvent('mousedown', this.bound.start[i]);
6640		}, this);
6641	},
6642
6643	start: function(event, el){
6644		this.active = el;
6645		this.coordinates = this.list.getCoordinates();
6646		if (this.options.ghost){
6647			var position = el.getPosition();
6648			this.offset = event.page.y - position.y;
6649			this.trash = new Element('div').inject(document.body);
6650			this.ghost = el.clone().inject(this.trash).setStyles({
6651				'position': 'absolute',
6652				'left': position.x,
6653				'top': event.page.y - this.offset
6654			});
6655			document.addListener('mousemove', this.bound.moveGhost);
6656			this.fireEvent('onDragStart', [el, this.ghost]);
6657		}
6658		document.addListener('mousemove', this.bound.move);
6659		document.addListener('mouseup', this.bound.end);
6660		this.fireEvent('onStart', el);
6661		event.stop();
6662	},
6663
6664	moveGhost: function(event){
6665		var value = event.page.y - this.offset;
6666		value = value.limit(this.coordinates.top, this.coordinates.bottom - this.ghost.offsetHeight);
6667		this.ghost.setStyle('top', value);
6668		event.stop();
6669	},
6670
6671	move: function(event){
6672		var now = event.page.y;
6673		this.previous = this.previous || now;
6674		var up = ((this.previous - now) > 0);
6675		var prev = this.active.getPrevious();
6676		var next = this.active.getNext();
6677		if (prev && up && now < prev.getCoordinates().bottom) this.active.injectBefore(prev);
6678		if (next && !up && now > next.getCoordinates().top) this.active.injectAfter(next);
6679		this.previous = now;
6680	},
6681
6682	serialize: function(converter){
6683		return this.list.getChildren().map(converter || function(el){
6684			return this.elements.indexOf(el);
6685		}, this);
6686	},
6687
6688	end: function(){
6689		this.previous = null;
6690		document.removeListener('mousemove', this.bound.move);
6691		document.removeListener('mouseup', this.bound.end);
6692		if (this.options.ghost){
6693			document.removeListener('mousemove', this.bound.moveGhost);
6694			this.fireEvent('onDragComplete', [this.active, this.ghost]);
6695		}
6696		this.fireEvent('onComplete', this.active);
6697	}
6698
6699});
6700
6701Sortables.implement(new Events, new Options);
6702
6703/*
6704Script: Tips.js
6705	Tooltips, BubbleTips, whatever they are, they will appear on mouseover
6706
6707License:
6708	MIT-style license.
6709
6710Credits:
6711	The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com>
6712*/
6713
6714/*
6715Class: Tips
6716	Display a tip on any element with a title and/or href.
6717
6718Note:
6719	Tips requires an XHTML doctype.
6720
6721Arguments:
6722	elements - a collection of elements to apply the tooltips to on mouseover.
6723	options - an object. See options Below.
6724
6725Options:
6726	maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30.
6727	showDelay - the delay the onShow method is called. (defaults to 100 ms)
6728	hideDelay - the delay the onHide method is called. (defaults to 100 ms)
6729
6730	className - the prefix for your tooltip classNames. defaults to 'tool'.
6731
6732		the whole tooltip will have as classname: tool-tip
6733
6734		the title will have as classname: tool-title
6735
6736		the text will have as classname: tool-text
6737
6738	offsets - the distance of your tooltip from the mouse. an Object with x/y properties.
6739	fixed - if set to true, the toolTip will not follow the mouse.
6740	
6741Events:
6742	onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect);
6743	onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect);
6744
6745Example:
6746	(start code)
6747	<img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/>
6748	<script>
6749		var myTips = new Tips($$('.toolTipImg'), {
6750			maxTitleChars: 50	//I like my captions a little long
6751		});
6752	</script>
6753	(end)
6754
6755Note:
6756	The title of the element will always be used as the tooltip body. If you put :: on your title, the text before :: will become the tooltip title.
6757*/
6758
6759var Tips = new Class({
6760
6761	options: {
6762		onShow: function(tip){
6763			tip.setStyle('visibility', 'visible');
6764		},
6765		onHide: function(tip){
6766			tip.setStyle('visibility', 'hidden');
6767		},
6768		maxTitleChars: 30,
6769		showDelay: 100,
6770		hideDelay: 100,
6771		className: 'tool',
6772		offsets: {'x': 16, 'y': 16},
6773		fixed: false
6774	},
6775
6776	initialize: function(elements, options){
6777		this.setOptions(options);
6778		this.toolTip = new Element('div', {
6779			'class': this.options.className + '-tip',
6780			'styles': {
6781				'position': 'absolute',
6782				'top': '0',
6783				'left': '0',
6784				'visibility': 'hidden'
6785			}
6786		}).inject(document.body);
6787		this.wrapper = new Element('div').inject(this.toolTip);
6788		$$(elements).each(this.build, this);
6789		if (this.options.initialize) this.options.initialize.call(this);
6790	},
6791
6792	build: function(el){
6793		el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') 
6793: (el.rel || false);
6794		if (el.title){
6795			var dual = el.title.split('::');
6796			if (dual.length > 1){
6797				el.$tmp.myTitle = dual[0].trim();
6798				el.$tmp.myText = dual[1].trim();
6799			} else {
6800				el.$tmp.myText = el.title;
6801			}
6802			el.removeAttribute('title');
6803		} else {
6804			el.$tmp.myText = false;
6805		}
6806		if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
6807		el.addEvent('mouseenter', function(event){
6808			this.start(el);
6809			if (!this.options.fixed) this.locate(event);
6810			else this.position(el);
6811		}.bind(this));
6812		if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
6813		var end = this.end.bind(this);
6814		el.addEvent('mouseleave', end);
6815		el.addEvent('trash', end);
6816	},
6817
6818	start: function(el){
6819		this.wrapper.empty();
6820		if (el.$tmp.myTitle){
6821			this.title = new Element('span').inject(new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)).setHTML(el.$tmp.myTitle);
6822		}
6823		if (el.$tmp.myText){
6824			this.text = new Element('span').inject(new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)).setHTML(el.$tmp.myText);
6825		}
6826		$clear(this.timer);
6827		this.timer = this.show.delay(this.options.showDelay, this);
6828	},
6829
6830	end: function(event){
6831		$clear(this.timer);
6832		this.timer = this.hide.delay(this.options.hideDelay, this);
6833	},
6834
6835	position: function(element){
6836		var pos = element.getPosition();
6837		this.toolTip.setStyles({
6838			'left': pos.x + this.options.offsets.x,
6839			'top': pos.y + this.options.offsets.y
6840		});
6841	},
6842
6843	locate: function(event){
6844		var win = {'x': window.getWidth(), 'y': window.getHeight()};
6845		var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
6846		var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
6847		var prop = {'x': 'left', 'y': 'top'};
6848		for (var z in prop){
6849			var pos = event.page[z] + this.options.offsets[z];
6850			if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
6851			this.toolTip.setStyle(prop[z], pos);
6852		};
6853	},
6854
6855	show: function(){
6856		if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
6857		this.fireEvent('onShow', [this.toolTip]);
6858	},
6859
6860	hide: function(){
6861		this.fireEvent('onHide', [this.toolTip]);
6862	}
6863
6864});
6865
6866Tips.implement(new Events, new Options);
6867
6868/*
6869Script: Group.js
6870	For Grouping Classes or Elements Events. The Event added to the Group will fire when all of the events of the items of the group are fired.
6871
6872License:
6873	MIT-style license.
6874*/
6875
6876/*
6877Class: Group
6878	An "Utility" Class.
6879
6880Arguments:
6881	List of Class instances
6882
6883Example:
6884	(start code)
6885	xhr1 = new Ajax('data.js', {evalScript: true});
6886	xhr2 = new Ajax('abstraction.js', {evalScript: true});
6887	xhr3 = new Ajax('template.js', {evalScript: true});
6888
6889	var group = new Group(xhr1, xhr2, xhr3);
6890	group.addEvent('onComplete', function(){
6891		alert('All Scripts loaded');
6892	});
6893
6894	xhr1.request();
6895	xhr2.request();
6896	xhr3.request();
6897	(end)
6898
6899*/
6900
6901var Group = new Class({
6902
6903	initialize: function(){
6904		this.instances = $A(arguments);
6905		this.events = {};
6906		this.checker = {};
6907	},
6908
6909	/*
6910	Property: addEvent
6911		adds an event to the stack of events of the Class instances.
6912
6913	Arguments:
6914		type - string; the event name (e.g. 'onComplete')
6915		fn - function to execute when all instances fired this event
6916	*/
6917
6918	addEvent: function(type, fn){
6919		this.checker[type] = this.checker[type] || {};
6920		this.events[type] = this.events[type] || [];
6921		if (this.events[type].contains(fn)) return false;
6922		else this.events[type].push(fn);
6923		this.instances.each(function(instance, i){
6924			instance.addEvent(type, this.check.bind(this, [type, instance, i]));
6925		}, this);
6926		return this;
6927	},
6928
6929	check: function(type, instance, i){
6930		this.checker[type][i] = true;
6931		var every = this.instances.every(function(current, j){
6932			return this.checker[type][j] || false;
6933		}, this);
6934		if (!every) return;
6935		this.checker[type] = {};
6936		this.events[type].each(function(event){
6937			event.call(this, this.instances, instance);
6938		}, this);
6939	}
6940
6941});
6942
6943/*
6944Script: Accordion.js
6945	Contains <Accordion>
6946
6947License:
6948	MIT-style license.
6949*/
6950
6951/*
6952Class: Accordion
6953	The Accordion class creates a group of elements that are toggled when their handles are clicked. When one elements toggles in, the others toggles back.
6954	Inherits methods, properties, options and events from <Fx.Elements>.
6955	
6956Note:
6957	The Accordion requires an XHTML doctype.
6958
6959Arguments:
6960	togglers - required, a collection of elements, the elements handlers that will be clickable.
6961	elements - required, a collection of elements the transitions will be applied to.
6962	options - optional, see options below, and <Fx.Base> options and events.
6963
6964Options:
6965	show - integer, the Index of the element to show at start.
6966	display - integer, the Index of the element to show at start (with a transition). defaults to 0.
6967	fixedHeight - integer, if you want the elements to have a fixed height. defaults to false.
6968	fixedWidth - integer, if you want the elements to have a fixed width. defaults to false.
6969	height - boolean, will add a height transition to the accordion if true. defaults to true.
6970	opacity - boolean, will add an opacity transition to the accordion if true. defaults to true.
6971	width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work!
6972	alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false.
6973	
6974Events:
6975	onActive - function to execute when an element starts to show
6976	onBackground - function to execute when an element starts to hide
6977*/
6978
6979var Accordion = Fx.Elements.extend({
6980
6981	options: {
6982		onActive: Class.empty,
6983		onBackground: Class.empty,
6984		display: 0,
6985		show: false,
6986		height: true,
6987		width: false,
6988		opacity: true,
6989		fixedHeight: false,
6990		fixedWidth: false,
6991		wait: false,
6992		alwaysHide: false
6993	},
6994
6995	initialize: function(){
6996		var options, togglers, elements, container;
6997		$each(arguments, function(argument, i){
6998			switch($type(argument)){
6999				case 'object': options = argument; break;
7000				case 'element': container = $(argument); break;
7001				default:
7002					var temp = $$(argument);
7003					if (!togglers) togglers = temp;
7004					else elements = temp;
7005			}
7006		});
7007		this.togglers = togglers || [];
7008		this.elements = elements || [];
7009		this.container = $(container);
7010		this.setOptions(options);
7011		this.previous = -1;
7012		if (this.options.alwaysHide) this.options.wait = true;
7013		if ($chk(this.options.show)){
7014			this.options.display = false;
7015			this.previous = this.options.show;
7016		}
7017		if (this.options.start){
7018			this.options.display = false;
7019			this.options.show = false;
7020		}
7021		this.effects = {};
7022		if (this.options.opacity) this.effects.opacity = 'fullOpacity';
7023		if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
7024		if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
7025		for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
7026		this.elements.each(function(el, i){
7027			if (this.options.show === i){
7028				this.fireEvent('onActive', [this.togglers[i], el]);
7029			} else {
7030				for (var fx in this.effects) el.setStyle(fx, 0);
7031			}
7032		}, this);
7033		this.parent(this.elements);
7034		if ($chk(this.options.display)) this.display(this.options.display);
7035	},
7036
7037	/*
7038	Property: addSection
7039		Dynamically adds a new section into the accordion at the specified position.
7040
7041	Arguments:
7042		toggler - (dom element) the element that toggles the accordion section open.
7043		element - (dom element) the element that stretches open when the toggler is clicked.
7044		pos - (integer) the index where these objects are to be inserted within the accordion.
7045	*/
7046
7047	addSection: function(toggler, element, pos){
7048		toggler = $(toggler);
7049		element = $(element);
7050		var test = this.togglers.contains(toggler);
7051		var len = this.togglers.length;
7052		this.togglers.include(toggler);
7053		this.elements.include(element);
7054		if (len && (!test || pos)){
7055			pos = $pick(pos, len - 1);
7056			toggler.injectBefore(this.togglers[pos]);
7057			element.injectAfter(toggler);
7058		} else if (this.container && !test){
7059			toggler.inject(this.container);
7060			element.inject(this.container);
7061		}
7062		var idx = this.togglers.indexOf(toggler);
7063		toggler.addEvent('click', this.display.bind(this, idx));
7064		if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
7065		if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
7066		element.fullOpacity = 1;
7067		if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
7068		if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
7069		element.setStyle('overflow', 'hidden');
7070		if (!test){
7071			for (var fx in this.effects) element.setStyle(fx, 0);
7072		}
7073		return this;
7074	},
7075
7076	/*
7077	Property: display
7078		Shows a specific section and hides all others. Useful when triggering an accordion from outside.
7079
7080	Arguments:
7081		index - integer, the index of the item to show, or the actual element to show.
7082	*/
7083
7084	display: function(index){
7085		index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
7086		if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
7087		this.previous = index;
7088		var obj = {};
7089		this.elements.each(function(el, i){
7090			obj[i] = {};
7091			var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
7092			this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]);
7093			for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
7094		}, this);
7095		return this.start(obj);
7096	},
7097
7098	showThisHideOpen: function(index){return this.display(index);}
7099
7100});
7101
7102Fx.Accordion = Accordion;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.