PageSourceSearch

https://konto.is/externals/mootools/mootools-core-1.3.2-full-compat.js?c=729

js konto.is collected 2026-10-10 03:22:05 UTC 152,327 bytes, 5,953 lines download raw bytes

1/*
2---
3MooTools: the javascript framework
4
5web build:
6 - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7
7
8packager build:
9 - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
10
11/*
12---
13
14name: Core
15
16description: The heart of MooTools.
17
18license: MIT-style license.
19
20copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).
21
22authors: The MooTools production team (http://mootools.net/developers/)
23
24inspiration:
25  - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
26  - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
27
28provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
29
30...
31*/
32
33(function(){
34
35this.MooTools = {
36	version: '1.3.2',
37	build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587'
38};
39
40// typeOf, instanceOf
41
42var typeOf = this.typeOf = function(item){
43	if (item == null) return 'null';
44	if (item.$family) return item.$family();
45
46	if (item.nodeName){
47		if (item.nodeType == 1) return 'element';
48		if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
49	} else if (typeof item.length == 'number'){
50		if (item.callee) return 'arguments';
51		if ('item' in item) return 'collection';
52	}
53
54	return typeof item;
55};
56
57var instanceOf = this.instanceOf = function(item, object){
58	if (item == null) return false;
59	var constructor = item.$constructor || item.constructor;
60	while (constructor){
61		if (constructor === object) return true;
62		constructor = constructor.parent;
63	}
64	return item instanceof object;
65};
66
67// Function overloading
68
69var Function = this.Function;
70
71var enumerables = true;
72for (var i in {toString: 1}) enumerables = null;
73if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
74
75Function.prototype.overloadSetter = function(usePlural){
76	var self = this;
77	return function(a, b){
78		if (a == null) return this;
79		if (usePlural || typeof a != 'string'){
80			for (var k in a) self.call(this, k, a[k]);
81			if (enumerables) for (var i = enumerables.length; i--;){
82				k = enumerables[i];
83				if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
84			}
85		} else {
86			self.call(this, a, b);
87		}
88		return this;
89	};
90};
91
92Function.prototype.overloadGetter = function(usePlural){
93	var self = this;
94	return function(a){
95		var args, result;
96		if (usePlural || typeof a != 'string') args = a;
97		else if (arguments.length > 1) args = arguments;
98		if (args){
99			result = {};
100			for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
101		} else {
102			result = self.call(this, a);
103		}
104		return result;
105	};
106};
107
108Function.prototype.extend = function(key, value){
109	this[key] = value;
110}.overloadSetter();
111
112Function.prototype.implement = function(key, value){
113	this.prototype[key] = value;
114}.overloadSetter();
115
116// From
117
118var slice = Array.prototype.slice;
119
120Function.from = function(item){
121	return (typeOf(item) == 'function') ? item : function(){
122		return item;
123	};
124};
125
126Array.from = function(item){
127	if (item == null) return [];
128	return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
129};
130
131Number.from = function(item){
132	var number = parseFloat(item);
133	return isFinite(number) ? number : null;
134};
135
136String.from = function(item){
137	return item + '';
138};
139
140// hide, protect
141
142Function.implement({
143
144	hide: function(){
145		this.$hidden = true;
146		return this;
147	},
148
149	protect: function(){
150		this.$protected = true;
151		return this;
152	}
153
154});
155
156// Type
157
158var Type = this.Type = function(name, object){
159	if (name){
160		var lower = name.toLowerCase();
161		var typeCheck = function(item){
162			return (typeOf(item) == lower);
163		};
164
165		Type['is' + name] = typeCheck;
166		if (object != null){
167			object.prototype.$family = (function(){
168				return lower;
169			}).hide();
170			//<1.2compat>
171			object.type = typeCheck;
172			//</1.2compat>
173		}
174	}
175
176	if (object == null) return null;
177
178	object.extend(this);
179	object.$constructor = Type;
180	object.prototype.$constructor = object;
181
182	return object;
183};
184
185var toString = Object.prototype.toString;
186
187Type.isEnumerable = function(item){
188	return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
189};
190
191var hooks = {};
192
193var hooksOf = function(object){
194	var type = typeOf(object.prototype);
195	return hooks[type] || (hooks[type] = []);
196};
197
198var implement = function(name, method){
199	if (method && method.$hidden) return;
200
201	var hooks = hooksOf(this);
202
203	for (var i = 0; i < hooks.length; i++){
204		var hook = hooks[i];
205		if (typeOf(hook) == 'type') implement.call(hook, name, method);
206		else hook.call(this, name, method);
207	}
208	
209	var previous = this.prototype[name];
210	if (previous == null || !previous.$protected) this.prototype[name] = method;
211
212	if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
213		return method.apply(item, slice.call(arguments, 1));
214	});
215};
216
217var extend = function(name, method){
218	if (method && method.$hidden) return;
219	var previous = this[name];
220	if (previous == null || !previous.$protected) this[name] = method;
221};
222
223Type.implement({
224
225	implement: implement.overloadSetter(),
226
227	extend: extend.overloadSetter(),
228
229	alias: function(name, existing){
230		implement.call(this, name, this.prototype[existing]);
231	}.overloadSetter(),
232
233	mirror: function(hook){
234		hooksOf(this).push(hook);
235		return this;
236	}
237
238});
239
240new Type('Type', Type);
241
242// Default Types
243
244var force = function(name, object, methods){
245	var isType = (object != Object),
246		prototype = object.prototype;
247
248	if (isType) object = new Type(name, object);
249
250	for (var i = 0, l = methods.length; i < l; i++){
251		var key = methods[i],
252			generic = object[key],
253			proto = prototype[key];
254
255		if (generic) generic.protect();
256
257		if (isType && proto){
258			delete prototype[key];
259			prototype[key] = proto.protect();
260		}
261	}
262
263	if (isType) object.implement(prototype);
264
265	return force;
266};
267
268force('String', String, [
269	'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
270	'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
271])('Array', Array, [
272	'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
273	'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
274])('Number', Number, [
275	'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
276])('Function', Function, [
277	'apply', 'call', 'bind'
278])('RegExp', RegExp, [
279	'exec', 'test'
280])('Object', Object, [
281	'create', 'defineProperty', 'defineProperties', 'keys',
282	'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
283	'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
284])('Date', Date, ['now']);
285
286Object.extend = extend.overloadSetter();
287
288Date.extend('now', function(){
289	return +(new Date);
290});
291
292new Type('Boolean', Boolean);
293
294// fixes NaN returning as Number
295
296Number.prototype.$family = function(){
297	return isFinite(this) ? 'number' : 'null';
298}.hide();
299
300// Number.random
301
302Number.extend('random', function(min, max){
303	return Math.floor(Math.random() * (max - min + 1) + min);
304});
305
306// forEach, each
307
308var hasOwnProperty = Object.prototype.hasOwnProperty;
309Object.extend('forEach', function(object, fn, bind){
310	for (var key in object){
311		if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
312	}
313});
314
315Object.each = Object.forEach;
316
317Array.implement({
318
319	forEach: function(fn, bind){
320		for (var i = 0, l = this.length; i < l; i++){
321			if (i in this) fn.call(bind, this[i], i, this);
322		}
323	},
324
325	each: function(fn, bind){
326		Array.forEach(this, fn, bind);
327		return this;
328	}
329
330});
331
332// Array & Object cloning, Object merging and appending
333
334var cloneOf = function(item){
335	switch (typeOf(item)){
336		case 'array': return item.clone();
337		case 'object': return Object.clone(item);
338		default: return item;
339	}
340};
341
342Array.implement('clone', function(){
343	var i = this.length, clone = new Array(i);
344	while (i--) clone[i] = cloneOf(this[i]);
345	return clone;
346});
347
348var mergeOne = function(source, key, current){
349	switch (typeOf(current)){
350		case 'object':
351			if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
352			else source[key] = Object.clone(current);
353		break;
354		case 'array': source[key] = current.clone(); break;
355		default: source[key] = current;
356	}
357	return source;
358};
359
360Object.extend({
361
362	merge: function(source, k, v){
363		if (typeOf(k) == 'string') return mergeOne(source, k, v);
364		for (var i = 1, l = arguments.length; i < l; i++){
365			var object = arguments[i];
366			for (var key in object) mergeOne(source, key, object[key]);
367		}
368		return source;
369	},
370
371	clone: function(object){
372		var clone = {};
373		for (var key in object) clone[key] = cloneOf(object[key]);
374		return clone;
375	},
376
377	append: function(original){
378		for (var i = 1, l = arguments.length; i < l; i++){
379			var extended = arguments[i] || {};
380			for (var key in extended) original[key] = extended[key];
381		}
382		return original;
383	}
384
385});
386
387// Object-less types
388
389['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
390	new Type(name);
391});
392
393// Unique ID
394
395var UID = Date.now();
396
397String.extend('uniqueID', function(){
398	return (UID++).toString(36);
399});
400
401//<1.2compat>
402
403var Hash = this.Hash = new Type('Hash', function(object){
404	if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
405	for (var key in object) this[key] = object[key];
406	return this;
407});
408
409Hash.implement({
410
411	forEach: function(fn, bind){
412		Object.forEach(this, fn, bind);
413	},
414
415	getClean: function(){
416		var clean = {};
417		for (var key in this){
418			if (this.hasOwnProperty(key)) clean[key] = this[key];
419		}
420		return clean;
421	},
422
423	getLength: function(){
424		var length = 0;
425		for (var key in this){
426			if (this.hasOwnProperty(key)) length++;
427		}
428		return length;
429	}
430
431});
432
433Hash.alias('each', 'forEach');
434
435Object.type = Type.isObject;
436
437var Native = this.Native = function(properties){
438	return new Type(properties.name, properties.initialize);
439};
440
441Native.type = Type.type;
442
443Native.implement = function(objects, methods){
444	for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
445	return Native;
446};
447
448var arrayType = Array.type;
449Array.type = function(item){
450	return instanceOf(item, Array) || arrayType(item);
451};
452
453this.$A = function(item){
454	return Array.from(item).slice();
455};
456
457this.$arguments = function(i){
458	return function(){
459		return arguments[i];
460	};
461};
462
463this.$chk = function(obj){
464	return !!(obj || obj === 0);
465};
466
467this.$clear = function(timer){
468	clearTimeout(timer);
469	clearInterval(timer);
470	return null;
471};
472
473this.$defined = function(obj){
474	return (obj != null);
475};
476
477this.$each = function(iterable, fn, bind){
478	var type = typeOf(iterable);
479	((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind);
480};
481
482this.$empty = function(){};
483
484this.$extend = function(original, extended){
485	return Object.append(original, extended);
486};
487
488this.$H = function(object){
489	return new Hash(object);
490};
491
492this.$merge = function(){
493	var args = Array.slice(arguments);
494	args.unshift({});
495	return Object.merge.apply(null, args);
496};
497
498this.$lambda = Function.from;
499this.$mixin = Object.merge;
500this.$random = Number.random;
501this.$splat = Array.from;
502this.$time = Date.now;
503
504this.$type = function(object){
505	var type = typeOf(object);
506	if (type == 'elements') return 'array';
507	return (type == 'null') ? false : type;
508};
509
510this.$unlink = function(object){
511	switch (typeOf(object)){
512		case 'object': return Object.clone(object);
513		case 'array': return Array.clone(object);
514		case 'hash': return new Hash(object);
515		default: return object;
516	}
517};
518
519//</1.2compat>
520
521})();
522
523
524/*
525---
526
527name: Array
528
529description: Contains Array Prototypes like each, contains, and erase.
530
531license: MIT-style license.
532
533requires: Type
534
535provides: Array
536
537...
538*/
539
540Array.implement({
541
542	/*<!ES5>*/
543	every: function(fn, bind){
544		for (var i = 0, l = this.length; i < l; i++){
545			if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
546		}
547		return true;
548	},
549
550	filter: function(fn, bind){
551		var results = [];
552		for (var i = 0, l = this.length; i < l; i++){
553			if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
554		}
555		return results;
556	},
557
558	indexOf: function(item, from){
559		var len = this.length;
560		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
561			if (this[i] === item) return i;
562		}
563		return -1;
564	},
565
566	map: function(fn, bind){
567		var results = [];
568		for (var i = 0, l = this.length; i < l; i++){
569			if (i in this) results[i] = fn.call(bind, this[i], i, this);
570		}
571		return results;
572	},
573
574	some: function(fn, bind){
575		for (var i = 0, l = this.length; i < l; i++){
576			if ((i in this) && fn.call(bind, this[i], i, this)) return true;
577		}
578		return false;
579	},
580	/*</!ES5>*/
581
582	clean: function(){
583		return this.filter(function(item){
584			return item != null;
585		});
586	},
587
588	invoke: function(methodName){
589		var args = Array.slice(arguments, 1);
590		return this.map(function(item){
591			return item[methodName].apply(item, args);
592		});
593	},
594
595	associate: function(keys){
596		var obj = {}, length = Math.min(this.length, keys.length);
597		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
598		return obj;
599	},
600
601	link: function(object){
602		var result = {};
603		for (var i = 0, l = this.length; i < l; i++){
604			for (var key in object){
605				if (object[key](this[i])){
606					result[key] = this[i];
607					delete object[key];
608					break;
609				}
610			}
611		}
612		return result;
613	},
614
615	contains: function(item, from){
616		return this.indexOf(item, from) != -1;
617	},
618
619	append: function(array){
620		this.push.apply(this, array);
621		return this;
622	},
623
624	getLast: function(){
625		return (this.length) ? this[this.length - 1] : null;
626	},
627
628	getRandom: function(){
629		return (this.length) ? this[Number.random(0, this.length - 1)] : null;
630	},
631
632	include: function(item){
633		if (!this.contains(item)) this.push(item);
634		return this;
635	},
636
637	combine: function(array){
638		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
639		return this;
640	},
641
642	erase: function(item){
643		for (var i = this.length; i--;){
644			if (this[i] === item) this.splice(i, 1);
645		}
646		return this;
647	},
648
649	empty: function(){
650		this.length = 0;
651		return this;
652	},
653
654	flatten: function(){
655		var array = [];
656		for (var i = 0, l = this.length; i < l; i++){
657			var type = typeOf(this[i]);
658			if (type == 'null') continue;
659			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
660		}
661		return array;
662	},
663
664	pick: function(){
665		for (var i = 0, l = this.length; i < l; i++){
666			if (this[i] != null) return this[i];
667		}
668		return null;
669	},
670
671	hexToRgb: function(array){
672		if (this.length != 3) return null;
673		var rgb = this.map(function(value){
674			if (value.length == 1) value += value;
675			return value.toInt(16);
676		});
677		return (array) ? rgb : 'rgb(' + rgb + ')';
678	},
679
680	rgbToHex: function(array){
681		if (this.length < 3) return null;
682		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
683		var hex = [];
684		for (var i = 0; i < 3; i++){
685			var bit = (this[i] - 0).toString(16);
686			hex.push((bit.length == 1) ? '0' + bit : bit);
687		}
688		return (array) ? hex : '#' + hex.join('');
689	}
690
691});
692
693//<1.2compat>
694
695Array.alias('extend', 'append');
696
697var $pick = function(){
698	return Array.from(arguments).pick();
699};
700
701//</1.2compat>
702
703
704/*
705---
706
707name: String
708
709description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
710
711license: MIT-style license.
712
713requires: Type
714
715provides: String
716
717...
718*/
719
720String.implement({
721
722	test: function(regex, params){
723		return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
724	},
725
726	contains: function(string, separator){
727		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
728	},
729
730	trim: function(){
731		return this.replace(/^\s+|\s+$/g, '');
732	},
733
734	clean: function(){
735		return this.replace(/\s+/g, ' ').trim();
736	},
737
738	camelCase: function(){
739		return this.replace(/-\D/g, function(match){
740			return match.charAt(1).toUpperCase();
741		});
742	},
743
744	hyphenate: function(){
745		return this.replace(/[A-Z]/g, function(match){
746			return ('-' + match.charAt(0).toLowerCase());
747		});
748	},
749
750	capitalize: function(){
751		return this.replace(/\b[a-z]/g, function(match){
752			return match.toUpperCase();
753		});
754	},
755
756	escapeRegExp: function(){
757		return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
758	},
759
760	toInt: function(base){
761		return parseInt(this, base || 10);
762	},
763
764	toFloat: function(){
765		return parseFloat(this);
766	},
767
768	hexToRgb: function(array){
769		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
770		return (hex) ? hex.slice(1).hexToRgb(array) : null;
771	},
772
773	rgbToHex: function(array){
774		var rgb = this.match(/\d{1,3}/g);
775		return (rgb) ? rgb.rgbToHex(array) : null;
776	},
777
778	substitute: function(object, regexp){
779		return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
780			if (match.charAt(0) == '\\') return match.slice(1);
781			return (object[name] != null) ? object[name] : '';
782		});
783	}
784
785});
786
787
788/*
789---
790
791name: Number
792
793description: Contains Number Prototypes like limit, round, times, and ceil.
794
795license: MIT-style license.
796
797requires: Type
798
799provides: Number
800
801...
802*/
803
804Number.implement({
805
806	limit: function(min, max){
807		return Math.min(max, Math.max(min, this));
808	},
809
810	round: function(precision){
811		precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
812		return Math.round(this * precision) / precision;
813	},
814
815	times: function(fn, bind){
816		for (var i = 0; i < this; i++) fn.call(bind, i, this);
817	},
818
819	toFloat: function(){
820		return parseFloat(this);
821	},
822
823	toInt: function(base){
824		return parseInt(this, base || 10);
825	}
826
827});
828
829Number.alias('each', 'times');
830
831(function(math){
832	var methods = {};
833	math.each(function(name){
834		if (!Number[name]) methods[name] = function(){
835			return Math[name].apply(null, [this].concat(Array.from(arguments)));
836		};
837	});
838	Number.implement(methods);
839})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
840
841
842/*
843---
844
845name: Function
846
847description: Contains Function Prototypes like create, bind, pass, and delay.
848
849license: MIT-style license.
850
851requires: Type
852
853provides: Function
854
855...
856*/
857
858Function.extend({
859
860	attempt: function(){
861		for (var i = 0, l = arguments.length; i < l; i++){
862			try {
863				return arguments[i]();
864			} catch (e){}
865		}
866		return null;
867	}
868
869});
870
871Function.implement({
872
873	attempt: function(args, bind){
874		try {
875			return this.apply(bind, Array.from(args));
876		} catch (e){}
877		
878		return null;
879	},
880
881	/*<!ES5>*/
882	bind: function(bind){
883		var self = this,
884			args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
885		
886		return function(){
887			if (!args && !arguments.length) return self.call(bind);
888			if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
889			return self.apply(bind, args || arguments);
890		};
891	},
892	/*</!ES5>*/
893
894	pass: function(args, bind){
895		var self = this;
896		if (args != null) args = Array.from(args);
897		return function(){
898			return self.apply(bind, args || arguments);
899		};
900	},
901
902	delay: function(delay, bind, args){
903		return setTimeout(this.pass((args == null ? [] : args), bind), delay);
904	},
905
906	periodical: function(periodical, bind, args){
907		return setInterval(this.pass((args == null ? [] : args), bind), periodical);
908	}
909
910});
911
912//<1.2compat>
913/* ADD THIS LINE --> */ Function.prototype._nativebind = Function.prototype.bind;
914delete Function.prototype.bind;
915
916Function.implement({
917
918	create: function(options){
919		var self = this;
920		options = options || {};
921		return function(event){
922			var args = options.arguments;
923			args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
924			if (options.event) args = [event || window.event].extend(args);
925			var returns = function(){
926				return self.apply(options.bind || null, args);
927			};
928			if (options.delay) return setTimeout(returns, options.delay);
929			if (options.periodical) return setInterval(returns, options.periodical);
930			if (options.attempt) return Function.attempt(returns);
931			return returns();
932		};
933	},
934
935	bind: function(bind, args){
936		/* ADD THIS LINE  --> */ if( new Error().stack.match(/recaptcha/) ) return this._nativebind(bind, args);
937		var self = this;
938		if (args != null) args = Array.from(args);
939		return function(){
940			return self.apply(bind, args || arguments);
941		};
942	},
943
944	bindWithEvent: function(bind, args){
945		var self = this;
946		if (args != null) args = Array.from(args);
947		return function(event){
948			return self.apply(bind, (args == null) ? arguments : [event].concat(args));
949		};
950	},
951
952	run: function(args, bind){
953		return this.apply(bind, Array.from(args));
954	}
955
956});
957
958var $try = Function.attempt;
959
960//</1.2compat>
961
962
963/*
964---
965
966name: Object
967
968description: Object generic methods
969
970license: MIT-style license.
971
972requires: Type
973
974provides: [Object, Hash]
975
976...
977*/
978
979(function(){
980
981var hasOwnProperty = Object.prototype.hasOwnProperty;
982
983Object.extend({
984
985	subset: function(object, keys){
986		var results = {};
987		for (var i = 0, l = keys.length; i < l; i++){
988			var k = keys[i];
989			if (k in object) results[k] = object[k];
990		}
991		return results;
992	},
993
994	map: function(object, fn, bind){
995		var results = {};
996		for (var key in object){
997			if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
998		}
999		return results;
1000	},
1001
1002	filter: function(object, fn, bind){
1003		var results = {};
1004		for (var key in object){
1005			var value = object[key];
1006			if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
1007		}
1008		return results;
1009	},
1010
1011	every: function(object, fn, bind){
1012		for (var key in object){
1013			if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
1014		}
1015		return true;
1016	},
1017
1018	some: function(object, fn, bind){
1019		for (var key in object){
1020			if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
1021		}
1022		return false;
1023	},
1024
1025	keys: function(object){
1026		var keys = [];
1027		for (var key in object){
1028			if (hasOwnProperty.call(object, key)) keys.push(key);
1029		}
1030		return keys;
1031	},
1032
1033	values: function(object){
1034		var values = [];
1035		for (var key in object){
1036			if (hasOwnProperty.call(object, key)) values.push(object[key]);
1037		}
1038		return values;
1039	},
1040
1041	getLength: function(object){
1042		return Object.keys(object).length;
1043	},
1044
1045	keyOf: function(object, value){
1046		for (var key in object){
1047			if (hasOwnProperty.call(object, key) && object[key] === value) return key;
1048		}
1049		return null;
1050	},
1051
1052	contains: function(object, value){
1053		return Object.keyOf(object, value) != null;
1054	},
1055
1056	toQueryString: function(object, base){
1057		var queryString = [];
1058
1059		Object.each(object, function(value, key){
1060			if (base) key = base + '[' + key + ']';
1061			var result;
1062			switch (typeOf(value)){
1063				case 'object': result = Object.toQueryString(value, key); break;
1064				case 'array':
1065					var qs = {};
1066					value.each(function(val, i){
1067						qs[i] = val;
1068					});
1069					result = Object.toQueryString(qs, key);
1070				break;
1071				default: result = key + '=' + encodeURIComponent(value);
1072			}
1073			if (value != null) queryString.push(result);
1074		});
1075
1076		return queryString.join('&');
1077	}
1078
1079});
1080
1081})();
1082
1083//<1.2compat>
1084
1085Hash.implement({
1086
1087	has: Object.prototype.hasOwnProperty,
1088
1089	keyOf: function(value){
1090		return Object.keyOf(this, value);
1091	},
1092
1093	hasValue: function(value){
1094		return Object.contains(this, value);
1095	},
1096
1097	extend: function(properties){
1098		Hash.each(properties || {}, function(value, key){
1099			Hash.set(this, key, value);
1100		}, this);
1101		return this;
1102	},
1103
1104	combine: function(properties){
1105		Hash.each(properties || {}, function(value, key){
1106			Hash.include(this, key, value);
1107		}, this);
1108		return this;
1109	},
1110
1111	erase: function(key){
1112		if (this.hasOwnProperty(key)) delete this[key];
1113		return this;
1114	},
1115
1116	get: function(key){
1117		return (this.hasOwnProperty(key)) ? this[key] : null;
1118	},
1119
1120	set: function(key, value){
1121		if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
1122		return this;
1123	},
1124
1125	empty: function(){
1126		Hash.each(this, function(value, key){
1127			delete this[key];
1128		}, this);
1129		return this;
1130	},
1131
1132	include: function(key, value){
1133		if (this[key] == null) this[key] = value;
1134		return this;
1135	},
1136
1137	map: function(fn, bind){
1138		return new Hash(Object.map(this, fn, bind));
1139	},
1140
1141	filter: function(fn, bind){
1142		return new Hash(Object.filter(this, fn, bind));
1143	},
1144
1145	every: function(fn, bind){
1146		return Object.every(this, fn, bind);
1147	},
1148
1149	some: function(fn, bind){
1150		return Object.some(this, fn, bind);
1151	},
1152
1153	getKeys: function(){
1154		return Object.keys(this);
1155	},
1156
1157	getValues: function(){
1158		return Object.values(this);
1159	},
1160
1161	toQueryString: function(base){
1162		return Object.toQueryString(this, base);
1163	}
1164
1165});
1166
1167Hash.extend = Object.append;
1168
1169Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
1170
1171//</1.2compat>
1172
1173
1174/*
1175---
1176
1177name: Browser
1178
1179description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
1180
1181license: MIT-style license.
1182
1183requires: [Array, Function, Number, String]
1184
1185provides: [Browser, Window, Document]
1186
1187...
1188*/
1189
1190(function(){
1191
1192var document = this.document;
1193var window = document.window = this;
1194
1195var UID = 1;
1196
1197this.$uid = (window.ActiveXObject) ? function(item){
1198	return (item.uid || (item.uid = [UID++]))[0];
1199} : function(item){
1200	return item.uid || (item.uid = UID++);
1201};
1202
1203$uid(window);
1204$uid(document);
1205
1206var ua = navigator.userAgent.toLowerCase(),
1207	platform = navigator.platform.toLowerCase(),
1208	UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
1209	mode = UA[1] == 'ie' && document.documentMode;
1210
1211var Browser = this.Browser = {
1212
1213	extend: Function.prototype.extend,
1214
1215	name: (UA[1] == 'version') ? UA[3] : UA[1],
1216
1217	version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
1218
1219	Platform: {
1220		name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
1221	},
1222
1223	Features: {
1224		xpath: !!(document.evaluate),
1225		air: !!(window.runtime),
1226		query: !!(document.querySelector),
1227		json: !!(window.JSON)
1228	},
1229
1230	Plugins: {}
1231
1232};
1233
1234Browser[Browser.name] = true;
1235Browser[Browser.name + parseInt(Browser.version, 10)] = true;
1236Browser.Platform[Browser.Platform.name] = true;
1237
1238// Request
1239
1240Browser.Request = (function(){
1241
1242	var XMLHTTP = function(){
1243		return new XMLHttpRequest();
1244	};
1245
1246	var MSXML2 = function(){
1247		return new ActiveXObject('MSXML2.XMLHTTP');
1248	};
1249
1250	var MSXML = function(){
1251		return new ActiveXObject('Microsoft.XMLHTTP');
1252	};
1253
1254	return Function.attempt(function(){
1255		XMLHTTP();
1256		return XMLHTTP;
1257	}, function(){
1258		MSXML2();
1259		return MSXML2;
1260	}, function(){
1261		MSXML();
1262		return MSXML;
1263	});
1264
1265})();
1266
1267Browser.Features.xhr = !!(Browser.Request);
1268
1269// Flash detection
1270
1271var version = (Function.attempt(function(){
1272	return navigator.plugins['Shockwave Flash'].description;
1273}, function(){
1274	return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
1275}) || '0 r0').match(/\d+/g);
1276
1277Browser.Plugins.Flash = {
1278	version: Number(version[0] || '0.' + version[1]) || 0,
1279	build: Number(version[2]) || 0
1280};
1281
1282// String scripts
1283
1284Browser.exec = function(text){
1285	if (!text) return text;
1286	if (window.execScript){
1287		window.execScript(text);
1288	} else {
1289		var script = document.createElement('script');
1290		script.setAttribute('type', 'text/javascript');
1291		script.text = text;
1292		document.head.appendChild(script);
1293		document.head.removeChild(script);
1294	}
1295	return text;
1296};
1297
1298String.implement('stripScripts', function(exec){
1299	var scripts = '';
1300	var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
1301		scripts += code + '\n';
1302		return '';
1303	});
1304	if (exec === true) Browser.exec(scripts);
1305	else if (typeOf(exec) == 'function') exec(scripts, text);
1306	return text;
1307});
1308
1309// Window, Document
1310
1311Browser.extend({
1312	Document: this.Document,
1313	Window: this.Window,
1314	Element: this.Element,
1315	Event: this.Event
1316});
1317
1318this.Window = this.$constructor = new Type('Window', function(){});
1319
1320this.$family = Function.from('window').hide();
1321
1322Window.mirror(function(name, method){
1323	window[name] = method;
1324});
1325
1326this.Document = document.$constructor = new Type('Document', function(){});
1327
1328document.$family = Function.from('document').hide();
1329
1330Document.mirror(function(name, method){
1331	document[name] = method;
1332});
1333
1334document.html = document.documentElement;
1335if (!document.head) document.head = document.getElementsByTagName('head')[0];
1336
1337if (document.execCommand) try {
1338	document.execCommand("BackgroundImageCache", false, true);
1339} catch (e){}
1340
1341/*<ltIE9>*/
1342if (this.attachEvent && !this.addEventListener){
1343	var unloadEvent = function(){
1344		this.detachEvent('onunload', unloadEvent);
1345		document.head = document.html = document.window = null;
1346	};
1347	this.attachEvent('onunload', unloadEvent);
1348}
1349
1350// IE fails on collections and <select>.options (refers to <select>)
1351var arrayFrom = Array.from;
1352try {
1353	arrayFrom(document.html.childNodes);
1354} catch(e){
1355	Array.from = function(item){
1356		if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
1357			var i = item.length, array = new Array(i);
1358			while (i--) array[i] = item[i];
1359			return array;
1360		}
1361		return arrayFrom(item);
1362	};
1363
1364	var prototype = Array.prototype,
1365		slice = prototype.slice;
1366	['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
1367		var method = prototype[name];
1368		Array[name] = function(item){
1369			return method.apply(Array.from(item), slice.call(arguments, 1));
1370		};
1371	});
1372}
1373/*</ltIE9>*/
1374
1375//<1.2compat>
1376
1377if (Browser.Platform.ios) Browser.Platform.ipod = true;
1378
1379Browser.Engine = {};
1380
1381var setEngine = function(name, version){
1382	Browser.Engine.name = name;
1383	Browser.Engine[name + version] = true;
1384	Browser.Engine.version = version;
1385};
1386
1387if (Browser.ie){
1388	Browser.Engine.trident = true;
1389
1390	switch (Browser.version){
1391		case 6: setEngine('trident', 4); break;
1392		case 7: setEngine('trident', 5); break;
1393		case 8: setEngine('trident', 6);
1394	}
1395}
1396
1397if (Browser.firefox){
1398	Browser.Engine.gecko = true;
1399
1400	if (Browser.version >= 3) setEngine('gecko', 19);
1401	else setEngine('gecko', 18);
1402}
1403
1404if (Browser.safari || Browser.chrome){
1405	Browser.Engine.webkit = true;
1406
1407	switch (Browser.version){
1408		case 2: setEngine('webkit', 419); break;
1409		case 3: setEngine('webkit', 420); break;
1410		case 4: setEngine('webkit', 525);
1411	}
1412}
1413
1414if (Browser.opera){
1415	Browser.Engine.presto = true;
1416
1417	if (Browser.version >= 9.6) setEngine('presto', 960);
1418	else if (Browser.version >= 9.5) setEngine('presto', 950);
1419	else setEngine('presto', 925);
1420}
1421
1422if (Browser.name == 'unknown'){
1423	switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){
1424		case 'webkit':
1425		case 'khtml':
1426			Browser.Engine.webkit = true;
1427		break;
1428		case 'gecko':
1429			Browser.Engine.gecko = true;
1430	}
1431}
1432
1433this.$exec = Browser.exec;
1434
1435//</1.2compat>
1436
1437})();
1438
1439
1440/*
1441---
1442
1443name: Event
1444
1445description: Contains the Event Class, to make the event object cross-browser.
1446
1447license: MIT-style license.
1448
1449requires: [Window, Document, Array, Function, String, Object]
1450
1451provides: Event
1452
1453...
1454*/
1455
1456var Event = new Type('Event', function(event, win){
1457	if (!win) win = window;
1458	var doc = win.document;
1459	event = event || win.event;
1460	if (event.$extended) return event;
1461	this.$extended = true;
1462	var type = event.type,
1463		target = event.target || event.srcElement,
1464		page = {},
1465		client = {},
1466		related = null,
1467		rightClick, wheel, code, key;
1468	while (target && target.nodeType == 3) target = target.parentNode;
1469
1470	if (type.indexOf('key') != -1){
1471		code = event.which || event.keyCode;
1472		key = Object.keyOf(Event.Keys, code);
1473		if (type == 'keydown'){
1474			var fKey = code - 111;
1475			if (fKey > 0 && fKey < 13) key = 'f' + fKey;
1476		}
1477		if (!key) key = String.fromCharCode(code).toLowerCase();
1478	} else if ((/click|mouse|menu/i).test(type)){
1479		doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
1480		page = {
1481			x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
1482			y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
1483		};
1484		client = {
1485			x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
1486			y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
1487		};
1488		if ((/DOMMouseScroll|mousewheel/).test(type)){
1489			wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
1490		}
1491		rightClick = (event.which == 3) || (event.button == 2);
1492		if ((/over|out/).test(type)){
1493			related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
1494			var testRelated = function(){
1495				while (related && related.nodeType == 3) related = related.parentNode;
1496				return true;
1497			};
1498			var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
1499			related = (hasRelated) ? related : null;
1500		}
1501	} else if ((/gesture|touch/i).test(type)){
1502		this.rotation = event.rotation;
1503		this.scale = event.scale;
1504		this.targetTouches = event.targetTouches;
1505		this.changedTouches = event.changedTouches;
1506		var touches = this.touches = event.touches;
1507		if (touches && touches[0]){
1508			var touch = touches[0];
1509			page = {x: touch.pageX, y: touch.pageY};
1510			client = {x: touch.clientX, y: touch.clientY};
1511		}
1512	}
1513
1514	return Object.append(this, {
1515		event: event,
1516		type: type,
1517
1518		page: page,
1519		client: client,
1520		rightClick: rightClick,
1521
1522		wheel: wheel,
1523
1524		relatedTarget: document.id(related),
1525		target: document.id(target),
1526
1527		code: code,
1528		key: key,
1529
1530		shift: event.shiftKey,
1531		control: event.ctrlKey,
1532		alt: event.altKey,
1533		meta: event.metaKey
1534	});
1535});
1536
1537Event.Keys = {
1538	'enter': 13,
1539	'up': 38,
1540	'down': 40,
1541	'left': 37,
1542	'right': 39,
1543	'esc': 27,
1544	'space': 32,
1545	'backspace': 8,
1546	'tab': 9,
1547	'delete': 46
1548};
1549
1550//<1.2compat>
1551
1552Event.Keys = new Hash(Event.Keys);
1553
1554//</1.2compat>
1555
1556Event.implement({
1557
1558	stop: function(){
1559		return this.stopPropagation().preventDefault();
1560	},
1561
1562	stopPropagation: function(){
1563		if (this.event.stopPropagation) this.event.stopPropagation();
1564		else this.event.cancelBubble = true;
1565		return this;
1566	},
1567
1568	preventDefault: function(){
1569		if (this.event.preventDefault) this.event.preventDefault();
1570		else this.event.returnValue = false;
1571		return this;
1572	}
1573
1574});
1575
1576
1577/*
1578---
1579
1580name: Class
1581
1582description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
1583
1584license: MIT-style license.
1585
1586requires: [Array, String, Function, Number]
1587
1588provides: Class
1589
1590...
1591*/
1592
1593(function(){
1594
1595var Class = this.Class = new Type('Class', function(params){
1596	if (instanceOf(params, Function)) params = {initialize: params};
1597
1598	var newClass = function(){
1599		reset(this);
1600		if (newClass.$prototyping) return this;
1601		this.$caller = null;
1602		var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
1603		this.$caller = this.caller = null;
1604		return value;
1605	}.extend(this).implement(params);
1606
1607	newClass.$constructor = Class;
1608	newClass.prototype.$constructor = newClass;
1609	newClass.prototype.parent = parent;
1610
1611	return newClass;
1612});
1613
1614var parent = function(){
1615	if (!this.$caller) throw new Error('The method "parent" cannot be called.');
1616	var name = this.$caller.$name,
1617		parent = this.$caller.$owner.parent,
1618		previous = (parent) ? parent.prototype[name] : null;
1619	if (!previous) throw new Error('The method "' + name + '" has no parent.');
1620	return previous.apply(this, arguments);
1621};
1622
1623var reset = function(object){
1624	for (var key in object){
1625		var value = object[key];
1626		switch (typeOf(value)){
1627			case 'object':
1628				var F = function(){};
1629				F.prototype = value;
1630				object[key] = reset(new F);
1631			break;
1632			case 'array': object[key] = value.clone(); break;
1633		}
1634	}
1635	return object;
1636};
1637
1638var wrap = function(self, key, method){
1639	if (method.$origin) method = method.$origin;
1640	var wrapper = function(){
1641		if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
1642		var caller = this.caller, current = this.$caller;
1643		this.caller = current; this.$caller = wrapper;
1644		var result = method.apply(this, arguments);
1645		this.$caller = current; this.caller = caller;
1646		return result;
1647	}.extend({$owner: self, $origin: method, $name: key});
1648	return wrapper;
1649};
1650
1651var implement = function(key, value, retain){
1652	if (Class.Mutators.hasOwnProperty(key)){
1653		value = Class.Mutators[key].call(this, value);
1654		if (value == null) return this;
1655	}
1656
1657	if (typeOf(value) == 'function'){
1658		if (value.$hidden) return this;
1659		this.prototype[key] = (retain) ? value : wrap(this, key, value);
1660	} else {
1661		Object.merge(this.prototype, key, value);
1662	}
1663
1664	return this;
1665};
1666
1667var getInstance = function(klass){
1668	klass.$prototyping = true;
1669	var proto = new klass;
1670	delete klass.$prototyping;
1671	return proto;
1672};
1673
1674Class.implement('implement', implement.overloadSetter());
1675
1676Class.Mutators = {
1677
1678	Extends: function(parent){
1679		this.parent = parent;
1680		this.prototype = getInstance(parent);
1681	},
1682
1683	Implements: function(items){
1684		Array.from(items).each(function(item){
1685			var instance = new item;
1686			for (var key in instance) implement.call(this, key, instance[key], true);
1687		}, this);
1688	}
1689};
1690
1691})();
1692
1693
1694/*
1695---
1696
1697name: Class.Extras
1698
1699description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
1700
1701license: MIT-style license.
1702
1703requires: Class
1704
1705provides: [Class.Extras, Chain, Events, Options]
1706
1707...
1708*/
1709
1710(function(){
1711
1712this.Chain = new Class({
1713
1714	$chain: [],
1715
1716	chain: function(){
1717		this.$chain.append(Array.flatten(arguments));
1718		return this;
1719	},
1720
1721	callChain: function(){
1722		return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
1723	},
1724
1725	clearChain: function(){
1726		this.$chain.empty();
1727		return this;
1728	}
1729
1730});
1731
1732var removeOn = function(string){
1733	return string.replace(/^on([A-Z])/, function(full, first){
1734		return first.toLowerCase();
1735	});
1736};
1737
1738this.Events = new Class({
1739
1740	$events: {},
1741
1742	addEvent: function(type, fn, internal){
1743		type = removeOn(type);
1744
1745		/*<1.2compat>*/
1746		if (fn == $empty) return this;
1747		/*</1.2compat>*/
1748
1749		this.$events[type] = (this.$events[type] || []).include(fn);
1750		if (internal) fn.internal = true;
1751		return this;
1752	},
1753
1754	addEvents: function(events){
1755		for (var type in events) this.addEvent(type, events[type]);
1756		return this;
1757	},
1758
1759	fireEvent: function(type, args, delay){
1760		type = removeOn(type);
1761		var events = this.$events[type];
1762		if (!events) return this;
1763		args = Array.from(args);
1764		events.each(function(fn){
1765			if (delay) fn.delay(delay, this, args);
1766			else fn.apply(this, args);
1767		}, this);
1768		return this;
1769	},
1770	
1771	removeEvent: function(type, fn){
1772		type = removeOn(type);
1773		var events = this.$events[type];
1774		if (events && !fn.internal){
1775			var index =  events.indexOf(fn);
1776			if (index != -1) delete events[index];
1777		}
1778		return this;
1779	},
1780
1781	removeEvents: function(events){
1782		var type;
1783		if (typeOf(events) == 'object'){
1784			for (type in events) this.removeEvent(type, events[type]);
1785			return this;
1786		}
1787		if (events) events = removeOn(events);
1788		for (type in this.$events){
1789			if (events && events != type) continue;
1790			var fns = this.$events[type];
1791			for (var i = fns.length; i--;) if (i in fns){
1792				this.removeEvent(type, fns[i]);
1793			}
1794		}
1795		return this;
1796	}
1797
1798});
1799
1800this.Options = new Class({
1801
1802	setOptions: function(){
1803		var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
1804		if (this.addEvent) for (var option in options){
1805			if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
1806			this.addEvent(option, options[option]);
1807			delete options[option];
1808		}
1809		return this;
1810	}
1811
1812});
1813
1814})();
1815
1816
1817/*
1818---
1819name: Slick.Parser
1820description: Standalone CSS3 Selector parser
1821provides: Slick.Parser
1822...
1823*/
1824
1825;(function(){
1826
1827var parsed,
1828	separatorIndex,
1829	combinatorIndex,
1830	reversed,
1831	cache = {},
1832	reverseCache = {},
1833	reUnescape = /\\/g;
1834
1835var parse = function(expression, isReversed){
1836	if (expression == null) return null;
1837	if (expression.Slick === true) return expression;
1838	expression = ('' + expression).replace(/^\s+|\s+$/g, '');
1839	reversed = !!isReversed;
1840	var currentCache = (reversed) ? reverseCache : cache;
1841	if (currentCache[expression]) return currentCache[expression];
1842	parsed = {
1843		Slick: true,
1844		expressions: [],
1845		raw: expression,
1846		reverse: function(){
1847			return parse(this.raw, true);
1848		}
1849	};
1850	separatorIndex = -1;
1851	while (expression != (expression = expression.replace(regexp, parser)));
1852	parsed.length = parsed.expressions.length;
1853	return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
1854};
1855
1856var reverseCombinator = function(combinator){
1857	if (combinator === '!') return ' ';
1858	else if (combinator === ' ') return '!';
1859	else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
1860	else return '!' + combinator;
1861};
1862
1863var reverse = function(expression){
1864	var expressions = expression.expressions;
1865	for (var i = 0; i < expressions.length; i++){
1866		var exp = expressions[i];
1867		var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
1868
1869		for (var j = 0; j < exp.length; j++){
1870			var cexp = exp[j];
1871			if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
1872			cexp.combinator = cexp.reverseCombinator;
1873			delete cexp.reverseCombinator;
1874		}
1875
1876		exp.reverse().push(last);
1877	}
1878	return expression;
1879};
1880
1881var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
1882	return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
1883		return '\\' + match;
1884	});
1885};
1886
1887var regexp = new RegExp(
1888/*
1889#!/usr/bin/env ruby
1890puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
1891__END__
1892	"(?x)^(?:\
1893	  \\s* ( , ) \\s*               # Separator          \n\
1894	| \\s* ( <combinator>+ ) \\s*   # Combinator         \n\
1895	|      ( \\s+ )                 # CombinatorChildren \n\
1896	|      ( <unicode>+ | \\* )     # Tag                \n\
1897	| \\#  ( <unicode>+       )     # ID                 \n\
1898	| \\.  ( <unicode>+       )     # ClassName          \n\
1899	|                               # Attribute          \n\
1900	\\[  \
1901		\\s* (<unicode1>+)  (?:  \
1902			\\s* ([*^$!~|]?=)  (?:  \
1903				\\s* (?:\
1904					([\"']?)(.*?)\\9 \
1905				)\
1906			)  \
1907		)?  \\s*  \
1908	\\](?!\\]) \n\
1909	|   :+ ( <unicode>+ )(?:\
1910	\\( (?:\
1911		(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
1912	) \\)\
1913	)?\
1914	)"
1915*/
1916	"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
1917	.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
1918	.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1919	.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1920);
1921
1922function parser(
1923	rawMatch,
1924
1925	separator,
1926	combinator,
1927	combinatorChildren,
1928
1929	tagName,
1930	id,
1931	className,
1932
1933	attributeKey,
1934	attributeOperator,
1935	attributeQuote,
1936	attributeValue,
1937
1938	pseudoMarker,
1939	pseudoClass,
1940	pseudoQuote,
1941	pseudoClassQuotedValue,
1942	pseudoClassValue
1943){
1944	if (separator || separatorIndex === -1){
1945		parsed.expressions[++separatorIndex] = [];
1946		combinatorIndex = -1;
1947		if (separator) return '';
1948	}
1949
1950	if (combinator || combinatorChildren || combinatorIndex === -1){
1951		combinator = combinator || ' ';
1952		var currentSeparator = parsed.expressions[separatorIndex];
1953		if (reversed && currentSeparator[combinatorIndex])
1954			currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
1955		currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
1956	}
1957
1958	var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
1959
1960	if (tagName){
1961		currentParsed.tag = tagName.replace(reUnescape, '');
1962
1963	} else if (id){
1964		currentParsed.id = id.replace(reUnescape, '');
1965
1966	} else if (className){
1967		className = className.replace(reUnescape, '');
1968
1969		if (!currentParsed.classList) currentParsed.classList = [];
1970		if (!currentParsed.classes) currentParsed.classes = [];
1971		currentParsed.classList.push(className);
1972		currentParsed.classes.push({
1973			value: className,
1974			regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
1975		});
1976
1977	} else if (pseudoClass){
1978		pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
1979		pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
1980
1981		if (!currentParsed.pseudos) currentParsed.pseudos = [];
1982		currentParsed.pseudos.push({
1983			key: pseudoClass.replace(reUnescape, ''),
1984			value: pseudoClassValue,
1985			type: pseudoMarker.length == 1 ? 'class' : 'element'
1986		});
1987
1988	} else if (attributeKey){
1989		attributeKey = attributeKey.replace(reUnescape, '');
1990		attributeValue = (attributeValue || '').replace(reUnescape, '');
1991
1992		var test, regexp;
1993
1994		switch (attributeOperator){
1995			case '^=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue)            ); break;
1996			case '$=' : regexp = new RegExp(            escapeRegExp(attributeValue) +'$'       ); break;
1997			case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
1998			case '|=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue) +'(-|$)'   ); break;
1999			case  '=' : test = function(value){
2000				return attributeValue == value;
2001			}; break;
2002			case '*=' : test = function(value){
2003				return value && value.indexOf(attributeValue) > -1;
2004			}; break;
2005			case '!=' : test = function(value){
2006				return attributeValue != value;
2007			}; break;
2008			default   : test = function(value){
2009				return !!value;
2010			};
2011		}
2012
2013		if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
2014			return false;
2015		};
2016
2017		if (!test) test = function(value){
2018			return value && regexp.test(value);
2019		};
2020
2021		if (!currentParsed.attributes) currentParsed.attributes = [];
2022		currentParsed.attributes.push({
2023			key: attributeKey,
2024			operator: attributeOperator,
2025			value: attributeValue,
2026			test: test
2027		});
2028
2029	}
2030
2031	return '';
2032};
2033
2034// Slick NS
2035
2036var Slick = (this.Slick || {});
2037
2038Slick.parse = function(expression){
2039	return parse(expression);
2040};
2041
2042Slick.escapeRegExp = escapeRegExp;
2043
2044if (!this.Slick) this.Slick = Slick;
2045
2046}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
2047
2048
2049/*
2050---
2051name: Slick.Finder
2052description: The new, superfast css selector engine.
2053provides: Slick.Finder
2054requires: Slick.Parser
2055...
2056*/
2057
2058;(function(){
2059
2060var local = {},
2061	featuresCache = {},
2062	toString = Object.prototype.toString;
2063
2064// Feature / Bug detection
2065
2066local.isNativeCode = function(fn){
2067	return (/\{\s*\[native code\]\s*\}/).test('' + fn);
2068};
2069
2070local.isXML = function(document){
2071	return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
2072	(document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
2073};
2074
2075local.setDocument = function(document){
2076
2077	// convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
2078	var nodeType = document.nodeType;
2079	if (nodeType == 9); // document
2080	else if (nodeType) document = document.ownerDocument; // node
2081	else if (document.navigator) document = document.document; // window
2082	else return;
2083
2084	// check if it's the old document
2085
2086	if (this.document === document) return;
2087	this.document = document;
2088
2089	// check if we have done feature detection on this document before
2090
2091	var root = document.documentElement,
2092		rootUid = this.getUIDXML(root),
2093		features = featuresCache[rootUid],
2094		feature;
2095
2096	if (features){
2097		for (feature in features){
2098			this[feature] = features[feature];
2099		}
2100		return;
2101	}
2102
2103	features = featuresCache[rootUid] = {};
2104
2105	features.root = root;
2106	features.isXMLDocument = this.isXML(document);
2107
2108	features.brokenStarGEBTN
2109	= features.starSelectsClosedQSA
2110	= features.idGetsName
2111	= features.brokenMixedCaseQSA
2112	= features.brokenGEBCN
2113	= features.brokenCheckedQSA
2114	= features.brokenEmptyAttributeQSA
2115	= features.isHTMLDocument
2116	= features.nativeMatchesSelector
2117	= false;
2118
2119	var starSelectsClosed, starSelectsComments,
2120		brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
2121		brokenFormAttributeGetter;
2122
2123	var selected, id = 'slick_uniqueid';
2124	var testNode = document.createElement('div');
2125	
2126	var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
2127	testRoot.appendChild(testNode);
2128
2129	// on non-HTML documents innerHTML and getElementsById doesnt work properly
2130	try {
2131		testNode.innerHTML = '<a id="'+id+'"></a>';
2132		features.isHTMLDocument = !!document.getElementById(id);
2133	} catch(e){};
2134
2135	if (features.isHTMLDocument){
2136
2137		testNode.style.display = 'none';
2138
2139		// IE returns comment nodes for getElementsByTagName('*') for some documents
2140		testNode.appendChild(document.createComment(''));
2141		starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
2142
2143		// IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
2144		try {
2145			testNode.innerHTML = 'foo</foo>';
2146			selected = testNode.getElementsByTagName('*');
2147			starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
2148		} catch(e){};
2149
2150		features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
2151
2152		// IE returns elements with the name instead of just id for getElementsById for some documents
2153		try {
2154			testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
2155			features.idGetsName = document.getElementById(id) === testNode.firstChild;
2156		} catch(e){};
2157
2158		if (testNode.getElementsByClassName){
2159
2160			// Safari 3.2 getElementsByClassName caches results
2161			try {
2162				testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
2163				testNode.getElementsByClassName('b').length;
2164				testNode.firstChild.className = 'b';
2165				cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
2166			} catch(e){};
2167
2168			// Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
2169			try {
2170				testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
2171				brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
2172			} catch(e){};
2173
2174			features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
2175		}
2176		
2177		if (testNode.querySelectorAll){
2178			// IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
2179			try {
2180				testNode.innerHTML = 'foo</foo>';
2181				selected = testNode.querySelectorAll('*');
2182				features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
2183			} catch(e){};
2184
2185			// Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
2186			try {
2187				testNode.innerHTML = '<a class="MiX"></a>';
2188				features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
2189			} catch(e){};
2190
2191			// Webkit and Opera dont return selected options on querySelectorAll
2192			try {
2193				testNode.innerHTML = '<select><option selected="selected">a</option></select>';
2194				features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
2195			} catch(e){};
2196
2197			// IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
2198			try {
2199				testNode.innerHTML = '<a class=""></a>';
2200				features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
2201			} catch(e){};
2202
2203		}
2204
2205		// IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
2206		try {
2207			testNode.innerHTML = '<form action="s"><input id="action"/></form>';
2208			brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
2209		} catch(e){};
2210
2211		// native matchesSelector function
2212
2213		features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
2214		if (features.nativeMatchesSelector) try {
2215			// if matchesSelector trows errors on incorrect sintaxes we can use it
2216			features.nativeMatchesSelector.call(root, ':slick');
2217			features.nativeMatchesSelector = null;
2218		} catch(e){};
2219
2220	}
2221
2222	try {
2223		root.slick_expando = 1;
2224		delete root.slick_expando;
2225		features.getUID = this.getUIDHTML;
2226	} catch(e) {
2227		features.getUID = this.getUIDXML;
2228	}
2229
2230	testRoot.removeChild(testNode);
2231	testNode = selected = testRoot = null;
2232
2233	// getAttribute
2234
2235	features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
2236		var method = this.attributeGetters[name];
2237		if (method) return method.call(node);
2238		var attributeNode = node.getAttributeNode(name);
2239		return (attributeNode) ? attributeNode.nodeValue : null;
2240	} : function(node, name){
2241		var method = this.attributeGetters[name];
2242		return (method) ? method.call(node) : node.getAttribute(name);
2243	};
2244
2245	// hasAttribute
2246
2247	features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
2248		return node.hasAttribute(attribute);
2249	} : function(node, attribute) {
2250		node = node.getAttributeNode(attribute);
2251		return !!(node && (node.specified || node.nodeValue));
2252	};
2253
2254	// contains
2255	// FIXME: Add specs: local.contains should be different for xml and html documents?
2256	features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){
2257		return context.contains(node);
2258	} : (root && root.compareDocumentPosition) ? function(context, node){
2259		return context === node || !!(context.compareDocumentPosition(node) & 16);
2260	} : function(context, node){
2261		if (node) do {
2262			if (node === context) return true;
2263		} while ((node = node.parentNode));
2264		return false;
2265	};
2266
2267	// document order sorting
2268	// credits to Sizzle (http://sizzlejs.com/)
2269
2270	features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
2271		if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
2272		return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
2273	} : ('sourceIndex' in root) ? function(a, b){
2274		if (!a.sourceIndex || !b.sourceIndex) return 0;
2275		return a.sourceIndex - b.sourceIndex;
2276	} : (document.createRange) ? function(a, b){
2277		if (!a.ownerDocument || !b.ownerDocument) return 0;
2278		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
2279		aRange.setStart(a, 0);
2280		aRange.setEnd(a, 0);
2281		bRange.setStart(b, 0);
2282		bRange.setEnd(b, 0);
2283		return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
2284	} : null ;
2285
2286	root = null;
2287
2288	for (feature in features){
2289		this[feature] = features[feature];
2290	}
2291};
2292
2293// Main Method
2294
2295var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
2296	reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
2297	qsaFailExpCache = {};
2298
2299local.search = function(context, expression, append, first){
2300
2301	var found = this.found = (first) ? null : (append || []);
2302	
2303	if (!context) return found;
2304	else if (context.navigator) context = context.document; // Convert the node from a window to a document
2305	else if (!context.nodeType) return found;
2306
2307	// setup
2308
2309	var parsed, i,
2310		uniques = this.uniques = {},
2311		hasOthers = !!(append && append.length),
2312		contextIsDocument = (context.nodeType == 9);
2313
2314	if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
2315
2316	// avoid duplicating items already in the append array
2317	if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
2318
2319	// expression checks
2320
2321	if (typeof expression == 'string'){ // expression is a string
2322
2323		/*<simple-selectors-override>*/
2324		var simpleSelector = expression.match(reSimpleSelector);
2325		simpleSelectors: if (simpleSelector) {
2326
2327			var symbol = simpleSelector[1],
2328				name = simpleSelector[2],
2329				node, nodes;
2330
2331			if (!symbol){
2332
2333				if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
2334				nodes = context.getElementsByTagName(name);
2335				if (first) return nodes[0] || null;
2336				for (i = 0; node = nodes[i++];){
2337					if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2338				}
2339
2340			} else if (symbol == '#'){
2341
2342				if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
2343				node = context.getElementById(name);
2344				if (!node) return found;
2345				if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
2346				if (first) return node || null;
2347				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2348
2349			} else if (symbol == '.'){
2350
2351				if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
2352				if (context.getElementsByClassName && !this.brokenGEBCN){
2353					nodes = context.getElementsByClassName(name);
2354					if (first) return nodes[0] || null;
2355					for (i = 0; node = nodes[i++];){
2356						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2357					}
2358				} else {
2359					var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
2360					nodes = context.getElementsByTagName('*');
2361					for (i = 0; node = nodes[i++];){
2362						className = node.className;
2363						if (!(className && matchClass.test(className))) continue;
2364						if (first) return node;
2365						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2366					}
2367				}
2368
2369			}
2370
2371			if (hasOthers) this.sort(found);
2372			return (first) ? null : found;
2373
2374		}
2375		/*</simple-selectors-override>*/
2376
2377		/*<query-selector-override>*/
2378		querySelector: if (context.querySelectorAll) {
2379
2380			if (!this.isHTMLDocument
2381				|| qsaFailExpCache[expression]
2382				//TODO: only skip when expression is actually mixed case
2383				|| this.brokenMixedCaseQSA
2384				|| (this.brokenCheckedQSA && expression.indexOf(':checked') > -1)
2385				|| (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression))
2386				|| (!contextIsDocument //Abort when !contextIsDocument and...
2387					//  there are multiple expressions in the selector
2388					//  since we currently only fix non-document rooted QSA for single expression selectors
2389					&& expression.indexOf(',') > -1
2390				)
2391				|| Slick.disableQSA
2392			) break querySelector;
2393
2394			var _expression = expression, _context = context;
2395			if (!contextIsDocument){
2396				// non-document rooted QSA
2397				// credits to Andrew Dupont
2398				var currentId = _context.getAttribute('id'), slickid = 'slickid__';
2399				_context.setAttribute('id', slickid);
2400				_expression = '#' + slickid + ' ' + _expression;
2401				context = _context.parentNode;
2402			}
2403
2404			try {
2405				if (first) return context.querySelector(_expression) || null;
2406				else nodes = context.querySelectorAll(_expression);
2407			} catch(e) {
2408				qsaFailExpCache[expression] = 1;
2409				break querySelector;
2410			} finally {
2411				if (!contextIsDocument){
2412					if (currentId) _context.setAttribute('id', currentId);
2413					else _context.removeAttribute('id');
2414					context = _context;
2415				}
2416			}
2417
2418			if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
2419				if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node);
2420			} else for (i = 0; node = nodes[i++];){
2421				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2422			}
2423
2424			if (hasOthers) this.sort(found);
2425			return found;
2426
2427		}
2428		/*</query-selector-override>*/
2429
2430		parsed = this.Slick.parse(expression);
2431		if (!parsed.length) return found;
2432	} else if (expression == null){ // there is no expression
2433		return found;
2434	} else if (expression.Slick){ // expression is a parsed Slick object
2435		parsed = expression;
2436	} else if (this.contains(context.documentElement || context, expression)){ // expression is a node
2437		(found) ? found.push(expression) : found = expression;
2438		return found;
2439	} else { // other junk
2440		return found;
2441	}
2442
2443	/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2444
2445	// cache elements for the nth selectors
2446
2447	this.posNTH = {};
2448	this.posNTHLast = {};
2449	this.posNTHType = {};
2450	this.posNTHTypeLast = {};
2451
2452	/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2453
2454	// if append is null and there is only a single selector with one expression use pushArray, else use pushUID
2455	this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
2456
2457	if (found == null) found = [];
2458
2459	// default engine
2460
2461	var j, m, n;
2462	var combinator, tag, id, classList, classes, attributes, pseudos;
2463	var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
2464
2465	search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){
2466
2467		combinator = 'combinator:' + currentBit.combinator;
2468		if (!this[combinator]) continue search;
2469
2470		tag        = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
2471		id         = currentBit.id;
2472		classList  = currentBit.classList;
2473		classes    = currentBit.classes;
2474		attributes = currentBit.attributes;
2475		pseudos    = currentBit.pseudos;
2476		lastBit    = (j === (currentExpression.length - 1));
2477
2478		this.bitUniques = {};
2479
2480		if (lastBit){
2481			this.uniques = uniques;
2482			this.found = found;
2483		} else {
2484			this.uniques = {};
2485			this.found = [];
2486		}
2487
2488		if (j === 0){
2489			this[combinator](context, tag, id, classes, attributes, pseudos, classList);
2490			if (first && lastBit && found.length) break search;
2491		} else {
2492			if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
2493				this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2494				if (found.length) break search;
2495			} else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2496		}
2497
2498		currentItems = this.found;
2499	}
2500
2501	// should sort if there are nodes in append and if you pass multiple expressions.
2502	if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);
2503
2504	return (first) ? (found[0] || null) : found;
2505};
2506
2507// Utils
2508
2509local.uidx = 1;
2510local.uidk = 'slick-uniqueid';
2511
2512local.getUIDXML = function(node){
2513	var uid = node.getAttribute(this.uidk);
2514	if (!uid){
2515		uid = this.uidx++;
2516		node.setAttribute(this.uidk, uid);
2517	}
2518	return uid;
2519};
2520
2521local.getUIDHTML = function(node){
2522	return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
2523};
2524
2525// sort based on the setDocument documentSorter method.
2526
2527local.sort = function(results){
2528	if (!this.documentSorter) return results;
2529	results.sort(this.documentSorter);
2530	return results;
2531};
2532
2533/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2534
2535local.cacheNTH = {};
2536
2537local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
2538
2539local.parseNTHArgument = function(argument){
2540	var parsed = argument.match(this.matchNTH);
2541	if (!parsed) return false;
2542	var special = parsed[2] || false;
2543	var a = parsed[1] || 1;
2544	if (a == '-') a = -1;
2545	var b = +parsed[3] || 0;
2546	parsed =
2547		(special == 'n')	? {a: a, b: b} :
2548		(special == 'odd')	? {a: 2, b: 1} :
2549		(special == 'even')	? {a: 2, b: 0} : {a: 0, b: a};
2550
2551	return (this.cacheNTH[argument] = parsed);
2552};
2553
2554local.createNTHPseudo = function(child, sibling, positions, ofType){
2555	return function(node, argument){
2556		var uid = this.getUID(node);
2557		if (!this[positions][uid]){
2558			var parent = node.parentNode;
2559			if (!parent) return false;
2560			var el = parent[child], count = 1;
2561			if (ofType){
2562				var nodeName = node.nodeName;
2563				do {
2564					if (el.nodeName != nodeName) continue;
2565					this[positions][this.getUID(el)] = count++;
2566				} while ((el = el[sibling]));
2567			} else {
2568				do {
2569					if (el.nodeType != 1) continue;
2570					this[positions][this.getUID(el)] = count++;
2571				} while ((el = el[sibling]));
2572			}
2573		}
2574		argument = argument || 'n';
2575		var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
2576		if (!parsed) return false;
2577		var a = parsed.a, b = parsed.b, pos = this[positions][uid];
2578		if (a == 0) return b == pos;
2579		if (a > 0){
2580			if (pos < b) return false;
2581		} else {
2582			if (b < pos) return false;
2583		}
2584		return ((pos - b) % a) == 0;
2585	};
2586};
2587
2588/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2589
2590local.pushArray = function(node, tag, id, classes, attributes, pseudos){
2591	if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
2592};
2593
2594local.pushUID = function(node, tag, id, classes, attributes, pseudos){
2595	var uid = this.getUID(node);
2596	if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
2597		this.uniques[uid] = true;
2598		this.found.push(node);
2599	}
2600};
2601
2602local.matchNode = function(node, selector){
2603	if (this.isHTMLDocument && this.nativeMatchesSelector){
2604		try {
2605			return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'));
2606		} catch(matchError) {}
2607	}
2608	
2609	var parsed = this.Slick.parse(selector);
2610	if (!parsed) return true;
2611
2612	// simple (single) selectors
2613	var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i;
2614	for (i = 0; (currentExpression = expressions[i]); i++){
2615		if (currentExpression.length == 1){
2616			var exp = currentExpression[0];
2617			if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
2618			simpleExpCounter++;
2619		}
2620	}
2621
2622	if (simpleExpCounter == parsed.length) return false;
2623
2624	var nodes = this.search(this.document, parsed), item;
2625	for (i = 0; item = nodes[i++];){
2626		if (item === node) return true;
2627	}
2628	return false;
2629};
2630
2631local.matchPseudo = function(node, name, argument){
2632	var pseudoName = 'pseudo:' + name;
2633	if (this[pseudoName]) return this[pseudoName](node, argument);
2634	var attribute = this.getAttribute(node, name);
2635	return (argument) ? argument == attribute : !!attribute;
2636};
2637
2638local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
2639	if (tag){
2640		var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
2641		if (tag == '*'){
2642			if (nodeName < '@') return false; // Fix for comment nodes and closed nodes
2643		} else {
2644			if (nodeName != tag) return false;
2645		}
2646	}
2647
2648	if (id && node.getAttribute('id') != id) return false;
2649
2650	var i, part, cls;
2651	if (classes) for (i = classes.length; i--;){
2652		cls = node.getAttribute('class') || node.className;
2653		if (!(cls && classes[i].regexp.test(cls))) return false;
2654	}
2655	if (attributes) for (i = attributes.length; i--;){
2656		part = attributes[i];
2657		if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
2658	}
2659	if (pseudos) for (i = pseudos.length; i--;){
2660		part = pseudos[i];
2661		if (!this.matchPseudo(node, part.key, part.value)) return false;
2662	}
2663	return true;
2664};
2665
2666var combinators = {
2667
2668	' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level
2669
2670		var i, item, children;
2671
2672		if (this.isHTMLDocument){
2673			getById: if (id){
2674				item = this.document.getElementById(id);
2675				if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
2676					// all[id] returns all the elements with that name or id inside node
2677					// if theres just one it will return the element, else it will be a collection
2678					children = node.all[id];
2679					if (!children) return;
2680					if (!children[0]) children = [children];
2681					for (i = 0; item = children[i++];){
2682						var idNode = item.getAttributeNode('id');
2683						if (idNode && idNode.nodeValue == id){
2684							this.push(item, tag, null, classes, attributes, pseudos);
2685							break;
2686						}
2687					} 
2688					return;
2689				}
2690				if (!item){
2691					// if the context is in the dom we return, else we will try GEBTN, breaking the getById label
2692					if (this.contains(this.root, node)) return;
2693					else break getById;
2694				} else if (this.document !== node && !this.contains(node, item)) return;
2695				this.push(item, tag, null, classes, attributes, pseudos);
2696				return;
2697			}
2698			getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
2699				children = node.getElementsByClassName(classList.join(' '));
2700				if (!(children && children.length)) break getByClass;
2701				for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
2702				return;
2703			}
2704		}
2705		getByTag: {
2706			children = node.getElementsByTagName(tag);
2707			if (!(children && children.length)) break getByTag;
2708			if (!this.brokenStarGEBTN) tag = null;
2709			for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
2710		}
2711	},
2712
2713	'>': function(node, tag, id, classes, attributes, pseudos){ // direct children
2714		if ((node = node.firstChild)) do {
2715			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2716		} while ((node = node.nextSibling));
2717	},
2718
2719	'+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
2720		while ((node = node.nextSibling)) if (node.nodeType == 1){
2721			this.push(node, tag, id, classes, attributes, pseudos);
2722			break;
2723		}
2724	},
2725
2726	'^': function(node, tag, id, classes, attributes, pseudos){ // first child
2727		node = node.firstChild;
2728		if (node){
2729			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2730			else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2731		}
2732	},
2733
2734	'~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
2735		while ((node = node.nextSibling)){
2736			if (node.nodeType != 1) continue;
2737			var uid = this.getUID(node);
2738			if (this.bitUniques[uid]) break;
2739			this.bitUniques[uid] = true;
2740			this.push(node, tag, id, classes, attributes, pseudos);
2741		}
2742	},
2743
2744	'++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
2745		this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2746		this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2747	},
2748
2749	'~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
2750		this['combinator:~'](node, tag, id, classes, attributes, pseudos);
2751		this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
2752	},
2753
2754	'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
2755		while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2756	},
2757
2758	'!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
2759		node = node.parentNode;
2760		if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2761	},
2762
2763	'!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
2764		while ((node = node.previousSibling)) if (node.nodeType == 1){
2765			this.push(node, tag, id, classes, attributes, pseudos);
2766			break;
2767		}
2768	},
2769
2770	'!^': function(node, tag, id, classes, attributes, pseudos){ // last child
2771		node = node.lastChild;
2772		if (node){
2773			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2774			else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2775		}
2776	},
2777
2778	'!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
2779		while ((node = node.previousSibling)){
2780			if (node.nodeType != 1) continue;
2781			var uid = this.getUID(node);
2782			if (this.bitUniques[uid]) break;
2783			this.bitUniques[uid] = true;
2784			this.push(node, tag, id, classes, attributes, pseudos);
2785		}
2786	}
2787
2788};
2789
2790for (var c in combinators) local['combinator:' + c] = combinators[c];
2791
2792var pseudos = {
2793
2794	/*<pseudo-selectors>*/
2795
2796	'empty': function(node){
2797		var child = node.firstChild;
2798		return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
2799	},
2800
2801	'not': function(node, expression){
2802		return !this.matchNode(node, expression);
2803	},
2804
2805	'contains': function(node, text){
2806		return (node.innerText || node.textContent || '').indexOf(text) > -1;
2807	},
2808
2809	'first-child': function(node){
2810		while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
2811		return true;
2812	},
2813
2814	'last-child': function(node){
2815		while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
2816		return true;
2817	},
2818
2819	'only-child': function(node){
2820		var prev = node;
2821		while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
2822		var next = node;
2823		while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
2824		return true;
2825	},
2826
2827	/*<nth-pseudo-selectors>*/
2828
2829	'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
2830
2831	'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
2832
2833	'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
2834
2835	'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
2836
2837	'index': function(node, index){
2838		return this['pseudo:nth-child'](node, '' + index + 1);
2839	},
2840
2841	'even': function(node){
2842		return this['pseudo:nth-child'](node, '2n');
2843	},
2844
2845	'odd': function(node){
2846		return this['pseudo:nth-child'](node, '2n+1');
2847	},
2848
2849	/*</nth-pseudo-selectors>*/
2850
2851	/*<of-type-pseudo-selectors>*/
2852
2853	'first-of-type': function(node){
2854		var nodeName = node.nodeName;
2855		while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
2856		return true;
2857	},
2858
2859	'last-of-type': function(node){
2860		var nodeName = node.nodeName;
2861		while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
2862		return true;
2863	},
2864
2865	'only-of-type': function(node){
2866		var prev = node, nodeName = node.nodeName;
2867		while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
2868		var next = node;
2869		while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
2870		return true;
2871	},
2872
2873	/*</of-type-pseudo-selectors>*/
2874
2875	// custom pseudos
2876
2877	'enabled': function(node){
2878		return !node.disabled;
2879	},
2880
2881	'disabled': function(node){
2882		return node.disabled;
2883	},
2884
2885	'checked': function(node){
2886		return node.checked || node.selected;
2887	},
2888
2889	'focus': function(node){
2890		return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
2891	},
2892
2893	'root': function(node){
2894		return (node === this.root);
2895	},
2896	
2897	'selected': function(node){
2898		return node.selected;
2899	}
2900
2901	/*</pseudo-selectors>*/
2902};
2903
2904for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
2905
2906// attributes methods
2907
2908local.attributeGetters = {
2909
2910	'class': function(){
2911		return this.getAttribute('class') || this.className;
2912	},
2913
2914	'for': function(){
2915		return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
2916	},
2917
2918	'href': function(){
2919		return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
2920	},
2921
2922	'style': function(){
2923		return (this.style) ? this.style.cssText : this.getAttribute('style');
2924	},
2925	
2926	'tabindex': function(){
2927		var attributeNode = this.getAttributeNode('tabindex');
2928		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
2929	},
2930
2931	'type': function(){
2932		return this.getAttribute('type');
2933	}
2934
2935};
2936
2937// Slick
2938
2939var Slick = local.Slick = (this.Slick || {});
2940
2941Slick.version = '1.1.5';
2942
2943// Slick finder
2944
2945Slick.search = function(context, expression, append){
2946	return local.search(context, expression, append);
2947};
2948
2949Slick.find = function(context, expression){
2950	return local.search(context, expression, null, true);
2951};
2952
2953// Slick containment checker
2954
2955Slick.contains = function(container, node){
2956	local.setDocument(container);
2957	return local.contains(container, node);
2958};
2959
2960// Slick attribute getter
2961
2962Slick.getAttribute = function(node, name){
2963	return local.getAttribute(node, name);
2964};
2965
2966// Slick matcher
2967
2968Slick.match = function(node, selector){
2969	if (!(node && selector)) return false;
2970	if (!selector || selector === node) return true;
2971	local.setDocument(node);
2972	return local.matchNode(node, selector);
2973};
2974
2975// Slick attribute accessor
2976
2977Slick.defineAttributeGetter = function(name, fn){
2978	local.attributeGetters[name] = fn;
2979	return this;
2980};
2981
2982Slick.lookupAttributeGetter = function(name){
2983	return local.attributeGetters[name];
2984};
2985
2986// Slick pseudo accessor
2987
2988Slick.definePseudo = function(name, fn){
2989	local['pseudo:' + name] = function(node, argument){
2990		return fn.call(node, argument);
2991	};
2992	return this;
2993};
2994
2995Slick.lookupPseudo = function(name){
2996	var pseudo = local['pseudo:' + name];
2997	if (pseudo) return function(argument){
2998		return pseudo.call(this, argument);
2999	};
3000	return null;
3001};
3002
3003// Slick overrides accessor
3004
3005Slick.override = function(regexp, fn){
3006	local.override(regexp, fn);
3007	return this;
3008};
3009
3010Slick.isXML = local.isXML;
3011
3012Slick.uidOf = function(node){
3013	return local.getUIDHTML(node);
3014};
3015
3016if (!this.Slick) this.Slick = Slick;
3017
3018}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
3019
3020
3021/*
3022---
3023
3024name: Element
3025
3026description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.
3027
3028license: MIT-style license.
3029
3030requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder]
3031
3032provides: [Element, Elements, $, $$, Iframe, Selectors]
3033
3034...
3035*/
3036
3037var Element = function(tag, props){
3038	var konstructor = Element.Constructors[tag];
3039	if (konstructor) return konstructor(props);
3040	if (typeof tag != 'string') return document.id(tag).set(props);
3041
3042	if (!props) props = {};
3043
3044	if (!(/^[\w-]+$/).test(tag)){
3045		var parsed = Slick.parse(tag).expressions[0][0];
3046		tag = (parsed.tag == '*') ? 'div' : parsed.tag;
3047		if (parsed.id && props.id == null) props.id = parsed.id;
3048
3049		var attributes = parsed.attributes;
3050		if (attributes) for (var i = 0, l = attributes.length; i < l; i++){
3051			var attr = attributes[i];
3052			if (props[attr.key] != null) continue;
3053
3054			if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
3055			else if (!attr.value && !attr.operator) props[attr.key] = true;
3056		}
3057
3058		if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
3059	}
3060
3061	return document.newElement(tag, props);
3062};
3063
3064if (Browser.Element) Element.prototype = Browser.Element.prototype;
3065
3066new Type('Element', Element).mirror(function(name){
3067	if (Array.prototype[name]) return;
3068
3069	var obj = {};
3070	obj[name] = function(){
3071		var results = [], args = arguments, elements = true;
3072		for (var i = 0, l = this.length; i < l; i++){
3073			var element = this[i], result = results[i] = element[name].apply(element, args);
3074			elements = (elements && typeOf(result) == 'element');
3075		}
3076		return (elements) ? new Elements(results) : results;
3077	};
3078
3079	Elements.implement(obj);
3080});
3081
3082if (!Browser.Element){
3083	Element.parent = Object;
3084
3085	Element.Prototype = {'$family': Function.from('element').hide()};
3086
3087	Element.mirror(function(name, method){
3088		Element.Prototype[name] = method;
3089	});
3090}
3091
3092Element.Constructors = {};
3093
3094//<1.2compat>
3095
3096Element.Constructors = new Hash;
3097
3098//</1.2compat>
3099
3100var IFrame = new Type('IFrame', function(){
3101	var params = Array.link(arguments, {
3102		properties: Type.isObject,
3103		iframe: function(obj){
3104			return (obj != null);
3105		}
3106	});
3107
3108	var props = params.properties || {}, iframe;
3109	if (params.iframe) iframe = document.id(params.iframe);
3110	var onload = props.onload || function(){};
3111	delete props.onload;
3112	props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
3113	iframe = new Element(iframe || 'iframe', props);
3114
3115	var onLoad = function(){
3116		onload.call(iframe.contentWindow);
3117	};
3118
3119	if (window.frames[props.id]) onLoad();
3120	else iframe.addListener('load', onLoad);
3121	return iframe;
3122});
3123
3124var Elements = this.Elements = function(nodes){
3125	if (nodes && nodes.length){
3126		var uniques = {}, node;
3127		for (var i = 0; node = nodes[i++];){
3128			var uid = Slick.uidOf(node);
3129			if (!uniques[uid]){
3130				uniques[uid] = true;
3131				this.push(node);
3132			}
3133		}
3134	}
3135};
3136
3137Elements.prototype = {length: 0};
3138Elements.parent = Array;
3139
3140new Type('Elements', Elements).implement({
3141
3142	filter: function(filter, bind){
3143		if (!filter) return this;
3144		return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
3145			return item.match(filter);
3146		} : filter, bind));
3147	}.protect(),
3148
3149	push: function(){
3150		var length = this.length;
3151		for (var i = 0, l = arguments.length; i < l; i++){
3152			var item = document.id(arguments[i]);
3153			if (item) this[length++] = item;
3154		}
3155		return (this.length = length);
3156	}.protect(),
3157
3158	unshift: function(){
3159		var items = [];
3160		for (var i = 0, l = arguments.length; i < l; i++){
3161			var item = document.id(arguments[i]);
3162			if (item) items.push(item);
3163		}
3164		return Array.prototype.unshift.apply(this, items);
3165	}.protect(),
3166
3167	concat: function(){
3168		var newElements = new Elements(this);
3169		for (var i = 0, l = arguments.length; i < l; i++){
3170			var item = arguments[i];
3171			if (Type.isEnumerable(item)) newElements.append(item);
3172			else newElements.push(item);
3173		}
3174		return newElements;
3175	}.protect(),
3176
3177	append: function(collection){
3178		for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
3179		return this;
3180	}.protect(),
3181
3182	empty: function(){
3183		while (this.length) delete this[--this.length];
3184		return this;
3185	}.protect()
3186
3187});
3188
3189//<1.2compat>
3190
3191Elements.alias('extend', 'append');
3192
3193//</1.2compat>
3194
3195(function(){
3196
3197// FF, IE
3198var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
3199
3200splice.call(object, 1, 1);
3201if (object[1] == 1) Elements.implement('splice', function(){
3202	var length = this.length;
3203	splice.apply(this, arguments);
3204	while (length >= this.length) delete this[length--];
3205	return this;
3206}.protect());
3207
3208Elements.implement(Array.prototype);
3209
3210Array.mirror(Elements);
3211
3212/*<ltIE8>*/
3213var createElementAcceptsHTML;
3214try {
3215	var x = document.createElement('<input name=x>');
3216	createElementAcceptsHTML = (x.name == 'x');
3217} catch(e){}
3218
3219var escapeQuotes = function(html){
3220	return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
3221};
3222/*</ltIE8>*/
3223
3224Document.implement({
3225
3226	newElement: function(tag, props){
3227		if (props && props.checked != null) props.defaultChecked = props.checked;
3228		/*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
3229		if (createElementAcceptsHTML && props){
3230			tag = '<' + tag;
3231			if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
3232			if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
3233			tag += '>';
3234			delete props.name;
3235			delete props.type;
3236		}
3237		/*</ltIE8>*/
3238		return this.id(this.createElement(tag)).set(props);
3239	}
3240
3241});
3242
3243})();
3244
3245Document.implement({
3246
3247	newTextNode: function(text){
3248		return this.createTextNode(text);
3249	},
3250
3251	getDocument: function(){
3252		return this;
3253	},
3254
3255	getWindow: function(){
3256		return this.window;
3257	},
3258
3259	id: (function(){
3260
3261		var types = {
3262
3263			string: function(id, nocash, doc){
3264				id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
3265				return (id) ? types.element(id, nocash) : null;
3266			},
3267
3268			element: function(el, nocash){
3269				$uid(el);
3270				if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){
3271					Object.append(el, Element.Prototype);
3272				}
3273				return el;
3274			},
3275
3276			object: function(obj, nocash, doc){
3277				if (obj.toElement) return types.element(obj.toElement(doc), nocash);
3278				return null;
3279			}
3280
3281		};
3282
3283		types.textnode = types.whitespace = types.window = types.document = function(zero){
3284			return zero;
3285		};
3286
3287		return function(el, nocash, doc){
3288			if (el && el.$family && el.uid) return el;
3289			var type = typeOf(el);
3290			return (types[type]) ? types[type](el, nocash, doc || document) : null;
3291		};
3292
3293	})()
3294
3295});
3296
3297if (window.$ == null) Window.implement('$', function(el, nc){
3298	return document.id(el, nc, this.document);
3299});
3300
3301Window.implement({
3302
3303	getDocument: function(){
3304		return this.document;
3305	},
3306
3307	getWindow: function(){
3308		return this;
3309	}
3310
3311});
3312
3313[Document, Element].invoke('implement', {
3314
3315	getElements: function(expression){
3316		return Slick.search(this, expression, new Elements);
3317	},
3318
3319	getElement: function(expression){
3320		return document.id(Slick.find(this, expression));
3321	}
3322
3323});
3324
3325//<1.2compat>
3326
3327(function(search, find, match){
3328
3329	this.Selectors = {};
3330	var pseudos = this.Selectors.Pseudo = new Hash();
3331
3332	var addSlickPseudos = function(){
3333		for (var name in pseudos) if (pseudos.hasOwnProperty(name)){
3334			Slick.definePseudo(name, pseudos[name]);
3335			delete pseudos[name];
3336		}
3337	};
3338
3339	Slick.search = function(context, expression, append){
3340		addSlickPseudos();
3341		return search.call(this, context, expression, append);
3342	};
3343
3344	Slick.find = function(context, expression){
3345		addSlickPseudos();
3346		return find.call(this, context, expression);
3347	};
3348
3349	Slick.match = function(node, selector){
3350		addSlickPseudos();
3351		return match.call(this, node, selector);
3352	};
3353
3354})(Slick.search, Slick.find, Slick.match);
3355
3356if (window.$$ == null) Window.implement('$$', function(selector){
3357	var elements = new Elements;
3358	if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
3359	var args = Array.flatten(arguments);
3360	for (var i = 0, l = args.length; i < l; i++){
3361		var item = args[i];
3362		switch (typeOf(item)){
3363			case 'element': elements.push(item); break;
3364			case 'string': Slick.search(this.document, item, elements);
3365		}
3366	}
3367	return elements;
3368});
3369
3370//</1.2compat>
3371
3372if (window.$$ == null) Window.implement('$$', function(selector){
3373	if (arguments.length == 1){
3374		if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
3375		else if (Type.isEnumerable(selector)) return new Elements(selector);
3376	}
3377	return new Elements(arguments);
3378});
3379
3380(function(){
3381
3382var collected = {}, storage = {};
3383var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
3384
3385var get = function(uid){
3386	return (storage[uid] || (storage[uid] = {}));
3387};
3388
3389var clean = function(item){
3390	var uid = item.uid;
3391	if (item.removeEvents) item.removeEvents();
3392	if (item.clearAttributes) item.clearAttributes();
3393	if (uid != null){
3394		delete collected[uid];
3395		delete storage[uid];
3396	}
3397	return item;
3398};
3399
3400var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly',
3401	'rowSpan', 'tabIndex', 'useMap'
3402];
3403var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected',
3404	'noresize', 'defer', 'defaultChecked'
3405];
3406 var attributes = {
3407	'html': 'innerHTML',
3408	'class': 'className',
3409	'for': 'htmlFor',
3410	'text': (function(){
3411		var temp = document.createElement('div');
3412		return (temp.textContent == null) ? 'innerText' : 'textContent';
3413	})()
3414};
3415var readOnly = ['type'];
3416var expandos = ['value', 'defaultValue'];
3417var uriAttrs = /^(?:href|src|usemap)$/i;
3418
3419bools = bools.associate(bools);
3420camels = camels.associate(camels.map(String.toLowerCase));
3421readOnly = readOnly.associate(readOnly);
3422
3423Object.append(attributes, expandos.associate(expandos));
3424
3425var inserters = {
3426
3427	before: function(context, element){
3428		var parent = element.parentNode;
3429		if (parent) parent.insertBefore(context, element);
3430	},
3431
3432	after: function(context, element){
3433		var parent = element.parentNode;
3434		if (parent) parent.insertBefore(context, element.nextSibling);
3435	},
3436
3437	bottom: function(context, element){
3438		element.appendChild(context);
3439	},
3440
3441	top: function(context, element){
3442		element.insertBefore(context, element.firstChild);
3443	}
3444
3445};
3446
3447inserters.inside = inserters.bottom;
3448
3449//<1.2compat>
3450
3451Object.each(inserters, function(inserter, where){
3452
3453	where = where.capitalize();
3454
3455	var methods = {};
3456
3457	methods['inject' + where] = function(el){
3458		inserter(this, document.id(el, true));
3459		return this;
3460	};
3461
3462	methods['grab' + where] = function(el){
3463		inserter(document.id(el, true), this);
3464		return this;
3465	};
3466
3467	Element.implement(methods);
3468
3469});
3470
3471//</1.2compat>
3472
3473var injectCombinator = function(expression, combinator){
3474	if (!expression) return combinator;
3475
3476	expression = Object.clone(Slick.parse(expression));
3477
3478	var expressions = expression.expressions;
3479	for (var i = expressions.length; i--;)
3480		expressions[i][0].combinator = combinator;
3481
3482	return expression;
3483};
3484
3485Element.implement({
3486
3487	set: function(prop, value){
3488		var property = Element.Properties[prop];
3489		(property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
3490	}.overloadSetter(),
3491
3492	get: function(prop){
3493		var property = Element.Properties[prop];
3494		return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
3495	}.overloadGetter(),
3496
3497	erase: function(prop){
3498		var property = Element.Properties[prop];
3499		(property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
3500		return this;
3501	},
3502
3503	setProperty: function(attribute, value){
3504		attribute = camels[attribute] || attribute;
3505		if (value == null) return this.removeProperty(attribute);
3506		var key = attributes[attribute];
3507		(key) ? this[key] = value :
3508			(bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value);
3509		return this;
3510	},
3511
3512	setProperties: function(attributes){
3513		for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
3514		return this;
3515	},
3516
3517	getProperty: function(attribute){
3518		attribute = camels[attribute] || attribute;
3519		var key = attributes[attribute] || readOnly[attribute];
3520		return (key) ? this[key] :
3521			(bools[attribute]) ? !!this[attribute] :
3522			(uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) :
3523			(key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null;
3524	},
3525
3526	getProperties: function(){
3527		var args = Array.from(arguments);
3528		return args.map(this.getProperty, this).associate(args);
3529	},
3530
3531	removeProperty: function(attribute){
3532		attribute = camels[attribute] || attribute;
3533		var key = attributes[attribute];
3534		(key) ? this[key] = '' :
3535			(bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute);
3536		return this;
3537	},
3538
3539	removeProperties: function(){
3540		Array.each(arguments, this.removeProperty, this);
3541		return this;
3542	},
3543
3544	hasClass: function(className){
3545		return this.className.clean().contains(className, ' ');
3546	},
3547
3548	addClass: function(className){
3549		if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
3550		return this;
3551	},
3552
3553	removeClass: function(className){
3554		this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
3555		return this;
3556	},
3557
3558	toggleClass: function(className, force){
3559		if (force == null) force = !this.hasClass(className);
3560		return (force) ? this.addClass(className) : this.removeClass(className);
3561	},
3562
3563	adopt: function(){
3564		var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
3565		if (length > 1) parent = fragment = document.createDocumentFragment();
3566
3567		for (var i = 0; i < length; i++){
3568			var element = document.id(elements[i], true);
3569			if (element) parent.appendChild(element);
3570		}
3571
3572		if (fragment) this.appendChild(fragment);
3573
3574		return this;
3575	},
3576
3577	appendText: function(text, where){
3578		return this.grab(this.getDocument().newTextNode(text), where);
3579	},
3580
3581	grab: function(el, where){
3582		inserters[where || 'bottom'](document.id(el, true), this);
3583		return this;
3584	},
3585
3586	inject: function(el, where){
3587		inserters[where || 'bottom'](this, document.id(el, true));
3588		return this;
3589	},
3590
3591	replaces: function(el){
3592		el = document.id(el, true);
3593		el.parentNode.replaceChild(this, el);
3594		return this;
3595	},
3596
3597	wraps: function(el, where){
3598		el = document.id(el, true);
3599		return this.replaces(el).grab(el, where);
3600	},
3601
3602	getPrevious: function(expression){
3603		return document.id(Slick.find(this, injectCombinator(expression, '!~')));
3604	},
3605
3606	getAllPrevious: function(expression){
3607		return Slick.search(this, injectCombinator(expression, '!~'), new Elements);
3608	},
3609
3610	getNext: function(expression){
3611		return document.id(Slick.find(this, injectCombinator(expression, '~')));
3612	},
3613
3614	getAllNext: function(expression){
3615		return Slick.search(this, injectCombinator(expression, '~'), new Elements);
3616	},
3617
3618	getFirst: function(expression){
3619		return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
3620	},
3621
3622	getLast: function(expression){
3623		return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
3624	},
3625
3626	getParent: function(expression){
3627		return document.id(Slick.find(this, injectCombinator(expression, '!')));
3628	},
3629
3630	getParents: function(expression){
3631		return Slick.search(this, injectCombinator(expression, '!'), new Elements);
3632	},
3633
3634	getSiblings: function(expression){
3635		return Slick.search(this, injectCombinator(expression, '~~'), new Elements);
3636	},
3637
3638	getChildren: function(expression){
3639		return Slick.search(this, injectCombinator(expression, '>'), new Elements);
3640	},
3641
3642	getWindow: function(){
3643		return this.ownerDocument.window;
3644	},
3645
3646	getDocument: function(){
3647		return this.ownerDocument;
3648	},
3649
3650	getElementById: function(id){
3651		return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
3652	},
3653
3654	getSelected: function(){
3655		this.selectedIndex; // Safari 3.2.1
3656		return new Elements(Array.from(this.options).filter(function(option){
3657			return option.selected;
3658		}));
3659	},
3660
3661	toQueryString: function(){
3662		var queryString = [];
3663		this.getElements('input, select, textarea').each(function(el){
3664			var type = el.type;
3665			if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
3666
3667			var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
3668				// IE
3669				return document.id(opt).get('value');
3670			}) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
3671
3672			Array.from(value).each(function(val){
3673				if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
3674			});
3675		});
3676		return queryString.join('&');
3677	},
3678
3679	destroy: function(){
3680		var children = clean(this).getElementsByTagName('*');
3681		Array.each(children, clean);
3682		Element.dispose(this);
3683		return null;
3684	},
3685
3686	empty: function(){
3687		Array.from(this.childNodes).each(Element.dispose);
3688		return this;
3689	},
3690
3691	dispose: function(){
3692		return (this.parentNode) ? this.parentNode.removeChild(this) : this;
3693	},
3694
3695	match: function(expression){
3696		return !expression || Slick.match(this, expression);
3697	}
3698
3699});
3700
3701var cleanClone = function(node, element, keepid){
3702	if (!keepid) node.setAttributeNode(document.createAttribute('id'));
3703	if (node.clearAttributes){
3704		node.clearAttributes();
3705		node.mergeAttributes(element);
3706		node.removeAttribute('uid');
3707		if (node.options){
3708			var no = node.options, eo = element.options;
3709			for (var i = no.length; i--;) no[i].selected = eo[i].selected;
3710		}
3711	}
3712
3713	var prop = formProps[element.tagName.toLowerCase()];
3714	if (prop && element[prop]) node[prop] = element[prop];
3715};
3716
3717Element.implement('clone', function(contents, keepid){
3718	contents = contents !== false;
3719	var clone = this.cloneNode(contents), i;
3720
3721	if (contents){
3722		var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*');
3723		for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid);
3724	}
3725
3726	cleanClone(clone, this, keepid);
3727
3728	if (Browser.ie){
3729		var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
3730		for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
3731	}
3732	return document.id(clone);
3733});
3734
3735var contains = {contains: function(element){
3736	return Slick.contains(this, element);
3737}};
3738
3739if (!document.contains) Document.implement(contains);
3740if (!document.createElement('div').contains) Element.implement(contains);
3741
3742//<1.2compat>
3743
3744Element.implement('hasChild', function(element){
3745	return this !== element && this.contains(element);
3746});
3747
3748//</1.2compat>
3749
3750[Element, Window, Document].invoke('implement', {
3751
3752	addListener: function(type, fn){
3753		if (type == 'unload'){
3754			var old = fn, self = this;
3755			fn = function(){
3756				self.removeListener('unload', fn);
3757				old();
3758			};
3759		} else {
3760			collected[$uid(this)] = this;
3761		}
3762		if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]);
3763		else this.attachEvent('on' + type, fn);
3764		return this;
3765	},
3766
3767	removeListener: function(type, fn){
3768		if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]);
3769		else this.detachEvent('on' + type, fn);
3770		return this;
3771	},
3772
3773	retrieve: function(property, dflt){
3774		var storage = get($uid(this)), prop = storage[property];
3775		if (dflt != null && prop == null) prop = storage[property] = dflt;
3776		return prop != null ? prop : null;
3777	},
3778
3779	store: function(property, value){
3780		var storage = get($uid(this));
3781		storage[property] = value;
3782		return this;
3783	},
3784
3785	eliminate: function(property){
3786		var storage = get($uid(this));
3787		delete storage[property];
3788		return this;
3789	}
3790
3791});
3792
3793/*<ltIE9>*/
3794if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){
3795	Object.each(collected, clean);
3796	if (window.CollectGarbage) CollectGarbage();
3797});
3798/*</ltIE9>*/
3799
3800})();
3801
3802Element.Properties = {};
3803
3804//<1.2compat>
3805
3806Element.Properties = new Hash;
3807
3808//</1.2compat>
3809
3810Element.Properties.style = {
3811
3812	set: function(style){
3813		this.style.cssText = style;
3814	},
3815
3816	get: function(){
3817		return this.style.cssText;
3818	},
3819
3820	erase: function(){
3821		this.style.cssText = '';
3822	}
3823
3824};
3825
3826Element.Properties.tag = {
3827
3828	get: function(){
3829		return this.tagName.toLowerCase();
3830	}
3831
3832};
3833
3834/*<ltIE9>*/
3835(function(maxLength){
3836	if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = {
3837		get: function(){
3838			var maxlength = this.getAttribute('maxLength');
3839			return maxlength == maxLength ? null : maxlength;
3840		}
3841	};
3842})(document.createElement('input').getAttribute('maxLength'));
3843/*</ltIE9>*/
3844
3845/*<!webkit>*/
3846Element.Properties.html = (function(){
3847
3848	var tableTest = Function.attempt(function(){
3849		var table = document.createElement('table');
3850		table.innerHTML = '<tr><td></td></tr>';
3851	});
3852
3853	var wrapper = document.createElement('div');
3854
3855	var translations = {
3856		table: [1, '<table>', '</table>'],
3857		select: [1, '<select>', '</select>'],
3858		tbody: [2, '<table><tbody>', '</tbody></table>'],
3859		tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
3860	};
3861	translations.thead = translations.tfoot = translations.tbody;
3862
3863	var html = {
3864		set: function(){
3865			var html = Array.flatten(arguments).join('');
3866			var wrap = (!tableTest && translations[this.get('tag')]);
3867			if (wrap){
3868				var first = wrapper;
3869				first.innerHTML = wrap[1] + html + wrap[2];
3870				for (var i = wrap[0]; i--;) first = first.firstChild;
3871				this.empty().adopt(first.childNodes);
3872			} else {
3873				this.innerHTML = html;
3874			}
3875		}
3876	};
3877
3878	html.erase = html.set;
3879
3880	return html;
3881})();
3882/*</!webkit>*/
3883
3884
3885/*
3886---
3887
3888name: Element.Style
3889
3890description: Contains methods for interacting with the styles of Elements in a fashionable way.
3891
3892license: MIT-style license.
3893
3894requires: Element
3895
3896provides: Element.Style
3897
3898...
3899*/
3900
3901(function(){
3902
3903var html = document.html;
3904
3905Element.Properties.styles = {set: function(styles){
3906	this.setStyles(styles);
3907}};
3908
3909var hasOpacity = (html.style.opacity != null);
3910var reAlpha = /alpha\(opacity=([\d.]+)\)/i;
3911
3912var setOpacity = function(element, opacity){
3913	if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
3914	if (hasOpacity){
3915		element.style.opacity = opacity;
3916	} else {
3917		opacity = (opacity * 100).limit(0, 100).round();
3918		opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')';
3919		var filter = element.style.filter || element.getComputedStyle('filter') || '';
3920		element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
3921	}
3922};
3923
3924Element.Properties.opacity = {
3925
3926	set: function(opacity){
3927		var visibility = this.style.visibility;
3928		if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden';
3929		else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible';
3930
3931		setOpacity(this, opacity);
3932	},
3933
3934	get: (hasOpacity) ? function(){
3935		var opacity = this.style.opacity || this.getComputedStyle('opacity');
3936		return (opacity == '') ? 1 : opacity;
3937	} : function(){
3938		var opacity, filter = (this.style.filter || this.getComputedStyle('filter'));
3939		if (filter) opacity = filter.match(reAlpha);
3940		return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
3941	}
3942
3943};
3944
3945var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
3946
3947Element.implement({
3948
3949	getComputedStyle: function(property){
3950		if (this.currentStyle) return this.currentStyle[property.camelCase()];
3951		var defaultView = Element.getDocument(this).defaultView,
3952			computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
3953		return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
3954	},
3955
3956	setOpacity: function(value){
3957		setOpacity(this, value);
3958		return this;
3959	},
3960
3961	getOpacity: function(){
3962		return this.get('opacity');
3963	},
3964
3965	setStyle: function(property, value){
3966		switch (property){
3967			case 'opacity': return this.set('opacity', parseFloat(value));
3968			case 'float': property = floatName;
3969		}
3970		property = property.camelCase();
3971		if (typeOf(value) != 'string'){
3972			var map = (Element.Styles[property] || '@').split(' ');
3973			value = Array.from(value).map(function(val, i){
3974				if (!map[i]) return '';
3975				return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
3976			}).join(' ');
3977		} else if (value == String(Number(value))){
3978			value = Math.round(value);
3979		}
3980		this.style[property] = value;
3981		return this;
3982	},
3983
3984	getStyle: function(property){
3985		switch (property){
3986			case 'opacity': return this.get('opacity');
3987			case 'float': property = floatName;
3988		}
3989		property = property.camelCase();
3990		var result = this.style[property];
3991		if (!result || property == 'zIndex'){
3992			result = [];
3993			for (var style in Element.ShortStyles){
3994				if (property != style) continue;
3995				for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
3996				return result.join(' ');
3997			}
3998			result = this.getComputedStyle(property);
3999		}
4000		if (result){
4001			result = String(result);
4002			var color = result.match(/rgba?\([\d\s,]+\)/);
4003			if (color) result = result.replace(color[0], color[0].rgbToHex());
4004		}
4005		if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){
4006			if ((/^(height|width)$/).test(property)){
4007				var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
4008				values.each(function(value){
4009					size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
4010				}, this);
4011				return this['offset' + property.capitalize()] - size + 'px';
4012			}
4013			if (Browser.opera && String(result).indexOf('px') != -1) return result;
4014			if ((/^border(.+)Width|margin|padding/).test(property)) return '0px';
4015		}
4016		return result;
4017	},
4018
4019	setStyles: function(styles){
4020		for (var style in styles) this.setStyle(style, styles[style]);
4021		return this;
4022	},
4023
4024	getStyles: function(){
4025		var result = {};
4026		Array.flatten(arguments).each(function(key){
4027			result[key] = this.getStyle(key);
4028		}, this);
4029		return result;
4030	}
4031
4032});
4033
4034Element.Styles = {
4035	left: '@px', top: '@px', bottom: '@px', right: '@px',
4036	width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
4037	backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
4038	fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
4039	margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
4040	borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
4041	zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
4042};
4043
4044//<1.2compat>
4045
4046Element.Styles = new Hash(Element.Styles);
4047
4048//</1.2compat>
4049
4050Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
4051
4052['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
4053	var Short = Element.ShortStyles;
4054	var All = Element.Styles;
4055	['margin', 'padding'].each(function(style){
4056		var sd = style + direction;
4057		Short[style][sd] = All[sd] = '@px';
4058	});
4059	var bd = 'border' + direction;
4060	Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
4061	var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
4062	Short[bd] = {};
4063	Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
4064	Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
4065	Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
4066});
4067
4068})();
4069
4070
4071/*
4072---
4073
4074name: Element.Event
4075
4076description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events.
4077
4078license: MIT-style license.
4079
4080requires: [Element, Event]
4081
4082provides: Element.Event
4083
4084...
4085*/
4086
4087(function(){
4088
4089Element.Properties.events = {set: function(events){
4090	this.addEvents(events);
4091}};
4092
4093[Element, Window, Document].invoke('implement', {
4094
4095	addEvent: function(type, fn){
4096		var events = this.retrieve('events', {});
4097		if (!events[type]) events[type] = {keys: [], values: []};
4098		if (events[type].keys.contains(fn)) return this;
4099		events[type].keys.push(fn);
4100		var realType = type,
4101			custom = Element.Events[type],
4102			condition = fn,
4103			self = this;
4104		if (custom){
4105			if (custom.onAdd) custom.onAdd.call(this, fn);
4106			if (custom.condition){
4107				condition = function(event){
4108					if (custom.condition.call(this, event)) return fn.call(this, event);
4109					return true;
4110				};
4111			}
4112			realType = custom.base || realType;
4113		}
4114		var defn = function(){
4115			return fn.call(self);
4116		};
4117		var nativeEvent = Element.NativeEvents[realType];
4118		if (nativeEvent){
4119			if (nativeEvent == 2){
4120				defn = function(event){
4121					event = new Event(event, self.getWindow());
4122					if (condition.call(self, event) === false) event.stop();
4123				};
4124			}
4125			this.addListener(realType, defn, arguments[2]);
4126		}
4127		events[type].values.push(defn);
4128		return this;
4129	},
4130
4131	removeEvent: function(type, fn){
4132		var events = this.retrieve('events');
4133		if (!events || !events[type]) return this;
4134		var list = events[type];
4135		var index = list.keys.indexOf(fn);
4136		if (index == -1) return this;
4137		var value = list.values[index];
4138		delete list.keys[index];
4139		delete list.values[index];
4140		var custom = Element.Events[type];
4141		if (custom){
4142			if (custom.onRemove) custom.onRemove.call(this, fn);
4143			type = custom.base || type;
4144		}
4145		return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
4146	},
4147
4148	addEvents: function(events){
4149		for (var event in events) this.addEvent(event, events[event]);
4150		return this;
4151	},
4152
4153	removeEvents: function(events){
4154		var type;
4155		if (typeOf(events) == 'object'){
4156			for (type in events) this.removeEvent(type, events[type]);
4157			return this;
4158		}
4159		var attached = this.retrieve('events');
4160		if (!attached) return this;
4161		if (!events){
4162			for (type in attached) this.removeEvents(type);
4163			this.eliminate('events');
4164		} else if (attached[events]){
4165			attached[events].keys.each(function(fn){
4166				this.removeEvent(events, fn);
4167			}, this);
4168			delete attached[events];
4169		}
4170		return this;
4171	},
4172
4173	fireEvent: function(type, args, delay){
4174		var events = this.retrieve('events');
4175		if (!events || !events[type]) return this;
4176		args = Array.from(args);
4177
4178		events[type].keys.each(function(fn){
4179			if (delay) fn.delay(delay, this, args);
4180			else fn.apply(this, args);
4181		}, this);
4182		return this;
4183	},
4184
4185	cloneEvents: function(from, type){
4186		from = document.id(from);
4187		var events = from.retrieve('events');
4188		if (!events) return this;
4189		if (!type){
4190			for (var eventType in events) this.cloneEvents(from, eventType);
4191		} else if (events[type]){
4192			events[type].keys.each(function(fn){
4193				this.addEvent(type, fn);
4194			}, this);
4195		}
4196		return this;
4197	}
4198
4199});
4200
4201Element.NativeEvents = {
4202	click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
4203	mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
4204	mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
4205	keydown: 2, keypress: 2, keyup: 2, //keyboard
4206	orientationchange: 2, // mobile
4207	touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
4208	gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
4209	focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
4210	load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
4211	error: 1, abort: 1, scroll: 1 //misc
4212};
4213
4214var check = function(event){
4215	var related = event.relatedTarget;
4216	if (related == null) return true;
4217	if (!related) return false;
4218	return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
4219};
4220
4221Element.Events = {
4222
4223	mouseenter: {
4224		base: 'mouseover',
4225		condition: check
4226	},
4227
4228	mouseleave: {
4229		base: 'mouseout',
4230		condition: check
4231	},
4232
4233	mousewheel: {
4234		base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
4235	}
4236
4237};
4238
4239//<1.2compat>
4240
4241Element.Events = new Hash(Element.Events);
4242
4243//</1.2compat>
4244
4245})();
4246
4247
4248/*
4249---
4250
4251name: Element.Dimensions
4252
4253description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
4254
4255license: MIT-style license.
4256
4257credits:
4258  - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
4259  - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
4260
4261requires: [Element, Element.Style]
4262
4263provides: [Element.Dimensions]
4264
4265...
4266*/
4267
4268(function(){
4269
4270var element = document.createElement('div'),
4271	child = document.createElement('div');
4272element.style.height = '0';
4273element.appendChild(child);
4274var brokenOffsetParent = (child.offsetParent === element);
4275element = child = null;
4276
4277var isOffset = function(el){
4278	return styleString(el, 'position') != 'static' || isBody(el);
4279};
4280
4281var isOffsetStatic = function(el){
4282	return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName);
4283};
4284
4285Element.implement({
4286
4287	scrollTo: function(x, y){
4288		if (isBody(this)){
4289			this.getWindow().scrollTo(x, y);
4290		} else {
4291			this.scrollLeft = x;
4292			this.scrollTop = y;
4293		}
4294		return this;
4295	},
4296
4297	getSize: function(){
4298		if (isBody(this)) return this.getWindow().getSize();
4299		return {x: this.offsetWidth, y: this.offsetHeight};
4300	},
4301
4302	getScrollSize: function(){
4303		if (isBody(this)) return this.getWindow().getScrollSize();
4304		return {x: this.scrollWidth, y: this.scrollHeight};
4305	},
4306
4307	getScroll: function(){
4308		if (isBody(this)) return this.getWindow().getScroll();
4309		return {x: this.scrollLeft, y: this.scrollTop};
4310	},
4311
4312	getScrolls: function(){
4313		var element = this.parentNode, position = {x: 0, y: 0};
4314		while (element && !isBody(element)){
4315			position.x += element.scrollLeft;
4316			position.y += element.scrollTop;
4317			element = element.parentNode;
4318		}
4319		return position;
4320	},
4321
4322	getOffsetParent: brokenOffsetParent ? function(){
4323		var element = this;
4324		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
4325
4326		var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
4327		while ((element = element.parentNode)){
4328			if (isOffsetCheck(element)) return element;
4329		}
4330		return null;
4331	} : function(){
4332		var element = this;
4333		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
4334
4335		try {
4336			return element.offsetParent;
4337		} catch(e) {}
4338		return null;
4339	},
4340
4341	getOffsets: function(){
4342		if (this.getBoundingClientRect && !Browser.Platform.ios){
4343			var bound = this.getBoundingClientRect(),
4344				html = document.id(this.getDocument().documentElement),
4345				htmlScroll = html.getScroll(),
4346				elemScrolls = this.getScrolls(),
4347				isFixed = (styleString(this, 'position') == 'fixed');
4348
4349			return {
4350				x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
4351				y: bound.top.toInt()  + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
4352			};
4353		}
4354
4355		var element = this, position = {x: 0, y: 0};
4356		if (isBody(this)) return position;
4357
4358		while (element && !isBody(element)){
4359			position.x += element.offsetLeft;
4360			position.y += element.offsetTop;
4361
4362			if (Browser.firefox){
4363				if (!borderBox(element)){
4364					position.x += leftBorder(element);
4365					position.y += topBorder(element);
4366				}
4367				var parent = element.parentNode;
4368				if (parent && styleString(parent, 'overflow') != 'visible'){
4369					position.x += leftBorder(parent);
4370					position.y += topBorder(parent);
4371				}
4372			} else if (element != this && Browser.safari){
4373				position.x += leftBorder(element);
4374				position.y += topBorder(element);
4375			}
4376
4377			element = element.offsetParent;
4378		}
4379		if (Browser.firefox && !borderBox(this)){
4380			position.x -= leftBorder(this);
4381			position.y -= topBorder(this);
4382		}
4383		return position;
4384	},
4385
4386	getPosition: function(relative){
4387		if (isBody(this)) return {x: 0, y: 0};
4388		var offset = this.getOffsets(),
4389			scroll = this.getScrolls();
4390		var position = {
4391			x: offset.x - scroll.x,
4392			y: offset.y - scroll.y
4393		};
4394		
4395		if (relative && (relative = document.id(relative))){
4396			var relativePosition = relative.getPosition();
4397			return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
4398		}
4399		return position;
4400	},
4401
4402	getCoordinates: function(element){
4403		if (isBody(this)) return this.getWindow().getCoordinates();
4404		var position = this.getPosition(element),
4405			size = this.getSize();
4406		var obj = {
4407			left: position.x,
4408			top: position.y,
4409			width: size.x,
4410			height: size.y
4411		};
4412		obj.right = obj.left + obj.width;
4413		obj.bottom = obj.top + obj.height;
4414		return obj;
4415	},
4416
4417	computePosition: function(obj){
4418		return {
4419			left: obj.x - styleNumber(this, 'margin-left'),
4420			top: obj.y - styleNumber(this, 'margin-top')
4421		};
4422	},
4423
4424	setPosition: function(obj){
4425		return this.setStyles(this.computePosition(obj));
4426	}
4427
4428});
4429
4430
4431[Document, Window].invoke('implement', {
4432
4433	getSize: function(){
4434		var doc = getCompatElement(this);
4435		return {x: doc.clientWidth, y: doc.clientHeight};
4436	},
4437
4438	getScroll: function(){
4439		var win = this.getWindow(), doc = getCompatElement(this);
4440		return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
4441	},
4442
4443	getScrollSize: function(){
4444		var doc = getCompatElement(this),
4445			min = this.getSize(),
4446			body = this.getDocument().body;
4447
4448		return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
4449	},
4450
4451	getPosition: function(){
4452		return {x: 0, y: 0};
4453	},
4454
4455	getCoordinates: function(){
4456		var size = this.getSize();
4457		return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
4458	}
4459
4460});
4461
4462// private methods
4463
4464var styleString = Element.getComputedStyle;
4465
4466function styleNumber(element, style){
4467	return styleString(element, style).toInt() || 0;
4468}
4469
4470function borderBox(element){
4471	return styleString(element, '-moz-box-sizing') == 'border-box';
4472}
4473
4474function topBorder(element){
4475	return styleNumber(element, 'border-top-width');
4476}
4477
4478function leftBorder(element){
4479	return styleNumber(element, 'border-left-width');
4480}
4481
4482function isBody(element){
4483	return (/^(?:body|html)$/i).test(element.tagName);
4484}
4485
4486function getCompatElement(element){
4487	var doc = element.getDocument();
4488	return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
4489}
4490
4491})();
4492
4493//aliases
4494Element.alias({position: 'setPosition'}); //compatability
4495
4496[Window, Document, Element].invoke('implement', {
4497
4498	getHeight: function(){
4499		return this.getSize().y;
4500	},
4501
4502	getWidth: function(){
4503		return this.getSize().x;
4504	},
4505
4506	getScrollTop: function(){
4507		return this.getScroll().y;
4508	},
4509
4510	getScrollLeft: function(){
4511		return this.getScroll().x;
4512	},
4513
4514	getScrollHeight: function(){
4515		return this.getScrollSize().y;
4516	},
4517
4518	getScrollWidth: function(){
4519		return this.getScrollSize().x;
4520	},
4521
4522	getTop: function(){
4523		return this.getPosition().y;
4524	},
4525
4526	getLeft: function(){
4527		return this.getPosition().x;
4528	}
4529
4530});
4531
4532
4533/*
4534---
4535
4536name: Fx
4537
4538description: Contains the basic animation logic to be extended by all other Fx Classes.
4539
4540license: MIT-style license.
4541
4542requires: [Chain, Events, Options]
4543
4544provides: Fx
4545
4546...
4547*/
4548
4549(function(){
4550
4551var Fx = this.Fx = new Class({
4552
4553	Implements: [Chain, Events, Options],
4554
4555	options: {
4556		/*
4557		onStart: nil,
4558		onCancel: nil,
4559		onComplete: nil,
4560		*/
4561		fps: 60,
4562		unit: false,
4563		duration: 500,
4564		frames: null,
4565		frameSkip: true,
4566		link: 'ignore'
4567	},
4568
4569	initialize: function(options){
4570		this.subject = this.subject || this;
4571		this.setOptions(options);
4572	},
4573
4574	getTransition: function(){
4575		return function(p){
4576			return -(Math.cos(Math.PI * p) - 1) / 2;
4577		};
4578	},
4579
4580	step: function(now){
4581		if (this.options.frameSkip){
4582			var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
4583			this.time = now;
4584			this.frame += frames;
4585		} else {
4586			this.frame++;
4587		}
4588		
4589		if (this.frame < this.frames){
4590			var delta = this.transition(this.frame / this.frames);
4591			this.set(this.compute(this.from, this.to, delta));
4592		} else {
4593			this.frame = this.frames;
4594			this.set(this.compute(this.from, this.to, 1));
4595			this.stop();
4596		}
4597	},
4598
4599	set: function(now){
4600		return now;
4601	},
4602
4603	compute: function(from, to, delta){
4604		return Fx.compute(from, to, delta);
4605	},
4606
4607	check: function(){
4608		if (!this.isRunning()) return true;
4609		switch (this.options.link){
4610			case 'cancel': this.cancel(); return true;
4611			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
4612		}
4613		return false;
4614	},
4615
4616	start: function(from, to){
4617		if (!this.check(from, to)) return this;
4618		this.from = from;
4619		this.to = to;
4620		this.frame = (this.options.frameSkip) ? 0 : -1;
4621		this.time = null;
4622		this.transition = this.getTransition();
4623		var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
4624		this.duration = Fx.Durations[duration] || duration.toInt();
4625		this.frameInterval = 1000 / fps;
4626		this.frames = frames || Math.round(this.duration / this.frameInterval);
4627		this.fireEvent('start', this.subject);
4628		pushInstance.call(this, fps);
4629		return this;
4630	},
4631	
4632	stop: function(){
4633		if (this.isRunning()){
4634			this.time = null;
4635			pullInstance.call(this, this.options.fps);
4636			if (this.frames == this.frame){
4637				this.fireEvent('complete', this.subject);
4638				if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
4639			} else {
4640				this.fireEvent('stop', this.subject);
4641			}
4642		}
4643		return this;
4644	},
4645	
4646	cancel: function(){
4647		if (this.isRunning()){
4648			this.time = null;
4649			pullInstance.call(this, this.options.fps);
4650			this.frame = this.frames;
4651			this.fireEvent('cancel', this.subject).clearChain();
4652		}
4653		return this;
4654	},
4655	
4656	pause: function(){
4657		if (this.isRunning()){
4658			this.time = null;
4659			pullInstance.call(this, this.options.fps);
4660		}
4661		return this;
4662	},
4663	
4664	resume: function(){
4665		if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps);
4666		return this;
4667	},
4668	
4669	isRunning: function(){
4670		var list = instances[this.options.fps];
4671		return list && list.contains(this);
4672	}
4673
4674});
4675
4676Fx.compute = function(from, to, delta){
4677	return (to - from) * delta + from;
4678};
4679
4680Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
4681
4682// global timers
4683
4684var instances = {}, timers = {};
4685
4686var loop = function(){
4687	var now = Date.now();
4688	for (var i = this.length; i--;){
4689		var instance = this[i];
4690		if (instance) instance.step(now);
4691	}
4692};
4693
4694var pushInstance = function(fps){
4695	var list = instances[fps] || (instances[fps] = []);
4696	list.push(this);
4697	if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
4698};
4699
4700var pullInstance = function(fps){
4701	var list = instances[fps];
4702	if (list){
4703		list.erase(this);
4704		if (!list.length && timers[fps]){
4705			delete instances[fps];
4706			timers[fps] = clearInterval(timers[fps]);
4707		}
4708	}
4709};
4710
4711})();
4712
4713
4714/*
4715---
4716
4717name: Fx.CSS
4718
4719description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
4720
4721license: MIT-style license.
4722
4723requires: [Fx, Element.Style]
4724
4725provides: Fx.CSS
4726
4727...
4728*/
4729
4730Fx.CSS = new Class({
4731
4732	Extends: Fx,
4733
4734	//prepares the base from/to object
4735
4736	prepare: function(element, property, values){
4737		values = Array.from(values);
4738		if (values[1] == null){
4739			values[1] = values[0];
4740			values[0] = element.getStyle(property);
4741		}
4742		var parsed = values.map(this.parse);
4743		return {from: parsed[0], to: parsed[1]};
4744	},
4745
4746	//parses a value into an array
4747
4748	parse: function(value){
4749		value = Function.from(value)();
4750		value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
4751		return value.map(function(val){
4752			val = String(val);
4753			var found = false;
4754			Object.each(Fx.CSS.Parsers, function(parser, key){
4755				if (found) return;
4756				var parsed = parser.parse(val);
4757				if (parsed || parsed === 0) found = {value: parsed, parser: parser};
4758			});
4759			found = found || {value: val, parser: Fx.CSS.Parsers.String};
4760			return found;
4761		});
4762	},
4763
4764	//computes by a from and to prepared objects, using their parsers.
4765
4766	compute: function(from, to, delta){
4767		var computed = [];
4768		(Math.min(from.length, to.length)).times(function(i){
4769			computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
4770		});
4771		computed.$family = Function.from('fx:css:value');
4772		return computed;
4773	},
4774
4775	//serves the value as settable
4776
4777	serve: function(value, unit){
4778		if (typeOf(value) != 'fx:css:value') value = this.parse(value);
4779		var returned = [];
4780		value.each(function(bit){
4781			returned = returned.concat(bit.parser.serve(bit.value, unit));
4782		});
4783		return returned;
4784	},
4785
4786	//renders the change to an element
4787
4788	render: function(element, property, value, unit){
4789		element.setStyle(property, this.serve(value, unit));
4790	},
4791
4792	//searches inside the page css to find the values for a selector
4793
4794	search: function(selector){
4795		if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
4796		var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
4797		Array.each(document.styleSheets, function(sheet, j){
4798			var href = sheet.href;
4799			if (href && href.contains('://') && !href.contains(document.domain)) return;
4800			var rules = sheet.rules || sheet.cssRules;
4801			Array.each(rules, function(rule, i){
4802				if (!rule.style) return;
4803				var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
4804					return m.toLowerCase();
4805				}) : null;
4806				if (!selectorText || !selectorTest.test(selectorText)) return;
4807				Object.each(Element.Styles, function(value, style){
4808					if (!rule.style[style] || Element.ShortStyles[style]) return;
4809					value = String(rule.style[style]);
4810					to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value;
4811				});
4812			});
4813		});
4814		return Fx.CSS.Cache[selector] = to;
4815	}
4816
4817});
4818
4819Fx.CSS.Cache = {};
4820
4821Fx.CSS.Parsers = {
4822
4823	Color: {
4824		parse: function(value){
4825			if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
4826			return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
4827		},
4828		compute: function(from, to, delta){
4829			return from.map(function(value, i){
4830				return Math.round(Fx.compute(from[i], to[i], delta));
4831			});
4832		},
4833		serve: function(value){
4834			return value.map(Number);
4835		}
4836	},
4837
4838	Number: {
4839		parse: parseFloat,
4840		compute: Fx.compute,
4841		serve: function(value, unit){
4842			return (unit) ? value + unit : value;
4843		}
4844	},
4845
4846	String: {
4847		parse: Function.from(false),
4848		compute: function(zero, one){
4849			return one;
4850		},
4851		serve: function(zero){
4852			return zero;
4853		}
4854	}
4855
4856};
4857
4858//<1.2compat>
4859
4860Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);
4861
4862//</1.2compat>
4863
4864
4865/*
4866---
4867
4868name: Fx.Tween
4869
4870description: Formerly Fx.Style, effect to transition any CSS property for an element.
4871
4872license: MIT-style license.
4873
4874requires: Fx.CSS
4875
4876provides: [Fx.Tween, Element.fade, Element.highlight]
4877
4878...
4879*/
4880
4881Fx.Tween = new Class({
4882
4883	Extends: Fx.CSS,
4884
4885	initialize: function(element, options){
4886		this.element = this.subject = document.id(element);
4887		this.parent(options);
4888	},
4889
4890	set: function(property, now){
4891		if (arguments.length == 1){
4892			now = property;
4893			property = this.property || this.options.property;
4894		}
4895		this.render(this.element, property, now, this.options.unit);
4896		return this;
4897	},
4898
4899	start: function(property, from, to){
4900		if (!this.check(property, from, to)) return this;
4901		var args = Array.flatten(arguments);
4902		this.property = this.options.property || args.shift();
4903		var parsed = this.prepare(this.element, this.property, args);
4904		return this.parent(parsed.from, parsed.to);
4905	}
4906
4907});
4908
4909Element.Properties.tween = {
4910
4911	set: function(options){
4912		this.get('tween').cancel().setOptions(options);
4913		return this;
4914	},
4915
4916	get: function(){
4917		var tween = this.retrieve('tween');
4918		if (!tween){
4919			tween = new Fx.Tween(this, {link: 'cancel'});
4920			this.store('tween', tween);
4921		}
4922		return tween;
4923	}
4924
4925};
4926
4927Element.implement({
4928
4929	tween: function(property, from, to){
4930		this.get('tween').start(arguments);
4931		return this;
4932	},
4933
4934	fade: function(how){
4935		var fade = this.get('tween'), o = 'opacity', toggle;
4936		how = [how, 'toggle'].pick();
4937		switch (how){
4938			case 'in': fade.start(o, 1); break;
4939			case 'out': fade.start(o, 0); break;
4940			case 'show': fade.set(o, 1); break;
4941			case 'hide': fade.set(o, 0); break;
4942			case 'toggle':
4943				var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
4944				fade.start(o, (flag) ? 0 : 1);
4945				this.store('fade:flag', !flag);
4946				toggle = true;
4947			break;
4948			default: fade.start(o, arguments);
4949		}
4950		if (!toggle) this.eliminate('fade:flag');
4951		return this;
4952	},
4953
4954	highlight: function(start, end){
4955		if (!end){
4956			end = this.retrieve('highlight:original', this.getStyle('background-color'));
4957			end = (end == 'transparent') ? '#fff' : end;
4958		}
4959		var tween = this.get('tween');
4960		tween.start('background-color', start || '#ffff88', end).chain(function(){
4961			this.setStyle('background-color', this.retrieve('highlight:original'));
4962			tween.callChain();
4963		}.bind(this));
4964		return this;
4965	}
4966
4967});
4968
4969
4970/*
4971---
4972
4973name: Fx.Morph
4974
4975description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
4976
4977license: MIT-style license.
4978
4979requires: Fx.CSS
4980
4981provides: Fx.Morph
4982
4983...
4984*/
4985
4986Fx.Morph = new Class({
4987
4988	Extends: Fx.CSS,
4989
4990	initialize: function(element, options){
4991		this.element = this.subject = document.id(element);
4992		this.parent(options);
4993	},
4994
4995	set: function(now){
4996		if (typeof now == 'string') now = this.search(now);
4997		for (var p in now) this.render(this.element, p, now[p], this.options.unit);
4998		return this;
4999	},
5000
5001	compute: function(from, to, delta){
5002		var now = {};
5003		for (var p in from) now[p] = this.parent(from[p], to[p], delta);
5004		return now;
5005	},
5006
5007	start: function(properties){
5008		if (!this.check(properties)) return this;
5009		if (typeof properties == 'string') properties = this.search(properties);
5010		var from = {}, to = {};
5011		for (var p in properties){
5012			var parsed = this.prepare(this.element, p, properties[p]);
5013			from[p] = parsed.from;
5014			to[p] = parsed.to;
5015		}
5016		return this.parent(from, to);
5017	}
5018
5019});
5020
5021Element.Properties.morph = {
5022
5023	set: function(options){
5024		this.get('morph').cancel().setOptions(options);
5025		return this;
5026	},
5027
5028	get: function(){
5029		var morph = this.retrieve('morph');
5030		if (!morph){
5031			morph = new Fx.Morph(this, {link: 'cancel'});
5032			this.store('morph', morph);
5033		}
5034		return morph;
5035	}
5036
5037};
5038
5039Element.implement({
5040
5041	morph: function(props){
5042		this.get('morph').start(props);
5043		return this;
5044	}
5045
5046});
5047
5048
5049/*
5050---
5051
5052name: Fx.Transitions
5053
5054description: Contains a set of advanced transitions to be used with any of the Fx Classes.
5055
5056license: MIT-style license.
5057
5058credits:
5059  - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
5060
5061requires: Fx
5062
5063provides: Fx.Transitions
5064
5065...
5066*/
5067
5068Fx.implement({
5069
5070	getTransition: function(){
5071		var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
5072		if (typeof trans == 'string'){
5073			var data = trans.split(':');
5074			trans = Fx.Transitions;
5075			trans = trans[data[0]] || trans[data[0].capitalize()];
5076			if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
5077		}
5078		return trans;
5079	}
5080
5081});
5082
5083Fx.Transition = function(transition, params){
5084	params = Array.from(params);
5085	var easeIn = function(pos){
5086		return transition(pos, params);
5087	};
5088	return Object.append(easeIn, {
5089		easeIn: easeIn,
5090		easeOut: function(pos){
5091			return 1 - transition(1 - pos, params);
5092		},
5093		easeInOut: function(pos){
5094			return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
5095		}
5096	});
5097};
5098
5099Fx.Transitions = {
5100
5101	linear: function(zero){
5102		return zero;
5103	}
5104
5105};
5106
5107//<1.2compat>
5108
5109Fx.Transitions = new Hash(Fx.Transitions);
5110
5111//</1.2compat>
5112
5113Fx.Transitions.extend = function(transitions){
5114	for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
5115};
5116
5117Fx.Transitions.extend({
5118
5119	Pow: function(p, x){
5120		return Math.pow(p, x && x[0] || 6);
5121	},
5122
5123	Expo: function(p){
5124		return Math.pow(2, 8 * (p - 1));
5125	},
5126
5127	Circ: function(p){
5128		return 1 - Math.sin(Math.acos(p));
5129	},
5130
5131	Sine: function(p){
5132		return 1 - Math.cos(p * Math.PI / 2);
5133	},
5134
5135	Back: function(p, x){
5136		x = x && x[0] || 1.618;
5137		return Math.pow(p, 2) * ((x + 1) * p - x);
5138	},
5139
5140	Bounce: function(p){
5141		var value;
5142		for (var a = 0, b = 1; 1; a += b, b /= 2){
5143			if (p >= (7 - 4 * a) / 11){
5144				value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
5145				break;
5146			}
5147		}
5148		return value;
5149	},
5150
5151	Elastic: function(p, x){
5152		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
5153	}
5154
5155});
5156
5157['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
5158	Fx.Transitions[transition] = new Fx.Transition(function(p){
5159		return Math.pow(p, i + 2);
5160	});
5161});
5162
5163
5164/*
5165---
5166
5167name: Request
5168
5169description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
5170
5171license: MIT-style license.
5172
5173requires: [Object, Element, Chain, Events, Options, Browser]
5174
5175provides: Request
5176
5177...
5178*/
5179
5180(function(){
5181
5182var empty = function(){},
5183	progressSupport = ('onprogress' in new Browser.Request);
5184
5185var Request = this.Request = new Class({
5186
5187	Implements: [Chain, Events, Options],
5188
5189	options: {/*
5190		onRequest: function(){},
5191		onLoadstart: function(event, xhr){},
5192		onProgress: function(event, xhr){},
5193		onComplete: function(){},
5194		onCancel: function(){},
5195		onSuccess: function(responseText, responseXML){},
5196		onFailure: function(xhr){},
5197		onException: function(headerName, value){},
5198		onTimeout: function(){},
5199		user: '',
5200		password: '',*/
5201		url: '',
5202		data: '',
5203		headers: {
5204			'X-Requested-With': 'XMLHttpRequest',
5205			'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
5206		},
5207		async: true,
5208		format: false,
5209		method: 'post',
5210		link: 'ignore',
5211		isSuccess: null,
5212		emulation: true,
5213		urlEncoded: true,
5214		encoding: 'utf-8',
5215		evalScripts: false,
5216		evalResponse: false,
5217		timeout: 0,
5218		noCache: false
5219	},
5220
5221	initialize: function(options){
5222		this.xhr = new Browser.Request();
5223		this.setOptions(options);
5224		this.headers = this.options.headers;
5225	},
5226
5227	onStateChange: function(){
5228		var xhr = this.xhr;
5229		if (xhr.readyState != 4 || !this.running) return;
5230		this.running = false;
5231		this.status = 0;
5232		Function.attempt(function(){
5233			var status = xhr.status;
5234			this.status = (status == 1223) ? 204 : status;
5235		}.bind(this));
5236		xhr.onreadystatechange = empty;
5237		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
5238		clearTimeout(this.timer);
5239		
5240		this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML};
5241		if (this.options.isSuccess.call(this, this.status))
5242			this.success(this.response.text, this.response.xml);
5243		else
5244			this.failure();
5245	},
5246
5247	isSuccess: function(){
5248		var status = this.status;
5249		return (status >= 200 && status < 300);
5250	},
5251
5252	isRunning: function(){
5253		return !!this.running;
5254	},
5255
5256	processScripts: function(text){
5257		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
5258		return text.stripScripts(this.options.evalScripts);
5259	},
5260
5261	success: function(text, xml){
5262		this.onSuccess(this.processScripts(text), xml);
5263	},
5264
5265	onSuccess: function(){
5266		this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
5267	},
5268
5269	failure: function(){
5270		this.onFailure();
5271	},
5272
5273	onFailure: function(){
5274		this.fireEvent('complete').fireEvent('failure', this.xhr);
5275	},
5276	
5277	loadstart: function(event){
5278		this.fireEvent('loadstart', [event, this.xhr]);
5279	},
5280	
5281	progress: function(event){
5282		this.fireEvent('progress', [event, this.xhr]);
5283	},
5284	
5285	timeout: function(){
5286		this.fireEvent('timeout', this.xhr);
5287	},
5288
5289	setHeader: function(name, value){
5290		this.headers[name] = value;
5291		return this;
5292	},
5293
5294	getHeader: function(name){
5295		return Function.attempt(function(){
5296			return this.xhr.getResponseHeader(name);
5297		}.bind(this));
5298	},
5299
5300	check: function(){
5301		if (!this.running) return true;
5302		switch (this.options.link){
5303			case 'cancel': this.cancel(); return true;
5304			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
5305		}
5306		return false;
5307	},
5308	
5309	send: function(options){
5310		if (!this.check(options)) return this;
5311
5312		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
5313		this.running = true;
5314
5315		var type = typeOf(options);
5316		if (type == 'string' || type == 'element') options = {data: options};
5317
5318		var old = this.options;
5319		options = Object.append({data: old.data, url: old.url, method: old.method}, options);
5320		var data = options.data, url = String(options.url), method = options.method.toLowerCase();
5321
5322		switch (typeOf(data)){
5323			case 'element': data = document.id(data).toQueryString(); break;
5324			case 'object': case 'hash': data = Object.toQueryString(data);
5325		}
5326
5327		if (this.options.format){
5328			var format = 'format=' + this.options.format;
5329			data = (data) ? format + '&' + data : format;
5330		}
5331
5332		if (this.options.emulation && !['get', 'post'].contains(method)){
5333			var _method = '_method=' + method;
5334			data = (data) ? _method + '&' + data : _method;
5335			method = 'post';
5336		}
5337
5338		if (this.options.urlEncoded && ['post', 'put'].contains(method)){
5339			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
5340			this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding;
5341		}
5342
5343		if (!url) url = document.location.pathname;
5344		
5345		var trimPosition = url.lastIndexOf('/');
5346		if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);
5347
5348		if (this.options.noCache)
5349			url += (url.contains('?') ? '&' : '?') + String.uniqueID();
5350
5351		if (data && method == 'get'){
5352			url += (url.contains('?') ? '&' : '?') + data;
5353			data = null;
5354		}
5355
5356		var xhr = this.xhr;
5357		if (progressSupport){
5358			xhr.onloadstart = this.loadstart.bind(this);
5359			xhr.onprogress = this.progress.bind(this);
5360		}
5361
5362		xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
5363		if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
5364		
5365		xhr.onreadystatechange = this.onStateChange.bind(this);
5366
5367		Object.each(this.headers, function(value, key){
5368			try {
5369				xhr.setRequestHeader(key, value);
5370			} catch (e){
5371				this.fireEvent('exception', [key, value]);
5372			}
5373		}, this);
5374
5375		this.fireEvent('request');
5376		xhr.send(data);
5377		if (!this.options.async) this.onStateChange();
5378		if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
5379		return this;
5380	},
5381
5382	cancel: function(){
5383		if (!this.running) return this;
5384		this.running = false;
5385		var xhr = this.xhr;
5386		xhr.abort();
5387		clearTimeout(this.timer);
5388		xhr.onreadystatechange = empty;
5389		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
5390		this.xhr = new Browser.Request();
5391		this.fireEvent('cancel');
5392		return this;
5393	}
5394
5395});
5396
5397var methods = {};
5398['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
5399	methods[method] = function(data){
5400		var object = {
5401			method: method
5402		};
5403		if (data != null) object.data = data;
5404		return this.send(object);
5405	};
5406});
5407
5408Request.implement(methods);
5409
5410Element.Properties.send = {
5411
5412	set: function(options){
5413		var send = this.get('send').cancel();
5414		send.setOptions(options);
5415		return this;
5416	},
5417
5418	get: function(){
5419		var send = this.retrieve('send');
5420		if (!send){
5421			send = new Request({
5422				data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
5423			});
5424			this.store('send', send);
5425		}
5426		return send;
5427	}
5428
5429};
5430
5431Element.implement({
5432
5433	send: function(url){
5434		var sender = this.get('send');
5435		sender.send({data: this, url: url || sender.options.url});
5436		return this;
5437	}
5438
5439});
5440
5441})();
5442
5443/*
5444---
5445
5446name: Request.HTML
5447
5448description: Extends the basic Request Class with additional methods for interacting with HTML responses.
5449
5450license: MIT-style license.
5451
5452requires: [Element, Request]
5453
5454provides: Request.HTML
5455
5456...
5457*/
5458
5459Request.HTML = new Class({
5460
5461	Extends: Request,
5462
5463	options: {
5464		update: false,
5465		append: false,
5466		evalScripts: true,
5467		filter: false,
5468		headers: {
5469			Accept: 'text/html, application/xml, text/xml, */*'
5470		}
5471	},
5472
5473	success: function(text){
5474		var options = this.options, response = this.response;
5475
5476		response.html = text.stripScripts(function(script){
5477			response.javascript = script;
5478		});
5479
5480		var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
5481		if (match) response.html = match[1];
5482		var temp = new Element('div').set('html', response.html);
5483
5484		response.tree = temp.childNodes;
5485		response.elements = temp.getElements('*');
5486
5487		if (options.filter) response.tree = response.elements.filter(options.filter);
5488		if (options.update) document.id(options.update).empty().set('html', response.html);
5489		else if (options.append) document.id(options.append).adopt(temp.getChildren());
5490		if (options.evalScripts) Browser.exec(response.javascript);
5491
5492		this.onSuccess(response.tree, response.elements, response.html, response.javascript);
5493	}
5494
5495});
5496
5497Element.Properties.load = {
5498
5499	set: function(options){
5500		var load = this.get('load').cancel();
5501		load.setOptions(options);
5502		return this;
5503	},
5504
5505	get: function(){
5506		var load = this.retrieve('load');
5507		if (!load){
5508			load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'});
5509			this.store('load', load);
5510		}
5511		return load;
5512	}
5513
5514};
5515
5516Element.implement({
5517
5518	load: function(){
5519		this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString}));
5520		return this;
5521	}
5522
5523});
5524
5525
5526/*
5527---
5528
5529name: JSON
5530
5531description: JSON encoder and decoder.
5532
5533license: MIT-style license.
5534
5535See Also: <http://www.json.org/>
5536
5537requires: [Array, String, Number, Function]
5538
5539provides: JSON
5540
5541...
5542*/
5543
5544if (typeof JSON == 'undefined') this.JSON = {};
5545
5546//<1.2compat>
5547
5548JSON = new Hash({
5549	stringify: JSON.stringify,
5550	parse: JSON.parse
5551});
5552
5553//</1.2compat>
5554
5555(function(){
5556
5557var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
5558
5559var escape = function(chr){
5560	return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
5561};
5562
5563JSON.validate = function(string){
5564	string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
5565					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
5566					replace(/(?:^|:|,)(?:\s*\[)+/g, '');
5567
5568	return (/^[\],:{}\s]*$/).test(string);
5569};
5570
5571JSON.encode = JSON.stringify ? function(obj){
5572	return JSON.stringify(obj);
5573} : function(obj){
5574	if (obj && obj.toJSON) obj = obj.toJSON();
5575
5576	switch (typeOf(obj)){
5577		case 'string':
5578			return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
5579		case 'array':
5580			return '[' + obj.map(JSON.encode).clean() + ']';
5581		case 'object': case 'hash':
5582			var string = [];
5583			Object.each(obj, function(value, key){
5584				var json = JSON.encode(value);
5585				if (json) string.push(JSON.encode(key) + ':' + json);
5586			});
5587			return '{' + string + '}';
5588		case 'number': case 'boolean': return '' + obj;
5589		case 'null': return 'null';
5590	}
5591
5592	return null;
5593};
5594
5595JSON.decode = function(string, secure){
5596	if (!string || typeOf(string) != 'string') return null;
5597
5598	if (secure || JSON.secure){
5599		if (JSON.parse) return JSON.parse(string);
5600		if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
5601	}
5602
5603	return eval('(' + string + ')');
5604};
5605
5606})();
5607
5608
5609/*
5610---
5611
5612name: Request.JSON
5613
5614description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
5615
5616license: MIT-style license.
5617
5618requires: [Request, JSON]
5619
5620provides: Request.JSON
5621
5622...
5623*/
5624
5625Request.JSON = new Class({
5626
5627	Extends: Request,
5628
5629	options: {
5630		/*onError: function(text, error){},*/
5631		secure: true
5632	},
5633
5634	initialize: function(options){
5635		this.parent(options);
5636		Object.append(this.headers, {
5637			'Accept': 'application/json',
5638			'X-Request': 'JSON'
5639		});
5640	},
5641
5642	success: function(text){
5643		var json;
5644		try {
5645			json = this.response.json = JSON.decode(text, this.options.secure);
5646		} catch (error){
5647			this.fireEvent('error', [text, error]);
5648			return;
5649		}
5650		if (json == null) this.onFailure();
5651		else this.onSuccess(json, text);
5652	}
5653
5654});
5655
5656
5657/*
5658---
5659
5660name: Cookie
5661
5662description: Class for creating, reading, and deleting browser Cookies.
5663
5664license: MIT-style license.
5665
5666credits:
5667  - Based on the functions by Peter-Paul Koch (http://quirksmode.org).
5668
5669requires: [Options, Browser]
5670
5671provides: Cookie
5672
5673...
5674*/
5675
5676var Cookie = new Class({
5677
5678	Implements: Options,
5679
5680	options: {
5681		path: '/',
5682		domain: false,
5683		duration: false,
5684		secure: false,
5685		document: document,
5686		encode: true
5687	},
5688
5689	initialize: function(key, options){
5690		this.key = key;
5691		this.setOptions(options);
5692	},
5693
5694	write: function(value){
5695		if (this.options.encode) value = encodeURIComponent(value);
5696		if (this.options.domain) value += '; domain=' + this.options.domain;
5697		if (this.options.path) value += '; path=' + this.options.path;
5698		if (this.options.duration){
5699			var date = new Date();
5700			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
5701			value += '; expires=' + date.toGMTString();
5702		}
5703		if (this.options.secure) value += '; secure';
5704		this.options.document.cookie = this.key + '=' + value;
5705		return this;
5706	},
5707
5708	read: function(){
5709		var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
5710		return (value) ? decodeURIComponent(value[1]) : null;
5711	},
5712
5713	dispose: function(){
5714		new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write('');
5715		return this;
5716	}
5717
5718});
5719
5720Cookie.write = function(key, value, options){
5721	return new Cookie(key, options).write(value);
5722};
5723
5724Cookie.read = function(key){
5725	return new Cookie(key).read();
5726};
5727
5728Cookie.dispose = function(key, options){
5729	return new Cookie(key, options).dispose();
5730};
5731
5732
5733/*
5734---
5735
5736name: DOMReady
5737
5738description: Contains the custom event domready.
5739
5740license: MIT-style license.
5741
5742requires: [Browser, Element, Element.Event]
5743
5744provides: [DOMReady, DomReady]
5745
5746...
5747*/
5748
5749(function(window, document){
5750
5751var ready,
5752	loaded,
5753	checks = [],
5754	shouldPoll,
5755	timer,
5756	testElement = document.createElement('div');
5757
5758var domready = function(){
5759	clearTimeout(timer);
5760	if (ready) return;
5761	Browser.loaded = ready = true;
5762	document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
5763	
5764	document.fireEvent('domready');
5765	window.fireEvent('domready');
5766};
5767
5768var check = function(){
5769	for (var i = checks.length; i--;) if (checks[i]()){
5770		domready();
5771		return true;
5772	}
5773	return false;
5774};
5775
5776var poll = function(){
5777	clearTimeout(timer);
5778	if (!check()) timer = setTimeout(poll, 10);
5779};
5780
5781document.addListener('DOMContentLoaded', domready);
5782
5783/*<ltIE8>*/
5784// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
5785// testElement.doScroll() throws when the DOM is not ready, only in the top window
5786var doScrollWorks = function(){
5787	try {
5788		testElement.doScroll();
5789		return true;
5790	} catch (e){}
5791	return false;
5792}
5793// If doScroll works already, it can't be used to determine domready
5794//   e.g. in an iframe
5795if (testElement.doScroll && !doScrollWorks()){
5796	checks.push(doScrollWorks);
5797	shouldPoll = true;
5798}
5799/*</ltIE8>*/
5800
5801if (document.readyState) checks.push(function(){
5802	var state = document.readyState;
5803	return (state == 'loaded' || state == 'complete');
5804});
5805
5806if ('onreadystatechange' in document) document.addListener('readystatechange', check);
5807else shouldPoll = true;
5808
5809if (shouldPoll) poll();
5810
5811Element.Events.domready = {
5812	onAdd: function(fn){
5813		if (ready) fn.call(this);
5814	}
5815};
5816
5817// Make sure that domready fires before load
5818Element.Events.load = {
5819	base: 'load',
5820	onAdd: function(fn){
5821		if (loaded && this == window) fn.call(this);
5822	},
5823	condition: function(){
5824		if (this == window){
5825			domready();
5826			delete Element.Events.load;
5827		}
5828		return true;
5829	}
5830};
5831
5832// This is based on the custom load event
5833window.addEvent('load', function(){
5834	loaded = true;
5835});
5836
5837})(window, document);
5838
5839
5840/*
5841---
5842
5843name: Swiff
5844
5845description: Wrapper for embedding SWF movies. Supports External Interface Communication.
5846
5847license: MIT-style license.
5848
5849credits:
5850  - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
5851
5852requires: [Options, Object, Element]
5853
5854provides: Swiff
5855
5856...
5857*/
5858
5859(function(){
5860
5861var Swiff = this.Swiff = new Class({
5862
5863	Implements: Options,
5864
5865	options: {
5866		id: null,
5867		height: 1,
5868		width: 1,
5869		container: null,
5870		properties: {},
5871		params: {
5872			quality: 'high',
5873			allowScriptAccess: 'always',
5874			wMode: 'window',
5875			swLiveConnect: true
5876		},
5877		callBacks: {},
5878		vars: {}
5879	},
5880
5881	toElement: function(){
5882		return this.object;
5883	},
5884
5885	initialize: function(path, options){
5886		this.instance = 'Swiff_' + String.uniqueID();
5887
5888		this.setOptions(options);
5889		options = this.options;
5890		var id = this.id = options.id || this.instance;
5891		var container = document.id(options.container);
5892
5893		Swiff.CallBacks[this.instance] = {};
5894
5895		var params = options.params, vars = options.vars, callBacks = options.callBacks;
5896		var properties = Object.append({height: options.height, width: options.width}, options.properties);
5897
5898		var self = this;
5899
5900		for (var callBack in callBacks){
5901			Swiff.CallBacks[this.instance][callBack] = (function(option){
5902				return function(){
5903					return option.apply(self.object, arguments);
5904				};
5905			})(callBacks[callBack]);
5906			vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
5907		}
5908
5909		params.flashVars = Object.toQueryString(vars);
5910		if (Browser.ie){
5911			properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
5912			params.movie = path;
5913		} else {
5914			properties.type = 'application/x-shockwave-flash';
5915		}
5916		properties.data = path;
5917
5918		var build = '<object id="' + id + '"';
5919		for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
5920		build += '>';
5921		for (var param in params){
5922			if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
5923		}
5924		build += '</object>';
5925		this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
5926	},
5927
5928	replaces: function(element){
5929		element = document.id(element, true);
5930		element.parentNode.replaceChild(this.toElement(), element);
5931		return this;
5932	},
5933
5934	inject: function(element){
5935		document.id(element, true).appendChild(this.toElement());
5936		return this;
5937	},
5938
5939	remote: function(){
5940		return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments));
5941	}
5942
5943});
5944
5945Swiff.CallBacks = {};
5946
5947Swiff.remote = function(obj, fn){
5948	var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
5949	return eval(rs);
5950};
5951
5952})();
5953

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.