3 MooTools: the javascript framework
6 - http://mootools.net/core/f62dd4514b59c41f42c7579664bca750
9 - packager build Core/Core Core/Array Core/Event Core/Browser Core/Class.Extras Core/Element.Event Core/Element.Dimensions Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/DOMReady
16 description: The heart of MooTools.
18 license: MIT-style license.
20 copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).
22 authors: The MooTools production team (http://mootools.net/developers/)
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)
28 provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
37 build: 'a3eed692dd85050d80168ec2c708efe901bb7db3'
42 var typeOf = this.typeOf = function(item){
43 if (item == null) return 'null';
44 if (item.$family) return item.$family();
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';
57 var instanceOf = this.instanceOf = function(item, object){
58 if (item == null) return false;
59 var constructor = item.$constructor || item.constructor;
61 if (constructor === object) return true;
62 constructor = constructor.parent;
64 return item instanceof object;
67 // Function overloading
69 var Function = this.Function;
71 var enumerables = true;
72 for (var i in {toString: 1}) enumerables = null;
73 if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
75 Function.prototype.overloadSetter = function(usePlural){
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--;){
83 if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
86 self.call(this, a, b);
92 Function.prototype.overloadGetter = function(usePlural){
96 if (usePlural || typeof a != 'string') args = a;
97 else if (arguments.length > 1) args = arguments;
100 for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
102 result = self.call(this, a);
108 Function.prototype.extend = function(key, value){
112 Function.prototype.implement = function(key, value){
113 this.prototype[key] = value;
118 var slice = Array.prototype.slice;
120 Function.from = function(item){
121 return (typeOf(item) == 'function') ? item : function(){
126 Array.from = function(item){
127 if (item == null) return [];
128 return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
131 Number.from = function(item){
132 var number = parseFloat(item);
133 return isFinite(number) ? number : null;
136 String.from = function(item){
150 this.$protected = true;
158 var Type = this.Type = function(name, object){
160 var lower = name.toLowerCase();
161 var typeCheck = function(item){
162 return (typeOf(item) == lower);
165 Type['is' + name] = typeCheck;
167 object.prototype.$family = (function(){
171 object.type = typeCheck;
176 if (object == null) return null;
179 object.$constructor = Type;
180 object.prototype.$constructor = object;
185 var toString = Object.prototype.toString;
187 Type.isEnumerable = function(item){
188 return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
193 var hooksOf = function(object){
194 var type = typeOf(object.prototype);
195 return hooks[type] || (hooks[type] = []);
198 var implement = function(name, method){
199 if (method && method.$hidden) return this;
201 var hooks = hooksOf(this);
203 for (var i = 0; i < hooks.length; i++){
205 if (typeOf(hook) == 'type') implement.call(hook, name, method);
206 else hook.call(this, name, method);
209 var previous = this.prototype[name];
210 if (previous == null || !previous.$protected) this.prototype[name] = method;
212 if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
213 return method.apply(item, slice.call(arguments, 1));
219 var extend = function(name, method){
220 if (method && method.$hidden) return this;
221 var previous = this[name];
222 if (previous == null || !previous.$protected) this[name] = method;
228 implement: implement.overloadSetter(),
230 extend: extend.overloadSetter(),
232 alias: function(name, existing){
233 implement.call(this, name, this.prototype[existing]);
236 mirror: function(hook){
237 hooksOf(this).push(hook);
243 new Type('Type', Type);
247 var force = function(name, object, methods){
248 var isType = (object != Object),
249 prototype = object.prototype;
251 if (isType) object = new Type(name, object);
253 for (var i = 0, l = methods.length; i < l; i++){
254 var key = methods[i],
255 generic = object[key],
256 proto = prototype[key];
258 if (generic) generic.protect();
260 if (isType && proto){
261 delete prototype[key];
262 prototype[key] = proto.protect();
266 if (isType) object.implement(prototype);
271 force('String', String, [
272 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
273 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
275 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
276 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
277 ])('Number', Number, [
278 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
279 ])('Function', Function, [
280 'apply', 'call', 'bind'
281 ])('RegExp', RegExp, [
283 ])('Object', Object, [
284 'create', 'defineProperty', 'defineProperties', 'keys',
285 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
286 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
287 ])('Date', Date, ['now']);
289 Object.extend = extend.overloadSetter();
291 Date.extend('now', function(){
295 new Type('Boolean', Boolean);
297 // fixes NaN returning as Number
299 Number.prototype.$family = function(){
300 return isFinite(this) ? 'number' : 'null';
305 Number.extend('random', function(min, max){
306 return Math.floor(Math.random() * (max - min + 1) + min);
311 Object.extend('forEach', function(object, fn, bind){
312 for (var key in object){
313 if (object.hasOwnProperty(key)) fn.call(bind, object[key], key, object);
317 Object.each = Object.forEach;
321 forEach: function(fn, bind){
322 for (var i = 0, l = this.length; i < l; i++){
323 if (i in this) fn.call(bind, this[i], i, this);
327 each: function(fn, bind){
328 Array.forEach(this, fn, bind);
334 // Array & Object cloning, Object merging and appending
336 var cloneOf = function(item){
337 switch (typeOf(item)){
338 case 'array': return item.clone();
339 case 'object': return Object.clone(item);
340 default: return item;
344 Array.implement('clone', function(){
345 var i = this.length, clone = new Array(i);
346 while (i--) clone[i] = cloneOf(this[i]);
350 var mergeOne = function(source, key, current){
351 switch (typeOf(current)){
353 if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
354 else source[key] = Object.clone(current);
356 case 'array': source[key] = current.clone(); break;
357 default: source[key] = current;
364 merge: function(source, k, v){
365 if (typeOf(k) == 'string') return mergeOne(source, k, v);
366 for (var i = 1, l = arguments.length; i < l; i++){
367 var object = arguments[i];
368 for (var key in object) mergeOne(source, key, object[key]);
373 clone: function(object){
375 for (var key in object) clone[key] = cloneOf(object[key]);
379 append: function(original){
380 for (var i = 1, l = arguments.length; i < l; i++){
381 var extended = arguments[i] || {};
382 for (var key in extended) original[key] = extended[key];
391 ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
397 var UID = Date.now();
399 String.extend('uniqueID', function(){
400 return (UID++).toString(36);
405 var Hash = this.Hash = new Type('Hash', function(object){
406 if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
407 for (var key in object) this[key] = object[key];
413 forEach: function(fn, bind){
414 Object.forEach(this, fn, bind);
417 getClean: function(){
419 for (var key in this){
420 if (this.hasOwnProperty(key)) clean[key] = this[key];
425 getLength: function(){
427 for (var key in this){
428 if (this.hasOwnProperty(key)) length++;
435 Hash.alias('each', 'forEach');
437 Object.type = Type.isObject;
439 var Native = this.Native = function(properties){
440 return new Type(properties.name, properties.initialize);
443 Native.type = Type.type;
445 Native.implement = function(objects, methods){
446 for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
450 var arrayType = Array.type;
451 Array.type = function(item){
452 return instanceOf(item, Array) || arrayType(item);
455 this.$A = function(item){
456 return Array.from(item).slice();
459 this.$arguments = function(i){
465 this.$chk = function(obj){
466 return !!(obj || obj === 0);
469 this.$clear = function(timer){
471 clearInterval(timer);
475 this.$defined = function(obj){
476 return (obj != null);
479 this.$each = function(iterable, fn, bind){
480 var type = typeOf(iterable);
481 ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind);
484 this.$empty = function(){};
486 this.$extend = function(original, extended){
487 return Object.append(original, extended);
490 this.$H = function(object){
491 return new Hash(object);
494 this.$merge = function(){
495 var args = Array.slice(arguments);
497 return Object.merge.apply(null, args);
500 this.$lambda = Function.from;
501 this.$mixin = Object.merge;
502 this.$random = Number.random;
503 this.$splat = Array.from;
504 this.$time = Date.now;
506 this.$type = function(object){
507 var type = typeOf(object);
508 if (type == 'elements') return 'array';
509 return (type == 'null') ? false : type;
512 this.$unlink = function(object){
513 switch (typeOf(object)){
514 case 'object': return Object.clone(object);
515 case 'array': return Array.clone(object);
516 case 'hash': return new Hash(object);
517 default: return object;
531 description: Contains Array Prototypes like each, contains, and erase.
533 license: MIT-style license.
544 invoke: function(methodName){
545 var args = Array.slice(arguments, 1);
546 return this.map(function(item){
547 return item[methodName].apply(item, args);
551 every: function(fn, bind){
552 for (var i = 0, l = this.length; i < l; i++){
553 if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
558 filter: function(fn, bind){
560 for (var i = 0, l = this.length; i < l; i++){
561 if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
567 return this.filter(function(item){
572 indexOf: function(item, from){
573 var len = this.length;
574 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
575 if (this[i] === item) return i;
580 map: function(fn, bind){
582 for (var i = 0, l = this.length; i < l; i++){
583 if (i in this) results[i] = fn.call(bind, this[i], i, this);
588 some: function(fn, bind){
589 for (var i = 0, l = this.length; i < l; i++){
590 if ((i in this) && fn.call(bind, this[i], i, this)) return true;
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];
601 link: function(object){
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];
615 contains: function(item, from){
616 return this.indexOf(item, from) != -1;
619 append: function(array){
620 this.push.apply(this, array);
625 return (this.length) ? this[this.length - 1] : null;
628 getRandom: function(){
629 return (this.length) ? this[Number.random(0, this.length - 1)] : null;
632 include: function(item){
633 if (!this.contains(item)) this.push(item);
637 combine: function(array){
638 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
642 erase: function(item){
643 for (var i = this.length; i--;){
644 if (this[i] === item) this.splice(i, 1);
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]);
665 for (var i = 0, l = this.length; i < l; i++){
666 if (this[i] != null) return this[i];
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);
677 return (array) ? rgb : 'rgb(' + rgb + ')';
680 rgbToHex: function(array){
681 if (this.length < 3) return null;
682 if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
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);
688 return (array) ? hex : '#' + hex.join('');
695 Array.alias('extend', 'append');
697 var $pick = function(){
698 return Array.from(arguments).pick();
709 description: Contains Function Prototypes like create, bind, pass, and delay.
711 license: MIT-style license.
723 for (var i = 0, l = arguments.length; i < l; i++){
725 return arguments[i]();
735 attempt: function(args, bind){
737 return this.apply(bind, Array.from(args));
743 bind: function(bind){
745 args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
748 if (!args && !arguments.length) return self.call(bind);
749 if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
750 return self.apply(bind, args || arguments);
754 pass: function(args, bind){
756 if (args != null) args = Array.from(args);
758 return self.apply(bind, args || arguments);
762 delay: function(delay, bind, args){
763 return setTimeout(this.pass(args, bind), delay);
766 periodical: function(periodical, bind, args){
767 return setInterval(this.pass(args, bind), periodical);
774 delete Function.prototype.bind;
778 create: function(options){
780 options = options || {};
781 return function(event){
782 var args = options.arguments;
783 args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
784 if (options.event) args = [event || window.event].extend(args);
785 var returns = function(){
786 return self.apply(options.bind || null, args);
788 if (options.delay) return setTimeout(returns, options.delay);
789 if (options.periodical) return setInterval(returns, options.periodical);
790 if (options.attempt) return Function.attempt(returns);
795 bind: function(bind, args){
797 if (args != null) args = Array.from(args);
799 return self.apply(bind, args || arguments);
803 bindWithEvent: function(bind, args){
805 if (args != null) args = Array.from(args);
806 return function(event){
807 return self.apply(bind, (args == null) ? arguments : [event].concat(args));
811 run: function(args, bind){
812 return this.apply(bind, Array.from(args));
817 var $try = Function.attempt;
827 description: Contains Number Prototypes like limit, round, times, and ceil.
829 license: MIT-style license.
840 limit: function(min, max){
841 return Math.min(max, Math.max(min, this));
844 round: function(precision){
845 precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
846 return Math.round(this * precision) / precision;
849 times: function(fn, bind){
850 for (var i = 0; i < this; i++) fn.call(bind, i, this);
854 return parseFloat(this);
857 toInt: function(base){
858 return parseInt(this, base || 10);
863 Number.alias('each', 'times');
867 math.each(function(name){
868 if (!Number[name]) methods[name] = function(){
869 return Math[name].apply(null, [this].concat(Array.from(arguments)));
872 Number.implement(methods);
873 })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
881 description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
883 license: MIT-style license.
894 test: function(regex, params){
895 return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
898 contains: function(string, separator){
899 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
903 return this.replace(/^\s+|\s+$/g, '');
907 return this.replace(/\s+/g, ' ').trim();
910 camelCase: function(){
911 return this.replace(/-\D/g, function(match){
912 return match.charAt(1).toUpperCase();
916 hyphenate: function(){
917 return this.replace(/[A-Z]/g, function(match){
918 return ('-' + match.charAt(0).toLowerCase());
922 capitalize: function(){
923 return this.replace(/\b[a-z]/g, function(match){
924 return match.toUpperCase();
928 escapeRegExp: function(){
929 return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
932 toInt: function(base){
933 return parseInt(this, base || 10);
937 return parseFloat(this);
940 hexToRgb: function(array){
941 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
942 return (hex) ? hex.slice(1).hexToRgb(array) : null;
945 rgbToHex: function(array){
946 var rgb = this.match(/\d{1,3}/g);
947 return (rgb) ? rgb.rgbToHex(array) : null;
950 substitute: function(object, regexp){
951 return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
952 if (match.charAt(0) == '\\') return match.slice(1);
953 return (object[name] != null) ? object[name] : '';
965 description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
967 license: MIT-style license.
969 requires: [Array, Function, Number, String]
971 provides: [Browser, Window, Document]
978 var document = this.document;
979 var window = document.window = this;
983 this.$uid = (window.ActiveXObject) ? function(item){
984 return (item.uid || (item.uid = [UID++]))[0];
986 return item.uid || (item.uid = UID++);
992 var ua = navigator.userAgent.toLowerCase(),
993 platform = navigator.platform.toLowerCase(),
994 UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
995 mode = UA[1] == 'ie' && document.documentMode;
997 var Browser = this.Browser = {
999 extend: Function.prototype.extend,
1001 name: (UA[1] == 'version') ? UA[3] : UA[1],
1003 version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
1006 name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
1010 xpath: !!(document.evaluate),
1011 air: !!(window.runtime),
1012 query: !!(document.querySelector),
1013 json: !!(window.JSON)
1020 Browser[Browser.name] = true;
1021 Browser[Browser.name + parseInt(Browser.version, 10)] = true;
1022 Browser.Platform[Browser.Platform.name] = true;
1026 Browser.Request = (function(){
1028 var XMLHTTP = function(){
1029 return new XMLHttpRequest();
1032 var MSXML2 = function(){
1033 return new ActiveXObject('MSXML2.XMLHTTP');
1036 var MSXML = function(){
1037 return new ActiveXObject('Microsoft.XMLHTTP');
1040 return Function.attempt(function(){
1053 Browser.Features.xhr = !!(Browser.Request);
1057 var version = (Function.attempt(function(){
1058 return navigator.plugins['Shockwave Flash'].description;
1060 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
1061 }) || '0 r0').match(/\d+/g);
1063 Browser.Plugins.Flash = {
1064 version: Number(version[0] || '0.' + version[1]) || 0,
1065 build: Number(version[2]) || 0
1070 Browser.exec = function(text){
1071 if (!text) return text;
1072 if (window.execScript){
1073 window.execScript(text);
1075 var script = document.createElement('script');
1076 script.setAttribute('type', 'text/javascript');
1078 document.head.appendChild(script);
1079 document.head.removeChild(script);
1084 String.implement('stripScripts', function(exec){
1086 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
1087 scripts += code + '\n';
1090 if (exec === true) Browser.exec(scripts);
1091 else if (typeOf(exec) == 'function') exec(scripts, text);
1098 Document: this.Document,
1099 Window: this.Window,
1100 Element: this.Element,
1104 this.Window = this.$constructor = new Type('Window', function(){});
1106 this.$family = Function.from('window').hide();
1108 Window.mirror(function(name, method){
1109 window[name] = method;
1112 this.Document = document.$constructor = new Type('Document', function(){});
1114 document.$family = Function.from('document').hide();
1116 Document.mirror(function(name, method){
1117 document[name] = method;
1120 document.html = document.documentElement;
1121 document.head = document.getElementsByTagName('head')[0];
1123 if (document.execCommand) try {
1124 document.execCommand("BackgroundImageCache", false, true);
1127 if (this.attachEvent && !this.addEventListener){
1128 var unloadEvent = function(){
1129 this.detachEvent('onunload', unloadEvent);
1130 document.head = document.html = document.window = null;
1132 this.attachEvent('onunload', unloadEvent);
1135 // IE fails on collections and <select>.options (refers to <select>)
1136 var arrayFrom = Array.from;
1138 arrayFrom(document.html.childNodes);
1140 Array.from = function(item){
1141 if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
1142 var i = item.length, array = new Array(i);
1143 while (i--) array[i] = item[i];
1146 return arrayFrom(item);
1149 var prototype = Array.prototype,
1150 slice = prototype.slice;
1151 ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
1152 var method = prototype[name];
1153 Array[name] = function(item){
1154 return method.apply(Array.from(item), slice.call(arguments, 1));
1161 if (Browser.Platform.ios) Browser.Platform.ipod = true;
1163 Browser.Engine = {};
1165 var setEngine = function(name, version){
1166 Browser.Engine.name = name;
1167 Browser.Engine[name + version] = true;
1168 Browser.Engine.version = version;
1172 Browser.Engine.trident = true;
1174 switch (Browser.version){
1175 case 6: setEngine('trident', 4); break;
1176 case 7: setEngine('trident', 5); break;
1177 case 8: setEngine('trident', 6);
1181 if (Browser.firefox){
1182 Browser.Engine.gecko = true;
1184 if (Browser.version >= 3) setEngine('gecko', 19);
1185 else setEngine('gecko', 18);
1188 if (Browser.safari || Browser.chrome){
1189 Browser.Engine.webkit = true;
1191 switch (Browser.version){
1192 case 2: setEngine('webkit', 419); break;
1193 case 3: setEngine('webkit', 420); break;
1194 case 4: setEngine('webkit', 525);
1199 Browser.Engine.presto = true;
1201 if (Browser.version >= 9.6) setEngine('presto', 960);
1202 else if (Browser.version >= 9.5) setEngine('presto', 950);
1203 else setEngine('presto', 925);
1206 if (Browser.name == 'unknown'){
1207 switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){
1210 Browser.Engine.webkit = true;
1213 Browser.Engine.gecko = true;
1217 this.$exec = Browser.exec;
1229 description: Object generic methods
1231 license: MIT-style license.
1235 provides: [Object, Hash]
1243 subset: function(object, keys){
1245 for (var i = 0, l = keys.length; i < l; i++){
1247 results[k] = object[k];
1252 map: function(object, fn, bind){
1254 for (var key in object){
1255 if (object.hasOwnProperty(key)) results[key] = fn.call(bind, object[key], key, object);
1260 filter: function(object, fn, bind){
1262 Object.each(object, function(value, key){
1263 if (fn.call(bind, value, key, object)) results[key] = value;
1268 every: function(object, fn, bind){
1269 for (var key in object){
1270 if (object.hasOwnProperty(key) && !fn.call(bind, object[key], key)) return false;
1275 some: function(object, fn, bind){
1276 for (var key in object){
1277 if (object.hasOwnProperty(key) && fn.call(bind, object[key], key)) return true;
1282 keys: function(object){
1284 for (var key in object){
1285 if (object.hasOwnProperty(key)) keys.push(key);
1290 values: function(object){
1292 for (var key in object){
1293 if (object.hasOwnProperty(key)) values.push(object[key]);
1298 getLength: function(object){
1299 return Object.keys(object).length;
1302 keyOf: function(object, value){
1303 for (var key in object){
1304 if (object.hasOwnProperty(key) && object[key] === value) return key;
1309 contains: function(object, value){
1310 return Object.keyOf(object, value) != null;
1313 toQueryString: function(object, base){
1314 var queryString = [];
1316 Object.each(object, function(value, key){
1317 if (base) key = base + '[' + key + ']';
1319 switch (typeOf(value)){
1320 case 'object': result = Object.toQueryString(value, key); break;
1323 value.each(function(val, i){
1326 result = Object.toQueryString(qs, key);
1328 default: result = key + '=' + encodeURIComponent(value);
1330 if (value != null) queryString.push(result);
1333 return queryString.join('&');
1343 has: Object.prototype.hasOwnProperty,
1345 keyOf: function(value){
1346 return Object.keyOf(this, value);
1349 hasValue: function(value){
1350 return Object.contains(this, value);
1353 extend: function(properties){
1354 Hash.each(properties || {}, function(value, key){
1355 Hash.set(this, key, value);
1360 combine: function(properties){
1361 Hash.each(properties || {}, function(value, key){
1362 Hash.include(this, key, value);
1367 erase: function(key){
1368 if (this.hasOwnProperty(key)) delete this[key];
1373 return (this.hasOwnProperty(key)) ? this[key] : null;
1376 set: function(key, value){
1377 if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
1382 Hash.each(this, function(value, key){
1388 include: function(key, value){
1389 if (this[key] == null) this[key] = value;
1393 map: function(fn, bind){
1394 return new Hash(Object.map(this, fn, bind));
1397 filter: function(fn, bind){
1398 return new Hash(Object.filter(this, fn, bind));
1401 every: function(fn, bind){
1402 return Object.every(this, fn, bind);
1405 some: function(fn, bind){
1406 return Object.some(this, fn, bind);
1409 getKeys: function(){
1410 return Object.keys(this);
1413 getValues: function(){
1414 return Object.values(this);
1417 toQueryString: function(base){
1418 return Object.toQueryString(this, base);
1423 Hash.extend = Object.append;
1425 Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
1435 description: Contains the Event Class, to make the event object cross-browser.
1437 license: MIT-style license.
1439 requires: [Window, Document, Array, Function, String, Object]
1446 var Event = new Type('Event', function(event, win){
1447 if (!win) win = window;
1448 var doc = win.document;
1449 event = event || win.event;
1450 if (event.$extended) return event;
1451 this.$extended = true;
1452 var type = event.type,
1453 target = event.target || event.srcElement,
1456 while (target && target.nodeType == 3) target = target.parentNode;
1458 if (type.indexOf('key') != -1){
1459 var code = event.which || event.keyCode;
1460 var key = Object.keyOf(Event.Keys, code);
1461 if (type == 'keydown'){
1462 var fKey = code - 111;
1463 if (fKey > 0 && fKey < 13) key = 'f' + fKey;
1465 if (!key) key = String.fromCharCode(code).toLowerCase();
1466 } else if (type.test(/click|mouse|menu/i)){
1467 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
1469 x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
1470 y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
1473 x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
1474 y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
1476 if (type.test(/DOMMouseScroll|mousewheel/)){
1477 var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
1479 var rightClick = (event.which == 3) || (event.button == 2),
1481 if (type.test(/over|out/)){
1482 related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
1483 var testRelated = function(){
1484 while (related && related.nodeType == 3) related = related.parentNode;
1487 var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
1488 related = (hasRelated) ? related : null;
1490 } else if (type.test(/gesture|touch/i)){
1491 this.rotation = event.rotation;
1492 this.scale = event.scale;
1493 this.targetTouches = event.targetTouches;
1494 this.changedTouches = event.changedTouches;
1495 var touches = this.touches = event.touches;
1496 if (touches && touches[0]){
1497 var touch = touches[0];
1498 page = {x: touch.pageX, y: touch.pageY};
1499 client = {x: touch.clientX, y: touch.clientY};
1503 return Object.append(this, {
1509 rightClick: rightClick,
1513 relatedTarget: document.id(related),
1514 target: document.id(target),
1519 shift: event.shiftKey,
1520 control: event.ctrlKey,
1541 Event.Keys = new Hash(Event.Keys);
1548 return this.stopPropagation().preventDefault();
1551 stopPropagation: function(){
1552 if (this.event.stopPropagation) this.event.stopPropagation();
1553 else this.event.cancelBubble = true;
1557 preventDefault: function(){
1558 if (this.event.preventDefault) this.event.preventDefault();
1559 else this.event.returnValue = false;
1571 description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
1573 license: MIT-style license.
1575 requires: [Array, String, Function, Number]
1584 var Class = this.Class = new Type('Class', function(params){
1585 if (instanceOf(params, Function)) params = {initialize: params};
1587 var newClass = function(){
1589 if (newClass.$prototyping) return this;
1590 this.$caller = null;
1591 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
1592 this.$caller = this.caller = null;
1594 }.extend(this).implement(params);
1596 newClass.$constructor = Class;
1597 newClass.prototype.$constructor = newClass;
1598 newClass.prototype.parent = parent;
1603 var parent = function(){
1604 if (!this.$caller) throw new Error('The method "parent" cannot be called.');
1605 var name = this.$caller.$name,
1606 parent = this.$caller.$owner.parent,
1607 previous = (parent) ? parent.prototype[name] : null;
1608 if (!previous) throw new Error('The method "' + name + '" has no parent.');
1609 return previous.apply(this, arguments);
1612 var reset = function(object){
1613 for (var key in object){
1614 var value = object[key];
1615 switch (typeOf(value)){
1617 var F = function(){};
1618 F.prototype = value;
1619 object[key] = reset(new F);
1621 case 'array': object[key] = value.clone(); break;
1627 var wrap = function(self, key, method){
1628 if (method.$origin) method = method.$origin;
1629 var wrapper = function(){
1630 if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
1631 var caller = this.caller, current = this.$caller;
1632 this.caller = current; this.$caller = wrapper;
1633 var result = method.apply(this, arguments);
1634 this.$caller = current; this.caller = caller;
1636 }.extend({$owner: self, $origin: method, $name: key});
1640 var implement = function(key, value, retain){
1641 if (Class.Mutators.hasOwnProperty(key)){
1642 value = Class.Mutators[key].call(this, value);
1643 if (value == null) return this;
1646 if (typeOf(value) == 'function'){
1647 if (value.$hidden) return this;
1648 this.prototype[key] = (retain) ? value : wrap(this, key, value);
1650 Object.merge(this.prototype, key, value);
1656 var getInstance = function(klass){
1657 klass.$prototyping = true;
1658 var proto = new klass;
1659 delete klass.$prototyping;
1663 Class.implement('implement', implement.overloadSetter());
1667 Extends: function(parent){
1668 this.parent = parent;
1669 this.prototype = getInstance(parent);
1672 Implements: function(items){
1673 Array.from(items).each(function(item){
1674 var instance = new item;
1675 for (var key in instance) implement.call(this, key, instance[key], true);
1688 description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
1690 license: MIT-style license.
1694 provides: [Class.Extras, Chain, Events, Options]
1701 this.Chain = new Class({
1706 this.$chain.append(Array.flatten(arguments));
1710 callChain: function(){
1711 return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
1714 clearChain: function(){
1715 this.$chain.empty();
1721 var removeOn = function(string){
1722 return string.replace(/^on([A-Z])/, function(full, first){
1723 return first.toLowerCase();
1727 this.Events = new Class({
1731 addEvent: function(type, fn, internal){
1732 type = removeOn(type);
1735 if (fn == $empty) return this;
1738 this.$events[type] = (this.$events[type] || []).include(fn);
1739 if (internal) fn.internal = true;
1743 addEvents: function(events){
1744 for (var type in events) this.addEvent(type, events[type]);
1748 fireEvent: function(type, args, delay){
1749 type = removeOn(type);
1750 var events = this.$events[type];
1751 if (!events) return this;
1752 args = Array.from(args);
1753 events.each(function(fn){
1754 if (delay) fn.delay(delay, this, args);
1755 else fn.apply(this, args);
1760 removeEvent: function(type, fn){
1761 type = removeOn(type);
1762 var events = this.$events[type];
1763 if (events && !fn.internal){
1764 var index = events.indexOf(fn);
1765 if (index != -1) delete events[index];
1770 removeEvents: function(events){
1772 if (typeOf(events) == 'object'){
1773 for (type in events) this.removeEvent(type, events[type]);
1776 if (events) events = removeOn(events);
1777 for (type in this.$events){
1778 if (events && events != type) continue;
1779 var fns = this.$events[type];
1780 for (var i = fns.length; i--;) this.removeEvent(type, fns[i]);
1787 this.Options = new Class({
1789 setOptions: function(){
1790 var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
1791 if (!this.addEvent) return this;
1792 for (var option in options){
1793 if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
1794 this.addEvent(option, options[option]);
1795 delete options[option];
1808 description: Standalone CSS3 Selector parser
1809 provides: Slick.Parser
1823 var parse = function(expression, isReversed){
1824 if (expression == null) return null;
1825 if (expression.Slick === true) return expression;
1826 expression = ('' + expression).replace(/^\s+|\s+$/g, '');
1827 reversed = !!isReversed;
1828 var currentCache = (reversed) ? reverseCache : cache;
1829 if (currentCache[expression]) return currentCache[expression];
1830 parsed = {Slick: true, expressions: [], raw: expression, reverse: function(){
1831 return parse(this.raw, true);
1833 separatorIndex = -1;
1834 while (expression != (expression = expression.replace(regexp, parser)));
1835 parsed.length = parsed.expressions.length;
1836 return currentCache[expression] = (reversed) ? reverse(parsed) : parsed;
1839 var reverseCombinator = function(combinator){
1840 if (combinator === '!') return ' ';
1841 else if (combinator === ' ') return '!';
1842 else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
1843 else return '!' + combinator;
1846 var reverse = function(expression){
1847 var expressions = expression.expressions;
1848 for (var i = 0; i < expressions.length; i++){
1849 var exp = expressions[i];
1850 var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
1852 for (var j = 0; j < exp.length; j++){
1854 if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
1855 cexp.combinator = cexp.reverseCombinator;
1856 delete cexp.reverseCombinator;
1859 exp.reverse().push(last);
1864 var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
1865 return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, "\\$&");
1868 var regexp = new RegExp(
1871 puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
1874 \\s* ( , ) \\s* # Separator \n\
1875 | \\s* ( <combinator>+ ) \\s* # Combinator \n\
1876 | ( \\s+ ) # CombinatorChildren \n\
1877 | ( <unicode>+ | \\* ) # Tag \n\
1878 | \\# ( <unicode>+ ) # ID \n\
1879 | \\. ( <unicode>+ ) # ClassName \n\
1882 \\s* (<unicode1>+) (?: \
1883 \\s* ([*^$!~|]?=) (?: \
1890 | :+ ( <unicode>+ )(?:\
1892 (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
1897 "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|:+(<unicode>+)(?:\\((?:(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
1898 .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
1899 .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1900 .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1921 pseudoClassQuotedValue,
1924 if (separator || separatorIndex === -1){
1925 parsed.expressions[++separatorIndex] = [];
1926 combinatorIndex = -1;
1927 if (separator) return '';
1930 if (combinator || combinatorChildren || combinatorIndex === -1){
1931 combinator = combinator || ' ';
1932 var currentSeparator = parsed.expressions[separatorIndex];
1933 if (reversed && currentSeparator[combinatorIndex])
1934 currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
1935 currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
1938 var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
1941 currentParsed.tag = tagName.replace(reUnescape, '');
1944 currentParsed.id = id.replace(reUnescape, '');
1946 } else if (className){
1947 className = className.replace(reUnescape, '');
1949 if (!currentParsed.classList) currentParsed.classList = [];
1950 if (!currentParsed.classes) currentParsed.classes = [];
1951 currentParsed.classList.push(className);
1952 currentParsed.classes.push({
1954 regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
1957 } else if (pseudoClass){
1958 pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
1959 pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
1961 if (!currentParsed.pseudos) currentParsed.pseudos = [];
1962 currentParsed.pseudos.push({
1963 key: pseudoClass.replace(reUnescape, ''),
1964 value: pseudoClassValue
1967 } else if (attributeKey){
1968 attributeKey = attributeKey.replace(reUnescape, '');
1969 attributeValue = (attributeValue || '').replace(reUnescape, '');
1973 switch (attributeOperator){
1974 case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break;
1975 case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break;
1976 case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
1977 case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break;
1978 case '=' : test = function(value){
1979 return attributeValue == value;
1981 case '*=' : test = function(value){
1982 return value && value.indexOf(attributeValue) > -1;
1984 case '!=' : test = function(value){
1985 return attributeValue != value;
1987 default : test = function(value){
1992 if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
1996 if (!test) test = function(value){
1997 return value && regexp.test(value);
2000 if (!currentParsed.attributes) currentParsed.attributes = [];
2001 currentParsed.attributes.push({
2003 operator: attributeOperator,
2004 value: attributeValue,
2015 var Slick = (this.Slick || {});
2017 Slick.parse = function(expression){
2018 return parse(expression);
2021 Slick.escapeRegExp = escapeRegExp;
2023 if (!this.Slick) this.Slick = Slick;
2025 }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
2031 description: The new, superfast css selector engine.
2032 provides: Slick.Finder
2033 requires: Slick.Parser
2041 // Feature / Bug detection
2043 local.isNativeCode = function(fn){
2044 return (/\{\s*\[native code\]\s*\}/).test('' + fn);
2047 local.isXML = function(document){
2048 return (!!document.xmlVersion) || (!!document.xml) || (Object.prototype.toString.call(document) === '[object XMLDocument]') ||
2049 (document.nodeType === 9 && document.documentElement.nodeName !== 'HTML');
2052 local.setDocument = function(document){
2054 // convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
2056 if (document.nodeType === 9); // document
2057 else if (document.ownerDocument) document = document.ownerDocument; // node
2058 else if (document.navigator) document = document.document; // window
2061 // check if it's the old document
2063 if (this.document === document) return;
2064 this.document = document;
2065 var root = this.root = document.documentElement;
2067 this.isXMLDocument = this.isXML(document);
2069 this.brokenStarGEBTN
2070 = this.starSelectsClosedQSA
2072 = this.brokenMixedCaseQSA
2074 = this.brokenCheckedQSA
2075 = this.brokenEmptyAttributeQSA
2076 = this.isHTMLDocument
2079 var starSelectsClosed, starSelectsComments,
2080 brokenSecondClassNameGEBCN, cachedGetElementsByClassName;
2083 var testNode = document.createElement('div');
2084 root.appendChild(testNode);
2086 // on non-HTML documents innerHTML and getElementsById doesnt work properly
2088 id = 'slick_getbyid_test';
2089 testNode.innerHTML = '<a id="'+id+'"></a>';
2090 this.isHTMLDocument = !!document.getElementById(id);
2093 if (this.isHTMLDocument){
2095 testNode.style.display = 'none';
2097 // IE returns comment nodes for getElementsByTagName('*') for some documents
2098 testNode.appendChild(document.createComment(''));
2099 starSelectsComments = (testNode.getElementsByTagName('*').length > 0);
2101 // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
2103 testNode.innerHTML = 'foo</foo>';
2104 selected = testNode.getElementsByTagName('*');
2105 starSelectsClosed = (selected && selected.length && selected[0].nodeName.charAt(0) == '/');
2108 this.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
2110 // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
2111 if (testNode.querySelectorAll) try {
2112 testNode.innerHTML = 'foo</foo>';
2113 selected = testNode.querySelectorAll('*');
2114 this.starSelectsClosedQSA = (selected && selected.length && selected[0].nodeName.charAt(0) == '/');
2117 // IE returns elements with the name instead of just id for getElementsById for some documents
2119 id = 'slick_id_gets_name';
2120 testNode.innerHTML = '<a name="'+id+'"></a><b id="'+id+'"></b>';
2121 this.idGetsName = document.getElementById(id) === testNode.firstChild;
2124 // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
2126 testNode.innerHTML = '<a class="MiXedCaSe"></a>';
2127 this.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiXedCaSe').length;
2131 testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
2132 testNode.getElementsByClassName('b').length;
2133 testNode.firstChild.className = 'b';
2134 cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
2137 // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
2139 testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
2140 brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
2143 this.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
2145 // Webkit dont return selected options on querySelectorAll
2147 testNode.innerHTML = '<select><option selected="selected">a</option></select>';
2148 this.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
2151 // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
2153 testNode.innerHTML = '<a class=""></a>';
2154 this.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
2159 root.removeChild(testNode);
2164 this.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
2165 return node.hasAttribute(attribute);
2166 } : function(node, attribute) {
2167 node = node.getAttributeNode(attribute);
2168 return !!(node && (node.specified || node.nodeValue));
2172 // FIXME: Add specs: local.contains should be different for xml and html documents?
2173 this.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){
2174 return context.contains(node);
2175 } : (root && root.compareDocumentPosition) ? function(context, node){
2176 return context === node || !!(context.compareDocumentPosition(node) & 16);
2177 } : function(context, node){
2179 if (node === context) return true;
2180 } while ((node = node.parentNode));
2184 // document order sorting
2185 // credits to Sizzle (http://sizzlejs.com/)
2187 this.documentSorter = (root.compareDocumentPosition) ? function(a, b){
2188 if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
2189 return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
2190 } : ('sourceIndex' in root) ? function(a, b){
2191 if (!a.sourceIndex || !b.sourceIndex) return 0;
2192 return a.sourceIndex - b.sourceIndex;
2193 } : (document.createRange) ? function(a, b){
2194 if (!a.ownerDocument || !b.ownerDocument) return 0;
2195 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
2196 aRange.setStart(a, 0);
2197 aRange.setEnd(a, 0);
2198 bRange.setStart(b, 0);
2199 bRange.setEnd(b, 0);
2200 return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
2203 this.getUID = (this.isHTMLDocument) ? this.getUIDHTML : this.getUIDXML;
2209 local.search = function(context, expression, append, first){
2211 var found = this.found = (first) ? null : (append || []);
2215 if (!context) return found; // No context
2216 if (context.navigator) context = context.document; // Convert the node from a window to a document
2217 else if (!context.nodeType) return found; // Reject misc junk input
2223 var uniques = this.uniques = {};
2225 if (this.document !== (context.ownerDocument || context)) this.setDocument(context);
2227 // should sort if there are nodes in append and if you pass multiple expressions.
2228 // should remove duplicates if append already has items
2229 var shouldUniques = !!(append && append.length);
2231 // avoid duplicating items already in the append array
2232 if (shouldUniques) for (i = found.length; i--;) this.uniques[this.getUID(found[i])] = true;
2234 // expression checks
2236 if (typeof expression == 'string'){ // expression is a string
2240 for (i = this.overrides.length; i--;){
2241 var override = this.overrides[i];
2242 if (override.regexp.test(expression)){
2243 var result = override.method.call(context, expression, found, first);
2244 if (result === false) continue;
2245 if (result === true) return found;
2250 parsed = this.Slick.parse(expression);
2251 if (!parsed.length) return found;
2252 } else if (expression == null){ // there is no expression
2254 } else if (expression.Slick){ // expression is a parsed Slick object
2255 parsed = expression;
2256 } else if (this.contains(context.documentElement || context, expression)){ // expression is a node
2257 (found) ? found.push(expression) : found = expression;
2259 } else { // other junk
2263 // cache elements for the nth selectors
2265 /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2268 this.posNTHLast = {};
2269 this.posNTHType = {};
2270 this.posNTHTypeLast = {};
2272 /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2274 // if append is null and there is only a single selector with one expression use pushArray, else use pushUID
2275 this.push = (!shouldUniques && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
2277 if (found == null) found = [];
2282 var combinator, tag, id, classList, classes, attributes, pseudos;
2283 var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
2285 search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){
2287 combinator = 'combinator:' + currentBit.combinator;
2288 if (!this[combinator]) continue search;
2290 tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
2292 classList = currentBit.classList;
2293 classes = currentBit.classes;
2294 attributes = currentBit.attributes;
2295 pseudos = currentBit.pseudos;
2296 lastBit = (j === (currentExpression.length - 1));
2298 this.bitUniques = {};
2301 this.uniques = uniques;
2309 this[combinator](context, tag, id, classes, attributes, pseudos, classList);
2310 if (first && lastBit && found.length) break search;
2312 if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
2313 this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2314 if (found.length) break search;
2315 } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2318 currentItems = this.found;
2321 if (shouldUniques || (parsed.expressions.length > 1)) this.sort(found);
2323 return (first) ? (found[0] || null) : found;
2329 local.uidk = 'slick:uniqueid';
2331 local.getUIDXML = function(node){
2332 var uid = node.getAttribute(this.uidk);
2335 node.setAttribute(this.uidk, uid);
2340 local.getUIDHTML = function(node){
2341 return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
2344 // sort based on the setDocument documentSorter method.
2346 local.sort = function(results){
2347 if (!this.documentSorter) return results;
2348 results.sort(this.documentSorter);
2352 /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2354 local.cacheNTH = {};
2356 local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
2358 local.parseNTHArgument = function(argument){
2359 var parsed = argument.match(this.matchNTH);
2360 if (!parsed) return false;
2361 var special = parsed[2] || false;
2362 var a = parsed[1] || 1;
2363 if (a == '-') a = -1;
2364 var b = +parsed[3] || 0;
2366 (special == 'n') ? {a: a, b: b} :
2367 (special == 'odd') ? {a: 2, b: 1} :
2368 (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a};
2370 return (this.cacheNTH[argument] = parsed);
2373 local.createNTHPseudo = function(child, sibling, positions, ofType){
2374 return function(node, argument){
2375 var uid = this.getUID(node);
2376 if (!this[positions][uid]){
2377 var parent = node.parentNode;
2378 if (!parent) return false;
2379 var el = parent[child], count = 1;
2381 var nodeName = node.nodeName;
2383 if (el.nodeName !== nodeName) continue;
2384 this[positions][this.getUID(el)] = count++;
2385 } while ((el = el[sibling]));
2388 if (el.nodeType !== 1) continue;
2389 this[positions][this.getUID(el)] = count++;
2390 } while ((el = el[sibling]));
2393 argument = argument || 'n';
2394 var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
2395 if (!parsed) return false;
2396 var a = parsed.a, b = parsed.b, pos = this[positions][uid];
2397 if (a == 0) return b == pos;
2399 if (pos < b) return false;
2401 if (b < pos) return false;
2403 return ((pos - b) % a) == 0;
2407 /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2409 local.pushArray = function(node, tag, id, classes, attributes, pseudos){
2410 if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
2413 local.pushUID = function(node, tag, id, classes, attributes, pseudos){
2414 var uid = this.getUID(node);
2415 if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
2416 this.uniques[uid] = true;
2417 this.found.push(node);
2421 local.matchNode = function(node, selector){
2422 var parsed = this.Slick.parse(selector);
2423 if (!parsed) return true;
2425 // simple (single) selectors
2426 if(parsed.length == 1 && parsed.expressions[0].length == 1){
2427 var exp = parsed.expressions[0][0];
2428 return this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos);
2431 var nodes = this.search(this.document, parsed);
2432 for (var i = 0, item; item = nodes[i++];){
2433 if (item === node) return true;
2438 local.matchPseudo = function(node, name, argument){
2439 var pseudoName = 'pseudo:' + name;
2440 if (this[pseudoName]) return this[pseudoName](node, argument);
2441 var attribute = this.getAttribute(node, name);
2442 return (argument) ? argument == attribute : !!attribute;
2445 local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
2448 if (node.nodeName < '@') return false; // Fix for comment nodes and closed nodes
2450 if (node.nodeName != tag) return false;
2454 if (id && node.getAttribute('id') != id) return false;
2457 if (classes) for (i = classes.length; i--;){
2458 cls = ('className' in node) ? node.className : node.getAttribute('class');
2459 if (!(cls && classes[i].regexp.test(cls))) return false;
2461 if (attributes) for (i = attributes.length; i--;){
2462 part = attributes[i];
2463 if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
2465 if (pseudos) for (i = pseudos.length; i--;){
2467 if (!this.matchPseudo(node, part.key, part.value)) return false;
2474 ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level
2476 var i, item, children;
2478 if (this.isHTMLDocument){
2480 item = this.document.getElementById(id);
2481 if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
2482 // all[id] returns all the elements with that name or id inside node
2483 // if theres just one it will return the element, else it will be a collection
2484 children = node.all[id];
2485 if (!children) return;
2486 if (!children[0]) children = [children];
2487 for (i = 0; item = children[i++];) if (item.getAttributeNode('id').nodeValue == id){
2488 this.push(item, tag, null, classes, attributes, pseudos);
2494 // if the context is in the dom we return, else we will try GEBTN, breaking the getById label
2495 if (this.contains(this.document.documentElement, node)) return;
2497 } else if (this.document !== node && !this.contains(node, item)) return;
2498 this.push(item, tag, null, classes, attributes, pseudos);
2501 getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
2502 children = node.getElementsByClassName(classList.join(' '));
2503 if (!(children && children.length)) break getByClass;
2504 for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
2509 children = node.getElementsByTagName(tag);
2510 if (!(children && children.length)) break getByTag;
2511 if (!this.brokenStarGEBTN) tag = null;
2512 for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
2516 '>': function(node, tag, id, classes, attributes, pseudos){ // direct children
2517 if ((node = node.firstChild)) do {
2518 if (node.nodeType === 1) this.push(node, tag, id, classes, attributes, pseudos);
2519 } while ((node = node.nextSibling));
2522 '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
2523 while ((node = node.nextSibling)) if (node.nodeType === 1){
2524 this.push(node, tag, id, classes, attributes, pseudos);
2529 '^': function(node, tag, id, classes, attributes, pseudos){ // first child
2530 node = node.firstChild;
2532 if (node.nodeType === 1) this.push(node, tag, id, classes, attributes, pseudos);
2533 else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2537 '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
2538 while ((node = node.nextSibling)){
2539 if (node.nodeType !== 1) continue;
2540 var uid = this.getUID(node);
2541 if (this.bitUniques[uid]) break;
2542 this.bitUniques[uid] = true;
2543 this.push(node, tag, id, classes, attributes, pseudos);
2547 '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
2548 this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2549 this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2552 '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
2553 this['combinator:~'](node, tag, id, classes, attributes, pseudos);
2554 this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
2557 '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
2558 while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2561 '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
2562 node = node.parentNode;
2563 if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2566 '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
2567 while ((node = node.previousSibling)) if (node.nodeType === 1){
2568 this.push(node, tag, id, classes, attributes, pseudos);
2573 '!^': function(node, tag, id, classes, attributes, pseudos){ // last child
2574 node = node.lastChild;
2576 if (node.nodeType === 1) this.push(node, tag, id, classes, attributes, pseudos);
2577 else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2581 '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
2582 while ((node = node.previousSibling)){
2583 if (node.nodeType !== 1) continue;
2584 var uid = this.getUID(node);
2585 if (this.bitUniques[uid]) break;
2586 this.bitUniques[uid] = true;
2587 this.push(node, tag, id, classes, attributes, pseudos);
2593 for (var c in combinators) local['combinator:' + c] = combinators[c];
2597 /*<pseudo-selectors>*/
2599 'empty': function(node){
2600 var child = node.firstChild;
2601 return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
2604 'not': function(node, expression){
2605 return !this.matchNode(node, expression);
2608 'contains': function(node, text){
2609 return (node.innerText || node.textContent || '').indexOf(text) > -1;
2612 'first-child': function(node){
2613 while ((node = node.previousSibling)) if (node.nodeType === 1) return false;
2617 'last-child': function(node){
2618 while ((node = node.nextSibling)) if (node.nodeType === 1) return false;
2622 'only-child': function(node){
2624 while ((prev = prev.previousSibling)) if (prev.nodeType === 1) return false;
2626 while ((next = next.nextSibling)) if (next.nodeType === 1) return false;
2630 /*<nth-pseudo-selectors>*/
2632 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
2634 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
2636 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
2638 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
2640 'index': function(node, index){
2641 return this['pseudo:nth-child'](node, '' + index + 1);
2644 'even': function(node, argument){
2645 return this['pseudo:nth-child'](node, '2n');
2648 'odd': function(node, argument){
2649 return this['pseudo:nth-child'](node, '2n+1');
2652 /*</nth-pseudo-selectors>*/
2654 /*<of-type-pseudo-selectors>*/
2656 'first-of-type': function(node){
2657 var nodeName = node.nodeName;
2658 while ((node = node.previousSibling)) if (node.nodeName === nodeName) return false;
2662 'last-of-type': function(node){
2663 var nodeName = node.nodeName;
2664 while ((node = node.nextSibling)) if (node.nodeName === nodeName) return false;
2668 'only-of-type': function(node){
2669 var prev = node, nodeName = node.nodeName;
2670 while ((prev = prev.previousSibling)) if (prev.nodeName === nodeName) return false;
2672 while ((next = next.nextSibling)) if (next.nodeName === nodeName) return false;
2676 /*</of-type-pseudo-selectors>*/
2680 'enabled': function(node){
2681 return (node.disabled === false);
2684 'disabled': function(node){
2685 return (node.disabled === true);
2688 'checked': function(node){
2689 return node.checked || node.selected;
2692 'focus': function(node){
2693 return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
2696 'root': function(node){
2697 return (node === this.root);
2700 'selected': function(node){
2701 return node.selected;
2704 /*</pseudo-selectors>*/
2707 for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
2709 // attributes methods
2711 local.attributeGetters = {
2713 'class': function(){
2714 return ('className' in this) ? this.className : this.getAttribute('class');
2718 return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
2722 return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
2725 'style': function(){
2726 return (this.style) ? this.style.cssText : this.getAttribute('style');
2731 local.getAttribute = function(node, name){
2732 // FIXME: check if getAttribute() will get input elements on a form on this browser
2733 // getAttribute is faster than getAttributeNode().nodeValue
2734 var method = this.attributeGetters[name];
2735 if (method) return method.call(node);
2736 var attributeNode = node.getAttributeNode(name);
2737 return attributeNode ? attributeNode.nodeValue : null;
2742 local.overrides = [];
2744 local.override = function(regexp, method){
2745 this.overrides.push({regexp: regexp, method: method});
2750 /*<query-selector-override>*/
2752 var reEmptyAttribute = /\[.*[*$^]=(?:["']{2})?\]/;
2754 local.override(/./, function(expression, found, first){ //querySelectorAll override
2756 if (!this.querySelectorAll || this.nodeType != 9 || !local.isHTMLDocument || local.brokenMixedCaseQSA ||
2757 (local.brokenCheckedQSA && expression.indexOf(':checked') > -1) ||
2758 (local.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) || Slick.disableQSA) return false;
2762 if (first) return this.querySelector(expression) || null;
2763 else nodes = this.querySelectorAll(expression);
2768 var i, hasOthers = !!(found.length);
2770 if (local.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
2771 if (node.nodeName > '@' && (!hasOthers || !local.uniques[local.getUIDHTML(node)])) found.push(node);
2772 } else for (i = 0; node = nodes[i++];){
2773 if (!hasOthers || !local.uniques[local.getUIDHTML(node)]) found.push(node);
2776 if (hasOthers) local.sort(found);
2782 /*</query-selector-override>*/
2786 local.override(/^[\w-]+$|^\*$/, function(expression, found, first){ // tag override
2787 var tag = expression;
2788 if (tag == '*' && local.brokenStarGEBTN) return false;
2790 var nodes = this.getElementsByTagName(tag);
2792 if (first) return nodes[0] || null;
2793 var i, node, hasOthers = !!(found.length);
2795 for (i = 0; node = nodes[i++];){
2796 if (!hasOthers || !local.uniques[local.getUID(node)]) found.push(node);
2799 if (hasOthers) local.sort(found);
2806 /*<class-override>*/
2808 local.override(/^\.[\w-]+$/, function(expression, found, first){ // class override
2809 if (!local.isHTMLDocument || (!this.getElementsByClassName && this.querySelectorAll)) return false;
2811 var nodes, node, i, hasOthers = !!(found && found.length), className = expression.substring(1);
2812 if (this.getElementsByClassName && !local.brokenGEBCN){
2813 nodes = this.getElementsByClassName(className);
2814 if (first) return nodes[0] || null;
2815 for (i = 0; node = nodes[i++];){
2816 if (!hasOthers || !local.uniques[local.getUIDHTML(node)]) found.push(node);
2819 var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(className) +'(\\s|$)');
2820 nodes = this.getElementsByTagName('*');
2821 for (i = 0; node = nodes[i++];){
2822 className = node.className;
2823 if (!className || !matchClass.test(className)) continue;
2824 if (first) return node;
2825 if (!hasOthers || !local.uniques[local.getUIDHTML(node)]) found.push(node);
2828 if (hasOthers) local.sort(found);
2829 return (first) ? null : true;
2832 /*</class-override>*/
2836 local.override(/^#[\w-]+$/, function(expression, found, first){ // ID override
2837 if (!local.isHTMLDocument || this.nodeType != 9) return false;
2839 var id = expression.substring(1), el = this.getElementById(id);
2840 if (!el) return found;
2841 if (local.idGetsName && el.getAttributeNode('id').nodeValue != id) return false;
2842 if (first) return el || null;
2843 var hasOthers = !!(found.length);
2844 if (!hasOthers || !local.uniques[local.getUIDHTML(el)]) found.push(el);
2845 if (hasOthers) local.sort(found);
2853 if (typeof document != 'undefined') local.setDocument(document);
2857 var Slick = local.Slick = (this.Slick || {});
2859 Slick.version = '0.9dev';
2863 Slick.search = function(context, expression, append){
2864 return local.search(context, expression, append);
2867 Slick.find = function(context, expression){
2868 return local.search(context, expression, null, true);
2871 // Slick containment checker
2873 Slick.contains = function(container, node){
2874 local.setDocument(container);
2875 return local.contains(container, node);
2878 // Slick attribute getter
2880 Slick.getAttribute = function(node, name){
2881 return local.getAttribute(node, name);
2886 Slick.match = function(node, selector){
2887 if (!(node && selector)) return false;
2888 if (!selector || selector === node) return true;
2889 if (typeof selector != 'string') return false;
2890 local.setDocument(node);
2891 return local.matchNode(node, selector);
2894 // Slick attribute accessor
2896 Slick.defineAttributeGetter = function(name, fn){
2897 local.attributeGetters[name] = fn;
2901 Slick.lookupAttributeGetter = function(name){
2902 return local.attributeGetters[name];
2905 // Slick pseudo accessor
2907 Slick.definePseudo = function(name, fn){
2908 local['pseudo:' + name] = function(node, argument){
2909 return fn.call(node, argument);
2914 Slick.lookupPseudo = function(name){
2915 var pseudo = local['pseudo:' + name];
2916 if (pseudo) return function(argument){
2917 return pseudo.call(this, argument);
2922 // Slick overrides accessor
2924 Slick.override = function(regexp, fn){
2925 local.override(regexp, fn);
2929 Slick.isXML = local.isXML;
2931 Slick.uidOf = function(node){
2932 return local.getUIDHTML(node);
2935 if (!this.Slick) this.Slick = Slick;
2937 }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
2945 description: 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.
2947 license: MIT-style license.
2949 requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder]
2951 provides: [Element, Elements, $, $$, Iframe, Selectors]
2956 var Element = function(tag, props){
2957 var konstructor = Element.Constructors[tag];
2958 if (konstructor) return konstructor(props);
2959 if (typeof tag != 'string') return document.id(tag).set(props);
2961 if (!props) props = {};
2963 if (!tag.test(/^[\w-]+$/)){
2964 var parsed = Slick.parse(tag).expressions[0][0];
2965 tag = (parsed.tag == '*') ? 'div' : parsed.tag;
2966 if (parsed.id && props.id == null) props.id = parsed.id;
2968 var attributes = parsed.attributes;
2969 if (attributes) for (var i = 0, l = attributes.length; i < l; i++){
2970 var attr = attributes[i];
2971 if (attr.value != null && attr.operator == '=' && props[attr.key] == null)
2972 props[attr.key] = attr.value;
2975 if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
2978 return document.newElement(tag, props);
2981 if (Browser.Element) Element.prototype = Browser.Element.prototype;
2983 new Type('Element', Element).mirror(function(name){
2984 if (Array.prototype[name]) return;
2987 obj[name] = function(){
2988 var results = [], args = arguments, elements = true;
2989 for (var i = 0, l = this.length; i < l; i++){
2990 var element = this[i], result = results[i] = element[name].apply(element, args);
2991 elements = (elements && typeOf(result) == 'element');
2993 return (elements) ? new Elements(results) : results;
2996 Elements.implement(obj);
2999 if (!Browser.Element){
3000 Element.parent = Object;
3002 Element.Prototype = {'$family': Function.from('element').hide()};
3004 Element.mirror(function(name, method){
3005 Element.Prototype[name] = method;
3009 Element.Constructors = {};
3013 Element.Constructors = new Hash;
3017 var IFrame = new Type('IFrame', function(){
3018 var params = Array.link(arguments, {
3019 properties: Type.isObject,
3020 iframe: function(obj){
3021 return (obj != null);
3025 var props = params.properties || {}, iframe;
3026 if (params.iframe) iframe = document.id(params.iframe);
3027 var onload = props.onload || function(){};
3028 delete props.onload;
3029 props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
3030 iframe = new Element(iframe || 'iframe', props);
3032 var onLoad = function(){
3033 onload.call(iframe.contentWindow);
3036 if (window.frames[props.id]) onLoad();
3037 else iframe.addListener('load', onLoad);
3041 var Elements = this.Elements = function(nodes){
3042 if (nodes && nodes.length){
3043 var uniques = {}, node;
3044 for (var i = 0; node = nodes[i++];){
3045 var uid = Slick.uidOf(node);
3047 uniques[uid] = true;
3054 Elements.prototype = {length: 0};
3055 Elements.parent = Array;
3057 new Type('Elements', Elements).implement({
3059 filter: function(filter, bind){
3060 if (!filter) return this;
3061 return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
3062 return item.match(filter);
3067 var length = this.length;
3068 for (var i = 0, l = arguments.length; i < l; i++){
3069 var item = document.id(arguments[i]);
3070 if (item) this[length++] = item;
3072 return (this.length = length);
3076 var newElements = new Elements(this);
3077 for (var i = 0, l = arguments.length; i < l; i++){
3078 var item = arguments[i];
3079 if (Type.isEnumerable(item)) newElements.append(item);
3080 else newElements.push(item);
3085 append: function(collection){
3086 for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
3091 while (this.length) delete this[--this.length];
3100 var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
3102 splice.call(object, 1, 1);
3103 if (object[1] == 1) Elements.implement('splice', function(){
3104 var length = this.length;
3105 splice.apply(this, arguments);
3106 while (length >= this.length) delete this[length--];
3110 Elements.implement(Array.prototype);
3112 Array.mirror(Elements);
3115 var createElementAcceptsHTML;
3117 var x = document.createElement('<input name=x>');
3118 createElementAcceptsHTML = (x.name == 'x');
3121 var escapeQuotes = function(html){
3122 return ('' + html).replace(/&/g, '&').replace(/"/g, '"');
3126 Document.implement({
3128 newElement: function(tag, props){
3129 if (props && props.checked != null) props.defaultChecked = props.checked;
3130 /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
3131 if (createElementAcceptsHTML && props){
3133 if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
3134 if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
3140 return this.id(this.createElement(tag)).set(props);
3147 Document.implement({
3149 newTextNode: function(text){
3150 return this.createTextNode(text);
3153 getDocument: function(){
3157 getWindow: function(){
3165 string: function(id, nocash, doc){
3166 id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
3167 return (id) ? types.element(id, nocash) : null;
3170 element: function(el, nocash){
3172 if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){
3173 Object.append(el, Element.Prototype);
3178 object: function(obj, nocash, doc){
3179 if (obj.toElement) return types.element(obj.toElement(doc), nocash);
3185 types.textnode = types.whitespace = types.window = types.document = function(zero){
3189 return function(el, nocash, doc){
3190 if (el && el.$family && el.uid) return el;
3191 var type = typeOf(el);
3192 return (types[type]) ? types[type](el, nocash, doc || document) : null;
3199 if (window.$ == null) Window.implement('$', function(el, nc){
3200 return document.id(el, nc, this.document);
3205 getDocument: function(){
3206 return this.document;
3209 getWindow: function(){
3215 [Document, Element].invoke('implement', {
3217 getElements: function(expression){
3218 return Slick.search(this, expression, new Elements);
3221 getElement: function(expression){
3222 return document.id(Slick.find(this, expression));
3229 (function(search, find, match){
3231 this.Selectors = {};
3232 var pseudos = this.Selectors.Pseudo = new Hash();
3234 var addSlickPseudos = function(){
3235 for (var name in pseudos) if (pseudos.hasOwnProperty(name)){
3236 Slick.definePseudo(name, pseudos[name]);
3237 delete pseudos[name];
3241 Slick.search = function(context, expression, append){
3243 return search.call(this, context, expression, append);
3246 Slick.find = function(context, expression){
3248 return find.call(this, context, expression);
3251 Slick.match = function(node, selector){
3253 return match.call(this, node, selector);
3256 })(Slick.search, Slick.find, Slick.match);
3258 if (window.$$ == null) Window.implement('$$', function(selector){
3259 var elements = new Elements;
3260 if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
3261 var args = Array.flatten(arguments);
3262 for (var i = 0, l = args.length; i < l; i++){
3264 switch (typeOf(item)){
3265 case 'element': elements.push(item); break;
3266 case 'string': Slick.search(this.document, item, elements);
3274 if (window.$$ == null) Window.implement('$$', function(selector){
3275 if (arguments.length == 1){
3276 if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
3277 else if (Type.isEnumerable(selector)) return new Elements(selector);
3279 return new Elements(arguments);
3284 var collected = {}, storage = {};
3285 var props = {input: 'checked', option: 'selected', textarea: 'value'};
3287 var get = function(uid){
3288 return (storage[uid] || (storage[uid] = {}));
3291 var clean = function(item){
3292 if (item.removeEvents) item.removeEvents();
3293 if (item.clearAttributes) item.clearAttributes();
3296 delete collected[uid];
3297 delete storage[uid];
3302 var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly',
3303 'rowSpan', 'tabIndex', 'useMap'
3305 var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected',
3309 'html': 'innerHTML',
3310 'class': 'className',
3312 'text': (function(){
3313 var temp = document.createElement('div');
3314 return (temp.innerText == null) ? 'textContent' : 'innerText';
3317 var readOnly = ['type'];
3318 var expandos = ['value', 'defaultValue'];
3319 var uriAttrs = /^(?:href|src|usemap)$/i;
3321 bools = bools.associate(bools);
3322 camels = camels.associate(camels.map(String.toLowerCase));
3323 readOnly = readOnly.associate(readOnly);
3325 Object.append(attributes, expandos.associate(expandos));
3329 before: function(context, element){
3330 var parent = element.parentNode;
3331 if (parent) parent.insertBefore(context, element);
3334 after: function(context, element){
3335 var parent = element.parentNode;
3336 if (parent) parent.insertBefore(context, element.nextSibling);
3339 bottom: function(context, element){
3340 element.appendChild(context);
3343 top: function(context, element){
3344 element.insertBefore(context, element.firstChild);
3349 inserters.inside = inserters.bottom;
3353 Object.each(inserters, function(inserter, where){
3355 where = where.capitalize();
3359 methods['inject' + where] = function(el){
3360 inserter(this, document.id(el, true));
3364 methods['grab' + where] = function(el){
3365 inserter(document.id(el, true), this);
3369 Element.implement(methods);
3375 var injectCombinator = function(expression, combinator){
3376 if (!expression) return combinator;
3378 expression = Slick.parse(expression);
3380 var expressions = expression.expressions;
3381 for (var i = expressions.length; i--;)
3382 expressions[i][0].combinator = combinator;
3389 set: function(prop, value){
3390 var property = Element.Properties[prop];
3391 (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
3394 get: function(prop){
3395 var property = Element.Properties[prop];
3396 return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
3399 erase: function(prop){
3400 var property = Element.Properties[prop];
3401 (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
3405 setProperty: function(attribute, value){
3406 attribute = camels[attribute] || attribute;
3407 if (value == null) return this.removeProperty(attribute);
3408 var key = attributes[attribute];
3409 (key) ? this[key] = value :
3410 (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value);
3414 setProperties: function(attributes){
3415 for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
3419 getProperty: function(attribute){
3420 attribute = camels[attribute] || attribute;
3421 var key = attributes[attribute] || readOnly[attribute];
3422 return (key) ? this[key] :
3423 (bools[attribute]) ? !!this[attribute] :
3424 (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) :
3425 (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null;
3428 getProperties: function(){
3429 var args = Array.from(arguments);
3430 return args.map(this.getProperty, this).associate(args);
3433 removeProperty: function(attribute){
3434 attribute = camels[attribute] || attribute;
3435 var key = attributes[attribute];
3436 (key) ? this[key] = '' :
3437 (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute);
3441 removeProperties: function(){
3442 Array.each(arguments, this.removeProperty, this);
3446 hasClass: function(className){
3447 return this.className.clean().contains(className, ' ');
3450 addClass: function(className){
3451 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
3455 removeClass: function(className){
3456 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
3460 toggleClass: function(className, force){
3461 if (force == null) force = !this.hasClass(className);
3462 return (force) ? this.addClass(className) : this.removeClass(className);
3466 var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
3467 if (length > 1) parent = fragment = document.createDocumentFragment();
3469 for (var i = 0; i < length; i++){
3470 var element = document.id(elements[i], true);
3471 if (element) parent.appendChild(element);
3474 if (fragment) this.appendChild(fragment);
3479 appendText: function(text, where){
3480 return this.grab(this.getDocument().newTextNode(text), where);
3483 grab: function(el, where){
3484 inserters[where || 'bottom'](document.id(el, true), this);
3488 inject: function(el, where){
3489 inserters[where || 'bottom'](this, document.id(el, true));
3493 replaces: function(el){
3494 el = document.id(el, true);
3495 el.parentNode.replaceChild(this, el);
3499 wraps: function(el, where){
3500 el = document.id(el, true);
3501 return this.replaces(el).grab(el, where);
3504 getPrevious: function(expression){
3505 return document.id(Slick.find(this, injectCombinator(expression, '!~')));
3508 getAllPrevious: function(expression){
3509 return Slick.search(this, injectCombinator(expression, '!~'), new Elements);
3512 getNext: function(expression){
3513 return document.id(Slick.find(this, injectCombinator(expression, '~')));
3516 getAllNext: function(expression){
3517 return Slick.search(this, injectCombinator(expression, '~'), new Elements);
3520 getFirst: function(expression){
3521 return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
3524 getLast: function(expression){
3525 return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
3528 getParent: function(expression){
3529 return document.id(Slick.find(this, injectCombinator(expression, '!')));
3532 getParents: function(expression){
3533 return Slick.search(this, injectCombinator(expression, '!'), new Elements);
3536 getSiblings: function(expression){
3537 return Slick.search(this, injectCombinator(expression, '~~'), new Elements);
3540 getChildren: function(expression){
3541 return Slick.search(this, injectCombinator(expression, '>'), new Elements);
3544 getWindow: function(){
3545 return this.ownerDocument.window;
3548 getDocument: function(){
3549 return this.ownerDocument;
3552 getElementById: function(id){
3553 return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
3556 getSelected: function(){
3557 this.selectedIndex; // Safari 3.2.1
3558 return new Elements(Array.from(this.options).filter(function(option){
3559 return option.selected;
3563 toQueryString: function(){
3564 var queryString = [];
3565 this.getElements('input, select, textarea').each(function(el){
3567 if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
3569 var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
3571 return document.id(opt).get('value');
3572 }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
3574 Array.from(value).each(function(val){
3575 if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
3578 return queryString.join('&');
3581 clone: function(contents, keepid){
3582 contents = contents !== false;
3583 var clone = this.cloneNode(contents);
3584 var clean = function(node, element){
3585 if (!keepid) node.removeAttribute('id');
3587 node.clearAttributes();
3588 node.mergeAttributes(element);
3589 node.removeAttribute('uid');
3591 var no = node.options, eo = element.options;
3592 for (var j = no.length; j--;) no[j].selected = eo[j].selected;
3595 var prop = props[element.tagName.toLowerCase()];
3596 if (prop && element[prop]) node[prop] = element[prop];
3601 var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*');
3602 for (i = ce.length; i--;) clean(ce[i], te[i]);
3607 var ts = this.getElementsByTagName('object'),
3608 cs = clone.getElementsByTagName('object'),
3609 tl = ts.length, cl = cs.length;
3610 for (i = 0; i < tl && i < cl; i++)
3611 cs[i].outerHTML = ts[i].outerHTML;
3613 return document.id(clone);
3616 destroy: function(){
3617 var children = clean(this).getElementsByTagName('*');
3618 Array.each(children, clean);
3619 Element.dispose(this);
3624 Array.from(this.childNodes).each(Element.dispose);
3628 dispose: function(){
3629 return (this.parentNode) ? this.parentNode.removeChild(this) : this;
3632 match: function(expression){
3633 return !expression || Slick.match(this, expression);
3638 var contains = {contains: function(element){
3639 return Slick.contains(this, element);
3642 if (!document.contains) Document.implement(contains);
3643 if (!document.createElement('div').contains) Element.implement(contains);
3647 Element.implement('hasChild', function(element){
3648 return this !== element && this.contains(element);
3653 [Element, Window, Document].invoke('implement', {
3655 addListener: function(type, fn){
3656 if (type == 'unload'){
3657 var old = fn, self = this;
3659 self.removeListener('unload', fn);
3663 collected[this.uid] = this;
3665 if (this.addEventListener) this.addEventListener(type, fn, false);
3666 else this.attachEvent('on' + type, fn);
3670 removeListener: function(type, fn){
3671 if (this.removeEventListener) this.removeEventListener(type, fn, false);
3672 else this.detachEvent('on' + type, fn);
3676 retrieve: function(property, dflt){
3677 var storage = get(this.uid), prop = storage[property];
3678 if (dflt != null && prop == null) prop = storage[property] = dflt;
3679 return prop != null ? prop : null;
3682 store: function(property, value){
3683 var storage = get(this.uid);
3684 storage[property] = value;
3688 eliminate: function(property){
3689 var storage = get(this.uid);
3690 delete storage[property];
3697 if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){
3698 Object.each(collected, clean);
3699 if (window.CollectGarbage) CollectGarbage();
3704 Element.Properties = {};
3708 Element.Properties = new Hash;
3712 Element.Properties.style = {
3714 set: function(style){
3715 this.style.cssText = style;
3719 return this.style.cssText;
3723 this.style.cssText = '';
3728 Element.Properties.tag = {
3731 return this.tagName.toLowerCase();
3736 (function(maxLength){
3737 if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = {
3739 var maxlength = this.getAttribute('maxLength');
3740 return maxlength == maxLength ? null : maxlength;
3743 })(document.createElement('input').getAttribute('maxLength'));
3745 Element.Properties.html = (function(){
3747 var tableTest = Function.attempt(function(){
3748 var table = document.createElement('table');
3749 table.innerHTML = '<tr><td></td></tr>';
3752 var wrapper = document.createElement('div');
3754 var translations = {
3755 table: [1, '<table>', '</table>'],
3756 select: [1, '<select>', '</select>'],
3757 tbody: [2, '<table><tbody>', '</tbody></table>'],
3758 tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
3760 translations.thead = translations.tfoot = translations.tbody;
3764 var html = Array.flatten(arguments).join('');
3765 var wrap = (!tableTest && translations[this.get('tag')]);
3767 var first = wrapper;
3768 first.innerHTML = wrap[1] + html + wrap[2];
3769 for (var i = wrap[0]; i--;) first = first.firstChild;
3770 this.empty().adopt(first.childNodes);
3772 this.innerHTML = html;
3777 html.erase = html.set;
3788 description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events.
3790 license: MIT-style license.
3792 requires: [Element, Event]
3794 provides: Element.Event
3801 Element.Properties.events = {set: function(events){
3802 this.addEvents(events);
3805 [Element, Window, Document].invoke('implement', {
3807 addEvent: function(type, fn){
3808 var events = this.retrieve('events', {});
3809 if (!events[type]) events[type] = {keys: [], values: []};
3810 if (events[type].keys.contains(fn)) return this;
3811 events[type].keys.push(fn);
3812 var realType = type,
3813 custom = Element.Events[type],
3817 if (custom.onAdd) custom.onAdd.call(this, fn);
3818 if (custom.condition){
3819 condition = function(event){
3820 if (custom.condition.call(this, event)) return fn.call(this, event);
3824 realType = custom.base || realType;
3826 var defn = function(){
3827 return fn.call(self);
3829 var nativeEvent = Element.NativeEvents[realType];
3831 if (nativeEvent == 2){
3832 defn = function(event){
3833 event = new Event(event, self.getWindow());
3834 if (condition.call(self, event) === false) event.stop();
3837 this.addListener(realType, defn);
3839 events[type].values.push(defn);
3843 removeEvent: function(type, fn){
3844 var events = this.retrieve('events');
3845 if (!events || !events[type]) return this;
3846 var list = events[type];
3847 var index = list.keys.indexOf(fn);
3848 if (index == -1) return this;
3849 var value = list.values[index];
3850 delete list.keys[index];
3851 delete list.values[index];
3852 var custom = Element.Events[type];
3854 if (custom.onRemove) custom.onRemove.call(this, fn);
3855 type = custom.base || type;
3857 return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;
3860 addEvents: function(events){
3861 for (var event in events) this.addEvent(event, events[event]);
3865 removeEvents: function(events){
3867 if (typeOf(events) == 'object'){
3868 for (type in events) this.removeEvent(type, events[type]);
3871 var attached = this.retrieve('events');
3872 if (!attached) return this;
3874 for (type in attached) this.removeEvents(type);
3875 this.eliminate('events');
3876 } else if (attached[events]){
3877 attached[events].keys.each(function(fn){
3878 this.removeEvent(events, fn);
3880 delete attached[events];
3885 fireEvent: function(type, args, delay){
3886 var events = this.retrieve('events');
3887 if (!events || !events[type]) return this;
3888 args = Array.from(args);
3890 events[type].keys.each(function(fn){
3891 if (delay) fn.delay(delay, this, args);
3892 else fn.apply(this, args);
3897 cloneEvents: function(from, type){
3898 from = document.id(from);
3899 var events = from.retrieve('events');
3900 if (!events) return this;
3902 for (var eventType in events) this.cloneEvents(from, eventType);
3903 } else if (events[type]){
3904 events[type].keys.each(function(fn){
3905 this.addEvent(type, fn);
3915 if (typeof HTMLElement != 'undefined')
3916 HTMLElement.prototype.fireEvent = Element.prototype.fireEvent;
3919 Element.NativeEvents = {
3920 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
3921 mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
3922 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
3923 keydown: 2, keypress: 2, keyup: 2, //keyboard
3924 orientationchange: 2, // mobile
3925 touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
3926 gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
3927 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
3928 load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
3929 error: 1, abort: 1, scroll: 1 //misc
3932 var check = function(event){
3933 var related = event.relatedTarget;
3934 if (related == null) return true;
3935 if (!related) return false;
3936 return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
3952 base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
3959 Element.Events = new Hash(Element.Events);
3971 description: Contains methods for interacting with the styles of Elements in a fashionable way.
3973 license: MIT-style license.
3977 provides: Element.Style
3984 var html = document.html;
3986 Element.Properties.styles = {set: function(styles){
3987 this.setStyles(styles);
3990 var hasOpacity = (html.style.opacity != null);
3991 var reAlpha = /alpha\(opacity=([\d.]+)\)/i;
3993 var setOpacity = function(element, opacity){
3994 if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
3996 element.style.opacity = opacity;
3998 opacity = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
3999 var filter = element.style.filter || element.getComputedStyle('filter') || '';
4000 element.style.filter = filter.test(reAlpha) ? filter.replace(reAlpha, opacity) : filter + opacity;
4004 Element.Properties.opacity = {
4006 set: function(opacity){
4007 var visibility = this.style.visibility;
4008 if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden';
4009 else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible';
4011 setOpacity(this, opacity);
4014 get: (hasOpacity) ? function(){
4015 var opacity = this.style.opacity || this.getComputedStyle('opacity');
4016 return (opacity == '') ? 1 : opacity;
4018 var opacity, filter = (this.style.filter || this.getComputedStyle('filter'));
4019 if (filter) opacity = filter.match(reAlpha);
4020 return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
4025 var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
4029 getComputedStyle: function(property){
4030 if (this.currentStyle) return this.currentStyle[property.camelCase()];
4031 var defaultView = Element.getDocument(this).defaultView,
4032 computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
4033 return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
4036 setOpacity: function(value){
4037 setOpacity(this, value);
4041 getOpacity: function(){
4042 return this.get('opacity');
4045 setStyle: function(property, value){
4047 case 'opacity': return this.set('opacity', parseFloat(value));
4048 case 'float': property = floatName;
4050 property = property.camelCase();
4051 if (typeOf(value) != 'string'){
4052 var map = (Element.Styles[property] || '@').split(' ');
4053 value = Array.from(value).map(function(val, i){
4054 if (!map[i]) return '';
4055 return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
4057 } else if (value == String(Number(value))){
4058 value = Math.round(value);
4060 this.style[property] = value;
4064 getStyle: function(property){
4066 case 'opacity': return this.get('opacity');
4067 case 'float': property = floatName;
4069 property = property.camelCase();
4070 var result = this.style[property];
4071 if (!result || property == 'zIndex'){
4073 for (var style in Element.ShortStyles){
4074 if (property != style) continue;
4075 for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
4076 return result.join(' ');
4078 result = this.getComputedStyle(property);
4081 result = String(result);
4082 var color = result.match(/rgba?\([\d\s,]+\)/);
4083 if (color) result = result.replace(color[0], color[0].rgbToHex());
4085 if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){
4086 if (property.test(/^(height|width)$/)){
4087 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
4088 values.each(function(value){
4089 size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
4091 return this['offset' + property.capitalize()] - size + 'px';
4093 if (Browser.opera && String(result).indexOf('px') != -1) return result;
4094 if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
4099 setStyles: function(styles){
4100 for (var style in styles) this.setStyle(style, styles[style]);
4104 getStyles: function(){
4106 Array.flatten(arguments).each(function(key){
4107 result[key] = this.getStyle(key);
4115 left: '@px', top: '@px', bottom: '@px', right: '@px',
4116 width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
4117 backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
4118 fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
4119 margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
4120 borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
4121 zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
4126 Element.Styles = new Hash(Element.Styles);
4130 Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
4132 ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
4133 var Short = Element.ShortStyles;
4134 var All = Element.Styles;
4135 ['margin', 'padding'].each(function(style){
4136 var sd = style + direction;
4137 Short[style][sd] = All[sd] = '@px';
4139 var bd = 'border' + direction;
4140 Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
4141 var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
4143 Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
4144 Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
4145 Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
4154 name: Element.Dimensions
4156 description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
4158 license: MIT-style license.
4161 - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
4162 - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
4164 requires: [Element, Element.Style]
4166 provides: [Element.Dimensions]
4175 scrollTo: function(x, y){
4177 this.getWindow().scrollTo(x, y);
4179 this.scrollLeft = x;
4185 getSize: function(){
4186 if (isBody(this)) return this.getWindow().getSize();
4187 return {x: this.offsetWidth, y: this.offsetHeight};
4190 getScrollSize: function(){
4191 if (isBody(this)) return this.getWindow().getScrollSize();
4192 return {x: this.scrollWidth, y: this.scrollHeight};
4195 getScroll: function(){
4196 if (isBody(this)) return this.getWindow().getScroll();
4197 return {x: this.scrollLeft, y: this.scrollTop};
4200 getScrolls: function(){
4201 var element = this.parentNode, position = {x: 0, y: 0};
4202 while (element && !isBody(element)){
4203 position.x += element.scrollLeft;
4204 position.y += element.scrollTop;
4205 element = element.parentNode;
4210 getOffsetParent: function(){
4212 if (isBody(element)) return null;
4213 if (!Browser.ie) return element.offsetParent;
4214 while ((element = element.parentNode)){
4215 if (styleString(element, 'position') != 'static' || isBody(element)) return element;
4220 getOffsets: function(){
4221 if (this.getBoundingClientRect && !Browser.Platform.ios){
4222 var bound = this.getBoundingClientRect(),
4223 html = document.id(this.getDocument().documentElement),
4224 htmlScroll = html.getScroll(),
4225 elemScrolls = this.getScrolls(),
4226 isFixed = (styleString(this, 'position') == 'fixed');
4229 x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
4230 y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
4234 var element = this, position = {x: 0, y: 0};
4235 if (isBody(this)) return position;
4237 while (element && !isBody(element)){
4238 position.x += element.offsetLeft;
4239 position.y += element.offsetTop;
4241 if (Browser.firefox){
4242 if (!borderBox(element)){
4243 position.x += leftBorder(element);
4244 position.y += topBorder(element);
4246 var parent = element.parentNode;
4247 if (parent && styleString(parent, 'overflow') != 'visible'){
4248 position.x += leftBorder(parent);
4249 position.y += topBorder(parent);
4251 } else if (element != this && Browser.safari){
4252 position.x += leftBorder(element);
4253 position.y += topBorder(element);
4256 element = element.offsetParent;
4258 if (Browser.firefox && !borderBox(this)){
4259 position.x -= leftBorder(this);
4260 position.y -= topBorder(this);
4265 getPosition: function(relative){
4266 if (isBody(this)) return {x: 0, y: 0};
4267 var offset = this.getOffsets(),
4268 scroll = this.getScrolls();
4270 x: offset.x - scroll.x,
4271 y: offset.y - scroll.y
4274 if (relative && (relative = document.id(relative))){
4275 var relativePosition = relative.getPosition();
4276 return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
4281 getCoordinates: function(element){
4282 if (isBody(this)) return this.getWindow().getCoordinates();
4283 var position = this.getPosition(element),
4284 size = this.getSize();
4291 obj.right = obj.left + obj.width;
4292 obj.bottom = obj.top + obj.height;
4296 computePosition: function(obj){
4298 left: obj.x - styleNumber(this, 'margin-left'),
4299 top: obj.y - styleNumber(this, 'margin-top')
4303 setPosition: function(obj){
4304 return this.setStyles(this.computePosition(obj));
4310 [Document, Window].invoke('implement', {
4312 getSize: function(){
4313 var doc = getCompatElement(this);
4314 return {x: doc.clientWidth, y: doc.clientHeight};
4317 getScroll: function(){
4318 var win = this.getWindow(), doc = getCompatElement(this);
4319 return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
4322 getScrollSize: function(){
4323 var doc = getCompatElement(this),
4324 min = this.getSize(),
4325 body = this.getDocument().body;
4327 return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
4330 getPosition: function(){
4331 return {x: 0, y: 0};
4334 getCoordinates: function(){
4335 var size = this.getSize();
4336 return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
4343 var styleString = Element.getComputedStyle;
4345 function styleNumber(element, style){
4346 return styleString(element, style).toInt() || 0;
4349 function borderBox(element){
4350 return styleString(element, '-moz-box-sizing') == 'border-box';
4353 function topBorder(element){
4354 return styleNumber(element, 'border-top-width');
4357 function leftBorder(element){
4358 return styleNumber(element, 'border-left-width');
4361 function isBody(element){
4362 return (/^(?:body|html)$/i).test(element.tagName);
4365 function getCompatElement(element){
4366 var doc = element.getDocument();
4367 return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
4373 Element.alias({position: 'setPosition'}); //compatability
4375 [Window, Document, Element].invoke('implement', {
4377 getHeight: function(){
4378 return this.getSize().y;
4381 getWidth: function(){
4382 return this.getSize().x;
4385 getScrollTop: function(){
4386 return this.getScroll().y;
4389 getScrollLeft: function(){
4390 return this.getScroll().x;
4393 getScrollHeight: function(){
4394 return this.getScrollSize().y;
4397 getScrollWidth: function(){
4398 return this.getScrollSize().x;
4402 return this.getPosition().y;
4405 getLeft: function(){
4406 return this.getPosition().x;
4417 description: Contains the basic animation logic to be extended by all other Fx Classes.
4419 license: MIT-style license.
4421 requires: [Chain, Events, Options]
4430 var Fx = this.Fx = new Class({
4432 Implements: [Chain, Events, Options],
4446 initialize: function(options){
4447 this.subject = this.subject || this;
4448 this.setOptions(options);
4451 getTransition: function(){
4453 return -(Math.cos(Math.PI * p) - 1) / 2;
4458 var time = Date.now();
4459 if (time < this.time + this.options.duration){
4460 var delta = this.transition((time - this.time) / this.options.duration);
4461 this.set(this.compute(this.from, this.to, delta));
4463 this.set(this.compute(this.from, this.to, 1));
4472 compute: function(from, to, delta){
4473 return Fx.compute(from, to, delta);
4477 if (!this.timer) return true;
4478 switch (this.options.link){
4479 case 'cancel': this.cancel(); return true;
4480 case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
4485 start: function(from, to){
4486 if (!this.check(from, to)) return this;
4487 var duration = this.options.duration;
4488 this.options.duration = Fx.Durations[duration] || duration.toInt();
4492 this.transition = this.getTransition();
4498 complete: function(){
4499 if (this.stopTimer()) this.onComplete();
4504 if (this.stopTimer()) this.onCancel();
4508 onStart: function(){
4509 this.fireEvent('start', this.subject);
4512 onComplete: function(){
4513 this.fireEvent('complete', this.subject);
4514 if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
4517 onCancel: function(){
4518 this.fireEvent('cancel', this.subject).clearChain();
4531 stopTimer: function(){
4532 if (!this.timer) return false;
4533 this.time = Date.now() - this.time;
4534 this.timer = removeInstance(this);
4538 startTimer: function(){
4539 if (this.timer) return false;
4540 this.time = Date.now() - this.time;
4541 this.timer = addInstance(this);
4547 Fx.compute = function(from, to, delta){
4548 return (to - from) * delta + from;
4551 Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
4555 var instances = {}, timers = {};
4557 var loop = function(){
4558 for (var i = this.length; i--;){
4559 if (this[i]) this[i].step();
4563 var addInstance = function(instance){
4564 var fps = instance.options.fps,
4565 list = instances[fps] || (instances[fps] = []);
4566 list.push(instance);
4567 if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
4571 var removeInstance = function(instance){
4572 var fps = instance.options.fps,
4573 list = instances[fps] || [];
4574 list.erase(instance);
4575 if (!list.length && timers[fps]) timers[fps] = clearInterval(timers[fps]);
4587 description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
4589 license: MIT-style license.
4591 requires: [Fx, Element.Style]
4598 Fx.CSS = new Class({
4602 //prepares the base from/to object
4604 prepare: function(element, property, values){
4605 values = Array.from(values);
4606 if (values[1] == null){
4607 values[1] = values[0];
4608 values[0] = element.getStyle(property);
4610 var parsed = values.map(this.parse);
4611 return {from: parsed[0], to: parsed[1]};
4614 //parses a value into an array
4616 parse: function(value){
4617 value = Function.from(value)();
4618 value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
4619 return value.map(function(val){
4622 Object.each(Fx.CSS.Parsers, function(parser, key){
4624 var parsed = parser.parse(val);
4625 if (parsed || parsed === 0) found = {value: parsed, parser: parser};
4627 found = found || {value: val, parser: Fx.CSS.Parsers.String};
4632 //computes by a from and to prepared objects, using their parsers.
4634 compute: function(from, to, delta){
4636 (Math.min(from.length, to.length)).times(function(i){
4637 computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
4639 computed.$family = Function.from('fx:css:value');
4643 //serves the value as settable
4645 serve: function(value, unit){
4646 if (typeOf(value) != 'fx:css:value') value = this.parse(value);
4648 value.each(function(bit){
4649 returned = returned.concat(bit.parser.serve(bit.value, unit));
4654 //renders the change to an element
4656 render: function(element, property, value, unit){
4657 element.setStyle(property, this.serve(value, unit));
4660 //searches inside the page css to find the values for a selector
4662 search: function(selector){
4663 if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
4665 Array.each(document.styleSheets, function(sheet, j){
4666 var href = sheet.href;
4667 if (href && href.contains('://') && !href.contains(document.domain)) return;
4668 var rules = sheet.rules || sheet.cssRules;
4669 Array.each(rules, function(rule, i){
4670 if (!rule.style) return;
4671 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
4672 return m.toLowerCase();
4674 if (!selectorText || !selectorText.test('^' + selector + '$')) return;
4675 Element.Styles.each(function(value, style){
4676 if (!rule.style[style] || Element.ShortStyles[style]) return;
4677 value = String(rule.style[style]);
4678 to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
4682 return Fx.CSS.Cache[selector] = to;
4692 parse: function(value){
4693 if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
4694 return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
4696 compute: function(from, to, delta){
4697 return from.map(function(value, i){
4698 return Math.round(Fx.compute(from[i], to[i], delta));
4701 serve: function(value){
4702 return value.map(Number);
4708 compute: Fx.compute,
4709 serve: function(value, unit){
4710 return (unit) ? value + unit : value;
4715 parse: Function.from(false),
4716 compute: function(zero, one){
4719 serve: function(zero){
4728 Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);
4738 description: Formerly Fx.Style, effect to transition any CSS property for an element.
4740 license: MIT-style license.
4744 provides: [Fx.Tween, Element.fade, Element.highlight]
4749 Fx.Tween = new Class({
4753 initialize: function(element, options){
4754 this.element = this.subject = document.id(element);
4755 this.parent(options);
4758 set: function(property, now){
4759 if (arguments.length == 1){
4761 property = this.property || this.options.property;
4763 this.render(this.element, property, now, this.options.unit);
4767 start: function(property, from, to){
4768 if (!this.check(property, from, to)) return this;
4769 var args = Array.flatten(arguments);
4770 this.property = this.options.property || args.shift();
4771 var parsed = this.prepare(this.element, this.property, args);
4772 return this.parent(parsed.from, parsed.to);
4777 Element.Properties.tween = {
4779 set: function(options){
4780 this.get('tween').cancel().setOptions(options);
4785 var tween = this.retrieve('tween');
4787 tween = new Fx.Tween(this, {link: 'cancel'});
4788 this.store('tween', tween);
4797 tween: function(property, from, to){
4798 this.get('tween').start(arguments);
4802 fade: function(how){
4803 var fade = this.get('tween'), o = 'opacity', toggle;
4804 how = [how, 'toggle'].pick();
4806 case 'in': fade.start(o, 1); break;
4807 case 'out': fade.start(o, 0); break;
4808 case 'show': fade.set(o, 1); break;
4809 case 'hide': fade.set(o, 0); break;
4811 var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
4812 fade.start(o, (flag) ? 0 : 1);
4813 this.store('fade:flag', !flag);
4816 default: fade.start(o, arguments);
4818 if (!toggle) this.eliminate('fade:flag');
4822 highlight: function(start, end){
4824 end = this.retrieve('highlight:original', this.getStyle('background-color'));
4825 end = (end == 'transparent') ? '#fff' : end;
4827 var tween = this.get('tween');
4828 tween.start('background-color', start || '#ffff88', end).chain(function(){
4829 this.setStyle('background-color', this.retrieve('highlight:original'));
4843 description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
4845 license: MIT-style license.
4854 Fx.Morph = new Class({
4858 initialize: function(element, options){
4859 this.element = this.subject = document.id(element);
4860 this.parent(options);
4864 if (typeof now == 'string') now = this.search(now);
4865 for (var p in now) this.render(this.element, p, now[p], this.options.unit);
4869 compute: function(from, to, delta){
4871 for (var p in from) now[p] = this.parent(from[p], to[p], delta);
4875 start: function(properties){
4876 if (!this.check(properties)) return this;
4877 if (typeof properties == 'string') properties = this.search(properties);
4878 var from = {}, to = {};
4879 for (var p in properties){
4880 var parsed = this.prepare(this.element, p, properties[p]);
4881 from[p] = parsed.from;
4884 return this.parent(from, to);
4889 Element.Properties.morph = {
4891 set: function(options){
4892 this.get('morph').cancel().setOptions(options);
4897 var morph = this.retrieve('morph');
4899 morph = new Fx.Morph(this, {link: 'cancel'});
4900 this.store('morph', morph);
4909 morph: function(props){
4910 this.get('morph').start(props);
4920 name: Fx.Transitions
4922 description: Contains a set of advanced transitions to be used with any of the Fx Classes.
4924 license: MIT-style license.
4927 - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
4931 provides: Fx.Transitions
4938 getTransition: function(){
4939 var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
4940 if (typeof trans == 'string'){
4941 var data = trans.split(':');
4942 trans = Fx.Transitions;
4943 trans = trans[data[0]] || trans[data[0].capitalize()];
4944 if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
4951 Fx.Transition = function(transition, params){
4952 params = Array.from(params);
4953 return Object.append(transition, {
4954 easeIn: function(pos){
4955 return transition(pos, params);
4957 easeOut: function(pos){
4958 return 1 - transition(1 - pos, params);
4960 easeInOut: function(pos){
4961 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
4968 linear: function(zero){
4976 Fx.Transitions = new Hash(Fx.Transitions);
4980 Fx.Transitions.extend = function(transitions){
4981 for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
4984 Fx.Transitions.extend({
4986 Pow: function(p, x){
4987 return Math.pow(p, x && x[0] || 6);
4991 return Math.pow(2, 8 * (p - 1));
4995 return 1 - Math.sin(Math.acos(p));
4999 return 1 - Math.sin((1 - p) * Math.PI / 2);
5002 Back: function(p, x){
5003 x = x && x[0] || 1.618;
5004 return Math.pow(p, 2) * ((x + 1) * p - x);
5007 Bounce: function(p){
5009 for (var a = 0, b = 1; 1; a += b, b /= 2){
5010 if (p >= (7 - 4 * a) / 11){
5011 value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
5018 Elastic: function(p, x){
5019 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
5024 ['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
5025 Fx.Transitions[transition] = new Fx.Transition(function(p){
5026 return Math.pow(p, [i + 2]);
5036 description: Contains the custom event domready.
5038 license: MIT-style license.
5040 requires: [Browser, Element, Element.Event]
5042 provides: [DOMReady, DomReady]
5047 (function(window, document){
5056 // Thanks to Rich Dougherty <http://www.richdougherty.com/>
5058 isFramed = window.frameElement != null;
5061 var domready = function(){
5062 clearTimeout(timer);
5064 Browser.loaded = ready = true;
5065 document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
5067 document.fireEvent('domready');
5068 window.fireEvent('domready');
5071 var check = function(){
5072 for (var i = checks.length; i--;) if (checks[i]()){
5080 var poll = function(){
5081 clearTimeout(timer);
5082 if (!check()) timer = setTimeout(poll, 10);
5085 document.addListener('DOMContentLoaded', domready);
5087 // doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
5088 var testElement = document.createElement('div');
5089 if (testElement.doScroll && !isFramed){
5090 checks.push(function(){
5092 testElement.doScroll();
5101 if (document.readyState) checks.push(function(){
5102 var state = document.readyState;
5103 return (state == 'loaded' || state == 'complete');
5106 if ('onreadystatechange' in document) document.addListener('readystatechange', check);
5107 else shouldPoll = true;
5109 if (shouldPoll) poll();
5111 Element.Events.domready = {
5112 onAdd: function(fn){
5113 if (ready) fn.call(this);
5117 // Make sure that domready fires before load
5118 Element.Events.load = {
5120 onAdd: function(fn){
5121 if (loaded && this == window) fn.call(this);
5123 condition: function(){
5124 if (this == window){
5126 delete Element.Events.load;
5133 // This is based on the custom load event
5134 window.addEvent('load', function(){
5138 })(window, document);
5140 // MooTools: the javascript framework.
5141 // Load this file's selection again by visiting: http://mootools.net/more/4e3c76ec202edfd6dce2f7a94df9b03d
5142 // Or build this file again with packager using: packager build More/More More/Fx.Elements More/Fx.Slide More/Assets
5150 description: MooTools More
5152 license: MIT-style license
5166 provides: [MooTools.More]
5172 'version': '1.3.0.1',
5173 'build': '6dce99bed2792dffcbbbb4ddc15a1fb9a41994b5'
5180 script: Fx.Elements.js
5184 description: Effect to change any number of CSS properties of any number of Elements.
5186 license: MIT-style license
5195 provides: [Fx.Elements]
5200 Fx.Elements = new Class({
5204 initialize: function(elements, options){
5205 this.elements = this.subject = $$(elements);
5206 this.parent(options);
5209 compute: function(from, to, delta){
5212 for (var i in from){
5213 var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
5214 for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
5222 if (!this.elements[i]) continue;
5225 for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
5231 start: function(obj){
5232 if (!this.check(obj)) return this;
5233 var from = {}, to = {};
5236 if (!this.elements[i]) continue;
5238 var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
5240 for (var p in iProps){
5241 var parsed = this.prepare(this.elements[i], p, iProps[p]);
5242 iFrom[p] = parsed.from;
5247 return this.parent(from, to);
5260 description: Effect to slide an element in and out of view.
5262 license: MIT-style license
5269 - Core/Element.Style
5272 provides: [Fx.Slide]
5277 Fx.Slide = new Class({
5288 initialize: function(element, options){
5289 this.addEvent('complete', function(){
5290 this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);
5291 if (this.open && this.options.resetHeight) this.wrapper.setStyle('height', '');
5294 this.element = this.subject = document.id(element);
5295 this.parent(options);
5296 var wrapper = this.element.retrieve('wrapper');
5297 var styles = this.element.getStyles('margin', 'position', 'overflow');
5299 if (this.options.hideOverflow) styles = Object.append(styles, {overflow: 'hidden'});
5300 if (this.options.wrapper) wrapper = document.id(this.options.wrapper).setStyles(styles);
5302 this.wrapper = wrapper || new Element('div', {
5304 }).wraps(this.element);
5306 this.element.store('wrapper', this.wrapper).setStyle('margin', 0);
5311 vertical: function(){
5312 this.margin = 'margin-top';
5313 this.layout = 'height';
5314 this.offset = this.element.offsetHeight;
5317 horizontal: function(){
5318 this.margin = 'margin-left';
5319 this.layout = 'width';
5320 this.offset = this.element.offsetWidth;
5324 this.element.setStyle(this.margin, now[0]);
5325 this.wrapper.setStyle(this.layout, now[1]);
5329 compute: function(from, to, delta){
5330 return [0, 1].map(function(i){
5331 return Fx.compute(from[i], to[i], delta);
5335 start: function(how, mode){
5336 if (!this.check(how, mode)) return this;
5337 this[mode || this.options.mode]();
5338 var margin = this.element.getStyle(this.margin).toInt();
5339 var layout = this.wrapper.getStyle(this.layout).toInt();
5340 var caseIn = [[margin, layout], [0, this.offset]];
5341 var caseOut = [[margin, layout], [-this.offset, 0]];
5344 case 'in': start = caseIn; break;
5345 case 'out': start = caseOut; break;
5346 case 'toggle': start = (layout == 0) ? caseIn : caseOut;
5348 return this.parent(start[0], start[1]);
5351 slideIn: function(mode){
5352 return this.start('in', mode);
5355 slideOut: function(mode){
5356 return this.start('out', mode);
5359 hide: function(mode){
5360 this[mode || this.options.mode]();
5362 return this.set([-this.offset, 0]);
5365 show: function(mode){
5366 this[mode || this.options.mode]();
5368 return this.set([0, this.offset]);
5371 toggle: function(mode){
5372 return this.start('toggle', mode);
5377 Element.Properties.slide = {
5379 set: function(options){
5380 this.get('slide').cancel().setOptions(options);
5385 var slide = this.retrieve('slide');
5387 slide = new Fx.Slide(this, {link: 'cancel'});
5388 this.store('slide', slide);
5397 slide: function(how, mode){
5398 how = how || 'toggle';
5399 var slide = this.get('slide'), toggle;
5401 case 'hide': slide.hide(mode); break;
5402 case 'show': slide.show(mode); break;
5404 var flag = this.retrieve('slide:flag', slide.open);
5405 slide[flag ? 'slideOut' : 'slideIn'](mode);
5406 this.store('slide:flag', !flag);
5409 default: slide.start(how, mode);
5411 if (!toggle) this.eliminate('slide:flag');
5425 description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
5427 license: MIT-style license
5433 - Core/Element.Event
5443 javascript: function(source, properties){
5444 properties = Object.append({
5448 if (properties.onLoad){
5449 properties.onload = properties.onLoad;
5450 delete properties.onLoad;
5453 var script = new Element('script', {src: source, type: 'text/javascript'});
5454 var load = properties.onload || function(){},
5455 doc = properties.document;
5456 delete properties.onload;
5457 delete properties.document;
5459 return script.addEvents({
5461 readystatechange: function(){
5462 if (['loaded', 'complete'].contains(this.readyState)) load.call(this);
5464 }).set(properties).inject(doc.head);
5467 css: function(source, properties){
5468 properties = properties || {};
5469 var onload = properties.onload || properties.onLoad;
5471 properties.events = properties.events || {};
5472 properties.events.load = onload;
5473 delete properties.onload;
5474 delete properties.onLoad;
5476 return new Element('link', Object.merge({
5481 }, properties)).inject(document.head);
5484 image: function(source, properties){
5485 properties = Object.merge({
5486 onload: function(){},
5487 onabort: function(){},
5488 onerror: function(){}
5490 var image = new Image();
5491 var element = document.id(image) || new Element('img');
5492 ['load', 'abort', 'error'].each(function(name){
5493 var type = 'on' + name;
5494 var cap = name.capitalize();
5495 if (properties['on' + cap]){
5496 properties[type] = properties['on' + cap];
5497 delete properties['on' + cap];
5499 var event = properties[type];
5500 delete properties[type];
5501 image[type] = function(){
5503 if (!element.parentNode){
5504 element.width = image.width;
5505 element.height = image.height;
5507 image = image.onload = image.onabort = image.onerror = null;
5508 event.delay(1, element, element);
5509 element.fireEvent(name, element, 1);
5512 image.src = element.src = source;
5513 if (image && image.complete) image.onload.delay(1);
5514 return element.set(properties);
5517 images: function(sources, options){
5518 options = Object.merge({
5519 onComplete: function(){},
5520 onProgress: function(){},
5521 onError: function(){},
5524 sources = Array.from(sources);
5526 return new Elements(sources.map(function(source, index){
5527 return Asset.image(source, Object.append(options.properties, {
5530 options.onProgress.call(this, counter, index, source);
5531 if (counter == sources.length) options.onComplete();
5533 onerror: function(){
5535 options.onError.call(this, counter, index, source);
5536 if (counter == sources.length) options.onComplete();