PageSourceSearch

http://www.tormoznyekolodki.ru/components/com_virtuemart/js/mootools/mootools-release-1.11.js

js tormoznyekolodki.ru collected 2026-10-05 00:05:54 UTC 184,460 bytes, 7,108 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// fixed by C3PO on 13.11.2021
3662//		if (this.opera) return document.body.clientWidth;
3663//		return document.documentElement.clientWidth;
3664                return  Math.min(document.body.clientWidth, document.documentElement.clientWidth);
3665	},
3666
3667	/*
3668	Property: getHeight
3669		Returns an integer representing the height of the browser window (without the scrollbar).
3670	*/
3671
3672	getHeight: function(){
3673		if (this.webkit419) return this.innerHeight;
3674// fixed by C3PO on 13.11.2021
3675//		if (this.opera) return document.body.clientHeight;
3676//		return document.documentElement.clientHeight;
3677//                return document.body.clientHeight;
3678                return  Math.min(document.body.clientHeight, document.documentElement.clientHeight);
3679	},
3680
3681	/*
3682	Property: getScrollWidth
3683		Returns an integer representing the scrollWidth of the window.
3684		This value is equal to or bigger than <getWidth>.
3685
3686	See Also:
3687		<http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
3688	*/
3689
3690	getScrollWidth: function(){
3691		if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth);
3692		if (this.webkit) return document.body.scrollWidth;
3693		return document.documentElement.scrollWidth;
3694	},
3695
3696	/*
3697	Property: getScrollHeight
3698		Returns an integer representing the scrollHeight of the window.
3699		This value is equal to or bigger than <getHeight>.
3700
3701	See Also:
3702		<http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
3703	*/
3704
3705	getScrollHeight: function(){
3706		if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight);
3707		if (this.webkit) return document.body.scrollHeight;
3708		return document.documentElement.scrollHeight;
3709	},
3710
3711	/*
3712	Property: getScrollLeft
3713		Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).
3714
3715	See Also:
3716		<http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
3717	*/
3718
3719	getScrollLeft: function(){
3720		return this.pageXOffset || document.documentElement.scrollLeft;
3721	},
3722
3723	/*
3724	Property: getScrollTop
3725		Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).
3726
3727	See Also:
3728		<http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
3729	*/
3730
3731	getScrollTop: function(){
3732		return this.pageYOffset || document.documentElement.scrollTop;
3733	},
3734
3735	/*
3736	Property: getSize
3737		Same as <Element.getSize>
3738	*/
3739
3740	getSize: function(){
3741		return {
3742			'size': {'x': this.getWidth(), 'y': this.getHeight()},
3743			'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()},
3744			'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()}
3745		};
3746	},
3747
3748	//ignore
3749	getPosition: function(){return {'x': 0, 'y': 0};}
3750
3751});
3752
3753/*
3754Script: Fx.Base.js
3755	Contains <Fx.Base>, the foundamentals of the MooTools Effects.
3756
3757License:
3758	MIT-style license.
3759*/
3760
3761var Fx = {};
3762
3763/*
3764Class: Fx.Base
3765	Base class for the Effects.
3766
3767Options:
3768	transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.Sine.easeInOut>
3769	duration - the duration of the effect in ms; 500 is the default.
3770	unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%').
3771	wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true.
3772	fps - the frames per second for the transition; default is 50
3773	
3774Events:
3775	onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
3776	onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
3777	onCancel - the function to execute when you manually stop the effect.
3778*/
3779
3780Fx.Base = new Class({
3781
3782	options: {
3783		onStart: Class.empty,
3784		onComplete: Class.empty,
3785		onCancel: Class.empty,
3786		transition: function(p){
3787			return -(Math.cos(Math.PI * p) - 1) / 2;
3788		},
3789		duration: 500,
3790		unit: 'px',
3791		wait: true,
3792		fps: 50
3793	},
3794
3795	initialize: function(options){
3796		this.element = this.element || null;
3797		this.setOptions(options);
3798		if (this.options.initialize) this.options.initialize.call(this);
3799	},
3800
3801	step: function(){
3802		var time = $time();
3803		if (time < this.time + this.options.duration){
3804			this.delta = this.options.transition((time - this.time) / this.options.duration);
3805			this.setNow();
3806			this.increase();
3807		} else {
3808			this.stop(true);
3809			this.set(this.to);
3810			this.fireEvent('onComplete', this.element, 10);
3811			this.callChain();
3812		}
3813	},
3814
3815	/*
3816	Property: set
3817		Immediately sets the value with no transition.
3818
3819	Arguments:
3820		to - the point to jump to
3821
3822	Example:
3823		>var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
3824	*/
3825
3826	set: function(to){
3827		this.now = to;
3828		this.increase();
3829		return this;
3830	},
3831
3832	setNow: function(){
3833		this.now = this.compute(this.from, this.to);
3834	},
3835
3836	compute: function(from, to){
3837		return (to - from) * this.delta + from;
3838	},
3839
3840	/*
3841	Property: start
3842		Executes an effect from one position to the other.
3843
3844	Arguments:
3845		from - integer: staring value
3846		to - integer: the ending value
3847
3848	Examples:
3849		>var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque.
3850	*/
3851
3852	start: function(from, to){
3853		if (!this.options.wait) this.stop();
3854		else if (this.timer) return this;
3855		this.from = from;
3856		this.to = to;
3857		this.change = this.to - this.from;
3858		this.time = $time();
3859		this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
3860		this.fireEvent('onStart', this.element);
3861		return this;
3862	},
3863
3864	/*
3865	Property: stop
3866		Stops the transition.
3867	*/
3868
3869	stop: function(end){
3870		if (!this.timer) return this;
3871		this.timer = $clear(this.timer);
3872		if (!end) this.fireEvent('onCancel', this.element);
3873		return this;
3874	}/*compatibility*/,
3875	
3876	custom: function(from, to){
3877		return this.start(from, to);
3878	},
3879
3880	clearTimer: function(end){
3881		return this.stop(end);
3882	}
3883
3884	/*end compatibility*/
3885
3886});
3887
3888Fx.Base.implement(new Chain, new Events, new Options);
3889
3890/*
3891Script: Fx.CSS.js
3892	Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally.
3893
3894License:
3895	MIT-style license.
3896*/
3897
3898Fx.CSS = {
3899
3900	select: function(property, to){
3901		if (property.test(/color/i)) return this.Color;
3902		var type = $type(to);
3903		if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi;
3904		return this.Single;
3905	},
3906
3907	parse: function(el, property, fromTo){
3908		if (!fromTo.push) fromTo = [fromTo];
3909		var from = fromTo[0], to = fromTo[1];
3910		if (!$chk(to)){
3911			to = from;
3912			from = el.getStyle(property);
3913		}
3914		var css = this.select(property, to);
3915		return {'from': css.parse(from), 'to': css.parse(to), 'css': css};
3916	}
3917
3918};
3919
3920Fx.CSS.Single = {
3921
3922	parse: function(value){
3923		return parseFloat(value);
3924	},
3925
3926	getNow: function(from, to, fx){
3927		return fx.compute(from, to);
3928	},
3929
3930	getValue: function(value, unit, property){
3931		if (unit == 'px' && property != 'opacity') value = Math.round(value);
3932		return value + unit;
3933	}
3934
3935};
3936
3937Fx.CSS.Multi = {
3938
3939	parse: function(value){
3940		return value.push ? value : value.split(' ').map(function(v){
3941			return parseFloat(v);
3942		});
3943	},
3944
3945	getNow: function(from, to, fx){
3946		var now = [];
3947		for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
3948		return now;
3949	},
3950
3951	getValue: function(value, unit, property){
3952		if (unit == 'px' && property != 'opacity') value = value.map(Math.round);
3953		return value.join(unit + ' ') + unit;
3954	}
3955
3956};
3957
3958Fx.CSS.Color = {
3959
3960	parse: function(value){
3961		return value.push ? value : value.hexToRgb(true);
3962	},
3963
3964	getNow: function(from, to, fx){
3965		var now = [];
3966		for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
3967		return now;
3968	},
3969
3970	getValue: function(value){
3971		return 'rgb(' + value.join(',') + ')';
3972	}
3973
3974};
3975
3976/*
3977Script: Fx.Style.js
3978	Contains <Fx.Style>
3979
3980License:
3981	MIT-style license.
3982*/
3983
3984/*
3985Class: Fx.Style
3986	The Style effect, used to transition any css property from one value to another. Includes colors.
3987	Colors must be in hex format.
3988	Inherits methods, properties, options and events from <Fx.Base>.
3989
3990Arguments:
3991	el - the $(element) to apply the style transition to
3992	property - the property to transition
3993	options - the Fx.Base options (see: <Fx.Base>)
3994
3995Example:
3996	>var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
3997	>marginChange.start(10, 100);
3998*/
3999
4000Fx.Style = Fx.Base.extend({
4001
4002	initialize: function(el, property, options){
4003		this.element = $(el);
4004		this.property = property;
4005		this.parent(options);
4006	},
4007
4008	/*
4009	Property: hide
4010		Same as <Fx.Base.set> (0); hides the element immediately without transition.
4011	*/
4012
4013	hide: function(){
4014		return this.set(0);
4015	},
4016
4017	setNow: function(){
4018		this.now = this.css.getNow(this.from, this.to, this);
4019	},
4020
4021	/*
4022	Property: set
4023		Sets the element's css property (specified at instantiation) to the specified value immediately.
4024
4025	Example:
4026		(start code)
4027		var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4028		marginChange.set(10); //margin-top is set to 10px immediately
4029		(end)
4030	*/
4031
4032	set: function(to){
4033		this.css = Fx.CSS.select(this.property, to);
4034		return this.parent(this.css.parse(to));
4035	},
4036
4037	/*
4038	Property: start
4039		Displays the transition to the value/values passed in
4040
4041	Arguments:
4042		from - (integer; optional) the starting position for the transition
4043		to - (integer) the ending position for the transition
4044
4045	Note:
4046		If you provide only one argument, the transition will use the current css value for its starting value.
4047
4048	Example:
4049		(start code)
4050		var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4051		marginChange.start(10); //tries to read current margin top value and goes from current to 10
4052		(end)
4053	*/
4054
4055	start: function(from, to){
4056		if (this.timer && this.options.wait) return this;
4057		var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
4058		this.css = parsed.css;
4059		return this.parent(parsed.from, parsed.to);
4060	},
4061
4062	increase: function(){
4063		this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property));
4064	}
4065
4066});
4067
4068/*
4069Class: Element
4070	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4071*/
4072
4073Element.extend({
4074
4075	/*
4076	Property: effect
4077		Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>.
4078
4079	Arguments:
4080		property - (string) the css property to alter
4081		options - (object; optional) key/value set of options (see <Fx.Style>)
4082
4083	Example:
4084		>var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear});
4085		>myEffect.start(10, 100);
4086		>//OR
4087		>$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100);
4088	*/
4089
4090	effect: function(property, options){
4091		return new Fx.Style(this, property, options);
4092	}
4093
4094});
4095
4096/*
4097Script: Fx.Styles.js
4098	Contains <Fx.Styles>
4099
4100License:
4101	MIT-style license.
4102*/
4103
4104/*
4105Class: Fx.Styles
4106	Allows you to animate multiple css properties at once;
4107	Colors must be in hex format.
4108	Inherits methods, properties, options and events from <Fx.Base>.
4109
4110Arguments:
4111	el - the $(element) to apply the styles transition to
4112	options - the fx options (see: <Fx.Base>)
4113
4114Example:
4115	(start code)
4116	var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear});
4117
4118	//height from 10 to 100 and width from 900 to 300
4119	myEffects.start({
4120		'height': [10, 100],
4121		'width': [900, 300]
4122	});
4123
4124	//or height from current height to 100 and width from current width to 300
4125	myEffects.start({
4126		'height': 100,
4127		'width': 300
4128	});
4129	(end)
4130*/
4131
4132Fx.Styles = Fx.Base.extend({
4133
4134	initialize: function(el, options){
4135		this.element = $(el);
4136		this.parent(options);
4137	},
4138
4139	setNow: function(){
4140		for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this);
4141	},
4142
4143	set: function(to){
4144		var parsed = {};
4145		this.css = {};
4146		for (var p in to){
4147			this.css[p] = Fx.CSS.select(p, to[p]);
4148			parsed[p] = this.css[p].parse(to[p]);
4149		}
4150		return this.parent(parsed);
4151	},
4152
4153	/*
4154	Property: start
4155		Executes a transition for any number of css properties in tandem.
4156
4157	Arguments:
4158		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).
4159
4160	Example:
4161		see <Fx.Styles>
4162	*/
4163
4164	start: function(obj){
4165		if (this.timer && this.options.wait) return this;
4166		this.now = {};
4167		this.css = {};
4168		var from = {}, to = {};
4169		for (var p in obj){
4170			var parsed = Fx.CSS.parse(this.element, p, obj[p]);
4171			from[p] = parsed.from;
4172			to[p] = parsed.to;
4173			this.css[p] = parsed.css;
4174		}
4175		return this.parent(from, to);
4176	},
4177
4178	increase: function(){
4179		for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit, p));
4180	}
4181
4182});
4183
4184/*
4185Class: Element
4186	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4187*/
4188
4189Element.extend({
4190
4191	/*
4192	Property: effects
4193		Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>.
4194
4195	Example:
4196		>var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.Sine.easeInOut});
4197 		>myEffects.start({'height': [10, 100], 'width': [900, 300]});
4198	*/
4199
4200	effects: function(options){
4201		return new Fx.Styles(this, options);
4202	}
4203
4204});
4205
4206/*
4207Script: Fx.Elements.js
4208	Contains <Fx.Elements>
4209
4210License:
4211	MIT-style license.
4212*/
4213
4214/*
4215Class: Fx.Elements
4216	Fx.Elements allows you to apply any number of styles transitions to a selection of elements. Includes colors (must be in hex format).
4217	Inherits methods, properties, options and events from <Fx.Base>.
4218
4219Arguments:
4220	elements - a collection of elements the effects will be applied to.
4221	options - same as <Fx.Base> options.
4222*/
4223
4224Fx.Elements = Fx.Base.extend({
4225
4226	initialize: function(elements, options){
4227		this.elements = $$(elements);
4228		this.parent(options);
4229	},
4230
4231	setNow: function(){
4232		for (var i in this.from){
4233			var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {};
4234			for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this);
4235		}
4236	},
4237
4238	set: function(to){
4239		var parsed = {};
4240		this.css = {};
4241		for (var i in to){
4242			var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {};
4243			for (var p in iTo){
4244				iCss[p] = Fx.CSS.select(p, iTo[p]);
4245				iParsed[p] = iCss[p].parse(iTo[p]);
4246			}
4247		}
4248		return this.parent(parsed);
4249	},
4250
4251	/*
4252	Property: start
4253		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.
4254
4255	Example:
4256		(start code)
4257		var myElementsEffects = new Fx.Elements($$('a'));
4258		myElementsEffects.start({
4259			'0': { //let's change the first element's opacity and width
4260				'opacity': [0,1],
4261				'width': [100,200]
4262			},
4263			'4': { //and the fifth one's opacity
4264				'opacity': [0.2, 0.5]
4265			}
4266		});
4267		(end)
4268	*/
4269
4270	start: function(obj){
4271		if (this.timer && this.options.wait) return this;
4272		this.now = {};
4273		this.css = {};
4274		var from = {}, to = {};
4275		for (var i in obj){
4276			var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {};
4277			for (var p in iProps){
4278				var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]);
4279				iFrom[p] = parsed.from;
4280				iTo[p] = parsed.to;
4281				iCss[p] = parsed.css;
4282			}
4283		}
4284		return this.parent(from, to);
4285	},
4286
4287	increase: function(){
4288		for (var i in this.now){
4289			var iNow = this.now[i], iCss = this.css[i];
4290			for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit, p));
4291		}
4292	}
4293
4294});
4295
4296/*
4297Script: Fx.Scroll.js
4298	Contains <Fx.Scroll>
4299
4300License:
4301	MIT-style license.
4302*/
4303
4304/*
4305Class: Fx.Scroll
4306	Scroll any element with an overflow, including the window element.
4307	Inherits methods, properties, options and events from <Fx.Base>.
4308
4309Note:
4310	Fx.Scroll requires an XHTML doctype.
4311
4312Arguments:
4313	element - the element to scroll
4314	options - optional, see Options below.
4315
4316Options:
4317	all the Fx.Base options and events, plus:
4318	offset - the distance for the scrollTo point/element. an Object with x/y properties.
4319	overflown - an array of nested scrolling containers, see <Element.getPosition>
4320*/
4321
4322Fx.Scroll = Fx.Base.extend({
4323
4324	options: {
4325		overflown: [],
4326		offset: {'x': 0, 'y': 0},
4327		wheelStops: true
4328	},
4329
4330	initialize: function(element, options){
4331		this.now = [];
4332		this.element = $(element);
4333		this.bound = {'stop': this.stop.bind(this, false)};
4334		this.parent(options);
4335		if (this.options.wheelStops){
4336			this.addEvent('onStart', function(){
4337				document.addEvent('mousewheel', this.bound.stop);
4338			}.bind(this));
4339			this.addEvent('onComplete', function(){
4340				document.removeEvent('mousewheel', this.bound.stop);
4341			}.bind(this));
4342		}
4343	},
4344
4345	setNow: function(){
4346		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4347	},
4348
4349	/*
4350	Property: scrollTo
4351		Scrolls the chosen element to the x/y coordinates.
4352
4353	Arguments:
4354		x - the x coordinate to scroll the element to
4355		y - the y coordinate to scroll the element to
4356	*/
4357
4358	scrollTo: function(x, y){
4359		if (this.timer && this.options.wait) return this;
4360		var el = this.element.getSize();
4361		var values = {'x': x, 'y': y};
4362		for (var z in el.size){
4363			var max = el.scrollSize[z] - el.size[z];
4364			if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;
4365			else values[z] = el.scroll[z];
4366			values[z] += this.options.offset[z];
4367		}
4368		return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]);
4369	},
4370
4371	/*
4372	Property: toTop
4373		Scrolls the chosen element to its maximum top.
4374	*/
4375
4376	toTop: function(){
4377		return this.scrollTo(false, 0);
4378	},
4379
4380	/*
4381	Property: toBottom
4382		Scrolls the chosen element to its maximum bottom.
4383	*/
4384
4385	toBottom: function(){
4386		return this.scrollTo(false, 'full');
4387	},
4388
4389	/*
4390	Property: toLeft
4391		Scrolls the chosen element to its maximum left.
4392	*/
4393
4394	toLeft: function(){
4395		return this.scrollTo(0, false);
4396	},
4397
4398	/*
4399	Property: toRight
4400		Scrolls the chosen element to its maximum right.
4401	*/
4402
4403	toRight: function(){
4404		return this.scrollTo('full', false);
4405	},
4406
4407	/*
4408	Property: toElement
4409		Scrolls the specified element to the position the passed in element is found.
4410
4411	Arguments:
4412		el - the $(element) to scroll the window to
4413	*/
4414
4415	toElement: function(el){
4416		var parent = this.element.getPosition(this.options.overflown);
4417		var target = $(el).getPosition(this.options.overflown);
4418		return this.scrollTo(target.x - parent.x, target.y - parent.y);
4419	},
4420
4421	increase: function(){
4422		this.element.scrollTo(this.now[0], this.now[1]);
4423	}
4424
4425});
4426
4427/*
4428Script: Fx.Slide.js
4429	Contains <Fx.Slide>
4430
4431License:
4432	MIT-style license.
4433*/
4434
4435/*
4436Class: Fx.Slide
4437	The slide effect; slides an element in horizontally or vertically, the contents will fold inside.
4438	Inherits methods, properties, options and events from <Fx.Base>.
4439	
4440Note:
4441	Fx.Slide requires an XHTML doctype.
4442
4443Options:
4444	mode - set it to vertical or horizontal. Defaults to vertical.
4445	options - all the <Fx.Base> options
4446
4447Example:
4448	(start code)
4449	var mySlider = new Fx.Slide('myElement', {duration: 500});
4450	mySlider.toggle() //toggle the slider up and down.
4451	(end)
4452*/
4453
4454Fx.Slide = Fx.Base.extend({
4455
4456	options: {
4457		mode: 'vertical'
4458	},
4459
4460	initialize: function(el, options){
4461		this.element = $(el);
4462		this.wrapper = new Element('div', {'styles': $extend(this.element.getStyles('margin'), {'overflow': 'hidden'})}).injectAfter(this.element).adopt(this.element);
4463		this.element.setStyle('margin', 0);
4464		this.setOptions(options);
4465		this.now = [];
4466		this.parent(this.options);
4467		this.open = true;
4468		this.addEvent('onComplete', function(){
4469			this.open = (this.now[0] === 0);
4470		});
4471		if (window.webkit419) this.addEvent('onComplete', function(){
4472			if (this.open) this.element.remove().inject(this.wrapper);
4473		});
4474	},
4475
4476	setNow: function(){
4477		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4478	},
4479
4480	vertical: function(){
4481		this.margin = 'margin-top';
4482		this.layout = 'height';
4483		this.offset = this.element.offsetHeight;
4484	},
4485
4486	horizontal: function(){
4487		this.margin = 'margin-left';
4488		this.layout = 'width';
4489		this.offset = this.element.offsetWidth;
4490	},
4491
4492	/*
4493	Property: slideIn
4494		Slides the elements in view horizontally or vertically.
4495
4496	Arguments:
4497		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4498	*/
4499
4500	slideIn: function(mode){
4501		this[mode || this.options.mode]();
4502		return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.offset]);
4503	},
4504
4505	/*
4506	Property: slideOut
4507		Sides the elements out of view horizontally or vertically.
4508
4509	Arguments:
4510		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4511	*/
4512
4513	slideOut: function(mode){
4514		this[mode || this.options.mode]();
4515		return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]);
4516	},
4517
4518	/*
4519	Property: hide
4520		Hides the element without a transition.
4521
4522	Arguments:
4523		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4524	*/
4525
4526	hide: function(mode){
4527		this[mode || this.options.mode]();
4528		this.open = false;
4529		return this.set([-this.offset, 0]);
4530	},
4531
4532	/*
4533	Property: show
4534		Shows the element without a transition.
4535
4536	Arguments:
4537		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4538	*/
4539
4540	show: function(mode){
4541		this[mode || this.options.mode]();
4542		this.open = true;
4543		return this.set([0, this.offset]);
4544	},
4545
4546	/*
4547	Property: toggle
4548		Slides in or Out the element, depending on its state
4549
4550	Arguments:
4551		mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4552
4553	*/
4554
4555	toggle: function(mode){
4556		if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode);
4557		return this.slideOut(mode);
4558	},
4559
4560	increase: function(){
4561		this.element.setStyle(this.margin, this.now[0] + this.options.unit);
4562		this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit);
4563	}
4564
4565});
4566
4567/*
4568Script: Fx.Transitions.js
4569	Effects transitions, to be used with all the effects.
4570
4571License:
4572	MIT-style license.
4573
4574Credits:
4575	Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified & optimized to be used with mootools.
4576*/
4577
4578/*
4579Class: Fx.Transitions
4580	A collection of tweening transitions for use with the <Fx.Base> classes.
4581
4582Example:
4583	>//Elastic.easeOut with default values:
4584	>new Fx.Style('margin', {transition: Fx.Transitions.Elastic.easeOut});
4585	>//Elastic.easeOut with user-defined value for elasticity.
4586	> var myTransition = new Fx.Transition(Fx.Transitions.Elastic, 3);
4587	>new Fx.Style('margin', {transition: myTransition.easeOut});
4588
4589See also:
4590	http://www.robertpenner.com/easing/
4591*/
4592
4593Fx.Transition = function(transition, params){
4594	params = params || [];
4595	if ($type(params) != 'array') params = [params];
4596	return $extend(transition, {
4597		easeIn: function(pos){
4598			return transition(pos, params);
4599		},
4600		easeOut: function(pos){
4601			return 1 - transition(1 - pos, params);
4602		},
4603		easeInOut: function(pos){
4604			return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
4605		}
4606	});
4607};
4608
4609Fx.Transitions = new Abstract({
4610
4611	/*
4612	Property: linear
4613		displays a linear transition.
4614
4615	Graph:
4616		(see Linear.png)
4617	*/
4618
4619	linear: function(p){
4620		return p;
4621	}
4622
4623});
4624
4625Fx.Transitions.extend = function(transitions){
4626	for (var transition in transitions){
4627		Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
4628		/*compatibility*/
4629		Fx.Transitions.compat(transition);
4630		/*end compatibility*/
4631	}
4632};
4633
4634/*compatibility*/
4635
4636Fx.Transitions.compat = function(transition){
4637	['In', 'Out', 'InOut'].each(function(easeType){
4638		Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType];
4639	});
4640};
4641
4642/*end compatibility*/
4643
4644Fx.Transitions.extend({
4645
4646	/*
4647	Property: Quad
4648		displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut
4649
4650	Graph:
4651		(see Quad.png)
4652	*/
4653
4654	//auto generated
4655
4656	/*
4657	Property: Cubic
4658		displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut
4659
4660	Graph:
4661		(see Cubic.png)
4662	*/
4663
4664	//auto generated
4665
4666	/*
4667	Property: Quart
4668		displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut
4669
4670	Graph:
4671		(see Quart.png)
4672	*/
4673
4674	//auto generated
4675
4676	/*
4677	Property: Quint
4678		displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut
4679
4680	Graph:
4681		(see Quint.png)
4682	*/
4683
4684	//auto generated
4685
4686	/*
4687	Property: Pow
4688		Used to generate Quad, Cubic, Quart and Quint.
4689		By default is p^6.
4690
4691	Graph:
4692		(see Pow.png)
4693	*/
4694
4695	Pow: function(p, x){
4696		return Math.pow(p, x[0] || 6);
4697	},
4698
4699	/*
4700	Property: Expo
4701		displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut
4702
4703	Graph:
4704		(see Expo.png)
4705	*/
4706
4707	Expo: function(p){
4708		return Math.pow(2, 8 * (p - 1));
4709	},
4710
4711	/*
4712	Property: Circ
4713		displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut
4714
4715	Graph:
4716		(see Circ.png)
4717	*/
4718
4719	Circ: function(p){
4720		return 1 - Math.sin(Math.acos(p));
4721	},
4722
4723
4724	/*
4725	Property: Sine
4726		displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut
4727
4728	Graph:
4729		(see Sine.png)
4730	*/
4731
4732	Sine: function(p){
4733		return 1 - Math.sin((1 - p) * Math.PI / 2);
4734	},
4735
4736	/*
4737	Property: Back
4738		makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut
4739
4740	Graph:
4741		(see Back.png)
4742	*/
4743
4744	Back: function(p, x){
4745		x = x[0] || 1.618;
4746		return Math.pow(p, 2) * ((x + 1) * p - x);
4747	},
4748
4749	/*
4750	Property: Bounce
4751		makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut
4752
4753	Graph:
4754		(see Bounce.png)
4755	*/
4756
4757	Bounce: function(p){
4758		var value;
4759		for (var a = 0, b = 1; 1; a += b, b /= 2){
4760			if (p >= (7 - 4 * a) / 11){
4761				value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;
4762				break;
4763			}
4764		}
4765		return value;
4766	},
4767
4768	/*
4769	Property: Elastic
4770		Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut
4771
4772	Graph:
4773		(see Elastic.png)
4774	*/
4775
4776	Elastic: function(p, x){
4777		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
4778	}
4779
4780});
4781
4782['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
4783	Fx.Transitions[transition] = new Fx.Transition(function(p){
4784		return Math.pow(p, [i + 2]);
4785	});
4786	
4787	/*compatibility*/
4788	Fx.Transitions.compat(transition);
4789	/*end compatibility*/
4790});
4791
4792/*
4793Script: Drag.Base.js
4794	Contains <Drag.Base>, <Element.makeResizable>
4795
4796License:
4797	MIT-style license.
4798*/
4799
4800var Drag = {};
4801
4802/*
4803Class: Drag.Base
4804	Modify two css properties of an element based on the position of the mouse.
4805	
4806Note:
4807	Drag.Base requires an XHTML doctype.
4808
4809Arguments:
4810	el - the $(element) to apply the transformations to.
4811	options - optional. The options object.
4812
4813Options:
4814	handle - the $(element) to act as the handle for the draggable element. defaults to the $(element) itself.
4815	modifiers - an object. see Modifiers Below.
4816	limit - an object, see Limit below.
4817	grid - optional, distance in px for snap-to-grid dragging
4818	snap - optional, the distance you have to drag before the element starts to respond to the drag. defaults to false
4819
4820	modifiers:
4821		x - string, the style you want to modify when the mouse moves in an horizontal direction. defaults to 'left'
4822		y - string, the style you want to modify when the mouse moves in a vertical direction. defaults to 'top'
4823
4824	limit:
4825		x - array with start and end limit relative to modifiers.x
4826		y - array with start and end limit relative to modifiers.y
4827		
4828Events:
4829	onStart - optional, function to execute when the user starts to drag (on mousedown);
4830	onComplete - optional, function to execute when the user completes the drag.
4831	onDrag - optional, function to execute at every step of the drag
4832*/
4833
4834Drag.Base = new Class({
4835
4836	options: {
4837		handle: false,
4838		unit: 'px',
4839		onStart: Class.empty,
4840		onBeforeStart: Class.empty,
4841		onComplete: Class.empty,
4842		onSnap: Class.empty,
4843		onDrag: Class.empty,
4844		limit: false,
4845		modifiers: {x: 'left', y: 'top'},
4846		grid: false,
4847		snap: 6
4848	},
4849
4850	initialize: function(el, options){
4851		this.setOptions(options);
4852		this.element = $(el);
4853		this.handle = $(this.options.handle) || this.element;
4854		this.mouse = {'now': {}, 'pos': {}};
4855		this.value = {'start': {}, 'now': {}};
4856		this.bound = {
4857			'start': this.start.bindWithEvent(this),
4858			'check': this.check.bindWithEvent(this),
4859			'drag': this.drag.bindWithEvent(this),
4860			'stop': this.stop.bind(this)
4861		};
4862		this.attach();
4863		if (this.options.initialize) this.options.initialize.call(this);
4864	},
4865
4866	attach: function(){
4867		this.handle.addEvent('mousedown', this.bound.start);
4868		return this;
4869	},
4870
4871	detach: function(){
4872		this.handle.removeEvent('mousedown', this.bound.start);
4873		return this;
4874	},
4875
4876	start: function(event){
4877		this.fireEvent('onBeforeStart', this.element);
4878		this.mouse.start = event.page;
4879		var limit = this.options.limit;
4880		this.limit = {'x': [], 'y': []};
4881		for (var z in this.options.modifiers){
4882			if (!this.options.modifiers[z]) continue;
4883			this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
4884			this.mouse.pos[z] = event.page[z] - this.value.now[z];
4885			if (limit && limit[z]){
4886				for (var i = 0; i < 2; i++){
4887					if ($chk(limit[z][i])) this.limit[z][i] = ($type(limit[z][i]) == 'function') ? limit[z][i]() : limit[z][i];
4888				}
4889			}
4890		}
4891		if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};
4892		document.addListener('mousemove', this.bound.check);
4893		document.addListener('mouseup', this.bound.stop);
4894		this.fireEvent('onStart', this.element);
4895		event.stop();
4896	},
4897
4898	check: function(event){
4899		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)));
4900		if (distance > this.options.snap){
4901			document.removeListener('mousemove', this.bound.check);
4902			document.addListener('mousemove', this.bound.drag);
4903			this.drag(event);
4904			this.fireEvent('onSnap', this.element);
4905		}
4906		event.stop();
4907	},
4908
4909	drag: function(event){
4910		this.out = false;
4911		this.mouse.now = event.page;
4912		for (var z in this.options.modifiers){
4913			if (!this.options.modifiers[z]) continue;
4914			this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
4915			if (this.limit[z]){
4916				if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
4917					this.value.now[z] = this.limit[z][1];
4918					this.out = true;
4919				} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
4920					this.value.now[z] = this.limit[z][0];
4921					this.out = true;
4922				}
4923			}
4924			if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);
4925			this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
4926		}
4927		this.fireEvent('onDrag', this.element);
4928		event.stop();
4929	},
4930
4931	stop: function(){
4932		document.removeListener('mousemove', this.bound.check);
4933		document.removeListener('mousemove', this.bound.drag);
4934		document.removeListener('mouseup', this.bound.stop);
4935		this.fireEvent('onComplete', this.element);
4936	}
4937
4938});
4939
4940Drag.Base.implement(new Events, new Options);
4941
4942/*
4943Class: Element
4944	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4945*/
4946
4947Element.extend({
4948
4949	/*
4950	Property: makeResizable
4951		Makes an element resizable (by dragging) with the supplied options.
4952
4953	Arguments:
4954		options - see <Drag.Base> for acceptable options.
4955	*/
4956
4957	makeResizable: function(options){
4958		return new Drag.Base(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
4959	}
4960
4961});
4962
4963/*
4964Script: Drag.Move.js
4965	Contains <Drag.Move>, <Element.makeDraggable>
4966
4967License:
4968	MIT-style license.
4969*/
4970
4971/*
4972Class: Drag.Move
4973	Extends <Drag.Base>, has additional functionality for dragging an element, support snapping and droppables.
4974	Drag.move supports either position absolute or relative. If no position is found, absolute will be set.
4975	Inherits methods, properties, options and events from <Drag.Base>.
4976
4977Note:
4978	Drag.Move requires an XHTML doctype.
4979
4980Arguments:
4981	el - the $(element) to apply the drag to.
4982	options - optional. see Options below.
4983
4984Options:
4985	all the drag.Base options, plus:
4986	container - an element, will fill automatically limiting options based on the $(element) size and position. defaults to false (no limiting)
4987	droppables - an array of elements you can drop your draggable to.
4988	overflown - an array of nested scrolling containers, see Element::getPosition
4989*/
4990
4991Drag.Move = Drag.Base.extend({
4992
4993	options: {
4994		droppables: [],
4995		container: false,
4996		overflown: []
4997	},
4998
4999	initialize: function(el, options){
5000		this.setOptions(options);
5001		this.element = $(el);
5002		this.droppables = $$(this.options.droppables);
5003		this.container = $(this.options.container);
5004		this.position = {'element': this.element.getStyle('position'), 'container': false};
5005		if (this.container) this.position.container = this.container.getStyle('position');
5006		if (!['relative', 'absolute', 'fixed'].contains(this.position.element)) this.position.element = 'absolute';
5007		var top = this.element.getStyle('top').toInt();
5008		var left = this.element.getStyle('left').toInt();
5009		if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5010			top = $chk(top) ? top : this.element.getTop(this.options.overflown);
5011			left = $chk(left) ? left : this.element.getLeft(this.options.overflown);
5012		} else {
5013			top = $chk(top) ? top : 0;
5014			left = $chk(left) ? left : 0;
5015		}
5016		this.element.setStyles({'top': top, 'left': left, 'position': this.position.element});
5017		this.parent(this.element);
5018	},
5019
5020	start: function(event){
5021		this.overed = null;
5022		if (this.container){
5023			var cont = this.container.getCoordinates();
5024			var el = this.element.getCoordinates();
5025			if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5026				this.options.limit = {
5027					'x': [cont.left, cont.right - el.width],
5028					'y': [cont.top, cont.bottom - el.height]
5029				};
5030			} else {
5031				this.options.limit = {
5032					'y': [0, cont.height - el.height],
5033					'x': [0, cont.width - el.width]
5034				};
5035			}
5036		}
5037		this.parent(event);
5038	},
5039
5040	drag: function(event){
5041		this.parent(event);
5042		var overed = this.out ? false : this.droppables.filter(this.checkAgainst, this).getLast();
5043		if (this.overed != overed){
5044			if (this.overed) this.overed.fireEvent('leave', [this.element, this]);
5045			this.overed = overed ? overed.fireEvent('over', [this.element, this]) : null;
5046		}
5047		return this;
5048	},
5049
5050	checkAgainst: function(el){
5051		el = el.getCoordinates(this.options.overflown);
5052		var now = this.mouse.now;
5053		return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
5054	},
5055
5056	stop: function(){
5057		if (this.overed && !this.out) this.overed.fireEvent('drop', [this.element, this]);
5058		else this.element.fireEvent('emptydrop', this);
5059		this.parent();
5060		return this;
5061	}
5062
5063});
5064
5065/*
5066Class: Element
5067	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5068*/
5069
5070Element.extend({
5071
5072	/*
5073	Property: makeDraggable
5074		Makes an element draggable with the supplied options.
5075
5076	Arguments:
5077		options - see <Drag.Move> and <Drag.Base> for acceptable options.
5078	*/
5079
5080	makeDraggable: function(options){
5081		return new Drag.Move(this, options);
5082	}
5083
5084});
5085
5086/*
5087Script: XHR.js
5088	Contains the basic XMLHttpRequest Class Wrapper.
5089
5090License:
5091	MIT-style license.
5092*/
5093
5094/*
5095Class: XHR
5096	Basic XMLHttpRequest Wrapper.
5097
5098Arguments:
5099	options - an object with options names as keys. See options below.
5100
5101Options:
5102	method - 'post' or 'get' - the protocol for the request; optional, defaults to 'post'.
5103	async - boolean: asynchronous option; true uses asynchronous requests. Defaults to true.
5104	encoding - the encoding, defaults to utf-8.
5105	autoCancel - cancels the already running request if another one is sent. defaults to false.
5106	headers - accepts an object, that will be set to request headers.
5107	
5108Events:
5109	onRequest - function to execute when the XHR request is fired.
5110	onSuccess - function to execute when the XHR request completes.
5111	onStateChange - function to execute when the state of the XMLHttpRequest changes.
5112	onFailure - function to execute when the state of the XMLHttpRequest changes.
5113
5114Properties:
5115	running - true if the request is running.
5116	response - object, text and xml as keys. You can access this property in the onSuccess event.
5117
5118Example:
5119	>var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian');
5120*/
5121
5122var XHR = new Class({
5123
5124	options: {
5125		method: 'post',
5126		async: true,
5127		onRequest: Class.empty,
5128		onSuccess: Class.empty,
5129		onFailure: Class.empty,
5130		urlEncoded: true,
5131		encoding: 'utf-8',
5132		autoCancel: false,
5133		headers: {}
5134	},
5135
5136	setTransport: function(){
5137		this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
5138		return this;
5139	},
5140
5141	initialize: function(options){
5142		this.setTransport().setOptions(options);
5143		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
5144		this.headers = {};
5145		if (this.options.urlEncoded && this.options.method == 'post'){
5146			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
5147			this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
5148		}
5149		if (this.options.initialize) this.options.initialize.call(this);
5150	},
5151
5152	onStateChange: function(){
5153		if (this.transport.readyState != 4 || !this.running) return;
5154		this.running = false;
5155		var status = 0;
5156		try {status = this.transport.status;} catch(e){};
5157		if (this.options.isSuccess.call(this, status)) this.onSuccess();
5158		else this.onFailure();
5159		this.transport.onreadystatechange = Class.empty;
5160	},
5161
5162	isSuccess: function(status){
5163		return ((status >= 200) && (status < 300));
5164	},
5165
5166	onSuccess: function(){
5167		this.response = {
5168			'text': this.transport.responseText,
5169			'xml': this.transport.responseXML
5170		};
5171		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
5172		this.callChain();
5173	},
5174
5175	onFailure: function(){
5176		this.fireEvent('onFailure', this.transport);
5177	},
5178
5179	/*
5180	Property: setHeader
5181		Add/modify an header for the request. It will not override headers from the options.
5182
5183	Example:
5184		>var myXhr = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}});
5185		>myXhr.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT');
5186	*/
5187
5188	setHeader: function(name, value){
5189		this.headers[name] = value;
5190		return this;
5191	},
5192
5193	/*
5194	Property: send
5195		Opens the XHR connection and sends the data. Data has to be null or a string.
5196
5197	Example:
5198		>var myXhr = new XHR({method: 'post'});
5199		>myXhr.send(url, querystring);
5200		>
5201		>var syncXhr = new XHR({async: false, method: 'post'});
5202		>syncXhr.send(url, null);
5203		>
5204	*/
5205
5206	send: function(url, data){
5207		if (this.options.autoCancel) this.cancel();
5208		else if (this.running) return this;
5209		this.running = true;
5210		if (data && this.options.method == 'get'){
5211			url = url + (url.contains('?') ? '&' : '?') + data;
5212			data = null;
5213		}
5214		this.transport.open(this.options.method.toUpperCase(), url, this.options.async);
5215		this.transport.onreadystatechange = this.onStateChange.bind(this);
5216		//scheduled for deletion 15.01.20 by C3PO
5217		//if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');
5218		$extend(this.headers, this.options.headers);
5219		for (var type in this.headers) try {this.transport.setRequestHeader(type, this.headers[type]);} catch(e){};
5220		this.fireEvent('onRequest');
5221		this.transport.send($pick(data, null));
5222		return this;
5223	},
5224
5225	/*
5226	Property: cancel
5227		Cancels the running request. No effect if the request is not running.
5228
5229	Example:
5230		>var myXhr = new XHR({method: 'get'}).send(url);
5231		>myXhr.cancel();
5232	*/
5233
5234	cancel: function(){
5235		if (!this.running) return this;
5236		this.running = false;
5237		this.transport.abort();
5238		this.transport.onreadystatechange = Class.empty;
5239		this.setTransport();
5240		this.fireEvent('onCancel');
5241		return this;
5242	}
5243
5244});
5245
5246XHR.implement(new Chain, new Events, new Options);
5247
5248/*
5249Script: Ajax.js
5250	Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects.
5251
5252Credits:
5253	Loosely based on the version from prototype.js <http://prototype.conio.net>
5254
5255License:
5256	MIT-style license.
5257*/
5258
5259/*
5260Class: Ajax
5261	An Ajax class, For all your asynchronous needs.
5262	Inherits methods, properties, options and events from <XHR>.
5263
5264Arguments:
5265	url - the url pointing to the server-side script.
5266	options - optional, an object containing options.
5267
5268Options:
5269	data - you can write parameters here. Can be a querystring, an object or a Form element.
5270	update - $(element) to insert the response text of the XHR into, upon completion of the request.
5271	evalScripts - boolean; default is false. Execute scripts in the response text onComplete. When the response is javascript the whole response is evaluated.
5272	evalResponse - boolean; default is false. Force global evalulation of the whole response, no matter what content-type it is.
5273	
5274Events:
5275	onComplete - function to execute when the ajax request completes.
5276
5277Example:
5278	>var myAjax = new Ajax(url, {method: 'get'}).request();
5279*/
5280
5281var Ajax = XHR.extend({
5282
5283	options: {
5284		data: null,
5285		update: null,
5286		onComplete: Class.empty,
5287		evalScripts: false,
5288		evalResponse: false
5289	},
5290
5291	initialize: function(url, options){
5292		this.addEvent('onSuccess', this.onComplete);
5293		this.setOptions(options);
5294		/*compatibility*/
5295		this.options.data = this.options.data || this.options.postBody;
5296		/*end compatibility*/
5297		if (!['post', 'get'].contains(this.options.method)){
5298			this._method = '_method=' + this.options.method;
5299			this.options.method = 'post';
5300		}
5301		this.parent();
5302		this.setHeader('X-Requested-With', 'XMLHttpRequest');
5303		this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
5304		this.url = url;
5305	},
5306
5307	onComplete: function(){
5308		if (this.options.update) $(this.options.update).empty().setHTML(this.response.text);
5309		if (this.options.evalScripts || this.options.evalResponse) this.evalScripts();
5310		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
5311	},
5312
5313	/*
5314	Property: request
5315		Executes the ajax request.
5316
5317	Example:
5318		>var myAjax = new Ajax(url, {method: 'get'});
5319		>myAjax.request();
5320
5321		OR
5322
5323		>new Ajax(url, {method: 'get'}).request();
5324	*/
5325
5326	request: function(data){
5327		data = data || this.options.data;
5328		switch($type(data)){
5329			case 'element': data = $(data).toQueryString(); break;
5330			case 'object': data = Object.toQueryString(data);
5331		}
5332		if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
5333		return this.send(this.url, data);
5334	},
5335
5336	/*
5337	Property: evalScripts
5338		Executes scripts in the response text
5339	*/
5340
5341	evalScripts: function(){
5342		var script, scripts;
5343		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) scripts = this.response.text;
5344		else {
5345			scripts = [];
5346			var regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
5347			while ((script = regexp.exec(this.response.text))) scripts.push(script[1]);
5348			scripts = scripts.join('\n');
5349		}
5350		if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0);
5351	},
5352
5353	/*
5354	Property: getHeader
5355		Returns the given response header or null
5356	*/
5357
5358	getHeader: function(name){
5359		try {return this.transport.getResponseHeader(name);} catch(e){};
5360		return null;
5361	}
5362
5363});
5364
5365/* Section: Object related Functions */
5366
5367/*
5368Function: Object.toQueryString
5369	Generates a querystring from key/pair values in an object
5370
5371Arguments:
5372	source - the object to generate the querystring from.
5373
5374Returns:
5375	the query string.
5376
5377Example:
5378	>Object.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow"
5379*/
5380
5381Object.toQueryString = function(source){
5382	var queryString = [];
5383	for (var property in source) queryString.push(encodeURIComponent(property) + '=' + encodeURIComponent(source[property]));
5384	return queryString.join('&');
5385};
5386
5387/*
5388Class: Element
5389	Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5390*/
5391
5392Element.extend({
5393
5394	/*
5395	Property: send
5396		Sends a form with an ajax post request
5397
5398	Arguments:
5399		options - option collection for ajax request. See <Ajax> for the options list.
5400
5401	Returns:
5402		The Ajax Class Instance
5403
5404	Example:
5405		(start code)
5406		<form id="myForm" action="submit.php">
5407		<input name="email" value="[email protected]">
5408		<input name="zipCode" value="90210">
5409		</form>
5410		<script>
5411		$('myForm').send()
5412		</script>
5413		(end)
5414	*/
5415
5416	send: function(options){
5417		return new Ajax(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request();
5418	}
5419
5420});
5421
5422/*
5423Script: Cookie.js
5424	A cookie reader/creator
5425
5426Credits:
5427	based on the functions by Peter-Paul Koch (http://quirksmode.org)
5428*/
5429
5430/*
5431Class: Cookie
5432	Class for creating, getting, and removing cookies.
5433*/
5434
5435var Cookie = new Abstract({
5436
5437	options: {
5438		domain: false,
5439		path: false,
5440		duration: false,
5441		secure: false
5442	},
5443
5444	/*
5445	Property: set
5446		Sets a cookie in the browser.
5447
5448	Arguments:
5449		key - the key (name) for the cookie
5450		value - the value to set, cannot contain semicolons
5451		options - an object representing the Cookie options. See Options below. Default values are stored in Cookie.options.
5452
5453	Options:
5454		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.
5455		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.
5456		duration - the duration of the Cookie before it expires, in days.
5457					If set to false or 0, the cookie will be a session cookie that expires when the browser is closed. This is default.
5458		secure - Stored cookie information can be accessed only from a secure environment.
5459
5460	Returns:
5461		An object with the options, the key and the value. You can give it as first parameter to Cookie.remove.
5462
5463	Example:
5464		>Cookie.set('username', 'Harald'); // session cookie (duration is false), or ...
5465		>Cookie.set('username', 'JackBauer', {duration: 1}); // save this for 1 day
5466
5467	*/
5468
5469	set: function(key, value, options){
5470		options = $merge(this.options, options);
5471		value = encodeURIComponent(value);
5472		if (options.domain) value += '; domain=' + options.domain;
5473		if (options.path) value += '; path=' + options.path;
5474		if (options.duration){
5475			var date = new Date();
5476			date.setTime(date.getTime() + options.duration * 24 * 60 * 60 * 1000);
5477			value += '; expires=' + date.toGMTString();
5478		}
5479		if (options.secure) value += '; secure';
5480		document.cookie = key + '=' + value;
5481		return $extend(options, {'key': key, 'value': value});
5482	},
5483
5484	/*
5485	Property: get
5486		Gets the value of a cookie.
5487
5488	Arguments:
5489		key - the name of the cookie you wish to retrieve.
5490
5491	Returns:
5492		The cookie string value, or false if not found.
5493
5494	Example:
5495		>Cookie.get("username") //returns JackBauer
5496	*/
5497
5498	get: function(key){
5499		var value = document.cookie.match('(?:^|;)\\s*' + key.escapeRegExp() + '=([^;]*)');
5500		return value ? decodeURIComponent(value[1]) : false;
5501	},
5502
5503	/*
5504	Property: remove
5505		Removes a cookie from the browser.
5506
5507	Arguments:
5508		cookie - the name of the cookie to remove or a previous cookie (for domains)
5509		options - optional. you can also pass the domain and path here. Same as options in <Cookie.set>
5510
5511	Examples:
5512		>Cookie.remove('username') //bye-bye JackBauer, cya in 24 hours
5513		>
5514		>var myCookie = Cookie.set('username', 'Aaron', {domain: 'mootools.net'}); // Cookie.set returns an object with all values need to remove the cookie
5515		>Cookie.remove(myCookie);
5516	*/
5517
5518	remove: function(cookie, options){
5519		if ($type(cookie) == 'object') this.set(cookie.key, '', $merge(cookie, {duration: -1}));
5520		else this.set(cookie, '', $merge(options, {duration: -1}));
5521	}
5522
5523});
5524
5525/*
5526Script: Json.js
5527	Simple Json parser and Stringyfier, See: <http://www.json.org/>
5528
5529License:
5530	MIT-style license.
5531*/
5532
5533/*
5534Class: Json
5535	Simple Json parser and Stringyfier, See: <http://www.json.org/>
5536*/
5537
5538var Json = {
5539
5540	/*
5541	Property: toString
5542		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.
5543
5544	Arguments:
5545		obj - the object to convert to string
5546
5547	Returns:
5548		A json string
5549
5550	Example:
5551		(start code)
5552		Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}'
5553		(end)
5554	*/
5555
5556	toString: function(obj){
5557		switch($type(obj)){
5558			case 'string':
5559				return '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
5560			case 'array':
5561				return '[' + obj.map(Json.toString).join(',') + ']';
5562			case 'object':
5563				var string = [];
5564				for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property]));
5565				return '{' + string.join(',') + '}';
5566			case 'number':
5567				if (isFinite(obj)) break;
5568			case false:
5569				return 'null';
5570		}
5571		return String(obj);
5572	},
5573
5574	/*
5575	Property: evaluate
5576		converts a json string to an javascript Object.
5577
5578	Arguments:
5579		str - the string to evaluate. if its not a string, it returns false.
5580		secure - optionally, performs syntax check on json string. Defaults to false.
5581
5582	Credits:
5583		Json test regexp is by Douglas Crockford <http://crockford.org>.
5584
5585	Example:
5586		>var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}');
5587		>//myObject will become {apple: 'red', lemon: 'yellow'}
5588	*/
5589
5590	evaluate: function(str, secure){
5591		return (($type(str) != 'string') || (secure && !str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/))) ? null : eval('(' + str + ')');
5592	}
5593
5594};
5595
5596/*
5597Script: Json.Remote.js
5598	Contains <Json.Remote>.
5599
5600License:
5601	MIT-style license.
5602*/
5603
5604/*
5605Class: Json.Remote
5606	Wrapped XHR with automated sending and receiving of Javascript Objects in Json Format.
5607	Inherits methods, properties, options and events from <XHR>.
5608
5609Arguments:
5610	url - the url you want to send your object to.
5611	options - see <XHR> options
5612
5613Example:
5614	this code will send user information based on name/last name
5615	(start code)
5616	var jSonRequest = new Json.Remote("http://site.com/tellMeAge.php", {onComplete: function(person){
5617		alert(person.age); //is 25 years
5618		alert(person.height); //is 170 cm
5619		alert(person.weight); //is 120 kg
5620	}}).send({'name': 'John', 'lastName': 'Doe'});
5621	(end)
5622*/
5623
5624Json.Remote = XHR.extend({
5625
5626	initialize: function(url, options){
5627		this.url = url;
5628		this.addEvent('onSuccess', this.onComplete);
5629		this.parent(options);
5630		this.setHeader('X-Request', 'JSON');
5631	},
5632
5633	send: function(obj){
5634		return this.parent(this.url, 'json=' + Json.toString(obj));
5635	},
5636
5637	onComplete: function(){
5638		this.fireEvent('onComplete', [Json.evaluate(this.response.text, this.options.secure)]);
5639	}
5640
5641});
5642
5643/*
5644Script: Assets.js
5645	provides dynamic loading for images, css and javascript files.
5646
5647License:
5648	MIT-style license.
5649*/
5650
5651var Asset = new Abstract({
5652
5653	/*
5654	Property: javascript
5655		Injects a javascript file in the page.
5656
5657	Arguments:
5658		source - the path of the javascript file
5659		properties - some additional attributes you might want to add to the script element
5660
5661	Example:
5662		>
5662 new Asset.javascript('/scripts/myScript.js', {id: 'myScript'});
5663	*/
5664
5665	javascript: function(source, properties){
5666		properties = $merge({
5667			'onload': Class.empty
5668		}, properties);
5669		var script = new Element('script', {'src': source}).addEvents({
5670			'load': properties.onload,
5671			'readystatechange': function(){
5672				if (this.readyState == 'complete') this.fireEvent('load');
5673			}
5674		});
5675		delete properties.onload;
5676		return script.setProperties(properties).inject(document.head);
5677	},
5678
5679	/*
5680	Property: css
5681		Injects a css file in the page.
5682
5683	Arguments:
5684		source - the path of the css file
5685		properties - some additional attributes you might want to add to the link element
5686
5687	Example:
5688		> new Asset.css('/css/myStyle.css', {id: 'myStyle', title: 'myStyle'});
5689	*/
5690
5691	css: function(source, properties){
5692		return new Element('link', $merge({
5693			'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
5694		}, properties)).inject(document.head);
5695	},
5696
5697	/*
5698	Property: image
5699		Preloads an image and returns the img element. does not inject it to the page.
5700
5701	Arguments:
5702		source - the path of the image file
5703		properties - some additional attributes you might want to add to the img element
5704
5705	Example:
5706		> new Asset.image('/images/myImage.png', {id: 'myImage', title: 'myImage', onload: myFunction});
5707
5708	Returns:
5709		the img element. you can inject it anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5710	*/
5711
5712	image: function(source, properties){
5713		properties = $merge({
5714			'onload': Class.empty,
5715			'onabort': Class.empty,
5716			'onerror': Class.empty
5717		}, properties);
5718		var image = new Image();
5719		image.src = source;
5720		var element = new Element('img', {'src': source});
5721		['load', 'abort', 'error'].each(function(type){
5722			var event = properties['on' + type];
5723			delete properties['on' + type];
5724			element.addEvent(type, function(){
5725				this.removeEvent(type, arguments.callee);
5726				event.call(this);
5727			});
5728		});
5729		if (image.width && image.height) element.fireEvent('load', element, 1);
5730		return element.setProperties(properties);
5731	},
5732
5733	/*
5734	Property: images
5735		Preloads an array of images (as strings) and returns an array of img elements. does not inject them to the page.
5736
5737	Arguments:
5738		sources - array, the paths of the image files
5739		options - object, see below
5740
5741	Options:
5742		onComplete - a function to execute when all image files are loaded in the browser's cache
5743		onProgress - a function to execute when one image file is loaded in the browser's cache
5744
5745	Example:
5746		(start code)
5747		new Asset.images(['/images/myImage.png', '/images/myImage2.gif'], {
5748			onComplete: function(){
5749				alert('all images loaded!');
5750			}
5751		});
5752		(end)
5753
5754	Returns:
5755		the img elements as $$. you can inject them anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5756	*/
5757
5758	images: function(sources, options){
5759		options = $merge({
5760			onComplete: Class.empty,
5761			onProgress: Class.empty
5762		}, options);
5763		if (!sources.push) sources = [sources];
5764		var images = [];
5765		var counter = 0;
5766		sources.each(function(source){
5767			var img = new Asset.image(source, {
5768				'onload': function(){
5769					options.onProgress.call(this, counter);
5770					counter++;
5771					if (counter == sources.length) options.onComplete();
5772				}
5773			});
5774			images.push(img);
5775		});
5776		return new Elements(images);
5777	}
5778
5779});
5780
5781/*
5782Script: Hash.js
5783	Contains the class Hash.
5784
5785License:
5786	MIT-style license.
5787*/
5788
5789/*
5790Class: Hash
5791	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.
5792
5793Note:
5794	Each hash instance has the length property.
5795
5796Arguments:
5797	obj - an object to convert into a Hash instance.
5798
5799Example:
5800	(start code)
5801	var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'});
5802	hash.remove('b'); // b is removed.
5803	hash.set('c', 'hello');
5804	hash.get('c'); // returns 'hello'
5805	hash.length // returns 2 (a and c)
5806	(end)
5807*/
5808
5809var Hash = new Class({
5810
5811	length: 0,
5812
5813	initialize: function(object){
5814		this.obj = object || {};
5815		this.setLength();
5816	},
5817
5818	/*
5819	Property: get
5820		Retrieves a value from the hash.
5821
5822	Arguments:
5823		key - The key
5824
5825	Returns:
5826		The value
5827	*/
5828
5829	get: function(key){
5830		return (this.hasKey(key)) ? this.obj[key] : null;
5831	},
5832
5833	/*
5834	Property: hasKey
5835		Check the presence of a specified key-value pair in the hash.
5836
5837	Arguments:
5838		key - The key
5839
5840	Returns:
5841		True if the Hash contains a value for the specified key, otherwise false
5842	*/
5843
5844	hasKey: function(key){
5845		return (key in this.obj);
5846	},
5847
5848	/*
5849	Property: set
5850		Adds a key-value pair to the hash or replaces a previous value associated with the key.
5851
5852	Arguments:
5853		key - The key
5854		value - The value
5855	*/
5856
5857	set: function(key, value){
5858		if (!this.hasKey(key)) this.length++;
5859		this.obj[key] = value;
5860		return this;
5861	},
5862
5863	setLength: function(){
5864		this.length = 0;
5865		for (var p in this.obj) this.length++;
5866		return this;
5867	},
5868
5869	/*
5870	Property: remove
5871		Removes a key-value pair from the hash.
5872
5873	Arguments:
5874		key - The key
5875	*/
5876
5877	remove: function(key){
5878		if (this.hasKey(key)){
5879			delete this.obj[key];
5880			this.length--;
5881		}
5882		return this;
5883	},
5884
5885	/*
5886	Property: each
5887		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.
5888
5889	Arguments:
5890		fn - The function to call for each key-value pair
5891		bind - Optional, the object that will be referred to as "this" in the function
5892	*/
5893
5894	each: function(fn, bind){
5895		$each(this.obj, fn, bind);
5896	},
5897
5898	/*
5899	Property: extend
5900		Extends the current hash with an object containing key-value pairs. Values for duplicate keys will be replaced by the new ones.
5901
5902	Arguments:
5903		obj - An object containing key-value pairs
5904	*/
5905
5906	extend: function(obj){
5907		$extend(this.obj, obj);
5908		return this.setLength();
5909	},
5910
5911	/*
5912	Property: merge
5913		Merges the current hash with multiple objects.
5914	*/
5915
5916	merge: function(){
5917		this.obj = $merge.apply(null, [this.obj].extend(arguments));
5918		return this.setLength();
5919	},
5920
5921	/*
5922	Property: empty
5923		Empties all hash values properties and values.
5924	*/
5925
5926	empty: function(){
5927		this.obj = {};
5928		this.length = 0;
5929		return this;
5930	},
5931
5932	/*
5933	Property: keys
5934		Returns an array containing all the keys, in the same order as the values returned by <Hash.values>.
5935
5936	Returns:
5937		An array containing all the keys of the hash
5938	*/
5939
5940	keys: function(){
5941		var keys = [];
5942		for (var property in this.obj) keys.push(property);
5943		return keys;
5944	},
5945
5946	/*
5947	Property: values
5948		Returns an array containing all the values, in the same order as the keys returned by <Hash.keys>.
5949
5950	Returns:
5951		An array containing all the values of the hash
5952	*/
5953
5954	values: function(){
5955		var values = [];
5956		for (var property in this.obj) values.push(this.obj[property]);
5957		return values;
5958	}
5959
5960});
5961
5962/* Section: Utility Functions */
5963
5964/*
5965Function: $H
5966	Shortcut to create a Hash from an Object.
5967*/
5968
5969function $H(obj){
5970	return new Hash(obj);
5971};
5972
5973/*
5974Script: Hash.Cookie.js
5975	Stores and loads an Hash as a cookie using Json format.
5976*/
5977
5978/*
5979Class: Hash.Cookie
5980	Inherits all the methods from <Hash>, additional methods are save and load.
5981	Hash json string has a limit of 4kb (4096byte), so be careful with your Hash size.
5982	Creating a new instance automatically loads the data from the Cookie into the Hash.
5983	If the Hash is emptied, the cookie is also removed.
5984
5985Arguments:
5986	name - the key (name) for the cookie
5987	options - options are identical to <Cookie> and are simply passed along to it.
5988		In addition, it has the autoSave option, to save the cookie at every operation. defaults to true.
5989
5990Example:
5991	(start code)
5992	var fruits = new Hash.Cookie('myCookieName', {duration: 3600});
5993	fruits.extend({
5994		'lemon': 'yellow',
5995		'apple': 'red'
5996	});
5997	fruits.set('melon', 'green');
5998	fruits.get('lemon'); // yellow
5999
6000	// ... on another page ... values load automatically
6001
6002	var fruits = new Hash.Cookie('myCookieName', {duration: 365});
6003	fruits.get('melon'); // green
6004
6005	fruits.erase(); // delete cookie
6006	(end)
6007*/
6008
6009Hash.Cookie = Hash.extend({
6010
6011	initialize: function(name, options){
6012		this.name = name;
6013		this.options = $extend({'autoSave': true}, options || {});
6014		this.load();
6015	},
6016
6017	/*
6018	Property: save
6019		Saves the Hash to the cookie. If the hash is empty, removes the cookie.
6020
6021	Returns:
6022		Returns false when the JSON string cookie is too long (4kb), otherwise true.
6023
6024	Example:
6025		(start code)
6026		var login = new Hash.Cookie('userstatus', {autoSave: false});
6027
6028		login.extend({
6029			'username': 'John',
6030			'credentials': [4, 7, 9]
6031		});
6032		login.set('last_message', 'User logged in!');
6033
6034		login.save(); // finally save the Hash
6035		(end)
6036	*/
6037
6038	save: function(){
6039		if (this.length == 0){
6040			Cookie.remove(this.name, this.options);
6041			return true;
6042		}
6043		var str = Json.toString(this.obj);
6044		if (str.length > 4096) return false; //cookie would be truncated!
6045		Cookie.set(this.name, str, this.options);
6046		return true;
6047	},
6048	
6049	/*
6050	Property: load
6051		Loads the cookie and assigns it to the Hash.
6052	*/
6053
6054	load: function(){
6055		this.obj = Json.evaluate(Cookie.get(this.name), true) || {};
6056		this.setLength();
6057	}
6058
6059});
6060
6061Hash.Cookie.Methods = {};
6062['extend', 'set', 'merge', 'empty', 'remove'].each(function(method){
6063	Hash.Cookie.Methods[method] = function(){
6064		Hash.prototype[method].apply(this, arguments);
6065		if (this.options.autoSave) this.save();
6066		return this;
6067	};
6068});
6069Hash.Cookie.implement(Hash.Cookie.Methods);
6070
6071/*
6072Script: Color.js
6073	Contains the Color class.
6074
6075License:
6076	MIT-style license.
6077*/
6078
6079/*
6080Class: Color
6081	Creates a new Color Object, which is an array with some color specific methods.
6082Arguments:
6083	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.
6084	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'.
6085
6086Example:
6087	(start code)
6088	var black = new Color('#000');
6089	var purple = new Color([255,0,255]);
6090	// mix black with white and purple, each time at 10% of the new color
6091	var darkpurple = black.mix('#fff', purple, 10);
6092	$('myDiv').setStyle('background-color', darkpurple);
6093	(end)
6094*/
6095
6096var Color = new Class({
6097
6098	initialize: function(color, type){
6099		type = type || (color.push ? 'rgb' : 'hex');
6100		var rgb, hsb;
6101		switch(type){
6102			case 'rgb':
6103				rgb = color;
6104				hsb = rgb.rgbToHsb();
6105				break;
6106			case 'hsb':
6107				rgb = color.hsbToRgb();
6108				hsb = color;
6109				break;
6110			default:
6111				rgb = color.hexToRgb(true);
6112				hsb = rgb.rgbToHsb();
6113		}
6114		rgb.hsb = hsb;
6115		rgb.hex = rgb.rgbToHex();
6116		return $extend(rgb, Color.prototype);
6117	},
6118
6119	/*
6120	Property: mix
6121		Mixes two or more colors with the Color.
6122		
6123	Arguments:
6124		color - a color to mix. you can use as arguments how many colors as you want to mix with the original one.
6125		alpha - if you use a number as the last argument, it will be threated as the amount of the color to mix.
6126	*/
6127
6128	mix: function(){
6129		var colors = $A(arguments);
6130		var alpha = ($type(colors[colors.length - 1]) == 'number') ? colors.pop() : 50;
6131		var rgb = this.copy();
6132		colors.each(function(color){
6133			color = new Color(color);
6134			for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
6135		});
6136		return new Color(rgb, 'rgb');
6137	},
6138
6139	/*
6140	Property: invert
6141		Inverts the Color.
6142	*/
6143
6144	invert: function(){
6145		return new Color(this.map(function(value){
6146			return 255 - value;
6147		}));
6148	},
6149
6150	/*
6151	Property: setHue
6152		Modifies the hue of the Color, and returns a new one.
6153	
6154	Arguments:
6155		value - the hue to set
6156	*/
6157
6158	setHue: function(value){
6159		return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
6160	},
6161
6162	/*
6163	Property: setSaturation
6164		Changes the saturation of the Color, and returns a new one.
6165	
6166	Arguments:
6167		percent - the percentage of the saturation to set
6168	*/
6169
6170	setSaturation: function(percent){
6171		return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
6172	},
6173
6174	/*
6175	Property: setBrightness
6176		Changes the brightness of the Color, and returns a new one.
6177	
6178	Arguments:
6179		percent - the percentage of the brightness to set
6180	*/
6181
6182	setBrightness: function(percent){
6183		return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
6184	}
6185
6186});
6187
6188/* Section: Utility Functions */
6189
6190/*
6191Function: $RGB
6192	Shortcut to create a new color, based on red, green, blue values.
6193
6194Arguments:
6195	r - (integer) red value (0-255)
6196	g - (integer) green value (0-255)
6197	b - (integer) blue value (0-255)
6198
6199*/
6200
6201function $RGB(r, g, b){
6202	return new Color([r, g, b], 'rgb');
6203};
6204
6205/*
6206Function: $HSB
6207	Shortcut to create a new color, based on hue, saturation, brightness values.
6208
6209Arguments:
6210	h - (integer) hue value (0-100)
6211	s - (integer) saturation value (0-100)
6212	b - (integer) brightness value (0-100)
6213*/
6214
6215function $HSB(h, s, b){
6216	return new Color([h, s, b], 'hsb');
6217};
6218
6219/*
6220Class: Array
6221	A collection of The Array Object prototype methods.
6222*/
6223
6224Array.extend({
6225	
6226	/*
6227	Property: rgbToHsb
6228		Converts a RGB array to an HSB array.
6229
6230	Returns:
6231		the HSB array.
6232	*/
6233
6234	rgbToHsb: function(){
6235		var red = this[0], green = this[1], blue = this[2];
6236		var hue, saturation, brightness;
6237		var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
6238		var delta = max - min;
6239		brightness = max / 255;
6240		saturation = (max != 0) ? delta / max : 0;
6241		if (saturation == 0){
6242			hue = 0;
6243		} else {
6244			var rr = (max - red) / delta;
6245			var gr = (max - green) / delta;
6246			var br = (max - blue) / delta;
6247			if (red == max) hue = br - gr;
6248			else if (green == max) hue = 2 + rr - br;
6249			else hue = 4 + gr - rr;
6250			hue /= 6;
6251			if (hue < 0) hue++;
6252		}
6253		return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
6254	},
6255
6256	/*
6257	Property: hsbToRgb
6258		Converts an HSB array to an RGB array.
6259
6260	Returns:
6261		the RGB array.
6262	*/
6263
6264	hsbToRgb: function(){
6265		var br = Math.round(this[2] / 100 * 255);
6266		if (this[1] == 0){
6267			return [br, br, br];
6268		} else {
6269			var hue = this[0] % 360;
6270			var f = hue % 60;
6271			var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
6272			var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
6273			var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
6274			switch(Math.floor(hue / 60)){
6275				case 0: return [br, t, p];
6276				case 1: return [q, br, p];
6277				case 2: return [p, br, t];
6278				case 3: return [p, q, br];
6279				case 4: return [t, p, br];
6280				case 5: return [br, p, q];
6281			}
6282		}
6283		return false;
6284	}
6285
6286});
6287
6288/*
6289Script: Scroller.js
6290	Contains the <Scroller>.
6291
6292License:
6293	MIT-style license.
6294*/
6295
6296/*
6297Class: Scroller
6298	The Scroller is a class to scroll any element with an overflow (including the window) when the mouse 
6298cursor reaches certain buondaries of that element.
6299	You must call its start method to start listening to mouse movements.
6300
6301Note:
6302	The Scroller requires an XHTML doctype.
6303
6304Arguments:
6305	element - required, the element to scroll.
6306	options - optional, see options below, and <Fx.Base> options.
6307
6308Options:
6309	area - integer, the necessary boundaries to make the element scroll.
6310	velocity - integer, velocity ratio, the modifier for the window scrolling speed.
6311
6312Events:
6313	onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets.
6314		Automatically passes as parameters x and y values.
6315*/
6316
6317var Scroller = new Class({
6318
6319	options: {
6320		area: 20,
6321		velocity: 1,
6322		onChange: function(x, y){
6323			this.element.scrollTo(x, y);
6324		}
6325	},
6326
6327	initialize: function(element, options){
6328		this.setOptions(options);
6329		this.element = $(element);
6330		this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element;
6331	},
6332
6333	/*
6334	Property: start
6335		The scroller starts listening to mouse movements.
6336	*/
6337
6338	start: function(){
6339		this.coord = this.getCoords.bindWithEvent(this);
6340		this.mousemover.addListener('mousemove', this.coord);
6341	},
6342
6343	/*
6344	Property: stop
6345		The scroller stops listening to mouse movements.
6346	*/
6347
6348	stop: function(){
6349		this.mousemover.removeListener('mousemove', this.coord);
6350		this.timer = $clear(this.timer);
6351	},
6352
6353	getCoords: function(event){
6354		this.page = (this.element == window) ? event.client : event.page;
6355		if (!this.timer) this.timer = this.scroll.periodical(50, this);
6356	},
6357
6358	scroll: function(){
6359		var el = this.element.getSize();
6360		var pos = this.element.getPosition();
6361
6362		var change = {'x': 0, 'y': 0};
6363		for (var z in this.page){
6364			if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
6365				change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
6366			else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
6367				change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
6368		}
6369		if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
6370	}
6371
6372});
6373
6374Scroller.implement(new Events, new Options);
6375
6376/*
6377Script: Slider.js
6378	Contains <Slider>
6379
6380License:
6381	MIT-style license.
6382*/
6383
6384/*
6385Class: Slider
6386	Creates a slider with two elements: a knob and a container. Returns the values.
6387	
6388Note:
6389	The Slider requires an XHTML doctype.
6390
6391Arguments:
6392	element - the knob container
6393	knob - the handle
6394	options - see Options below
6395
6396Options:
6397	steps - the number of steps for your slider.
6398	mode - either 'horizontal' or 'vertical'. defaults to horizontal.
6399	offset - relative offset for knob position. default to 0.
6400	
6401Events:
6402	onChange - a function to fire when the value changes.
6403	onComplete - a function to fire when you're done dragging.
6404	onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position.
6405		Passes as parameter the new position.
6406*/
6407
6408var Slider = new Class({
6409
6410	options: {
6411		onChange: Class.empty,
6412		onComplete: Class.empty,
6413		onTick: function(pos){
6414			this.knob.setStyle(this.p, pos);
6415		},
6416		mode: 'horizontal',
6417		steps: 100,
6418		offset: 0
6419	},
6420
6421	initialize: function(el, knob, options){
6422		this.element = $(el);
6423		this.knob = $(knob);
6424		this.setOptions(options);
6425		this.previousChange = -1;
6426		this.previousEnd = -1;
6427		this.step = -1;
6428		this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
6429		var mod, offset;
6430		switch(this.options.mode){
6431			case 'horizontal':
6432				this.z = 'x';
6433				this.p = 'left';
6434				mod = {'x': 'left', 'y': false};
6435				offset = 'offsetWidth';
6436				break;
6437			case 'vertical':
6438				this.z = 'y';
6439				this.p = 'top';
6440				mod = {'x': false, 'y': 'top'};
6441				offset = 'offsetHeight';
6442		}
6443		this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
6444		this.half = this.knob[offset]/2;
6445		this.getPos = this.element['get' + this.p.capitalize()].bind(this.element);
6446		this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset);
6447		var lim = {};
6448		lim[this.z] = [- this.options.offset, this.max - this.options.offset];
6449		this.drag = new Drag.Base(this.knob, {
6450			limit: lim,
6451			modifiers: mod,
6452			snap: 0,
6453			onStart: function(){
6454				this.draggedKnob();
6455			}.bind(this),
6456			onDrag: function(){
6457				this.draggedKnob();
6458			}.bind(this),
6459			onComplete: function(){
6460				this.draggedKnob();
6461				this.end();
6462			}.bind(this)
6463		});
6464		if (this.options.initialize) this.options.initialize.call(this);
6465	},
6466
6467	/*
6468	Property: set
6469		The slider will get the step you pass.
6470
6471	Arguments:
6472		step - one integer
6473	*/
6474
6475	set: function(step){
6476		this.step = step.limit(0, this.options.steps);
6477		this.checkStep();
6478		this.end();
6479		this.fireEvent('onTick', this.toPosition(this.step));
6480		return this;
6481	},
6482
6483	clickedElement: function(event){
6484		var position = event.page[this.z] - this.getPos() - this.half;
6485		position = position.limit(-this.options.offset, this.max -this.options.offset);
6486		this.step = this.toStep(position);
6487		this.checkStep();
6488		this.end();
6489		this.fireEvent('onTick', position);
6490	},
6491
6492	draggedKnob: function(){
6493		this.step = this.toStep(this.drag.value.now[this.z]);
6494		this.checkStep();
6495	},
6496
6497	checkStep: function(){
6498		if (this.previousChange != this.step){
6499			this.previousChange = this.step;
6500			this.fireEvent('onChange', this.step);
6501		}
6502	},
6503
6504	end: function(){
6505		if (this.previousEnd !== this.step){
6506			this.previousEnd = this.step;
6507			this.fireEvent('onComplete', this.step + '');
6508		}
6509	},
6510
6511	toStep: function(position){
6512		return Math.round((position + this.options.offset) / this.max * this.options.steps);
6513	},
6514
6515	toPosition: function(step){
6516		return this.max * step / this.options.steps;
6517	}
6518
6519});
6520
6521Slider.implement(new Events);
6522Slider.implement(new Options);
6523
6524/*
6525Script: SmoothScroll.js
6526	Contains <SmoothScroll>
6527
6528License:
6529	MIT-style license.
6530*/
6531
6532/*
6533Class: SmoothScroll
6534	Auto targets all the anchors in a page and display a smooth scrolling effect upon clicking them.
6535	Inherits methods, properties, options and events from <Fx.Scroll>.
6536
6537Note:
6538	SmoothScroll requires an XHTML doctype.
6539
6540Arguments:
6541	options - the Fx.Scroll options (see: <Fx.Scroll>) plus links, a collection of elements you want your smoothscroll on. Defaults to document.links.
6542
6543Example:
6544	>new SmoothScroll();
6545*/
6546
6547var SmoothScroll = Fx.Scroll.extend({
6548
6549	initialize: function(options){
6550		this.parent(window, options);
6551		this.links = (this.options.links) ? $$(this.options.links) : $$(document.links);
6552		var location = window.location.href.match(/^[^#]*/)[0] + '#';
6553		this.links.each(function(link){
6554			if (link.href.indexOf(location) != 0) return;
6555			var anchor = link.href.substr(location.length);
6556			if (anchor && $(anchor)) this.useLink(link, anchor);
6557		}, this);
6558		if (!window.webkit419) this.addEvent('onComplete', function(){
6559			window.location.hash = this.anchor;
6560		});
6561	},
6562
6563	useLink: function(link, anchor){
6564		link.addEvent('click', function(event){
6565			this.anchor = anchor;
6566			this.toElement(anchor);
6567			event.stop();
6568		}.bindWithEvent(this));
6569	}
6570
6571});
6572
6573/*
6574Script: Sortables.js
6575	Contains <Sortables> Class.
6576
6577License:
6578	MIT-style license.
6579*/
6580
6581/*
6582Class: Sortables
6583	Creates an interface for <Drag.Base> and drop, resorting of a list.
6584
6585Note:
6586	The Sortables require an XHTML doctype.
6587
6588Arguments:
6589	list - required, the list that will become sortable.
6590	options - an Object, see options below.
6591
6592Options:
6593	handles - a collection of elements to be used for drag handles. defaults to the elements.
6594	
6595Events:
6596	onStart - function executed when the item starts dragging
6597	onComplete - function executed when the item ends dragging
6598*/
6599
6600var Sortables = new Class({
6601
6602	options: {
6603		handles: false,
6604		onStart: Class.empty,
6605		onComplete: Class.empty,
6606		ghost: true,
6607		snap: 3,
6608		onDragStart: function(element, ghost){
6609			ghost.setStyle('opacity', 0.7);
6610			element.setStyle('opacity', 0.7);
6611		},
6612		onDragComplete: function(element, ghost){
6613			element.setStyle('opacity', 1);
6614			ghost.remove();
6615			this.trash.remove();
6616		}
6617	},
6618
6619	initialize: function(list, options){
6620		this.setOptions(options);
6621		this.list = $(list);
6622		this.elements = this.list.getChildren();
6623		this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements;
6624		this.bound = {
6625			'start': [],
6626			'moveGhost': this.moveGhost.bindWithEvent(this)
6627		};
6628		for (var i = 0, l = this.handles.length; i < l; i++){
6629			this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]);
6630		}
6631		this.attach();
6632		if (this.options.initialize) this.options.initialize.call(this);
6633		this.bound.move = this.move.bindWithEvent(this);
6634		this.bound.end = this.end.bind(this);
6635	},
6636
6637	attach: function(){
6638		this.handles.each(function(handle, i){
6639			handle.addEvent('mousedown', this.bound.start[i]);
6640		}, this);
6641	},
6642
6643	detach: function(){
6644		this.handles.each(function(handle, i){
6645			handle.removeEvent('mousedown', this.bound.start[i]);
6646		}, this);
6647	},
6648
6649	start: function(event, el){
6650		this.active = el;
6651		this.coordinates = this.list.getCoordinates();
6652		if (this.options.ghost){
6653			var position = el.getPosition();
6654			this.offset = event.page.y - position.y;
6655			this.trash = new Element('div').inject(document.body);
6656			this.ghost = el.clone().inject(this.trash).setStyles({
6657				'position': 'absolute',
6658				'left': position.x,
6659				'top': event.page.y - this.offset
6660			});
6661			document.addListener('mousemove', this.bound.moveGhost);
6662			this.fireEvent('onDragStart', [el, this.ghost]);
6663		}
6664		document.addListener('mousemove', this.bound.move);
6665		document.addListener('mouseup', this.bound.end);
6666		this.fireEvent('onStart', el);
6667		event.stop();
6668	},
6669
6670	moveGhost: function(event){
6671		var value = event.page.y - this.offset;
6672		value = value.limit(this.coordinates.top, this.coordinates.bottom - this.ghost.offsetHeight);
6673		this.ghost.setStyle('top', value);
6674		event.stop();
6675	},
6676
6677	move: function(event){
6678		var now = event.page.y;
6679		this.previous = this.previous || now;
6680		var up = ((this.previous - now) > 0);
6681		var prev = this.active.getPrevious();
6682		var next = this.active.getNext();
6683		if (prev && up && now < prev.getCoordinates().bottom) this.active.injectBefore(prev);
6684		if (next && !up && now > next.getCoordinates().top) this.active.injectAfter(next);
6685		this.previous = now;
6686	},
6687
6688	serialize: function(converter){
6689		return this.list.getChildren().map(converter || function(el){
6690			return this.elements.indexOf(el);
6691		}, this);
6692	},
6693
6694	end: function(){
6695		this.previous = null;
6696		document.removeListener('mousemove', this.bound.move);
6697		document.removeListener('mouseup', this.bound.end);
6698		if (this.options.ghost){
6699			document.removeListener('mousemove', this.bound.moveGhost);
6700			this.fireEvent('onDragComplete', [this.active, this.ghost]);
6701		}
6702		this.fireEvent('onComplete', this.active);
6703	}
6704
6705});
6706
6707Sortables.implement(new Events, new Options);
6708
6709/*
6710Script: Tips.js
6711	Tooltips, BubbleTips, whatever they are, they will appear on mouseover
6712
6713License:
6714	MIT-style license.
6715
6716Credits:
6717	The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com>
6718*/
6719
6720/*
6721Class: Tips
6722	Display a tip on any element with a title and/or href.
6723
6724Note:
6725	Tips requires an XHTML doctype.
6726
6727Arguments:
6728	elements - a collection of elements to apply the tooltips to on mouseover.
6729	options - an object. See options Below.
6730
6731Options:
6732	maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30.
6733	showDelay - the delay the onShow method is called. (defaults to 100 ms)
6734	hideDelay - the delay the onHide method is called. (defaults to 100 ms)
6735
6736	className - the prefix for your tooltip classNames. defaults to 'tool'.
6737
6738		the whole tooltip will have as classname: tool-tip
6739
6740		the title will have as classname: tool-title
6741
6742		the text will have as classname: tool-text
6743
6744	offsets - the distance of your tooltip from the mouse. an Object with x/y properties.
6745	fixed - if set to true, the toolTip will not follow the mouse.
6746	
6747Events:
6748	onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect);
6749	onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect);
6750
6751Example:
6752	(start code)
6753	<img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/>
6754	<script>
6755		var myTips = new Tips($$('.toolTipImg'), {
6756			maxTitleChars: 50	//I like my captions a little long
6757		});
6758	</script>
6759	(end)
6760
6761Note:
6762	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.
6763*/
6764
6765var Tips = new Class({
6766
6767	options: {
6768		onShow: function(tip){
6769			tip.setStyle('visibility', 'visible');
6770		},
6771		onHide: function(tip){
6772			tip.setStyle('visibility', 'hidden');
6773		},
6774		maxTitleChars: 30,
6775		showDelay: 100,
6776		hideDelay: 100,
6777		className: 'tool',
6778		offsets: {'x': 16, 'y': 16},
6779		fixed: false
6780	},
6781
6782	initialize: function(elements, options){
6783		this.setOptions(options);
6784		this.toolTip = new Element('div', {
6785			'class': this.options.className + '-tip',
6786			'styles': {
6787				'position': 'absolute',
6788				'top': '0',
6789				'left': '0',
6790				'visibility': 'hidden'
6791			}
6792		}).inject(document.body);
6793		this.wrapper = new Element('div').inject(this.toolTip);
6794		$$(elements).each(this.build, this);
6795		if (this.options.initialize) this.options.initialize.call(this);
6796	},
6797
6798	build: function(el){
6799		el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') 
6799: (el.rel || false);
6800		if (el.title){
6801			var dual = el.title.split('::');
6802			if (dual.length > 1){
6803				el.$tmp.myTitle = dual[0].trim();
6804				el.$tmp.myText = dual[1].trim();
6805			} else {
6806				el.$tmp.myText = el.title;
6807			}
6808			el.removeAttribute('title');
6809		} else {
6810			el.$tmp.myText = false;
6811		}
6812		if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
6813		el.addEvent('mouseenter', function(event){
6814			this.start(el);
6815			if (!this.options.fixed) this.locate(event);
6816			else this.position(el);
6817		}.bind(this));
6818		if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
6819		var end = this.end.bind(this);
6820		el.addEvent('mouseleave', end);
6821		el.addEvent('trash', end);
6822	},
6823
6824	start: function(el){
6825		this.wrapper.empty();
6826		if (el.$tmp.myTitle){
6827			this.title = new Element('span').inject(new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)).setHTML(el.$tmp.myTitle);
6828		}
6829		if (el.$tmp.myText){
6830			this.text = new Element('span').inject(new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)).setHTML(el.$tmp.myText);
6831		}
6832		$clear(this.timer);
6833		this.timer = this.show.delay(this.options.showDelay, this);
6834	},
6835
6836	end: function(event){
6837		$clear(this.timer);
6838		this.timer = this.hide.delay(this.options.hideDelay, this);
6839	},
6840
6841	position: function(element){
6842		var pos = element.getPosition();
6843		this.toolTip.setStyles({
6844			'left': pos.x + this.options.offsets.x,
6845			'top': pos.y + this.options.offsets.y
6846		});
6847	},
6848
6849	locate: function(event){
6850		var win = {'x': window.getWidth(), 'y': window.getHeight()};
6851		var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
6852		var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
6853		var prop = {'x': 'left', 'y': 'top'};
6854		for (var z in prop){
6855			var pos = event.page[z] + this.options.offsets[z];
6856			if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
6857			this.toolTip.setStyle(prop[z], pos);
6858		};
6859	},
6860
6861	show: function(){
6862		if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
6863		this.fireEvent('onShow', [this.toolTip]);
6864	},
6865
6866	hide: function(){
6867		this.fireEvent('onHide', [this.toolTip]);
6868	}
6869
6870});
6871
6872Tips.implement(new Events, new Options);
6873
6874/*
6875Script: Group.js
6876	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.
6877
6878License:
6879	MIT-style license.
6880*/
6881
6882/*
6883Class: Group
6884	An "Utility" Class.
6885
6886Arguments:
6887	List of Class instances
6888
6889Example:
6890	(start code)
6891	xhr1 = new Ajax('data.js', {evalScript: true});
6892	xhr2 = new Ajax('abstraction.js', {evalScript: true});
6893	xhr3 = new Ajax('template.js', {evalScript: true});
6894
6895	var group = new Group(xhr1, xhr2, xhr3);
6896	group.addEvent('onComplete', function(){
6897		alert('All Scripts loaded');
6898	});
6899
6900	xhr1.request();
6901	xhr2.request();
6902	xhr3.request();
6903	(end)
6904
6905*/
6906
6907var Group = new Class({
6908
6909	initialize: function(){
6910		this.instances = $A(arguments);
6911		this.events = {};
6912		this.checker = {};
6913	},
6914
6915	/*
6916	Property: addEvent
6917		adds an event to the stack of events of the Class instances.
6918
6919	Arguments:
6920		type - string; the event name (e.g. 'onComplete')
6921		fn - function to execute when all instances fired this event
6922	*/
6923
6924	addEvent: function(type, fn){
6925		this.checker[type] = this.checker[type] || {};
6926		this.events[type] = this.events[type] || [];
6927		if (this.events[type].contains(fn)) return false;
6928		else this.events[type].push(fn);
6929		this.instances.each(function(instance, i){
6930			instance.addEvent(type, this.check.bind(this, [type, instance, i]));
6931		}, this);
6932		return this;
6933	},
6934
6935	check: function(type, instance, i){
6936		this.checker[type][i] = true;
6937		var every = this.instances.every(function(current, j){
6938			return this.checker[type][j] || false;
6939		}, this);
6940		if (!every) return;
6941		this.checker[type] = {};
6942		this.events[type].each(function(event){
6943			event.call(this, this.instances, instance);
6944		}, this);
6945	}
6946
6947});
6948
6949/*
6950Script: Accordion.js
6951	Contains <Accordion>
6952
6953License:
6954	MIT-style license.
6955*/
6956
6957/*
6958Class: Accordion
6959	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.
6960	Inherits methods, properties, options and events from <Fx.Elements>.
6961	
6962Note:
6963	The Accordion requires an XHTML doctype.
6964
6965Arguments:
6966	togglers - required, a collection of elements, the elements handlers that will be clickable.
6967	elements - required, a collection of elements the transitions will be applied to.
6968	options - optional, see options below, and <Fx.Base> options and events.
6969
6970Options:
6971	show - integer, the Index of the element to show at start.
6972	display - integer, the Index of the element to show at start (with a transition). defaults to 0.
6973	fixedHeight - integer, if you want the elements to have a fixed height. defaults to false.
6974	fixedWidth - integer, if you want the elements to have a fixed width. defaults to false.
6975	height - boolean, will add a height transition to the accordion if true. defaults to true.
6976	opacity - boolean, will add an opacity transition to the accordion if true. defaults to true.
6977	width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work!
6978	alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false.
6979	
6980Events:
6981	onActive - function to execute when an element starts to show
6982	onBackground - function to execute when an element starts to hide
6983*/
6984
6985var Accordion = Fx.Elements.extend({
6986
6987	options: {
6988		onActive: Class.empty,
6989		onBackground: Class.empty,
6990		display: 0,
6991		show: false,
6992		height: true,
6993		width: false,
6994		opacity: true,
6995		fixedHeight: false,
6996		fixedWidth: false,
6997		wait: false,
6998		alwaysHide: false
6999	},
7000
7001	initialize: function(){
7002		var options, togglers, elements, container;
7003		$each(arguments, function(argument, i){
7004			switch($type(argument)){
7005				case 'object': options = argument; break;
7006				case 'element': container = $(argument); break;
7007				default:
7008					var temp = $$(argument);
7009					if (!togglers) togglers = temp;
7010					else elements = temp;
7011			}
7012		});
7013		this.togglers = togglers || [];
7014		this.elements = elements || [];
7015		this.container = $(container);
7016		this.setOptions(options);
7017		this.previous = -1;
7018		if (this.options.alwaysHide) this.options.wait = true;
7019		if ($chk(this.options.show)){
7020			this.options.display = false;
7021			this.previous = this.options.show;
7022		}
7023		if (this.options.start){
7024			this.options.display = false;
7025			this.options.show = false;
7026		}
7027		this.effects = {};
7028		if (this.options.opacity) this.effects.opacity = 'fullOpacity';
7029		if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
7030		if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
7031		for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
7032		this.elements.each(function(el, i){
7033			if (this.options.show === i){
7034				this.fireEvent('onActive', [this.togglers[i], el]);
7035			} else {
7036				for (var fx in this.effects) el.setStyle(fx, 0);
7037			}
7038		}, this);
7039		this.parent(this.elements);
7040		if ($chk(this.options.display)) this.display(this.options.display);
7041	},
7042
7043	/*
7044	Property: addSection
7045		Dynamically adds a new section into the accordion at the specified position.
7046
7047	Arguments:
7048		toggler - (dom element) the element that toggles the accordion section open.
7049		element - (dom element) the element that stretches open when the toggler is clicked.
7050		pos - (integer) the index where these objects are to be inserted within the accordion.
7051	*/
7052
7053	addSection: function(toggler, element, pos){
7054		toggler = $(toggler);
7055		element = $(element);
7056		var test = this.togglers.contains(toggler);
7057		var len = this.togglers.length;
7058		this.togglers.include(toggler);
7059		this.elements.include(element);
7060		if (len && (!test || pos)){
7061			pos = $pick(pos, len - 1);
7062			toggler.injectBefore(this.togglers[pos]);
7063			element.injectAfter(toggler);
7064		} else if (this.container && !test){
7065			toggler.inject(this.container);
7066			element.inject(this.container);
7067		}
7068		var idx = this.togglers.indexOf(toggler);
7069		toggler.addEvent('click', this.display.bind(this, idx));
7070		if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
7071		if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
7072		element.fullOpacity = 1;
7073		if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
7074		if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
7075		element.setStyle('overflow', 'hidden');
7076		if (!test){
7077			for (var fx in this.effects) element.setStyle(fx, 0);
7078		}
7079		return this;
7080	},
7081
7082	/*
7083	Property: display
7084		Shows a specific section and hides all others. Useful when triggering an accordion from outside.
7085
7086	Arguments:
7087		index - integer, the index of the item to show, or the actual element to show.
7088	*/
7089
7090	display: function(index){
7091		index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
7092		if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
7093		this.previous = index;
7094		var obj = {};
7095		this.elements.each(function(el, i){
7096			obj[i] = {};
7097			var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
7098			this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]);
7099			for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
7100		}, this);
7101		return this.start(obj);
7102	},
7103
7104	showThisHideOpen: function(index){return this.display(index);}
7105
7106});
7107
7108Fx.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.