2 //This library: http://dev.clientcide.com/depender/build?download=true&version=Clientcide+3.1.0&require=Core%2FBrowser&require=Core%2FClass.Extras&require=Core%2FClass&require=Core%2FCore&require=Core%2FElement.Delegation&require=Core%2FElement.Dimensions&require=Core%2FElement.Event&require=Core%2FElement.Style&require=Core%2FElement&require=Core%2FFx.CSS&require=Core%2FFx.Morph&require=Core%2FFx.Transitions&require=Core%2FFx.Tween&require=Core%2FFx&require=Core%2FRequest.HTML&require=Core%2FRequest.JSON&require=Core%2FRequest&require=Core%2FSlick.Finder&require=Core%2FSlick.Parser&require=Core%2FArray&require=Core%2FEvent&require=Core%2FFunction&require=Core%2FNumber&require=Core%2FObject&require=Core%2FString&require=Core%2FCookie&require=Core%2FDOMReady&require=Core%2FJSON&require=Core%2FSwiff&require=Clientcide%2FBehavior.StickyWin&require=Clientcide%2FCollapsible&require=Clientcide%2FMultipleOpenAccordion&require=Clientcide%2FTabSwapper&require=Clientcide%2FStickyWin.Ajax&require=Clientcide%2FStickyWin.Alert&require=Clientcide%2FStickyWin.Confirm&require=Clientcide%2FStickyWin.Drag&require=Clientcide%2FStickyWin.Fx&require=Clientcide%2FStickyWin.Modal&require=Clientcide%2FStickyWin.UI&require=More%2FElement.Forms&require=More%2FOverText&require=More%2FFx.Accordion&require=More%2FFx.Move&require=More%2FFx.Reveal&require=More%2FFx.Scroll&require=More%2FFx.Slide&require=More%2FKeyboard.Extras&require=More%2FSpinner&require=More%2FMore&require=More%2FRequest.JSONP&require=More%2FRequest.Periodical&require=More%2FArray.Extras&require=More%2FDate.Extras&require=More%2FNumber.Format&require=More%2FURI.Relative&require=More%2FAssets&require=More%2FColor&require=More%2FHash.Cookie
3 //Contents: Core:Source/Core/Core.js, Core:Source/Types/Object.js, Core:Source/Types/Array.js, Core:Source/Types/Function.js, Core:Source/Types/Number.js, Core:Source/Types/String.js, Core:Source/Browser/Browser.js, Core:Source/Slick/Slick.Parser.js, Core:Source/Slick/Slick.Finder.js, Core:Source/Element/Element.js, Core:Source/Class/Class.js, Core:Source/Class/Class.Extras.js, Core:Source/Request/Request.js, Core:Source/Utilities/JSON.js, Core:Source/Request/Request.JSON.js, Core:Source/Types/DOMEvent.js, Core:Source/Element/Element.Event.js, Core:Source/Element/Element.Delegation.js, Core:Source/Fx/Fx.js, Core:Source/Element/Element.Style.js, Core:Source/Fx/Fx.CSS.js, Core:Source/Fx/Fx.Morph.js, Core:Source/Utilities/Swiff.js, Core:Source/Fx/Fx.Transitions.js, More:Source/More/More.js, More:Source/Class/Class.Binds.js, More:Source/Class/Class.Occlude.js, Core:Source/Element/Element.Dimensions.js, More:Source/Element/Element.Measure.js, More:Source/Element/Element.Position.js, More:Source/Element/Element.Shortcuts.js, More:Source/Forms/OverText.js, More:Source/Utilities/IframeShim.js, More:Source/Interface/Mask.js, Core:Source/Utilities/DOMReady.js, More:Source/Element/Element.Pin.js, More:Source/Types/Object.Extras.js, Clientcide:Source/Core/Clientcide.js, Clientcide:Source/Core/dbug.js, Clientcide:Source/UI/StyleWriter.js, Clientcide:Source/UI/StickyWin.js, Clientcide:Source/UI/StickyWin.Modal.js, More:Source/Types/String.Extras.js, Clientcide:Source/UI/StickyWin.UI.js, Clientcide:Source/UI/StickyWin.Alert.js, Clientcide:Source/UI/StickyWin.Confirm.js, More:Source/Fx/Fx.Move.js, More:Source/Fx/Fx.Scroll.js, More:Source/Class/Class.Refactor.js, Core:Source/Fx/Fx.Tween.js, Clientcide:Source/UI/StickyWin.Fx.js, More:Source/Types/Array.Extras.js, Core:Source/Request/Request.HTML.js, Clientcide:Source/Layout/TabSwapper.js, More:Source/Element/Element.Forms.js, More:Source/Fx/Fx.Reveal.js, Clientcide:Source/Layout/Collapsible.js, More:Source/Utilities/Table.js, Behavior:Source/Element.Data.js, Behavior:Source/BehaviorAPI.js, Behavior:Source/Behavior.js, More:Source/Drag/Drag.js, More:Source/Drag/Drag.Move.js, Clientcide:Source/UI/StickyWin.Drag.js, Clientcide:Source/Behaviors/Behavior.StickyWin.js, More:Source/Utilities/Color.js, More:Source/Class/Events.Pseudos.js, More:Source/Element/Element.Event.Pseudos.js, More:Source/Element/Element.Event.Pseudos.Keys.js, More:Source/Interface/Keyboard.js, More:Source/Interface/Keyboard.Extras.js, More:Source/Locale/Locale.js, More:Source/Locale/Locale.en-US.Number.js, More:Source/Types/Number.Format.js, More:Source/Request/Request.Periodical.js, More:Source/Request/Request.JSONP.js, More:Source/Types/String.QueryString.js, More:Source/Types/URI.js, More:Source/Types/URI.Relative.js, Core:Source/Utilities/Cookie.js, More:Source/Locale/Locale.en-US.Date.js, More:Source/Types/Date.js, More:Source/Types/Date.Extras.js, More:Source/Fx/Fx.Elements.js, More:Source/Fx/Fx.Accordion.js, More:Source/Types/Hash.js, More:Source/Utilities/Hash.Cookie.js, More:Source/Utilities/Assets.js, More:Source/Interface/Spinner.js, More:Source/Fx/Fx.Slide.js, Clientcide:Source/UI/StickyWin.UI.Pointy.js, Clientcide:Source/UI/StickyWin.PointyTip.js, Clientcide:Source/UI/StickyWin.Ajax.js, Clientcide:Source/Layout/MultipleOpenAccordion.js
5 // Begin: Source/Core/Core.js
11 description: The heart of MooTools.
13 license: MIT-style license.
15 copyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/).
17 authors: The MooTools production team (http://mootools.net/developers/)
20 - 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)
21 - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
23 provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
32 build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0'
37 var typeOf = this.typeOf = function(item){
38 if (item == null) return 'null';
39 if (item.$family != null) return item.$family();
42 if (item.nodeType == 1) return 'element';
43 if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
44 } else if (typeof item.length == 'number'){
45 if (item.callee) return 'arguments';
46 if ('item' in item) return 'collection';
52 var instanceOf = this.instanceOf = function(item, object){
53 if (item == null) return false;
54 var constructor = item.$constructor || item.constructor;
56 if (constructor === object) return true;
57 constructor = constructor.parent;
60 if (!item.hasOwnProperty) return false;
62 return item instanceof object;
65 // Function overloading
67 var Function = this.Function;
69 var enumerables = true;
70 for (var i in {toString: 1}) enumerables = null;
71 if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
73 Function.prototype.overloadSetter = function(usePlural){
75 return function(a, b){
76 if (a == null) return this;
77 if (usePlural || typeof a != 'string'){
78 for (var k in a) self.call(this, k, a[k]);
79 if (enumerables) for (var i = enumerables.length; i--;){
81 if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
84 self.call(this, a, b);
90 Function.prototype.overloadGetter = function(usePlural){
94 if (typeof a != 'string') args = a;
95 else if (arguments.length > 1) args = arguments;
96 else if (usePlural) args = [a];
99 for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
101 result = self.call(this, a);
107 Function.prototype.extend = function(key, value){
111 Function.prototype.implement = function(key, value){
112 this.prototype[key] = value;
117 var slice = Array.prototype.slice;
119 Function.from = function(item){
120 return (typeOf(item) == 'function') ? item : function(){
125 Array.from = function(item){
126 if (item == null) return [];
127 return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
130 Number.from = function(item){
131 var number = parseFloat(item);
132 return isFinite(number) ? number : null;
135 String.from = function(item){
149 this.$protected = true;
157 var Type = this.Type = function(name, object){
159 var lower = name.toLowerCase();
160 var typeCheck = function(item){
161 return (typeOf(item) == lower);
164 Type['is' + name] = typeCheck;
166 object.prototype.$family = (function(){
170 object.type = typeCheck;
175 if (object == null) return null;
178 object.$constructor = Type;
179 object.prototype.$constructor = object;
184 var toString = Object.prototype.toString;
186 Type.isEnumerable = function(item){
187 return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
192 var hooksOf = function(object){
193 var type = typeOf(object.prototype);
194 return hooks[type] || (hooks[type] = []);
197 var implement = function(name, method){
198 if (method && method.$hidden) return;
200 var hooks = hooksOf(this);
202 for (var i = 0; i < hooks.length; i++){
204 if (typeOf(hook) == 'type') implement.call(hook, name, method);
205 else hook.call(this, name, method);
208 var previous = this.prototype[name];
209 if (previous == null || !previous.$protected) this.prototype[name] = method;
211 if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
212 return method.apply(item, slice.call(arguments, 1));
216 var extend = function(name, method){
217 if (method && method.$hidden) return;
218 var previous = this[name];
219 if (previous == null || !previous.$protected) this[name] = method;
224 implement: implement.overloadSetter(),
226 extend: extend.overloadSetter(),
228 alias: function(name, existing){
229 implement.call(this, name, this.prototype[existing]);
232 mirror: function(hook){
233 hooksOf(this).push(hook);
239 new Type('Type', Type);
243 var force = function(name, object, methods){
244 var isType = (object != Object),
245 prototype = object.prototype;
247 if (isType) object = new Type(name, object);
249 for (var i = 0, l = methods.length; i < l; i++){
250 var key = methods[i],
251 generic = object[key],
252 proto = prototype[key];
254 if (generic) generic.protect();
255 if (isType && proto) object.implement(key, proto.protect());
259 var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]);
260 object.forEachMethod = function(fn){
261 if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){
262 fn.call(prototype, prototype[methods[i]], methods[i]);
264 for (var key in prototype) fn.call(prototype, prototype[key], key)
271 force('String', String, [
272 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
273 'slice', 'split', 'substr', 'substring', 'trim', '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 var hasOwnProperty = Object.prototype.hasOwnProperty;
312 Object.extend('forEach', function(object, fn, bind){
313 for (var key in object){
314 if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
318 Object.each = Object.forEach;
322 forEach: function(fn, bind){
323 for (var i = 0, l = this.length; i < l; i++){
324 if (i in this) fn.call(bind, this[i], i, this);
328 each: function(fn, bind){
329 Array.forEach(this, fn, bind);
335 // Array & Object cloning, Object merging and appending
337 var cloneOf = function(item){
338 switch (typeOf(item)){
339 case 'array': return item.clone();
340 case 'object': return Object.clone(item);
341 default: return item;
345 Array.implement('clone', function(){
346 var i = this.length, clone = new Array(i);
347 while (i--) clone[i] = cloneOf(this[i]);
351 var mergeOne = function(source, key, current){
352 switch (typeOf(current)){
354 if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
355 else source[key] = Object.clone(current);
357 case 'array': source[key] = current.clone(); break;
358 default: source[key] = current;
365 merge: function(source, k, v){
366 if (typeOf(k) == 'string') return mergeOne(source, k, v);
367 for (var i = 1, l = arguments.length; i < l; i++){
368 var object = arguments[i];
369 for (var key in object) mergeOne(source, key, object[key]);
374 clone: function(object){
376 for (var key in object) clone[key] = cloneOf(object[key]);
380 append: function(original){
381 for (var i = 1, l = arguments.length; i < l; i++){
382 var extended = arguments[i] || {};
383 for (var key in extended) original[key] = extended[key];
392 ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
398 var UID = Date.now();
400 String.extend('uniqueID', function(){
401 return (UID++).toString(36);
406 var Hash = this.Hash = new Type('Hash', function(object){
407 if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
408 for (var key in object) this[key] = object[key];
414 forEach: function(fn, bind){
415 Object.forEach(this, fn, bind);
418 getClean: function(){
420 for (var key in this){
421 if (this.hasOwnProperty(key)) clean[key] = this[key];
426 getLength: function(){
428 for (var key in this){
429 if (this.hasOwnProperty(key)) length++;
436 Hash.alias('each', 'forEach');
438 Object.type = Type.isObject;
440 var Native = this.Native = function(properties){
441 return new Type(properties.name, properties.initialize);
444 Native.type = Type.type;
446 Native.implement = function(objects, methods){
447 for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
451 var arrayType = Array.type;
452 Array.type = function(item){
453 return instanceOf(item, Array) || arrayType(item);
456 this.$A = function(item){
457 return Array.from(item).slice();
460 this.$arguments = function(i){
466 this.$chk = function(obj){
467 return !!(obj || obj === 0);
470 this.$clear = function(timer){
472 clearInterval(timer);
476 this.$defined = function(obj){
477 return (obj != null);
480 this.$each = function(iterable, fn, bind){
481 var type = typeOf(iterable);
482 ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind);
485 this.$empty = function(){};
487 this.$extend = function(original, extended){
488 return Object.append(original, extended);
491 this.$H = function(object){
492 return new Hash(object);
495 this.$merge = function(){
496 var args = Array.slice(arguments);
498 return Object.merge.apply(null, args);
501 this.$lambda = Function.from;
502 this.$mixin = Object.merge;
503 this.$random = Number.random;
504 this.$splat = Array.from;
505 this.$time = Date.now;
507 this.$type = function(object){
508 var type = typeOf(object);
509 if (type == 'elements') return 'array';
510 return (type == 'null') ? false : type;
513 this.$unlink = function(object){
514 switch (typeOf(object)){
515 case 'object': return Object.clone(object);
516 case 'array': return Array.clone(object);
517 case 'hash': return new Hash(object);
518 default: return object;
527 // Begin: Source/Types/Object.js
533 description: Object generic methods
535 license: MIT-style license.
539 provides: [Object, Hash]
546 var hasOwnProperty = Object.prototype.hasOwnProperty;
550 subset: function(object, keys){
552 for (var i = 0, l = keys.length; i < l; i++){
554 if (k in object) results[k] = object[k];
559 map: function(object, fn, bind){
561 for (var key in object){
562 if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
567 filter: function(object, fn, bind){
569 for (var key in object){
570 var value = object[key];
571 if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
576 every: function(object, fn, bind){
577 for (var key in object){
578 if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
583 some: function(object, fn, bind){
584 for (var key in object){
585 if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
590 keys: function(object){
592 for (var key in object){
593 if (hasOwnProperty.call(object, key)) keys.push(key);
598 values: function(object){
600 for (var key in object){
601 if (hasOwnProperty.call(object, key)) values.push(object[key]);
606 getLength: function(object){
607 return Object.keys(object).length;
610 keyOf: function(object, value){
611 for (var key in object){
612 if (hasOwnProperty.call(object, key) && object[key] === value) return key;
617 contains: function(object, value){
618 return Object.keyOf(object, value) != null;
621 toQueryString: function(object, base){
622 var queryString = [];
624 Object.each(object, function(value, key){
625 if (base) key = base + '[' + key + ']';
627 switch (typeOf(value)){
628 case 'object': result = Object.toQueryString(value, key); break;
631 value.each(function(val, i){
634 result = Object.toQueryString(qs, key);
636 default: result = key + '=' + encodeURIComponent(value);
638 if (value != null) queryString.push(result);
641 return queryString.join('&');
652 has: Object.prototype.hasOwnProperty,
654 keyOf: function(value){
655 return Object.keyOf(this, value);
658 hasValue: function(value){
659 return Object.contains(this, value);
662 extend: function(properties){
663 Hash.each(properties || {}, function(value, key){
664 Hash.set(this, key, value);
669 combine: function(properties){
670 Hash.each(properties || {}, function(value, key){
671 Hash.include(this, key, value);
676 erase: function(key){
677 if (this.hasOwnProperty(key)) delete this[key];
682 return (this.hasOwnProperty(key)) ? this[key] : null;
685 set: function(key, value){
686 if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
691 Hash.each(this, function(value, key){
697 include: function(key, value){
698 if (this[key] == null) this[key] = value;
702 map: function(fn, bind){
703 return new Hash(Object.map(this, fn, bind));
706 filter: function(fn, bind){
707 return new Hash(Object.filter(this, fn, bind));
710 every: function(fn, bind){
711 return Object.every(this, fn, bind);
714 some: function(fn, bind){
715 return Object.some(this, fn, bind);
719 return Object.keys(this);
722 getValues: function(){
723 return Object.values(this);
726 toQueryString: function(base){
727 return Object.toQueryString(this, base);
732 Hash.extend = Object.append;
734 Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
739 // Begin: Source/Types/Array.js
745 description: Contains Array Prototypes like each, contains, and erase.
747 license: MIT-style license.
759 every: function(fn, bind){
760 for (var i = 0, l = this.length >>> 0; i < l; i++){
761 if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
766 filter: function(fn, bind){
768 for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){
770 if (fn.call(bind, value, i, this)) results.push(value);
775 indexOf: function(item, from){
776 var length = this.length >>> 0;
777 for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){
778 if (this[i] === item) return i;
783 map: function(fn, bind){
784 var length = this.length >>> 0, results = Array(length);
785 for (var i = 0; i < length; i++){
786 if (i in this) results[i] = fn.call(bind, this[i], i, this);
791 some: function(fn, bind){
792 for (var i = 0, l = this.length >>> 0; i < l; i++){
793 if ((i in this) && fn.call(bind, this[i], i, this)) return true;
800 return this.filter(function(item){
805 invoke: function(methodName){
806 var args = Array.slice(arguments, 1);
807 return this.map(function(item){
808 return item[methodName].apply(item, args);
812 associate: function(keys){
813 var obj = {}, length = Math.min(this.length, keys.length);
814 for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
818 link: function(object){
820 for (var i = 0, l = this.length; i < l; i++){
821 for (var key in object){
822 if (object[key](this[i])){
823 result[key] = this[i];
832 contains: function(item, from){
833 return this.indexOf(item, from) != -1;
836 append: function(array){
837 this.push.apply(this, array);
842 return (this.length) ? this[this.length - 1] : null;
845 getRandom: function(){
846 return (this.length) ? this[Number.random(0, this.length - 1)] : null;
849 include: function(item){
850 if (!this.contains(item)) this.push(item);
854 combine: function(array){
855 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
859 erase: function(item){
860 for (var i = this.length; i--;){
861 if (this[i] === item) this.splice(i, 1);
873 for (var i = 0, l = this.length; i < l; i++){
874 var type = typeOf(this[i]);
875 if (type == 'null') continue;
876 array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
882 for (var i = 0, l = this.length; i < l; i++){
883 if (this[i] != null) return this[i];
888 hexToRgb: function(array){
889 if (this.length != 3) return null;
890 var rgb = this.map(function(value){
891 if (value.length == 1) value += value;
892 return value.toInt(16);
894 return (array) ? rgb : 'rgb(' + rgb + ')';
897 rgbToHex: function(array){
898 if (this.length < 3) return null;
899 if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
901 for (var i = 0; i < 3; i++){
902 var bit = (this[i] - 0).toString(16);
903 hex.push((bit.length == 1) ? '0' + bit : bit);
905 return (array) ? hex : '#' + hex.join('');
912 Array.alias('extend', 'append');
914 var $pick = function(){
915 return Array.from(arguments).pick();
921 // Begin: Source/Types/Function.js
927 description: Contains Function Prototypes like create, bind, pass, and delay.
929 license: MIT-style license.
941 for (var i = 0, l = arguments.length; i < l; i++){
943 return arguments[i]();
953 attempt: function(args, bind){
955 return this.apply(bind, Array.from(args));
962 bind: function(that){
964 args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
967 var bound = function(){
968 var context = that, length = arguments.length;
969 if (this instanceof bound){
970 F.prototype = self.prototype;
973 var result = (!args && !length)
975 : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
976 return context == that ? result : context;
982 pass: function(args, bind){
984 if (args != null) args = Array.from(args);
986 return self.apply(bind, args || arguments);
990 delay: function(delay, bind, args){
991 return setTimeout(this.pass((args == null ? [] : args), bind), delay);
994 periodical: function(periodical, bind, args){
995 return setInterval(this.pass((args == null ? [] : args), bind), periodical);
1002 delete Function.prototype.bind;
1004 Function.implement({
1006 create: function(options){
1008 options = options || {};
1009 return function(event){
1010 var args = options.arguments;
1011 args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
1012 if (options.event) args = [event || window.event].extend(args);
1013 var returns = function(){
1014 return self.apply(options.bind || null, args);
1016 if (options.delay) return setTimeout(returns, options.delay);
1017 if (options.periodical) return setInterval(returns, options.periodical);
1018 if (options.attempt) return Function.attempt(returns);
1023 bind: function(bind, args){
1025 if (args != null) args = Array.from(args);
1027 return self.apply(bind, args || arguments);
1031 bindWithEvent: function(bind, args){
1033 if (args != null) args = Array.from(args);
1034 return function(event){
1035 return self.apply(bind, (args == null) ? arguments : [event].concat(args));
1039 run: function(args, bind){
1040 return this.apply(bind, Array.from(args));
1045 if (Object.create == Function.prototype.create) Object.create = null;
1047 var $try = Function.attempt;
1052 // Begin: Source/Types/Number.js
1058 description: Contains Number Prototypes like limit, round, times, and ceil.
1060 license: MIT-style license.
1071 limit: function(min, max){
1072 return Math.min(max, Math.max(min, this));
1075 round: function(precision){
1076 precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
1077 return Math.round(this * precision) / precision;
1080 times: function(fn, bind){
1081 for (var i = 0; i < this; i++) fn.call(bind, i, this);
1084 toFloat: function(){
1085 return parseFloat(this);
1088 toInt: function(base){
1089 return parseInt(this, base || 10);
1094 Number.alias('each', 'times');
1098 math.each(function(name){
1099 if (!Number[name]) methods[name] = function(){
1100 return Math[name].apply(null, [this].concat(Array.from(arguments)));
1103 Number.implement(methods);
1104 })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
1107 // Begin: Source/Types/String.js
1113 description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
1115 license: MIT-style license.
1126 test: function(regex, params){
1127 return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
1130 contains: function(string, separator){
1131 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1;
1135 return String(this).replace(/^\s+|\s+$/g, '');
1139 return String(this).replace(/\s+/g, ' ').trim();
1142 camelCase: function(){
1143 return String(this).replace(/-\D/g, function(match){
1144 return match.charAt(1).toUpperCase();
1148 hyphenate: function(){
1149 return String(this).replace(/[A-Z]/g, function(match){
1150 return ('-' + match.charAt(0).toLowerCase());
1154 capitalize: function(){
1155 return String(this).replace(/\b[a-z]/g, function(match){
1156 return match.toUpperCase();
1160 escapeRegExp: function(){
1161 return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
1164 toInt: function(base){
1165 return parseInt(this, base || 10);
1168 toFloat: function(){
1169 return parseFloat(this);
1172 hexToRgb: function(array){
1173 var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
1174 return (hex) ? hex.slice(1).hexToRgb(array) : null;
1177 rgbToHex: function(array){
1178 var rgb = String(this).match(/\d{1,3}/g);
1179 return (rgb) ? rgb.rgbToHex(array) : null;
1182 substitute: function(object, regexp){
1183 return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
1184 if (match.charAt(0) == '\\') return match.slice(1);
1185 return (object[name] != null) ? object[name] : '';
1192 // Begin: Source/Browser/Browser.js
1198 description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
1200 license: MIT-style license.
1202 requires: [Array, Function, Number, String]
1204 provides: [Browser, Window, Document]
1211 var document = this.document;
1212 var window = document.window = this;
1214 var ua = navigator.userAgent.toLowerCase(),
1215 platform = navigator.platform.toLowerCase(),
1216 UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
1217 mode = UA[1] == 'ie' && document.documentMode;
1219 var Browser = this.Browser = {
1221 extend: Function.prototype.extend,
1223 name: (UA[1] == 'version') ? UA[3] : UA[1],
1225 version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
1228 name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
1232 xpath: !!(document.evaluate),
1233 air: !!(window.runtime),
1234 query: !!(document.querySelector),
1235 json: !!(window.JSON)
1242 Browser[Browser.name] = true;
1243 Browser[Browser.name + parseInt(Browser.version, 10)] = true;
1244 Browser.Platform[Browser.Platform.name] = true;
1248 Browser.Request = (function(){
1250 var XMLHTTP = function(){
1251 return new XMLHttpRequest();
1254 var MSXML2 = function(){
1255 return new ActiveXObject('MSXML2.XMLHTTP');
1258 var MSXML = function(){
1259 return new ActiveXObject('Microsoft.XMLHTTP');
1262 return Function.attempt(function(){
1275 Browser.Features.xhr = !!(Browser.Request);
1279 var version = (Function.attempt(function(){
1280 return navigator.plugins['Shockwave Flash'].description;
1282 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
1283 }) || '0 r0').match(/\d+/g);
1285 Browser.Plugins.Flash = {
1286 version: Number(version[0] || '0.' + version[1]) || 0,
1287 build: Number(version[2]) || 0
1292 Browser.exec = function(text){
1293 if (!text) return text;
1294 if (window.execScript){
1295 window.execScript(text);
1297 var script = document.createElement('script');
1298 script.setAttribute('type', 'text/javascript');
1300 document.head.appendChild(script);
1301 document.head.removeChild(script);
1306 String.implement('stripScripts', function(exec){
1308 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
1309 scripts += code + '\n';
1312 if (exec === true) Browser.exec(scripts);
1313 else if (typeOf(exec) == 'function') exec(scripts, text);
1320 Document: this.Document,
1321 Window: this.Window,
1322 Element: this.Element,
1326 this.Window = this.$constructor = new Type('Window', function(){});
1328 this.$family = Function.from('window').hide();
1330 Window.mirror(function(name, method){
1331 window[name] = method;
1334 this.Document = document.$constructor = new Type('Document', function(){});
1336 document.$family = Function.from('document').hide();
1338 Document.mirror(function(name, method){
1339 document[name] = method;
1342 document.html = document.documentElement;
1343 if (!document.head) document.head = document.getElementsByTagName('head')[0];
1345 if (document.execCommand) try {
1346 document.execCommand("BackgroundImageCache", false, true);
1350 if (this.attachEvent && !this.addEventListener){
1351 var unloadEvent = function(){
1352 this.detachEvent('onunload', unloadEvent);
1353 document.head = document.html = document.window = null;
1355 this.attachEvent('onunload', unloadEvent);
1358 // IE fails on collections and <select>.options (refers to <select>)
1359 var arrayFrom = Array.from;
1361 arrayFrom(document.html.childNodes);
1363 Array.from = function(item){
1364 if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
1365 var i = item.length, array = new Array(i);
1366 while (i--) array[i] = item[i];
1369 return arrayFrom(item);
1372 var prototype = Array.prototype,
1373 slice = prototype.slice;
1374 ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
1375 var method = prototype[name];
1376 Array[name] = function(item){
1377 return method.apply(Array.from(item), slice.call(arguments, 1));
1385 if (Browser.Platform.ios) Browser.Platform.ipod = true;
1387 Browser.Engine = {};
1389 var setEngine = function(name, version){
1390 Browser.Engine.name = name;
1391 Browser.Engine[name + version] = true;
1392 Browser.Engine.version = version;
1396 Browser.Engine.trident = true;
1398 switch (Browser.version){
1399 case 6: setEngine('trident', 4); break;
1400 case 7: setEngine('trident', 5); break;
1401 case 8: setEngine('trident', 6);
1405 if (Browser.firefox){
1406 Browser.Engine.gecko = true;
1408 if (Browser.version >= 3) setEngine('gecko', 19);
1409 else setEngine('gecko', 18);
1412 if (Browser.safari || Browser.chrome){
1413 Browser.Engine.webkit = true;
1415 switch (Browser.version){
1416 case 2: setEngine('webkit', 419); break;
1417 case 3: setEngine('webkit', 420); break;
1418 case 4: setEngine('webkit', 525);
1423 Browser.Engine.presto = true;
1425 if (Browser.version >= 9.6) setEngine('presto', 960);
1426 else if (Browser.version >= 9.5) setEngine('presto', 950);
1427 else setEngine('presto', 925);
1430 if (Browser.name == 'unknown'){
1431 switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){
1434 Browser.Engine.webkit = true;
1437 Browser.Engine.gecko = true;
1441 this.$exec = Browser.exec;
1448 // Begin: Source/Slick/Slick.Parser.js
1452 description: Standalone CSS3 Selector parser
1453 provides: Slick.Parser
1467 var parse = function(expression, isReversed){
1468 if (expression == null) return null;
1469 if (expression.Slick === true) return expression;
1470 expression = ('' + expression).replace(/^\s+|\s+$/g, '');
1471 reversed = !!isReversed;
1472 var currentCache = (reversed) ? reverseCache : cache;
1473 if (currentCache[expression]) return currentCache[expression];
1478 reverse: function(){
1479 return parse(this.raw, true);
1482 separatorIndex = -1;
1483 while (expression != (expression = expression.replace(regexp, parser)));
1484 parsed.length = parsed.expressions.length;
1485 return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
1488 var reverseCombinator = function(combinator){
1489 if (combinator === '!') return ' ';
1490 else if (combinator === ' ') return '!';
1491 else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
1492 else return '!' + combinator;
1495 var reverse = function(expression){
1496 var expressions = expression.expressions;
1497 for (var i = 0; i < expressions.length; i++){
1498 var exp = expressions[i];
1499 var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
1501 for (var j = 0; j < exp.length; j++){
1503 if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
1504 cexp.combinator = cexp.reverseCombinator;
1505 delete cexp.reverseCombinator;
1508 exp.reverse().push(last);
1513 var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
1514 return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
1515 return '\\' + match;
1519 var regexp = new RegExp(
1522 puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
1525 \\s* ( , ) \\s* # Separator \n\
1526 | \\s* ( <combinator>+ ) \\s* # Combinator \n\
1527 | ( \\s+ ) # CombinatorChildren \n\
1528 | ( <unicode>+ | \\* ) # Tag \n\
1529 | \\# ( <unicode>+ ) # ID \n\
1530 | \\. ( <unicode>+ ) # ClassName \n\
1533 \\s* (<unicode1>+) (?: \
1534 \\s* ([*^$!~|]?=) (?: \
1541 | :+ ( <unicode>+ )(?:\
1543 (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
1548 "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
1549 .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
1550 .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1551 .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
1573 pseudoClassQuotedValue,
1576 if (separator || separatorIndex === -1){
1577 parsed.expressions[++separatorIndex] = [];
1578 combinatorIndex = -1;
1579 if (separator) return '';
1582 if (combinator || combinatorChildren || combinatorIndex === -1){
1583 combinator = combinator || ' ';
1584 var currentSeparator = parsed.expressions[separatorIndex];
1585 if (reversed && currentSeparator[combinatorIndex])
1586 currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
1587 currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
1590 var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
1593 currentParsed.tag = tagName.replace(reUnescape, '');
1596 currentParsed.id = id.replace(reUnescape, '');
1598 } else if (className){
1599 className = className.replace(reUnescape, '');
1601 if (!currentParsed.classList) currentParsed.classList = [];
1602 if (!currentParsed.classes) currentParsed.classes = [];
1603 currentParsed.classList.push(className);
1604 currentParsed.classes.push({
1606 regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
1609 } else if (pseudoClass){
1610 pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
1611 pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
1613 if (!currentParsed.pseudos) currentParsed.pseudos = [];
1614 currentParsed.pseudos.push({
1615 key: pseudoClass.replace(reUnescape, ''),
1616 value: pseudoClassValue,
1617 type: pseudoMarker.length == 1 ? 'class' : 'element'
1620 } else if (attributeKey){
1621 attributeKey = attributeKey.replace(reUnescape, '');
1622 attributeValue = (attributeValue || '').replace(reUnescape, '');
1626 switch (attributeOperator){
1627 case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break;
1628 case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break;
1629 case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
1630 case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break;
1631 case '=' : test = function(value){
1632 return attributeValue == value;
1634 case '*=' : test = function(value){
1635 return value && value.indexOf(attributeValue) > -1;
1637 case '!=' : test = function(value){
1638 return attributeValue != value;
1640 default : test = function(value){
1645 if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
1649 if (!test) test = function(value){
1650 return value && regexp.test(value);
1653 if (!currentParsed.attributes) currentParsed.attributes = [];
1654 currentParsed.attributes.push({
1656 operator: attributeOperator,
1657 value: attributeValue,
1668 var Slick = (this.Slick || {});
1670 Slick.parse = function(expression){
1671 return parse(expression);
1674 Slick.escapeRegExp = escapeRegExp;
1676 if (!this.Slick) this.Slick = Slick;
1678 }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
1681 // Begin: Source/Slick/Slick.Finder.js
1685 description: The new, superfast css selector engine.
1686 provides: Slick.Finder
1687 requires: Slick.Parser
1695 toString = Object.prototype.toString;
1697 // Feature / Bug detection
1699 local.isNativeCode = function(fn){
1700 return (/\{\s*\[native code\]\s*\}/).test('' + fn);
1703 local.isXML = function(document){
1704 return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
1705 (document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
1708 local.setDocument = function(document){
1710 // convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
1711 var nodeType = document.nodeType;
1712 if (nodeType == 9); // document
1713 else if (nodeType) document = document.ownerDocument; // node
1714 else if (document.navigator) document = document.document; // window
1717 // check if it's the old document
1719 if (this.document === document) return;
1720 this.document = document;
1722 // check if we have done feature detection on this document before
1724 var root = document.documentElement,
1725 rootUid = this.getUIDXML(root),
1726 features = featuresCache[rootUid],
1730 for (feature in features){
1731 this[feature] = features[feature];
1736 features = featuresCache[rootUid] = {};
1738 features.root = root;
1739 features.isXMLDocument = this.isXML(document);
1741 features.brokenStarGEBTN
1742 = features.starSelectsClosedQSA
1743 = features.idGetsName
1744 = features.brokenMixedCaseQSA
1745 = features.brokenGEBCN
1746 = features.brokenCheckedQSA
1747 = features.brokenEmptyAttributeQSA
1748 = features.isHTMLDocument
1749 = features.nativeMatchesSelector
1752 var starSelectsClosed, starSelectsComments,
1753 brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
1754 brokenFormAttributeGetter;
1756 var selected, id = 'slick_uniqueid';
1757 var testNode = document.createElement('div');
1759 var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
1760 testRoot.appendChild(testNode);
1762 // on non-HTML documents innerHTML and getElementsById doesnt work properly
1764 testNode.innerHTML = '<a id="'+id+'"></a>';
1765 features.isHTMLDocument = !!document.getElementById(id);
1768 if (features.isHTMLDocument){
1770 testNode.style.display = 'none';
1772 // IE returns comment nodes for getElementsByTagName('*') for some documents
1773 testNode.appendChild(document.createComment(''));
1774 starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
1776 // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
1778 testNode.innerHTML = 'foo</foo>';
1779 selected = testNode.getElementsByTagName('*');
1780 starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
1783 features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
1785 // IE returns elements with the name instead of just id for getElementsById for some documents
1787 testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
1788 features.idGetsName = document.getElementById(id) === testNode.firstChild;
1791 if (testNode.getElementsByClassName){
1793 // Safari 3.2 getElementsByClassName caches results
1795 testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
1796 testNode.getElementsByClassName('b').length;
1797 testNode.firstChild.className = 'b';
1798 cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
1801 // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
1803 testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
1804 brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
1807 features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
1810 if (testNode.querySelectorAll){
1811 // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
1813 testNode.innerHTML = 'foo</foo>';
1814 selected = testNode.querySelectorAll('*');
1815 features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
1818 // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
1820 testNode.innerHTML = '<a class="MiX"></a>';
1821 features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
1824 // Webkit and Opera dont return selected options on querySelectorAll
1826 testNode.innerHTML = '<select><option selected="selected">a</option></select>';
1827 features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
1830 // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
1832 testNode.innerHTML = '<a class=""></a>';
1833 features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
1838 // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
1840 testNode.innerHTML = '<form action="s"><input id="action"/></form>';
1841 brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
1844 // native matchesSelector function
1846 features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
1847 if (features.nativeMatchesSelector) try {
1848 // if matchesSelector trows errors on incorrect sintaxes we can use it
1849 features.nativeMatchesSelector.call(root, ':slick');
1850 features.nativeMatchesSelector = null;
1856 root.slick_expando = 1;
1857 delete root.slick_expando;
1858 features.getUID = this.getUIDHTML;
1860 features.getUID = this.getUIDXML;
1863 testRoot.removeChild(testNode);
1864 testNode = selected = testRoot = null;
1868 features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
1869 var method = this.attributeGetters[name];
1870 if (method) return method.call(node);
1871 var attributeNode = node.getAttributeNode(name);
1872 return (attributeNode) ? attributeNode.nodeValue : null;
1873 } : function(node, name){
1874 var method = this.attributeGetters[name];
1875 return (method) ? method.call(node) : node.getAttribute(name);
1880 features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
1881 return node.hasAttribute(attribute);
1882 } : function(node, attribute) {
1883 node = node.getAttributeNode(attribute);
1884 return !!(node && (node.specified || node.nodeValue));
1888 // FIXME: Add specs: local.contains should be different for xml and html documents?
1889 var nativeRootContains = root && this.isNativeCode(root.contains),
1890 nativeDocumentContains = document && this.isNativeCode(document.contains);
1892 features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){
1893 return context.contains(node);
1894 } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){
1895 // IE8 does not have .contains on document.
1896 return context === node || ((context === document) ? document.documentElement : context).contains(node);
1897 } : (root && root.compareDocumentPosition) ? function(context, node){
1898 return context === node || !!(context.compareDocumentPosition(node) & 16);
1899 } : function(context, node){
1901 if (node === context) return true;
1902 } while ((node = node.parentNode));
1906 // document order sorting
1907 // credits to Sizzle (http://sizzlejs.com/)
1909 features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
1910 if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
1911 return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
1912 } : ('sourceIndex' in root) ? function(a, b){
1913 if (!a.sourceIndex || !b.sourceIndex) return 0;
1914 return a.sourceIndex - b.sourceIndex;
1915 } : (document.createRange) ? function(a, b){
1916 if (!a.ownerDocument || !b.ownerDocument) return 0;
1917 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
1918 aRange.setStart(a, 0);
1919 aRange.setEnd(a, 0);
1920 bRange.setStart(b, 0);
1921 bRange.setEnd(b, 0);
1922 return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
1927 for (feature in features){
1928 this[feature] = features[feature];
1934 var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
1935 reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
1936 qsaFailExpCache = {};
1938 local.search = function(context, expression, append, first){
1940 var found = this.found = (first) ? null : (append || []);
1942 if (!context) return found;
1943 else if (context.navigator) context = context.document; // Convert the node from a window to a document
1944 else if (!context.nodeType) return found;
1949 uniques = this.uniques = {},
1950 hasOthers = !!(append && append.length),
1951 contextIsDocument = (context.nodeType == 9);
1953 if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
1955 // avoid duplicating items already in the append array
1956 if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
1958 // expression checks
1960 if (typeof expression == 'string'){ // expression is a string
1962 /*<simple-selectors-override>*/
1963 var simpleSelector = expression.match(reSimpleSelector);
1964 simpleSelectors: if (simpleSelector) {
1966 var symbol = simpleSelector[1],
1967 name = simpleSelector[2],
1972 if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
1973 nodes = context.getElementsByTagName(name);
1974 if (first) return nodes[0] || null;
1975 for (i = 0; node = nodes[i++];){
1976 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
1979 } else if (symbol == '#'){
1981 if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
1982 node = context.getElementById(name);
1983 if (!node) return found;
1984 if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
1985 if (first) return node || null;
1986 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
1988 } else if (symbol == '.'){
1990 if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
1991 if (context.getElementsByClassName && !this.brokenGEBCN){
1992 nodes = context.getElementsByClassName(name);
1993 if (first) return nodes[0] || null;
1994 for (i = 0; node = nodes[i++];){
1995 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
1998 var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
1999 nodes = context.getElementsByTagName('*');
2000 for (i = 0; node = nodes[i++];){
2001 className = node.className;
2002 if (!(className && matchClass.test(className))) continue;
2003 if (first) return node;
2004 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2010 if (hasOthers) this.sort(found);
2011 return (first) ? null : found;
2014 /*</simple-selectors-override>*/
2016 /*<query-selector-override>*/
2017 querySelector: if (context.querySelectorAll) {
2019 if (!this.isHTMLDocument
2020 || qsaFailExpCache[expression]
2021 //TODO: only skip when expression is actually mixed case
2022 || this.brokenMixedCaseQSA
2023 || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1)
2024 || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression))
2025 || (!contextIsDocument //Abort when !contextIsDocument and...
2026 // there are multiple expressions in the selector
2027 // since we currently only fix non-document rooted QSA for single expression selectors
2028 && expression.indexOf(',') > -1
2031 ) break querySelector;
2033 var _expression = expression, _context = context;
2034 if (!contextIsDocument){
2035 // non-document rooted QSA
2036 // credits to Andrew Dupont
2037 var currentId = _context.getAttribute('id'), slickid = 'slickid__';
2038 _context.setAttribute('id', slickid);
2039 _expression = '#' + slickid + ' ' + _expression;
2040 context = _context.parentNode;
2044 if (first) return context.querySelector(_expression) || null;
2045 else nodes = context.querySelectorAll(_expression);
2047 qsaFailExpCache[expression] = 1;
2048 break querySelector;
2050 if (!contextIsDocument){
2051 if (currentId) _context.setAttribute('id', currentId);
2052 else _context.removeAttribute('id');
2057 if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
2058 if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node);
2059 } else for (i = 0; node = nodes[i++];){
2060 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
2063 if (hasOthers) this.sort(found);
2067 /*</query-selector-override>*/
2069 parsed = this.Slick.parse(expression);
2070 if (!parsed.length) return found;
2071 } else if (expression == null){ // there is no expression
2073 } else if (expression.Slick){ // expression is a parsed Slick object
2074 parsed = expression;
2075 } else if (this.contains(context.documentElement || context, expression)){ // expression is a node
2076 (found) ? found.push(expression) : found = expression;
2078 } else { // other junk
2082 /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2084 // cache elements for the nth selectors
2087 this.posNTHLast = {};
2088 this.posNTHType = {};
2089 this.posNTHTypeLast = {};
2091 /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2093 // if append is null and there is only a single selector with one expression use pushArray, else use pushUID
2094 this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
2096 if (found == null) found = [];
2101 var combinator, tag, id, classList, classes, attributes, pseudos;
2102 var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
2104 search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){
2106 combinator = 'combinator:' + currentBit.combinator;
2107 if (!this[combinator]) continue search;
2109 tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
2111 classList = currentBit.classList;
2112 classes = currentBit.classes;
2113 attributes = currentBit.attributes;
2114 pseudos = currentBit.pseudos;
2115 lastBit = (j === (currentExpression.length - 1));
2117 this.bitUniques = {};
2120 this.uniques = uniques;
2128 this[combinator](context, tag, id, classes, attributes, pseudos, classList);
2129 if (first && lastBit && found.length) break search;
2131 if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
2132 this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2133 if (found.length) break search;
2134 } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
2137 currentItems = this.found;
2140 // should sort if there are nodes in append and if you pass multiple expressions.
2141 if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);
2143 return (first) ? (found[0] || null) : found;
2149 local.uidk = 'slick-uniqueid';
2151 local.getUIDXML = function(node){
2152 var uid = node.getAttribute(this.uidk);
2155 node.setAttribute(this.uidk, uid);
2160 local.getUIDHTML = function(node){
2161 return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
2164 // sort based on the setDocument documentSorter method.
2166 local.sort = function(results){
2167 if (!this.documentSorter) return results;
2168 results.sort(this.documentSorter);
2172 /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
2174 local.cacheNTH = {};
2176 local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
2178 local.parseNTHArgument = function(argument){
2179 var parsed = argument.match(this.matchNTH);
2180 if (!parsed) return false;
2181 var special = parsed[2] || false;
2182 var a = parsed[1] || 1;
2183 if (a == '-') a = -1;
2184 var b = +parsed[3] || 0;
2186 (special == 'n') ? {a: a, b: b} :
2187 (special == 'odd') ? {a: 2, b: 1} :
2188 (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a};
2190 return (this.cacheNTH[argument] = parsed);
2193 local.createNTHPseudo = function(child, sibling, positions, ofType){
2194 return function(node, argument){
2195 var uid = this.getUID(node);
2196 if (!this[positions][uid]){
2197 var parent = node.parentNode;
2198 if (!parent) return false;
2199 var el = parent[child], count = 1;
2201 var nodeName = node.nodeName;
2203 if (el.nodeName != nodeName) continue;
2204 this[positions][this.getUID(el)] = count++;
2205 } while ((el = el[sibling]));
2208 if (el.nodeType != 1) continue;
2209 this[positions][this.getUID(el)] = count++;
2210 } while ((el = el[sibling]));
2213 argument = argument || 'n';
2214 var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
2215 if (!parsed) return false;
2216 var a = parsed.a, b = parsed.b, pos = this[positions][uid];
2217 if (a == 0) return b == pos;
2219 if (pos < b) return false;
2221 if (b < pos) return false;
2223 return ((pos - b) % a) == 0;
2227 /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
2229 local.pushArray = function(node, tag, id, classes, attributes, pseudos){
2230 if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
2233 local.pushUID = function(node, tag, id, classes, attributes, pseudos){
2234 var uid = this.getUID(node);
2235 if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
2236 this.uniques[uid] = true;
2237 this.found.push(node);
2241 local.matchNode = function(node, selector){
2242 if (this.isHTMLDocument && this.nativeMatchesSelector){
2244 return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'));
2245 } catch(matchError) {}
2248 var parsed = this.Slick.parse(selector);
2249 if (!parsed) return true;
2251 // simple (single) selectors
2252 var expressions = parsed.expressions, simpleExpCounter = 0, i;
2253 for (i = 0; (currentExpression = expressions[i]); i++){
2254 if (currentExpression.length == 1){
2255 var exp = currentExpression[0];
2256 if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
2261 if (simpleExpCounter == parsed.length) return false;
2263 var nodes = this.search(this.document, parsed), item;
2264 for (i = 0; item = nodes[i++];){
2265 if (item === node) return true;
2270 local.matchPseudo = function(node, name, argument){
2271 var pseudoName = 'pseudo:' + name;
2272 if (this[pseudoName]) return this[pseudoName](node, argument);
2273 var attribute = this.getAttribute(node, name);
2274 return (argument) ? argument == attribute : !!attribute;
2277 local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
2279 var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
2281 if (nodeName < '@') return false; // Fix for comment nodes and closed nodes
2283 if (nodeName != tag) return false;
2287 if (id && node.getAttribute('id') != id) return false;
2290 if (classes) for (i = classes.length; i--;){
2291 cls = this.getAttribute(node, 'class');
2292 if (!(cls && classes[i].regexp.test(cls))) return false;
2294 if (attributes) for (i = attributes.length; i--;){
2295 part = attributes[i];
2296 if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
2298 if (pseudos) for (i = pseudos.length; i--;){
2300 if (!this.matchPseudo(node, part.key, part.value)) return false;
2307 ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level
2309 var i, item, children;
2311 if (this.isHTMLDocument){
2313 item = this.document.getElementById(id);
2314 if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
2315 // all[id] returns all the elements with that name or id inside node
2316 // if theres just one it will return the element, else it will be a collection
2317 children = node.all[id];
2318 if (!children) return;
2319 if (!children[0]) children = [children];
2320 for (i = 0; item = children[i++];){
2321 var idNode = item.getAttributeNode('id');
2322 if (idNode && idNode.nodeValue == id){
2323 this.push(item, tag, null, classes, attributes, pseudos);
2330 // if the context is in the dom we return, else we will try GEBTN, breaking the getById label
2331 if (this.contains(this.root, node)) return;
2333 } else if (this.document !== node && !this.contains(node, item)) return;
2334 this.push(item, tag, null, classes, attributes, pseudos);
2337 getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
2338 children = node.getElementsByClassName(classList.join(' '));
2339 if (!(children && children.length)) break getByClass;
2340 for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
2345 children = node.getElementsByTagName(tag);
2346 if (!(children && children.length)) break getByTag;
2347 if (!this.brokenStarGEBTN) tag = null;
2348 for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
2352 '>': function(node, tag, id, classes, attributes, pseudos){ // direct children
2353 if ((node = node.firstChild)) do {
2354 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2355 } while ((node = node.nextSibling));
2358 '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
2359 while ((node = node.nextSibling)) if (node.nodeType == 1){
2360 this.push(node, tag, id, classes, attributes, pseudos);
2365 '^': function(node, tag, id, classes, attributes, pseudos){ // first child
2366 node = node.firstChild;
2368 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2369 else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2373 '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
2374 while ((node = node.nextSibling)){
2375 if (node.nodeType != 1) continue;
2376 var uid = this.getUID(node);
2377 if (this.bitUniques[uid]) break;
2378 this.bitUniques[uid] = true;
2379 this.push(node, tag, id, classes, attributes, pseudos);
2383 '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
2384 this['combinator:+'](node, tag, id, classes, attributes, pseudos);
2385 this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2388 '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
2389 this['combinator:~'](node, tag, id, classes, attributes, pseudos);
2390 this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
2393 '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
2394 while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2397 '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
2398 node = node.parentNode;
2399 if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
2402 '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
2403 while ((node = node.previousSibling)) if (node.nodeType == 1){
2404 this.push(node, tag, id, classes, attributes, pseudos);
2409 '!^': function(node, tag, id, classes, attributes, pseudos){ // last child
2410 node = node.lastChild;
2412 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
2413 else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
2417 '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
2418 while ((node = node.previousSibling)){
2419 if (node.nodeType != 1) continue;
2420 var uid = this.getUID(node);
2421 if (this.bitUniques[uid]) break;
2422 this.bitUniques[uid] = true;
2423 this.push(node, tag, id, classes, attributes, pseudos);
2429 for (var c in combinators) local['combinator:' + c] = combinators[c];
2433 /*<pseudo-selectors>*/
2435 'empty': function(node){
2436 var child = node.firstChild;
2437 return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
2440 'not': function(node, expression){
2441 return !this.matchNode(node, expression);
2444 'contains': function(node, text){
2445 return (node.innerText || node.textContent || '').indexOf(text) > -1;
2448 'first-child': function(node){
2449 while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
2453 'last-child': function(node){
2454 while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
2458 'only-child': function(node){
2460 while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
2462 while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
2466 /*<nth-pseudo-selectors>*/
2468 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
2470 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
2472 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
2474 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
2476 'index': function(node, index){
2477 return this['pseudo:nth-child'](node, '' + (index + 1));
2480 'even': function(node){
2481 return this['pseudo:nth-child'](node, '2n');
2484 'odd': function(node){
2485 return this['pseudo:nth-child'](node, '2n+1');
2488 /*</nth-pseudo-selectors>*/
2490 /*<of-type-pseudo-selectors>*/
2492 'first-of-type': function(node){
2493 var nodeName = node.nodeName;
2494 while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
2498 'last-of-type': function(node){
2499 var nodeName = node.nodeName;
2500 while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
2504 'only-of-type': function(node){
2505 var prev = node, nodeName = node.nodeName;
2506 while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
2508 while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
2512 /*</of-type-pseudo-selectors>*/
2516 'enabled': function(node){
2517 return !node.disabled;
2520 'disabled': function(node){
2521 return node.disabled;
2524 'checked': function(node){
2525 return node.checked || node.selected;
2528 'focus': function(node){
2529 return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
2532 'root': function(node){
2533 return (node === this.root);
2536 'selected': function(node){
2537 return node.selected;
2540 /*</pseudo-selectors>*/
2543 for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
2545 // attributes methods
2547 var attributeGetters = local.attributeGetters = {
2550 return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
2554 return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
2557 'style': function(){
2558 return (this.style) ? this.style.cssText : this.getAttribute('style');
2561 'tabindex': function(){
2562 var attributeNode = this.getAttributeNode('tabindex');
2563 return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
2567 return this.getAttribute('type');
2570 'maxlength': function(){
2571 var attributeNode = this.getAttributeNode('maxLength');
2572 return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
2577 attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength;
2581 var Slick = local.Slick = (this.Slick || {});
2583 Slick.version = '1.1.7';
2587 Slick.search = function(context, expression, append){
2588 return local.search(context, expression, append);
2591 Slick.find = function(context, expression){
2592 return local.search(context, expression, null, true);
2595 // Slick containment checker
2597 Slick.contains = function(container, node){
2598 local.setDocument(container);
2599 return local.contains(container, node);
2602 // Slick attribute getter
2604 Slick.getAttribute = function(node, name){
2605 local.setDocument(node);
2606 return local.getAttribute(node, name);
2609 Slick.hasAttribute = function(node, name){
2610 local.setDocument(node);
2611 return local.hasAttribute(node, name);
2616 Slick.match = function(node, selector){
2617 if (!(node && selector)) return false;
2618 if (!selector || selector === node) return true;
2619 local.setDocument(node);
2620 return local.matchNode(node, selector);
2623 // Slick attribute accessor
2625 Slick.defineAttributeGetter = function(name, fn){
2626 local.attributeGetters[name] = fn;
2630 Slick.lookupAttributeGetter = function(name){
2631 return local.attributeGetters[name];
2634 // Slick pseudo accessor
2636 Slick.definePseudo = function(name, fn){
2637 local['pseudo:' + name] = function(node, argument){
2638 return fn.call(node, argument);
2643 Slick.lookupPseudo = function(name){
2644 var pseudo = local['pseudo:' + name];
2645 if (pseudo) return function(argument){
2646 return pseudo.call(this, argument);
2651 // Slick overrides accessor
2653 Slick.override = function(regexp, fn){
2654 local.override(regexp, fn);
2658 Slick.isXML = local.isXML;
2660 Slick.uidOf = function(node){
2661 return local.getUIDHTML(node);
2664 if (!this.Slick) this.Slick = Slick;
2666 }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
2669 // Begin: Source/Element/Element.js
2675 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.
2677 license: MIT-style license.
2679 requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder]
2681 provides: [Element, Elements, $, $$, Iframe, Selectors]
2686 var Element = function(tag, props){
2687 var konstructor = Element.Constructors[tag];
2688 if (konstructor) return konstructor(props);
2689 if (typeof tag != 'string') return document.id(tag).set(props);
2691 if (!props) props = {};
2693 if (!(/^[\w-]+$/).test(tag)){
2694 var parsed = Slick.parse(tag).expressions[0][0];
2695 tag = (parsed.tag == '*') ? 'div' : parsed.tag;
2696 if (parsed.id && props.id == null) props.id = parsed.id;
2698 var attributes = parsed.attributes;
2699 if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
2700 attr = attributes[i];
2701 if (props[attr.key] != null) continue;
2703 if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
2704 else if (!attr.value && !attr.operator) props[attr.key] = true;
2707 if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
2710 return document.newElement(tag, props);
2714 if (Browser.Element){
2715 Element.prototype = Browser.Element.prototype;
2716 // IE8 and IE9 require the wrapping.
2717 Element.prototype._fireEvent = (function(fireEvent){
2718 return function(type, event){
2719 return fireEvent.call(this, type, event);
2721 })(Element.prototype.fireEvent);
2724 new Type('Element', Element).mirror(function(name){
2725 if (Array.prototype[name]) return;
2728 obj[name] = function(){
2729 var results = [], args = arguments, elements = true;
2730 for (var i = 0, l = this.length; i < l; i++){
2731 var element = this[i], result = results[i] = element[name].apply(element, args);
2732 elements = (elements && typeOf(result) == 'element');
2734 return (elements) ? new Elements(results) : results;
2737 Elements.implement(obj);
2740 if (!Browser.Element){
2741 Element.parent = Object;
2743 Element.Prototype = {
2744 '$constructor': Element,
2745 '$family': Function.from('element').hide()
2748 Element.mirror(function(name, method){
2749 Element.Prototype[name] = method;
2753 Element.Constructors = {};
2757 Element.Constructors = new Hash;
2761 var IFrame = new Type('IFrame', function(){
2762 var params = Array.link(arguments, {
2763 properties: Type.isObject,
2764 iframe: function(obj){
2765 return (obj != null);
2769 var props = params.properties || {}, iframe;
2770 if (params.iframe) iframe = document.id(params.iframe);
2771 var onload = props.onload || function(){};
2772 delete props.onload;
2773 props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
2774 iframe = new Element(iframe || 'iframe', props);
2776 var onLoad = function(){
2777 onload.call(iframe.contentWindow);
2780 if (window.frames[props.id]) onLoad();
2781 else iframe.addListener('load', onLoad);
2785 var Elements = this.Elements = function(nodes){
2786 if (nodes && nodes.length){
2787 var uniques = {}, node;
2788 for (var i = 0; node = nodes[i++];){
2789 var uid = Slick.uidOf(node);
2791 uniques[uid] = true;
2798 Elements.prototype = {length: 0};
2799 Elements.parent = Array;
2801 new Type('Elements', Elements).implement({
2803 filter: function(filter, bind){
2804 if (!filter) return this;
2805 return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
2806 return item.match(filter);
2811 var length = this.length;
2812 for (var i = 0, l = arguments.length; i < l; i++){
2813 var item = document.id(arguments[i]);
2814 if (item) this[length++] = item;
2816 return (this.length = length);
2819 unshift: function(){
2821 for (var i = 0, l = arguments.length; i < l; i++){
2822 var item = document.id(arguments[i]);
2823 if (item) items.push(item);
2825 return Array.prototype.unshift.apply(this, items);
2829 var newElements = new Elements(this);
2830 for (var i = 0, l = arguments.length; i < l; i++){
2831 var item = arguments[i];
2832 if (Type.isEnumerable(item)) newElements.append(item);
2833 else newElements.push(item);
2838 append: function(collection){
2839 for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
2844 while (this.length) delete this[--this.length];
2852 Elements.alias('extend', 'append');
2859 var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
2861 splice.call(object, 1, 1);
2862 if (object[1] == 1) Elements.implement('splice', function(){
2863 var length = this.length;
2864 var result = splice.apply(this, arguments);
2865 while (length >= this.length) delete this[length--];
2869 Array.forEachMethod(function(method, name){
2870 Elements.implement(name, method);
2873 Array.mirror(Elements);
2876 var createElementAcceptsHTML;
2878 createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x');
2881 var escapeQuotes = function(html){
2882 return ('' + html).replace(/&/g, '&').replace(/"/g, '"');
2886 Document.implement({
2888 newElement: function(tag, props){
2889 if (props && props.checked != null) props.defaultChecked = props.checked;
2890 /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
2891 if (createElementAcceptsHTML && props){
2893 if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
2894 if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
2900 return this.id(this.createElement(tag)).set(props);
2909 Slick.uidOf(window);
2910 Slick.uidOf(document);
2912 Document.implement({
2914 newTextNode: function(text){
2915 return this.createTextNode(text);
2918 getDocument: function(){
2922 getWindow: function(){
2930 string: function(id, nocash, doc){
2931 id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
2932 return (id) ? types.element(id, nocash) : null;
2935 element: function(el, nocash){
2937 if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){
2938 var fireEvent = el.fireEvent;
2939 // wrapping needed in IE7, or else crash
2940 el._fireEvent = function(type, event){
2941 return fireEvent(type, event);
2943 Object.append(el, Element.Prototype);
2948 object: function(obj, nocash, doc){
2949 if (obj.toElement) return types.element(obj.toElement(doc), nocash);
2955 types.textnode = types.whitespace = types.window = types.document = function(zero){
2959 return function(el, nocash, doc){
2960 if (el && el.$family && el.uniqueNumber) return el;
2961 var type = typeOf(el);
2962 return (types[type]) ? types[type](el, nocash, doc || document) : null;
2969 if (window.$ == null) Window.implement('$', function(el, nc){
2970 return document.id(el, nc, this.document);
2975 getDocument: function(){
2976 return this.document;
2979 getWindow: function(){
2985 [Document, Element].invoke('implement', {
2987 getElements: function(expression){
2988 return Slick.search(this, expression, new Elements);
2991 getElement: function(expression){
2992 return document.id(Slick.find(this, expression));
2997 var contains = {contains: function(element){
2998 return Slick.contains(this, element);
3001 if (!document.contains) Document.implement(contains);
3002 if (!document.createElement('div').contains) Element.implement(contains);
3006 Element.implement('hasChild', function(element){
3007 return this !== element && this.contains(element);
3010 (function(search, find, match){
3012 this.Selectors = {};
3013 var pseudos = this.Selectors.Pseudo = new Hash();
3015 var addSlickPseudos = function(){
3016 for (var name in pseudos) if (pseudos.hasOwnProperty(name)){
3017 Slick.definePseudo(name, pseudos[name]);
3018 delete pseudos[name];
3022 Slick.search = function(context, expression, append){
3024 return search.call(this, context, expression, append);
3027 Slick.find = function(context, expression){
3029 return find.call(this, context, expression);
3032 Slick.match = function(node, selector){
3034 return match.call(this, node, selector);
3037 })(Slick.search, Slick.find, Slick.match);
3043 var injectCombinator = function(expression, combinator){
3044 if (!expression) return combinator;
3046 expression = Object.clone(Slick.parse(expression));
3048 var expressions = expression.expressions;
3049 for (var i = expressions.length; i--;)
3050 expressions[i][0].combinator = combinator;
3059 }, function(combinator, method){
3060 Element.implement(method, function(expression){
3061 return this.getElement(injectCombinator(expression, combinator));
3067 getAllPrevious: '!~',
3071 }, function(combinator, method){
3072 Element.implement(method, function(expression){
3073 return this.getElements(injectCombinator(expression, combinator));
3079 getFirst: function(expression){
3080 return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
3083 getLast: function(expression){
3084 return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
3087 getWindow: function(){
3088 return this.ownerDocument.window;
3091 getDocument: function(){
3092 return this.ownerDocument;
3095 getElementById: function(id){
3096 return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
3099 match: function(expression){
3100 return !expression || Slick.match(this, expression);
3107 if (window.$$ == null) Window.implement('$$', function(selector){
3108 var elements = new Elements;
3109 if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
3110 var args = Array.flatten(arguments);
3111 for (var i = 0, l = args.length; i < l; i++){
3113 switch (typeOf(item)){
3114 case 'element': elements.push(item); break;
3115 case 'string': Slick.search(this.document, item, elements);
3123 if (window.$$ == null) Window.implement('$$', function(selector){
3124 if (arguments.length == 1){
3125 if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
3126 else if (Type.isEnumerable(selector)) return new Elements(selector);
3128 return new Elements(arguments);
3135 before: function(context, element){
3136 var parent = element.parentNode;
3137 if (parent) parent.insertBefore(context, element);
3140 after: function(context, element){
3141 var parent = element.parentNode;
3142 if (parent) parent.insertBefore(context, element.nextSibling);
3145 bottom: function(context, element){
3146 element.appendChild(context);
3149 top: function(context, element){
3150 element.insertBefore(context, element.firstChild);
3155 inserters.inside = inserters.bottom;
3159 Object.each(inserters, function(inserter, where){
3161 where = where.capitalize();
3165 methods['inject' + where] = function(el){
3166 inserter(this, document.id(el, true));
3170 methods['grab' + where] = function(el){
3171 inserter(document.id(el, true), this);
3175 Element.implement(methods);
3181 // getProperty / setProperty
3183 var propertyGetters = {}, propertySetters = {};
3187 var properties = {};
3189 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan',
3190 'frameBorder', 'rowSpan', 'tabIndex', 'useMap'
3191 ], function(property){
3192 properties[property.toLowerCase()] = property;
3195 properties.html = 'innerHTML';
3196 properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent';
3198 Object.forEach(properties, function(real, key){
3199 propertySetters[key] = function(node, value){
3202 propertyGetters[key] = function(node){
3210 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked',
3211 'disabled', 'readOnly', 'multiple', 'selected', 'noresize',
3212 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay',
3217 Array.forEach(bools, function(bool){
3218 var lower = bool.toLowerCase();
3219 booleans[lower] = bool;
3220 propertySetters[lower] = function(node, value){
3221 node[bool] = !!value;
3223 propertyGetters[lower] = function(node){
3224 return !!node[bool];
3230 Object.append(propertySetters, {
3232 'class': function(node, value){
3233 ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value);
3236 'for': function(node, value){
3237 ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value);
3240 'style': function(node, value){
3241 (node.style) ? node.style.cssText = value : node.setAttribute('style', value);
3244 'value': function(node, value){
3245 node.value = (value != null) ? value : '';
3250 propertyGetters['class'] = function(node){
3251 return ('className' in node) ? node.className || null : node.getAttribute('class');
3255 var el = document.createElement('button');
3256 // IE sets type as readonly and throws
3257 try { el.type = 'button'; } catch(e){}
3258 if (el.type != 'button') propertySetters.type = function(node, value){
3259 node.setAttribute('type', value);
3265 var input = document.createElement('input');
3267 input.type = 'submit';
3268 if (input.value != 't') propertySetters.type = function(node, type){
3269 var value = node.value;
3276 /* getProperty, setProperty */
3279 var pollutesGetAttribute = (function(div){
3280 div.random = 'attribute';
3281 return (div.getAttribute('random') == 'attribute');
3282 })(document.createElement('div'));
3288 setProperty: function(name, value){
3289 var setter = propertySetters[name.toLowerCase()];
3291 setter(this, value);
3294 if (pollutesGetAttribute) var attributeWhiteList = this.retrieve('$attributeWhiteList', {});
3298 this.removeAttribute(name);
3300 if (pollutesGetAttribute) delete attributeWhiteList[name];
3303 this.setAttribute(name, '' + value);
3305 if (pollutesGetAttribute) attributeWhiteList[name] = true;
3312 setProperties: function(attributes){
3313 for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
3317 getProperty: function(name){
3318 var getter = propertyGetters[name.toLowerCase()];
3319 if (getter) return getter(this);
3321 if (pollutesGetAttribute){
3322 var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {});
3323 if (!attr) return null;
3324 if (attr.expando && !attributeWhiteList[name]){
3325 var outer = this.outerHTML;
3326 // segment by the opening tag and find mention of attribute name
3327 if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null;
3328 attributeWhiteList[name] = true;
3332 var result = Slick.getAttribute(this, name);
3333 return (!result && !Slick.hasAttribute(this, name)) ? null : result;
3336 getProperties: function(){
3337 var args = Array.from(arguments);
3338 return args.map(this.getProperty, this).associate(args);
3341 removeProperty: function(name){
3342 return this.setProperty(name, null);
3345 removeProperties: function(){
3346 Array.each(arguments, this.removeProperty, this);
3350 set: function(prop, value){
3351 var property = Element.Properties[prop];
3352 (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
3355 get: function(prop){
3356 var property = Element.Properties[prop];
3357 return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
3360 erase: function(prop){
3361 var property = Element.Properties[prop];
3362 (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
3366 hasClass: function(className){
3367 return this.className.clean().contains(className, ' ');
3370 addClass: function(className){
3371 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
3375 removeClass: function(className){
3376 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
3380 toggleClass: function(className, force){
3381 if (force == null) force = !this.hasClass(className);
3382 return (force) ? this.addClass(className) : this.removeClass(className);
3386 var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
3387 if (length > 1) parent = fragment = document.createDocumentFragment();
3389 for (var i = 0; i < length; i++){
3390 var element = document.id(elements[i], true);
3391 if (element) parent.appendChild(element);
3394 if (fragment) this.appendChild(fragment);
3399 appendText: function(text, where){
3400 return this.grab(this.getDocument().newTextNode(text), where);
3403 grab: function(el, where){
3404 inserters[where || 'bottom'](document.id(el, true), this);
3408 inject: function(el, where){
3409 inserters[where || 'bottom'](this, document.id(el, true));
3413 replaces: function(el){
3414 el = document.id(el, true);
3415 el.parentNode.replaceChild(this, el);
3419 wraps: function(el, where){
3420 el = document.id(el, true);
3421 return this.replaces(el).grab(el, where);
3424 getSelected: function(){
3425 this.selectedIndex; // Safari 3.2.1
3426 return new Elements(Array.from(this.options).filter(function(option){
3427 return option.selected;
3431 toQueryString: function(){
3432 var queryString = [];
3433 this.getElements('input, select, textarea').each(function(el){
3435 if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
3437 var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
3439 return document.id(opt).get('value');
3440 }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
3442 Array.from(value).each(function(val){
3443 if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
3446 return queryString.join('&');
3451 var collected = {}, storage = {};
3453 var get = function(uid){
3454 return (storage[uid] || (storage[uid] = {}));
3457 var clean = function(item){
3458 var uid = item.uniqueNumber;
3459 if (item.removeEvents) item.removeEvents();
3460 if (item.clearAttributes) item.clearAttributes();
3462 delete collected[uid];
3463 delete storage[uid];
3468 var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
3472 destroy: function(){
3473 var children = clean(this).getElementsByTagName('*');
3474 Array.each(children, clean);
3475 Element.dispose(this);
3480 Array.from(this.childNodes).each(Element.dispose);
3484 dispose: function(){
3485 return (this.parentNode) ? this.parentNode.removeChild(this) : this;
3488 clone: function(contents, keepid){
3489 contents = contents !== false;
3490 var clone = this.cloneNode(contents), ce = [clone], te = [this], i;
3493 ce.append(Array.from(clone.getElementsByTagName('*')));
3494 te.append(Array.from(this.getElementsByTagName('*')));
3497 for (i = ce.length; i--;){
3498 var node = ce[i], element = te[i];
3499 if (!keepid) node.removeAttribute('id');
3501 if (node.clearAttributes){
3502 node.clearAttributes();
3503 node.mergeAttributes(element);
3504 node.removeAttribute('uniqueNumber');
3506 var no = node.options, eo = element.options;
3507 for (var j = no.length; j--;) no[j].selected = eo[j].selected;
3511 var prop = formProps[element.tagName.toLowerCase()];
3512 if (prop && element[prop]) node[prop] = element[prop];
3517 var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
3518 for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
3521 return document.id(clone);
3526 [Element, Window, Document].invoke('implement', {
3528 addListener: function(type, fn){
3529 if (type == 'unload'){
3530 var old = fn, self = this;
3532 self.removeListener('unload', fn);
3536 collected[Slick.uidOf(this)] = this;
3538 if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]);
3539 else this.attachEvent('on' + type, fn);
3543 removeListener: function(type, fn){
3544 if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]);
3545 else this.detachEvent('on' + type, fn);
3549 retrieve: function(property, dflt){
3550 var storage = get(Slick.uidOf(this)), prop = storage[property];
3551 if (dflt != null && prop == null) prop = storage[property] = dflt;
3552 return prop != null ? prop : null;
3555 store: function(property, value){
3556 var storage = get(Slick.uidOf(this));
3557 storage[property] = value;
3561 eliminate: function(property){
3562 var storage = get(Slick.uidOf(this));
3563 delete storage[property];
3570 if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){
3571 Object.each(collected, clean);
3572 if (window.CollectGarbage) CollectGarbage();
3576 Element.Properties = {};
3580 Element.Properties = new Hash;
3584 Element.Properties.style = {
3586 set: function(style){
3587 this.style.cssText = style;
3591 return this.style.cssText;
3595 this.style.cssText = '';
3600 Element.Properties.tag = {
3603 return this.tagName.toLowerCase();
3608 Element.Properties.html = {
3610 set: function(html){
3611 if (html == null) html = '';
3612 else if (typeOf(html) == 'array') html = html.join('');
3613 this.innerHTML = html;
3617 this.innerHTML = '';
3623 // technique by jdbarlett - http://jdbartlett.com/innershiv/
3624 var div = document.createElement('div');
3625 div.innerHTML = '<nav></nav>';
3626 var supportsHTML5Elements = (div.childNodes.length == 1);
3627 if (!supportsHTML5Elements){
3628 var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '),
3629 fragment = document.createDocumentFragment(), l = tags.length;
3630 while (l--) fragment.createElement(tags[l]);
3636 var supportsTableInnerHTML = Function.attempt(function(){
3637 var table = document.createElement('table');
3638 table.innerHTML = '<tr><td></td></tr>';
3643 var tr = document.createElement('tr'), html = '<td></td>';
3644 tr.innerHTML = html;
3645 var supportsTRInnerHTML = (tr.innerHTML == html);
3649 if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){
3651 Element.Properties.html.set = (function(set){
3653 var translations = {
3654 table: [1, '<table>', '</table>'],
3655 select: [1, '<select>', '</select>'],
3656 tbody: [2, '<table><tbody>', '</tbody></table>'],
3657 tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
3660 translations.thead = translations.tfoot = translations.tbody;
3662 return function(html){
3663 var wrap = translations[this.get('tag')];
3664 if (!wrap && !supportsHTML5Elements) wrap = [0, '', ''];
3665 if (!wrap) return set.call(this, html);
3667 var level = wrap[0], wrapper = document.createElement('div'), target = wrapper;
3668 if (!supportsHTML5Elements) fragment.appendChild(wrapper);
3669 wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join('');
3670 while (level--) target = target.firstChild;
3671 this.empty().adopt(target.childNodes);
3672 if (!supportsHTML5Elements) fragment.removeChild(wrapper);
3676 })(Element.Properties.html.set);
3681 var testForm = document.createElement('form');
3682 testForm.innerHTML = '<select><option>s</option></select>';
3684 if (testForm.firstChild.value != 's') Element.Properties.value = {
3686 set: function(value){
3687 var tag = this.get('tag');
3688 if (tag != 'select') return this.setProperty('value', value);
3689 var options = this.getElements('option');
3690 for (var i = 0; i < options.length; i++){
3691 var option = options[i],
3692 attr = option.getAttributeNode('value'),
3693 optionValue = (attr && attr.specified) ? option.value : option.get('text');
3694 if (optionValue == value) return option.selected = true;
3699 var option = this, tag = option.get('tag');
3701 if (tag != 'select' && tag != 'option') return this.getProperty('value');
3703 if (tag == 'select' && !(option = option.getSelected()[0])) return '';
3705 var attr = option.getAttributeNode('value');
3706 return (attr && attr.specified) ? option.value : option.get('text');
3714 if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = {
3716 this.id = this.getAttributeNode('id').value = id;
3719 return this.id || null;
3722 this.id = this.getAttributeNode('id').value = '';
3730 // Begin: Source/Class/Class.js
3736 description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
3738 license: MIT-style license.
3740 requires: [Array, String, Function, Number]
3749 var Class = this.Class = new Type('Class', function(params){
3750 if (instanceOf(params, Function)) params = {initialize: params};
3752 var newClass = function(){
3754 if (newClass.$prototyping) return this;
3755 this.$caller = null;
3756 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
3757 this.$caller = this.caller = null;
3759 }.extend(this).implement(params);
3761 newClass.$constructor = Class;
3762 newClass.prototype.$constructor = newClass;
3763 newClass.prototype.parent = parent;
3768 var parent = function(){
3769 if (!this.$caller) throw new Error('The method "parent" cannot be called.');
3770 var name = this.$caller.$name,
3771 parent = this.$caller.$owner.parent,
3772 previous = (parent) ? parent.prototype[name] : null;
3773 if (!previous) throw new Error('The method "' + name + '" has no parent.');
3774 return previous.apply(this, arguments);
3777 var reset = function(object){
3778 for (var key in object){
3779 var value = object[key];
3780 switch (typeOf(value)){
3782 var F = function(){};
3783 F.prototype = value;
3784 object[key] = reset(new F);
3786 case 'array': object[key] = value.clone(); break;
3792 var wrap = function(self, key, method){
3793 if (method.$origin) method = method.$origin;
3794 var wrapper = function(){
3795 if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
3796 var caller = this.caller, current = this.$caller;
3797 this.caller = current; this.$caller = wrapper;
3798 var result = method.apply(this, arguments);
3799 this.$caller = current; this.caller = caller;
3801 }.extend({$owner: self, $origin: method, $name: key});
3805 var implement = function(key, value, retain){
3806 if (Class.Mutators.hasOwnProperty(key)){
3807 value = Class.Mutators[key].call(this, value);
3808 if (value == null) return this;
3811 if (typeOf(value) == 'function'){
3812 if (value.$hidden) return this;
3813 this.prototype[key] = (retain) ? value : wrap(this, key, value);
3815 Object.merge(this.prototype, key, value);
3821 var getInstance = function(klass){
3822 klass.$prototyping = true;
3823 var proto = new klass;
3824 delete klass.$prototyping;
3828 Class.implement('implement', implement.overloadSetter());
3832 Extends: function(parent){
3833 this.parent = parent;
3834 this.prototype = getInstance(parent);
3837 Implements: function(items){
3838 Array.from(items).each(function(item){
3839 var instance = new item;
3840 for (var key in instance) implement.call(this, key, instance[key], true);
3848 // Begin: Source/Class/Class.Extras.js
3854 description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
3856 license: MIT-style license.
3860 provides: [Class.Extras, Chain, Events, Options]
3867 this.Chain = new Class({
3872 this.$chain.append(Array.flatten(arguments));
3876 callChain: function(){
3877 return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
3880 clearChain: function(){
3881 this.$chain.empty();
3887 var removeOn = function(string){
3888 return string.replace(/^on([A-Z])/, function(full, first){
3889 return first.toLowerCase();
3893 this.Events = new Class({
3897 addEvent: function(type, fn, internal){
3898 type = removeOn(type);
3901 if (fn == $empty) return this;
3904 this.$events[type] = (this.$events[type] || []).include(fn);
3905 if (internal) fn.internal = true;
3909 addEvents: function(events){
3910 for (var type in events) this.addEvent(type, events[type]);
3914 fireEvent: function(type, args, delay){
3915 type = removeOn(type);
3916 var events = this.$events[type];
3917 if (!events) return this;
3918 args = Array.from(args);
3919 events.each(function(fn){
3920 if (delay) fn.delay(delay, this, args);
3921 else fn.apply(this, args);
3926 removeEvent: function(type, fn){
3927 type = removeOn(type);
3928 var events = this.$events[type];
3929 if (events && !fn.internal){
3930 var index = events.indexOf(fn);
3931 if (index != -1) delete events[index];
3936 removeEvents: function(events){
3938 if (typeOf(events) == 'object'){
3939 for (type in events) this.removeEvent(type, events[type]);
3942 if (events) events = removeOn(events);
3943 for (type in this.$events){
3944 if (events && events != type) continue;
3945 var fns = this.$events[type];
3946 for (var i = fns.length; i--;) if (i in fns){
3947 this.removeEvent(type, fns[i]);
3955 this.Options = new Class({
3957 setOptions: function(){
3958 var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
3959 if (this.addEvent) for (var option in options){
3960 if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
3961 this.addEvent(option, options[option]);
3962 delete options[option];
3972 // Begin: Source/Request/Request.js
3978 description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
3980 license: MIT-style license.
3982 requires: [Object, Element, Chain, Events, Options, Browser]
3991 var empty = function(){},
3992 progressSupport = ('onprogress' in new Browser.Request);
3994 var Request = this.Request = new Class({
3996 Implements: [Chain, Events, Options],
3999 onRequest: function(){},
4000 onLoadstart: function(event, xhr){},
4001 onProgress: function(event, xhr){},
4002 onComplete: function(){},
4003 onCancel: function(){},
4004 onSuccess: function(responseText, responseXML){},
4005 onFailure: function(xhr){},
4006 onException: function(headerName, value){},
4007 onTimeout: function(){},
4013 'X-Requested-With': 'XMLHttpRequest',
4014 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
4025 evalResponse: false,
4030 initialize: function(options){
4031 this.xhr = new Browser.Request();
4032 this.setOptions(options);
4033 this.headers = this.options.headers;
4036 onStateChange: function(){
4038 if (xhr.readyState != 4 || !this.running) return;
4039 this.running = false;
4041 Function.attempt(function(){
4042 var status = xhr.status;
4043 this.status = (status == 1223) ? 204 : status;
4045 xhr.onreadystatechange = empty;
4046 if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
4047 clearTimeout(this.timer);
4049 this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML};
4050 if (this.options.isSuccess.call(this, this.status))
4051 this.success(this.response.text, this.response.xml);
4056 isSuccess: function(){
4057 var status = this.status;
4058 return (status >= 200 && status < 300);
4061 isRunning: function(){
4062 return !!this.running;
4065 processScripts: function(text){
4066 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
4067 return text.stripScripts(this.options.evalScripts);
4070 success: function(text, xml){
4071 this.onSuccess(this.processScripts(text), xml);
4074 onSuccess: function(){
4075 this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
4078 failure: function(){
4082 onFailure: function(){
4083 this.fireEvent('complete').fireEvent('failure', this.xhr);
4086 loadstart: function(event){
4087 this.fireEvent('loadstart', [event, this.xhr]);
4090 progress: function(event){
4091 this.fireEvent('progress', [event, this.xhr]);
4094 timeout: function(){
4095 this.fireEvent('timeout', this.xhr);
4098 setHeader: function(name, value){
4099 this.headers[name] = value;
4103 getHeader: function(name){
4104 return Function.attempt(function(){
4105 return this.xhr.getResponseHeader(name);
4110 if (!this.running) return true;
4111 switch (this.options.link){
4112 case 'cancel': this.cancel(); return true;
4113 case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
4118 send: function(options){
4119 if (!this.check(options)) return this;
4121 this.options.isSuccess = this.options.isSuccess || this.isSuccess;
4122 this.running = true;
4124 var type = typeOf(options);
4125 if (type == 'string' || type == 'element') options = {data: options};
4127 var old = this.options;
4128 options = Object.append({data: old.data, url: old.url, method: old.method}, options);
4129 var data = options.data, url = String(options.url), method = options.method.toLowerCase();
4131 switch (typeOf(data)){
4132 case 'element': data = document.id(data).toQueryString(); break;
4133 case 'object': case 'hash': data = Object.toQueryString(data);
4136 if (this.options.format){
4137 var format = 'format=' + this.options.format;
4138 data = (data) ? format + '&' + data : format;
4141 if (this.options.emulation && !['get', 'post'].contains(method)){
4142 var _method = '_method=' + method;
4143 data = (data) ? _method + '&' + data : _method;
4147 if (this.options.urlEncoded && ['post', 'put'].contains(method)){
4148 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
4149 this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding;
4152 if (!url) url = document.location.pathname;
4154 var trimPosition = url.lastIndexOf('/');
4155 if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);
4157 if (this.options.noCache)
4158 url += (url.contains('?') ? '&' : '?') + String.uniqueID();
4160 if (data && method == 'get'){
4161 url += (url.contains('?') ? '&' : '?') + data;
4166 if (progressSupport){
4167 xhr.onloadstart = this.loadstart.bind(this);
4168 xhr.onprogress = this.progress.bind(this);
4171 xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
4172 if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
4174 xhr.onreadystatechange = this.onStateChange.bind(this);
4176 Object.each(this.headers, function(value, key){
4178 xhr.setRequestHeader(key, value);
4180 this.fireEvent('exception', [key, value]);
4184 this.fireEvent('request');
4186 if (!this.options.async) this.onStateChange();
4187 else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
4192 if (!this.running) return this;
4193 this.running = false;
4196 clearTimeout(this.timer);
4197 xhr.onreadystatechange = empty;
4198 if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
4199 this.xhr = new Browser.Request();
4200 this.fireEvent('cancel');
4207 ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
4208 methods[method] = function(data){
4212 if (data != null) object.data = data;
4213 return this.send(object);
4217 Request.implement(methods);
4219 Element.Properties.send = {
4221 set: function(options){
4222 var send = this.get('send').cancel();
4223 send.setOptions(options);
4228 var send = this.retrieve('send');
4230 send = new Request({
4231 data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
4233 this.store('send', send);
4242 send: function(url){
4243 var sender = this.get('send');
4244 sender.send({data: this, url: url || sender.options.url});
4253 // Begin: Source/Utilities/JSON.js
4259 description: JSON encoder and decoder.
4261 license: MIT-style license.
4263 SeeAlso: <http://www.json.org/>
4265 requires: [Array, String, Number, Function]
4272 if (typeof JSON == 'undefined') this.JSON = {};
4277 stringify: JSON.stringify,
4285 var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
4287 var escape = function(chr){
4288 return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
4291 JSON.validate = function(string){
4292 string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
4293 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
4294 replace(/(?:^|:|,)(?:\s*\[)+/g, '');
4296 return (/^[\],:{}\s]*$/).test(string);
4299 JSON.encode = JSON.stringify ? function(obj){
4300 return JSON.stringify(obj);
4302 if (obj && obj.toJSON) obj = obj.toJSON();
4304 switch (typeOf(obj)){
4306 return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
4308 return '[' + obj.map(JSON.encode).clean() + ']';
4309 case 'object': case 'hash':
4311 Object.each(obj, function(value, key){
4312 var json = JSON.encode(value);
4313 if (json) string.push(JSON.encode(key) + ':' + json);
4315 return '{' + string + '}';
4316 case 'number': case 'boolean': return '' + obj;
4317 case 'null': return 'null';
4323 JSON.decode = function(string, secure){
4324 if (!string || typeOf(string) != 'string') return null;
4326 if (secure || JSON.secure){
4327 if (JSON.parse) return JSON.parse(string);
4328 if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
4331 return eval('(' + string + ')');
4337 // Begin: Source/Request/Request.JSON.js
4343 description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
4345 license: MIT-style license.
4347 requires: [Request, JSON]
4349 provides: Request.JSON
4354 Request.JSON = new Class({
4359 /*onError: function(text, error){},*/
4363 initialize: function(options){
4364 this.parent(options);
4365 Object.append(this.headers, {
4366 'Accept': 'application/json',
4371 success: function(text){
4374 json = this.response.json = JSON.decode(text, this.options.secure);
4376 this.fireEvent('error', [text, error]);
4379 if (json == null) this.onFailure();
4380 else this.onSuccess(json, text);
4386 // Begin: Source/Types/DOMEvent.js
4392 description: Contains the Event Type, to make the event object cross-browser.
4394 license: MIT-style license.
4396 requires: [Window, Document, Array, Function, String, Object]
4407 var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
4408 if (!win) win = window;
4409 event = event || win.event;
4410 if (event.$extended) return event;
4412 this.$extended = true;
4413 this.shift = event.shiftKey;
4414 this.control = event.ctrlKey;
4415 this.alt = event.altKey;
4416 this.meta = event.metaKey;
4417 var type = this.type = event.type;
4418 var target = event.target || event.srcElement;
4419 while (target && target.nodeType == 3) target = target.parentNode;
4420 this.target = document.id(target);
4422 if (type.indexOf('key') == 0){
4423 var code = this.code = (event.which || event.keyCode);
4424 this.key = _keys[code]/*<1.3compat>*/ || Object.keyOf(Event.Keys, code)/*</1.3compat>*/;
4425 if (type == 'keydown'){
4426 if (code > 111 && code < 124) this.key = 'f' + (code - 111);
4427 else if (code > 95 && code < 106) this.key = code - 96;
4429 if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
4430 } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){
4431 var doc = win.document;
4432 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
4434 x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
4435 y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
4438 x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
4439 y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
4441 if (type == 'DOMMouseScroll' || type == 'mousewheel')
4442 this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
4444 this.rightClick = (event.which == 3 || event.button == 2);
4445 if (type == 'mouseover' || type == 'mouseout'){
4446 var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
4447 while (related && related.nodeType == 3) related = related.parentNode;
4448 this.relatedTarget = document.id(related);
4450 } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
4451 this.rotation = event.rotation;
4452 this.scale = event.scale;
4453 this.targetTouches = event.targetTouches;
4454 this.changedTouches = event.changedTouches;
4455 var touches = this.touches = event.touches;
4456 if (touches && touches[0]){
4457 var touch = touches[0];
4458 this.page = {x: touch.pageX, y: touch.pageY};
4459 this.client = {x: touch.clientX, y: touch.clientY};
4463 if (!this.client) this.client = {};
4464 if (!this.page) this.page = {};
4467 DOMEvent.implement({
4470 return this.preventDefault().stopPropagation();
4473 stopPropagation: function(){
4474 if (this.event.stopPropagation) this.event.stopPropagation();
4475 else this.event.cancelBubble = true;
4479 preventDefault: function(){
4480 if (this.event.preventDefault) this.event.preventDefault();
4481 else this.event.returnValue = false;
4487 DOMEvent.defineKey = function(code, key){
4492 DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
4494 DOMEvent.defineKeys({
4495 '38': 'up', '40': 'down', '37': 'left', '39': 'right',
4496 '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
4497 '46': 'delete', '13': 'enter'
4503 var Event = DOMEvent;
4509 Event.Keys = new Hash(Event.Keys);
4514 // Begin: Source/Element/Element.Event.js
4520 description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary.
4522 license: MIT-style license.
4524 requires: [Element, Event]
4526 provides: Element.Event
4533 Element.Properties.events = {set: function(events){
4534 this.addEvents(events);
4537 [Element, Window, Document].invoke('implement', {
4539 addEvent: function(type, fn){
4540 var events = this.retrieve('events', {});
4541 if (!events[type]) events[type] = {keys: [], values: []};
4542 if (events[type].keys.contains(fn)) return this;
4543 events[type].keys.push(fn);
4544 var realType = type,
4545 custom = Element.Events[type],
4549 if (custom.onAdd) custom.onAdd.call(this, fn, type);
4550 if (custom.condition){
4551 condition = function(event){
4552 if (custom.condition.call(this, event, type)) return fn.call(this, event);
4556 if (custom.base) realType = Function.from(custom.base).call(this, type);
4558 var defn = function(){
4559 return fn.call(self);
4561 var nativeEvent = Element.NativeEvents[realType];
4563 if (nativeEvent == 2){
4564 defn = function(event){
4565 event = new DOMEvent(event, self.getWindow());
4566 if (condition.call(self, event) === false) event.stop();
4569 this.addListener(realType, defn, arguments[2]);
4571 events[type].values.push(defn);
4575 removeEvent: function(type, fn){
4576 var events = this.retrieve('events');
4577 if (!events || !events[type]) return this;
4578 var list = events[type];
4579 var index = list.keys.indexOf(fn);
4580 if (index == -1) return this;
4581 var value = list.values[index];
4582 delete list.keys[index];
4583 delete list.values[index];
4584 var custom = Element.Events[type];
4586 if (custom.onRemove) custom.onRemove.call(this, fn, type);
4587 if (custom.base) type = Function.from(custom.base).call(this, type);
4589 return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
4592 addEvents: function(events){
4593 for (var event in events) this.addEvent(event, events[event]);
4597 removeEvents: function(events){
4599 if (typeOf(events) == 'object'){
4600 for (type in events) this.removeEvent(type, events[type]);
4603 var attached = this.retrieve('events');
4604 if (!attached) return this;
4606 for (type in attached) this.removeEvents(type);
4607 this.eliminate('events');
4608 } else if (attached[events]){
4609 attached[events].keys.each(function(fn){
4610 this.removeEvent(events, fn);
4612 delete attached[events];
4617 fireEvent: function(type, args, delay){
4618 var events = this.retrieve('events');
4619 if (!events || !events[type]) return this;
4620 args = Array.from(args);
4622 events[type].keys.each(function(fn){
4623 if (delay) fn.delay(delay, this, args);
4624 else fn.apply(this, args);
4629 cloneEvents: function(from, type){
4630 from = document.id(from);
4631 var events = from.retrieve('events');
4632 if (!events) return this;
4634 for (var eventType in events) this.cloneEvents(from, eventType);
4635 } else if (events[type]){
4636 events[type].keys.each(function(fn){
4637 this.addEvent(type, fn);
4645 Element.NativeEvents = {
4646 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
4647 mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
4648 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
4649 keydown: 2, keypress: 2, keyup: 2, //keyboard
4650 orientationchange: 2, // mobile
4651 touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
4652 gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
4653 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements
4654 load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
4655 error: 1, abort: 1, scroll: 1 //misc
4658 Element.Events = {mousewheel: {
4659 base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
4662 if ('onmouseenter' in document.documentElement){
4663 Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2;
4665 var check = function(event){
4666 var related = event.relatedTarget;
4667 if (related == null) return true;
4668 if (!related) return false;
4669 return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
4672 Element.Events.mouseenter = {
4677 Element.Events.mouseleave = {
4684 if (!window.addEventListener){
4685 Element.NativeEvents.propertychange = 2;
4686 Element.Events.change = {
4688 var type = this.type;
4689 return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'
4691 condition: function(event){
4692 return this.type != 'radio' || (event.event.propertyName == 'checked' && this.checked);
4700 Element.Events = new Hash(Element.Events);
4707 // Begin: Source/Element/Element.Delegation.js
4711 name: Element.Delegation
4713 description: Extends the Element native object to include the delegate method for more efficient event management.
4715 license: MIT-style license.
4717 requires: [Element.Event]
4719 provides: [Element.Delegation]
4726 var eventListenerSupport = !!window.addEventListener;
4728 Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2;
4730 var bubbleUp = function(self, match, fn, event, target){
4731 while (target && target != self){
4732 if (match(target, event)) return fn.call(target, event, target);
4733 target = document.id(target.parentNode);
4745 base: 'focus' + (eventListenerSupport ? '' : 'in'),
4749 base: eventListenerSupport ? 'blur' : 'focusout',
4755 var _key = '$delegation:';
4756 var formObserver = function(type){
4762 remove: function(self, uid){
4763 var list = self.retrieve(_key + type + 'listeners', {})[uid];
4764 if (list && list.forms) for (var i = list.forms.length; i--;){
4765 list.forms[i].removeEvent(type, list.fns[i]);
4769 listen: function(self, match, fn, event, target, uid){
4770 var form = (target.get('tag') == 'form') ? target : event.target.getParent('form');
4773 var listeners = self.retrieve(_key + type + 'listeners', {}),
4774 listener = listeners[uid] || {forms: [], fns: []},
4775 forms = listener.forms, fns = listener.fns;
4777 if (forms.indexOf(form) != -1) return;
4780 var _fn = function(event){
4781 bubbleUp(self, match, fn, event, target);
4783 form.addEvent(type, _fn);
4786 listeners[uid] = listener;
4787 self.store(_key + type + 'listeners', listeners);
4792 var inputObserver = function(type){
4795 listen: function(self, match, fn, event, target){
4796 var events = {blur: function(){
4797 this.removeEvents(events);
4799 events[type] = function(event){
4800 bubbleUp(self, match, fn, event, target);
4802 event.target.addEvents(events);
4807 if (!eventListenerSupport) Object.append(map, {
4808 submit: formObserver('submit'),
4809 reset: formObserver('reset'),
4810 change: inputObserver('change'),
4811 select: inputObserver('select')
4815 var proto = Element.prototype,
4816 addEvent = proto.addEvent,
4817 removeEvent = proto.removeEvent;
4819 var relay = function(old, method){
4820 return function(type, fn, useCapture){
4821 if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture);
4822 var parsed = Slick.parse(type).expressions[0][0];
4823 if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture);
4824 var newType = parsed.tag;
4825 parsed.pseudos.slice(1).each(function(pseudo){
4826 newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : '');
4828 old.call(this, type, fn);
4829 return method.call(this, newType, parsed.pseudos[0].value, fn);
4835 addEvent: function(type, match, fn){
4836 var storage = this.retrieve('$delegates', {}), stored = storage[type];
4837 if (stored) for (var _uid in stored){
4838 if (stored[_uid].fn == fn && stored[_uid].match == match) return this;
4841 var _type = type, _match = match, _fn = fn, _map = map[type] || {};
4842 type = _map.base || _type;
4844 match = function(target){
4845 return Slick.match(target, _match);
4848 var elementEvent = Element.Events[_type];
4849 if (elementEvent && elementEvent.condition){
4850 var __match = match, condition = elementEvent.condition;
4851 match = function(target, event){
4852 return __match(target, event) && condition.call(target, event, type);
4856 var self = this, uid = String.uniqueID();
4857 var delegator = _map.listen ? function(event, target){
4858 if (!target && event && event.target) target = event.target;
4859 if (target) _map.listen(self, match, fn, event, target, uid);
4860 } : function(event, target){
4861 if (!target && event && event.target) target = event.target;
4862 if (target) bubbleUp(self, match, fn, event, target);
4865 if (!stored) stored = {};
4869 delegator: delegator
4871 storage[_type] = stored;
4872 return addEvent.call(this, type, delegator, _map.capture);
4875 removeEvent: function(type, match, fn, _uid){
4876 var storage = this.retrieve('$delegates', {}), stored = storage[type];
4877 if (!stored) return this;
4880 var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {};
4881 type = _map.base || _type;
4882 if (_map.remove) _map.remove(this, _uid);
4883 delete stored[_uid];
4884 storage[_type] = stored;
4885 return removeEvent.call(this, type, delegator);
4889 if (fn) for (__uid in stored){
4891 if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid);
4892 } else for (__uid in stored){
4894 if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid);
4901 [Element, Window, Document].invoke('implement', {
4902 addEvent: relay(addEvent, delegation.addEvent),
4903 removeEvent: relay(removeEvent, delegation.removeEvent)
4909 // Begin: Source/Fx/Fx.js
4915 description: Contains the basic animation logic to be extended by all other Fx Classes.
4917 license: MIT-style license.
4919 requires: [Chain, Events, Options]
4928 var Fx = this.Fx = new Class({
4930 Implements: [Chain, Events, Options],
4946 initialize: function(options){
4947 this.subject = this.subject || this;
4948 this.setOptions(options);
4951 getTransition: function(){
4953 return -(Math.cos(Math.PI * p) - 1) / 2;
4957 step: function(now){
4958 if (this.options.frameSkip){
4959 var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
4961 this.frame += frames;
4966 if (this.frame < this.frames){
4967 var delta = this.transition(this.frame / this.frames);
4968 this.set(this.compute(this.from, this.to, delta));
4970 this.frame = this.frames;
4971 this.set(this.compute(this.from, this.to, 1));
4980 compute: function(from, to, delta){
4981 return Fx.compute(from, to, delta);
4985 if (!this.isRunning()) return true;
4986 switch (this.options.link){
4987 case 'cancel': this.cancel(); return true;
4988 case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
4993 start: function(from, to){
4994 if (!this.check(from, to)) return this;
4997 this.frame = (this.options.frameSkip) ? 0 : -1;
4999 this.transition = this.getTransition();
5000 var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
5001 this.duration = Fx.Durations[duration] || duration.toInt();
5002 this.frameInterval = 1000 / fps;
5003 this.frames = frames || Math.round(this.duration / this.frameInterval);
5004 this.fireEvent('start', this.subject);
5005 pushInstance.call(this, fps);
5010 if (this.isRunning()){
5012 pullInstance.call(this, this.options.fps);
5013 if (this.frames == this.frame){
5014 this.fireEvent('complete', this.subject);
5015 if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
5017 this.fireEvent('stop', this.subject);
5024 if (this.isRunning()){
5026 pullInstance.call(this, this.options.fps);
5027 this.frame = this.frames;
5028 this.fireEvent('cancel', this.subject).clearChain();
5034 if (this.isRunning()){
5036 pullInstance.call(this, this.options.fps);
5042 if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps);
5046 isRunning: function(){
5047 var list = instances[this.options.fps];
5048 return list && list.contains(this);
5053 Fx.compute = function(from, to, delta){
5054 return (to - from) * delta + from;
5057 Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
5061 var instances = {}, timers = {};
5063 var loop = function(){
5064 var now = Date.now();
5065 for (var i = this.length; i--;){
5066 var instance = this[i];
5067 if (instance) instance.step(now);
5071 var pushInstance = function(fps){
5072 var list = instances[fps] || (instances[fps] = []);
5074 if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
5077 var pullInstance = function(fps){
5078 var list = instances[fps];
5081 if (!list.length && timers[fps]){
5082 delete instances[fps];
5083 timers[fps] = clearInterval(timers[fps]);
5091 // Begin: Source/Element/Element.Style.js
5097 description: Contains methods for interacting with the styles of Elements in a fashionable way.
5099 license: MIT-style license.
5103 provides: Element.Style
5110 var html = document.html;
5113 // Check for oldIE, which does not remove styles when they're set to null
5114 var el = document.createElement('div');
5115 el.style.color = 'red';
5116 el.style.color = null;
5117 var doesNotRemoveStyles = el.style.color == 'red';
5121 Element.Properties.styles = {set: function(styles){
5122 this.setStyles(styles);
5125 var hasOpacity = (html.style.opacity != null),
5126 hasFilter = (html.style.filter != null),
5127 reAlpha = /alpha\(opacity=([\d.]+)\)/i;
5129 var setVisibility = function(element, opacity){
5130 element.store('$opacity', opacity);
5131 element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden';
5134 var setOpacity = (hasOpacity ? function(element, opacity){
5135 element.style.opacity = opacity;
5136 } : (hasFilter ? function(element, opacity){
5137 var style = element.style;
5138 if (!element.currentStyle || !element.currentStyle.hasLayout) style.zoom = 1;
5139 if (opacity == null || opacity == 1) opacity = '';
5140 else opacity = 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')';
5141 var filter = style.filter || element.getComputedStyle('filter') || '';
5142 style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
5143 if (!style.filter) style.removeAttribute('filter');
5144 } : setVisibility));
5146 var getOpacity = (hasOpacity ? function(element){
5147 var opacity = element.style.opacity || element.getComputedStyle('opacity');
5148 return (opacity == '') ? 1 : opacity.toFloat();
5149 } : (hasFilter ? function(element){
5150 var filter = (element.style.filter || element.getComputedStyle('filter')),
5152 if (filter) opacity = filter.match(reAlpha);
5153 return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
5154 } : function(element){
5155 var opacity = element.retrieve('$opacity');
5156 if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1);
5160 var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
5164 getComputedStyle: function(property){
5165 if (this.currentStyle) return this.currentStyle[property.camelCase()];
5166 var defaultView = Element.getDocument(this).defaultView,
5167 computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
5168 return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
5171 setStyle: function(property, value){
5172 if (property == 'opacity'){
5173 if (value != null) value = parseFloat(value);
5174 setOpacity(this, value);
5177 property = (property == 'float' ? floatName : property).camelCase();
5178 if (typeOf(value) != 'string'){
5179 var map = (Element.Styles[property] || '@').split(' ');
5180 value = Array.from(value).map(function(val, i){
5181 if (!map[i]) return '';
5182 return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
5184 } else if (value == String(Number(value))){
5185 value = Math.round(value);
5187 this.style[property] = value;
5189 if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){
5190 this.style.removeAttribute(property);
5196 getStyle: function(property){
5197 if (property == 'opacity') return getOpacity(this);
5198 property = (property == 'float' ? floatName : property).camelCase();
5199 var result = this.style[property];
5200 if (!result || property == 'zIndex'){
5202 for (var style in Element.ShortStyles){
5203 if (property != style) continue;
5204 for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
5205 return result.join(' ');
5207 result = this.getComputedStyle(property);
5210 result = String(result);
5211 var color = result.match(/rgba?\([\d\s,]+\)/);
5212 if (color) result = result.replace(color[0], color[0].rgbToHex());
5214 if (Browser.opera || Browser.ie){
5215 if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){
5216 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
5217 values.each(function(value){
5218 size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
5220 return this['offset' + property.capitalize()] - size + 'px';
5222 if (Browser.ie && (/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){
5229 setStyles: function(styles){
5230 for (var style in styles) this.setStyle(style, styles[style]);
5234 getStyles: function(){
5236 Array.flatten(arguments).each(function(key){
5237 result[key] = this.getStyle(key);
5245 left: '@px', top: '@px', bottom: '@px', right: '@px',
5246 width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
5247 backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
5248 fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
5249 margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
5250 borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
5251 zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
5258 setOpacity: function(value){
5259 setOpacity(this, value);
5263 getOpacity: function(){
5264 return getOpacity(this);
5269 Element.Properties.opacity = {
5271 set: function(opacity){
5272 setOpacity(this, opacity);
5273 setVisibility(this, opacity);
5277 return getOpacity(this);
5286 Element.Styles = new Hash(Element.Styles);
5290 Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
5292 ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
5293 var Short = Element.ShortStyles;
5294 var All = Element.Styles;
5295 ['margin', 'padding'].each(function(style){
5296 var sd = style + direction;
5297 Short[style][sd] = All[sd] = '@px';
5299 var bd = 'border' + direction;
5300 Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
5301 var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
5303 Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
5304 Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
5305 Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
5311 // Begin: Source/Fx/Fx.CSS.js
5317 description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
5319 license: MIT-style license.
5321 requires: [Fx, Element.Style]
5328 Fx.CSS = new Class({
5332 //prepares the base from/to object
5334 prepare: function(element, property, values){
5335 values = Array.from(values);
5336 var from = values[0], to = values[1];
5339 from = element.getStyle(property);
5340 var unit = this.options.unit;
5341 // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299
5342 if (unit && from.slice(-unit.length) != unit && parseFloat(from) != 0){
5343 element.setStyle(property, to + unit);
5344 var value = element.getComputedStyle(property);
5345 // IE and Opera support pixelLeft or pixelWidth
5346 if (!(/px$/.test(value))){
5347 value = element.style[('pixel-' + property).camelCase()];
5349 // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
5350 var left = element.style.left;
5351 element.style.left = to + unit;
5352 value = element.style.pixelLeft;
5353 element.style.left = left;
5356 from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0);
5357 element.setStyle(property, from + unit);
5360 return {from: this.parse(from), to: this.parse(to)};
5363 //parses a value into an array
5365 parse: function(value){
5366 value = Function.from(value)();
5367 value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
5368 return value.map(function(val){
5371 Object.each(Fx.CSS.Parsers, function(parser, key){
5373 var parsed = parser.parse(val);
5374 if (parsed || parsed === 0) found = {value: parsed, parser: parser};
5376 found = found || {value: val, parser: Fx.CSS.Parsers.String};
5381 //computes by a from and to prepared objects, using their parsers.
5383 compute: function(from, to, delta){
5385 (Math.min(from.length, to.length)).times(function(i){
5386 computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
5388 computed.$family = Function.from('fx:css:value');
5392 //serves the value as settable
5394 serve: function(value, unit){
5395 if (typeOf(value) != 'fx:css:value') value = this.parse(value);
5397 value.each(function(bit){
5398 returned = returned.concat(bit.parser.serve(bit.value, unit));
5403 //renders the change to an element
5405 render: function(element, property, value, unit){
5406 element.setStyle(property, this.serve(value, unit));
5409 //searches inside the page css to find the values for a selector
5411 search: function(selector){
5412 if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
5413 var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
5414 Array.each(document.styleSheets, function(sheet, j){
5415 var href = sheet.href;
5416 if (href && href.contains('://') && !href.contains(document.domain)) return;
5417 var rules = sheet.rules || sheet.cssRules;
5418 Array.each(rules, function(rule, i){
5419 if (!rule.style) return;
5420 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
5421 return m.toLowerCase();
5423 if (!selectorText || !selectorTest.test(selectorText)) return;
5424 Object.each(Element.Styles, function(value, style){
5425 if (!rule.style[style] || Element.ShortStyles[style]) return;
5426 value = String(rule.style[style]);
5427 to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value;
5431 return Fx.CSS.Cache[selector] = to;
5441 parse: function(value){
5442 if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
5443 return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
5445 compute: function(from, to, delta){
5446 return from.map(function(value, i){
5447 return Math.round(Fx.compute(from[i], to[i], delta));
5450 serve: function(value){
5451 return value.map(Number);
5457 compute: Fx.compute,
5458 serve: function(value, unit){
5459 return (unit) ? value + unit : value;
5464 parse: Function.from(false),
5465 compute: function(zero, one){
5468 serve: function(zero){
5477 Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);
5482 // Begin: Source/Fx/Fx.Morph.js
5488 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.
5490 license: MIT-style license.
5499 Fx.Morph = new Class({
5503 initialize: function(element, options){
5504 this.element = this.subject = document.id(element);
5505 this.parent(options);
5509 if (typeof now == 'string') now = this.search(now);
5510 for (var p in now) this.render(this.element, p, now[p], this.options.unit);
5514 compute: function(from, to, delta){
5516 for (var p in from) now[p] = this.parent(from[p], to[p], delta);
5520 start: function(properties){
5521 if (!this.check(properties)) return this;
5522 if (typeof properties == 'string') properties = this.search(properties);
5523 var from = {}, to = {};
5524 for (var p in properties){
5525 var parsed = this.prepare(this.element, p, properties[p]);
5526 from[p] = parsed.from;
5529 return this.parent(from, to);
5534 Element.Properties.morph = {
5536 set: function(options){
5537 this.get('morph').cancel().setOptions(options);
5542 var morph = this.retrieve('morph');
5544 morph = new Fx.Morph(this, {link: 'cancel'});
5545 this.store('morph', morph);
5554 morph: function(props){
5555 this.get('morph').start(props);
5562 // Begin: Source/Utilities/Swiff.js
5568 description: Wrapper for embedding SWF movies. Supports External Interface Communication.
5570 license: MIT-style license.
5573 - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
5575 requires: [Options, Object, Element]
5584 var Swiff = this.Swiff = new Class({
5586 Implements: Options,
5596 allowScriptAccess: 'always',
5604 toElement: function(){
5608 initialize: function(path, options){
5609 this.instance = 'Swiff_' + String.uniqueID();
5611 this.setOptions(options);
5612 options = this.options;
5613 var id = this.id = options.id || this.instance;
5614 var container = document.id(options.container);
5616 Swiff.CallBacks[this.instance] = {};
5618 var params = options.params, vars = options.vars, callBacks = options.callBacks;
5619 var properties = Object.append({height: options.height, width: options.width}, options.properties);
5623 for (var callBack in callBacks){
5624 Swiff.CallBacks[this.instance][callBack] = (function(option){
5626 return option.apply(self.object, arguments);
5628 })(callBacks[callBack]);
5629 vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
5632 params.flashVars = Object.toQueryString(vars);
5634 properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
5635 params.movie = path;
5637 properties.type = 'application/x-shockwave-flash';
5639 properties.data = path;
5641 var build = '<object id="' + id + '"';
5642 for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
5644 for (var param in params){
5645 if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
5647 build += '</object>';
5648 this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
5651 replaces: function(element){
5652 element = document.id(element, true);
5653 element.parentNode.replaceChild(this.toElement(), element);
5657 inject: function(element){
5658 document.id(element, true).appendChild(this.toElement());
5663 return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments));
5668 Swiff.CallBacks = {};
5670 Swiff.remote = function(obj, fn){
5671 var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
5678 // Begin: Source/Fx/Fx.Transitions.js
5682 name: Fx.Transitions
5684 description: Contains a set of advanced transitions to be used with any of the Fx Classes.
5686 license: MIT-style license.
5689 - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
5693 provides: Fx.Transitions
5700 getTransition: function(){
5701 var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
5702 if (typeof trans == 'string'){
5703 var data = trans.split(':');
5704 trans = Fx.Transitions;
5705 trans = trans[data[0]] || trans[data[0].capitalize()];
5706 if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
5713 Fx.Transition = function(transition, params){
5714 params = Array.from(params);
5715 var easeIn = function(pos){
5716 return transition(pos, params);
5718 return Object.append(easeIn, {
5720 easeOut: function(pos){
5721 return 1 - transition(1 - pos, params);
5723 easeInOut: function(pos){
5724 return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
5731 linear: function(zero){
5739 Fx.Transitions = new Hash(Fx.Transitions);
5743 Fx.Transitions.extend = function(transitions){
5744 for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
5747 Fx.Transitions.extend({
5749 Pow: function(p, x){
5750 return Math.pow(p, x && x[0] || 6);
5754 return Math.pow(2, 8 * (p - 1));
5758 return 1 - Math.sin(Math.acos(p));
5762 return 1 - Math.cos(p * Math.PI / 2);
5765 Back: function(p, x){
5766 x = x && x[0] || 1.618;
5767 return Math.pow(p, 2) * ((x + 1) * p - x);
5770 Bounce: function(p){
5772 for (var a = 0, b = 1; 1; a += b, b /= 2){
5773 if (p >= (7 - 4 * a) / 11){
5774 value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
5781 Elastic: function(p, x){
5782 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
5787 ['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
5788 Fx.Transitions[transition] = new Fx.Transition(function(p){
5789 return Math.pow(p, i + 2);
5794 // Begin: Source/More/More.js
5802 description: MooTools More
5804 license: MIT-style license
5819 provides: [MooTools.More]
5825 version: '1.4.3.1dev',
5830 // Begin: Source/Class/Class.Binds.js
5834 script: Class.Binds.js
5838 description: Automagically binds specified methods in a class to the instance of the class.
5840 license: MIT-style license
5849 provides: [Class.Binds]
5854 Class.Mutators.Binds = function(binds){
5855 if (!this.prototype.initialize) this.implement('initialize', function(){});
5856 return Array.from(binds).concat(this.prototype.Binds || []);
5859 Class.Mutators.initialize = function(initialize){
5861 Array.from(this.Binds).each(function(name){
5862 var original = this[name];
5863 if (original) this[name] = original.bind(this);
5865 return initialize.apply(this, arguments);
5870 // Begin: Source/Class/Class.Occlude.js
5874 script: Class.Occlude.js
5878 description: Prevents a class from being applied to a DOM element twice.
5880 license: MIT-style license.
5890 provides: [Class.Occlude]
5895 Class.Occlude = new Class({
5897 occlude: function(property, element){
5898 element = document.id(element || this.element);
5899 var instance = element.retrieve(property || this.property);
5900 if (instance && !this.occluded)
5901 return (this.occluded = instance);
5903 this.occluded = false;
5904 element.store(property || this.property, this);
5905 return this.occluded;
5911 // Begin: Source/Element/Element.Dimensions.js
5915 name: Element.Dimensions
5917 description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
5919 license: MIT-style license.
5922 - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
5923 - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
5925 requires: [Element, Element.Style]
5927 provides: [Element.Dimensions]
5934 var element = document.createElement('div'),
5935 child = document.createElement('div');
5936 element.style.height = '0';
5937 element.appendChild(child);
5938 var brokenOffsetParent = (child.offsetParent === element);
5939 element = child = null;
5941 var isOffset = function(el){
5942 return styleString(el, 'position') != 'static' || isBody(el);
5945 var isOffsetStatic = function(el){
5946 return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName);
5951 scrollTo: function(x, y){
5953 this.getWindow().scrollTo(x, y);
5955 this.scrollLeft = x;
5961 getSize: function(){
5962 if (isBody(this)) return this.getWindow().getSize();
5963 return {x: this.offsetWidth, y: this.offsetHeight};
5966 getScrollSize: function(){
5967 if (isBody(this)) return this.getWindow().getScrollSize();
5968 return {x: this.scrollWidth, y: this.scrollHeight};
5971 getScroll: function(){
5972 if (isBody(this)) return this.getWindow().getScroll();
5973 return {x: this.scrollLeft, y: this.scrollTop};
5976 getScrolls: function(){
5977 var element = this.parentNode, position = {x: 0, y: 0};
5978 while (element && !isBody(element)){
5979 position.x += element.scrollLeft;
5980 position.y += element.scrollTop;
5981 element = element.parentNode;
5986 getOffsetParent: brokenOffsetParent ? function(){
5988 if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
5990 var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
5991 while ((element = element.parentNode)){
5992 if (isOffsetCheck(element)) return element;
5997 if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
6000 return element.offsetParent;
6005 getOffsets: function(){
6006 if (this.getBoundingClientRect && !Browser.Platform.ios){
6007 var bound = this.getBoundingClientRect(),
6008 html = document.id(this.getDocument().documentElement),
6009 htmlScroll = html.getScroll(),
6010 elemScrolls = this.getScrolls(),
6011 isFixed = (styleString(this, 'position') == 'fixed');
6014 x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
6015 y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
6019 var element = this, position = {x: 0, y: 0};
6020 if (isBody(this)) return position;
6022 while (element && !isBody(element)){
6023 position.x += element.offsetLeft;
6024 position.y += element.offsetTop;
6026 if (Browser.firefox){
6027 if (!borderBox(element)){
6028 position.x += leftBorder(element);
6029 position.y += topBorder(element);
6031 var parent = element.parentNode;
6032 if (parent && styleString(parent, 'overflow') != 'visible'){
6033 position.x += leftBorder(parent);
6034 position.y += topBorder(parent);
6036 } else if (element != this && Browser.safari){
6037 position.x += leftBorder(element);
6038 position.y += topBorder(element);
6041 element = element.offsetParent;
6043 if (Browser.firefox && !borderBox(this)){
6044 position.x -= leftBorder(this);
6045 position.y -= topBorder(this);
6050 getPosition: function(relative){
6051 var offset = this.getOffsets(),
6052 scroll = this.getScrolls();
6054 x: offset.x - scroll.x,
6055 y: offset.y - scroll.y
6058 if (relative && (relative = document.id(relative))){
6059 var relativePosition = relative.getPosition();
6060 return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
6065 getCoordinates: function(element){
6066 if (isBody(this)) return this.getWindow().getCoordinates();
6067 var position = this.getPosition(element),
6068 size = this.getSize();
6075 obj.right = obj.left + obj.width;
6076 obj.bottom = obj.top + obj.height;
6080 computePosition: function(obj){
6082 left: obj.x - styleNumber(this, 'margin-left'),
6083 top: obj.y - styleNumber(this, 'margin-top')
6087 setPosition: function(obj){
6088 return this.setStyles(this.computePosition(obj));
6094 [Document, Window].invoke('implement', {
6096 getSize: function(){
6097 var doc = getCompatElement(this);
6098 return {x: doc.clientWidth, y: doc.clientHeight};
6101 getScroll: function(){
6102 var win = this.getWindow(), doc = getCompatElement(this);
6103 return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
6106 getScrollSize: function(){
6107 var doc = getCompatElement(this),
6108 min = this.getSize(),
6109 body = this.getDocument().body;
6111 return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
6114 getPosition: function(){
6115 return {x: 0, y: 0};
6118 getCoordinates: function(){
6119 var size = this.getSize();
6120 return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
6127 var styleString = Element.getComputedStyle;
6129 function styleNumber(element, style){
6130 return styleString(element, style).toInt() || 0;
6133 function borderBox(element){
6134 return styleString(element, '-moz-box-sizing') == 'border-box';
6137 function topBorder(element){
6138 return styleNumber(element, 'border-top-width');
6141 function leftBorder(element){
6142 return styleNumber(element, 'border-left-width');
6145 function isBody(element){
6146 return (/^(?:body|html)$/i).test(element.tagName);
6149 function getCompatElement(element){
6150 var doc = element.getDocument();
6151 return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
6157 Element.alias({position: 'setPosition'}); //compatability
6159 [Window, Document, Element].invoke('implement', {
6161 getHeight: function(){
6162 return this.getSize().y;
6165 getWidth: function(){
6166 return this.getSize().x;
6169 getScrollTop: function(){
6170 return this.getScroll().y;
6173 getScrollLeft: function(){
6174 return this.getScroll().x;
6177 getScrollHeight: function(){
6178 return this.getScrollSize().y;
6181 getScrollWidth: function(){
6182 return this.getScrollSize().x;
6186 return this.getPosition().y;
6189 getLeft: function(){
6190 return this.getPosition().x;
6196 // Begin: Source/Element/Element.Measure.js
6200 script: Element.Measure.js
6202 name: Element.Measure
6204 description: Extends the Element native object to include methods useful in measuring dimensions.
6206 credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
6208 license: MIT-style license
6214 - Core/Element.Style
6215 - Core/Element.Dimensions
6218 provides: [Element.Measure]
6225 var getStylesList = function(styles, planes){
6227 Object.each(planes, function(directions){
6228 Object.each(directions, function(edge){
6229 styles.each(function(style){
6230 list.push(style + '-' + edge + (style == 'border' ? '-width' : ''));
6237 var calculateEdgeSize = function(edge, styles){
6239 Object.each(styles, function(value, style){
6240 if (style.test(edge)) total = total + value.toInt();
6245 var isVisible = function(el){
6246 return !!(!el || el.offsetHeight || el.offsetWidth);
6252 measure: function(fn){
6253 if (isVisible(this)) return fn.call(this);
6254 var parent = this.getParent(),
6256 while (!isVisible(parent) && parent != document.body){
6257 toMeasure.push(parent.expose());
6258 parent = parent.getParent();
6260 var restore = this.expose(),
6261 result = fn.call(this);
6263 toMeasure.each(function(restore){
6270 if (this.getStyle('display') != 'none') return function(){};
6271 var before = this.style.cssText;
6274 position: 'absolute',
6275 visibility: 'hidden'
6278 this.style.cssText = before;
6282 getDimensions: function(options){
6283 options = Object.merge({computeSize: false}, options);
6284 var dim = {x: 0, y: 0};
6286 var getSize = function(el, options){
6287 return (options.computeSize) ? el.getComputedSize(options) : el.getSize();
6290 var parent = this.getParent('body');
6292 if (parent && this.getStyle('display') == 'none'){
6293 dim = this.measure(function(){
6294 return getSize(this, options);
6297 try { //safari sometimes crashes here, so catch it
6298 dim = getSize(this, options);
6302 return Object.append(dim, (dim.x || dim.x === 0) ? {
6312 getComputedSize: function(options){
6314 //legacy support for my stupid spelling error
6315 if (options && options.plains) options.planes = options.plains;
6318 options = Object.merge({
6319 styles: ['padding','border'],
6321 height: ['top','bottom'],
6322 width: ['left','right']
6328 size = {width: 0, height: 0},
6331 if (options.mode == 'vertical'){
6333 delete options.planes.width;
6334 } else if (options.mode == 'horizontal'){
6336 delete options.planes.height;
6339 getStylesList(options.styles, options.planes).each(function(style){
6340 styles[style] = this.getStyle(style).toInt();
6343 Object.each(options.planes, function(edges, plane){
6345 var capitalized = plane.capitalize(),
6346 style = this.getStyle(plane);
6348 if (style == 'auto' && !dimensions) dimensions = this.getDimensions();
6350 style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt();
6351 size['total' + capitalized] = style;
6353 edges.each(function(edge){
6354 var edgesize = calculateEdgeSize(edge, styles);
6355 size['computed' + edge.capitalize()] = edgesize;
6356 size['total' + capitalized] += edgesize;
6361 return Object.append(size, styles);
6369 // Begin: Source/Element/Element.Position.js
6373 script: Element.Position.js
6375 name: Element.Position
6377 description: Extends the Element native object to include methods useful positioning elements relative to others.
6379 license: MIT-style license
6387 - Core/Element.Dimensions
6390 provides: [Element.Position]
6395 (function(original){
6397 var local = Element.Position = {
6402 minimum: {x: 0, y: 0},
6403 maximum: {x: 0, y: 0},
6404 relFixedPosition: false,
6405 ignoreMargins: false,
6406 ignoreScroll: false,
6407 allowNegative: false,*/
6408 relativeTo: document.body,
6410 x: 'center', //left, center, right
6411 y: 'center' //top, center, bottom
6413 offset: {x: 0, y: 0}
6416 getOptions: function(element, options){
6417 options = Object.merge({}, local.options, options);
6418 local.setPositionOption(options);
6419 local.setEdgeOption(options);
6420 local.setOffsetOption(element, options);
6421 local.setDimensionsOption(element, options);
6425 setPositionOption: function(options){
6426 options.position = local.getCoordinateFromValue(options.position);
6429 setEdgeOption: function(options){
6430 var edgeOption = local.getCoordinateFromValue(options.edge);
6431 options.edge = edgeOption ? edgeOption :
6432 (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} :
6433 {x: 'left', y: 'top'};
6436 setOffsetOption: function(element, options){
6437 var parentOffset = {x: 0, y: 0},
6438 offsetParent = element.measure(function(){
6439 return document.id(this.getOffsetParent());
6441 parentScroll = offsetParent.getScroll();
6443 if (!offsetParent || offsetParent == element.getDocument().body) return;
6444 parentOffset = offsetParent.measure(function(){
6445 var position = this.getPosition();
6446 if (this.getStyle('position') == 'fixed'){
6447 var scroll = window.getScroll();
6448 position.x += scroll.x;
6449 position.y += scroll.y;
6455 parentPositioned: offsetParent != document.id(options.relativeTo),
6456 x: options.offset.x - parentOffset.x + parentScroll.x,
6457 y: options.offset.y - parentOffset.y + parentScroll.y
6461 setDimensionsOption: function(element, options){
6462 options.dimensions = element.getDimensions({
6464 styles: ['padding', 'border', 'margin']
6468 getPosition: function(element, options){
6470 options = local.getOptions(element, options);
6471 var relativeTo = document.id(options.relativeTo) || document.body;
6473 local.setPositionCoordinates(options, position, relativeTo);
6474 if (options.edge) local.toEdge(position, options);
6476 var offset = options.offset;
6477 position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt();
6478 position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt();
6480 local.toMinMax(position, options);
6482 if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position);
6483 if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position);
6484 if (options.ignoreMargins) local.toIgnoreMargins(position, options);
6486 position.left = Math.ceil(position.left);
6487 position.top = Math.ceil(position.top);
6494 setPositionCoordinates: function(options, position, relativeTo){
6495 var offsetY = options.offset.y,
6496 offsetX = options.offset.x,
6497 calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(),
6500 winSize = window.getSize();
6502 switch(options.position.x){
6503 case 'left': position.x = left + offsetX; break;
6504 case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break;
6505 default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break;
6508 switch(options.position.y){
6509 case 'top': position.y = top + offsetY; break;
6510 case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break;
6511 default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break;
6515 toMinMax: function(position, options){
6516 var xy = {left: 'x', top: 'y'}, value;
6517 ['minimum', 'maximum'].each(function(minmax){
6518 ['left', 'top'].each(function(lr){
6519 value = options[minmax] ? options[minmax][xy[lr]] : null;
6520 if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value;
6525 toRelFixedPosition: function(relativeTo, position){
6526 var winScroll = window.getScroll();
6527 position.top += winScroll.y;
6528 position.left += winScroll.x;
6531 toIgnoreScroll: function(relativeTo, position){
6532 var relScroll = relativeTo.getScroll();
6533 position.top -= relScroll.y;
6534 position.left -= relScroll.x;
6537 toIgnoreMargins: function(position, options){
6538 position.left += options.edge.x == 'right'
6539 ? options.dimensions['margin-right']
6540 : (options.edge.x != 'center'
6541 ? -options.dimensions['margin-left']
6542 : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2));
6544 position.top += options.edge.y == 'bottom'
6545 ? options.dimensions['margin-bottom']
6546 : (options.edge.y != 'center'
6547 ? -options.dimensions['margin-top']
6548 : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2));
6551 toEdge: function(position, options){
6552 var edgeOffset = {},
6553 dimensions = options.dimensions,
6554 edge = options.edge;
6557 case 'left': edgeOffset.x = 0; break;
6558 case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break;
6560 default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break;
6564 case 'top': edgeOffset.y = 0; break;
6565 case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break;
6567 default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break;
6570 position.x += edgeOffset.x;
6571 position.y += edgeOffset.y;
6574 getCoordinateFromValue: function(option){
6575 if (typeOf(option) != 'string') return option;
6576 option = option.toLowerCase();
6579 x: option.test('left') ? 'left'
6580 : (option.test('right') ? 'right' : 'center'),
6581 y: option.test(/upper|top/) ? 'top'
6582 : (option.test('bottom') ? 'bottom' : 'center')
6590 position: function(options){
6591 if (options && (options.x != null || options.y != null)){
6592 return (original ? original.apply(this, arguments) : this);
6594 var position = this.setStyle('position', 'absolute').calculatePosition(options);
6595 return (options && options.returnPos) ? position : this.setStyles(position);
6598 calculatePosition: function(options){
6599 return local.getPosition(this, options);
6604 })(Element.prototype.position);
6607 // Begin: Source/Element/Element.Shortcuts.js
6611 script: Element.Shortcuts.js
6613 name: Element.Shortcuts
6615 description: Extends the Element native object to include some shortcut methods.
6617 license: MIT-style license
6623 - Core/Element.Style
6626 provides: [Element.Shortcuts]
6633 isDisplayed: function(){
6634 return this.getStyle('display') != 'none';
6637 isVisible: function(){
6638 var w = this.offsetWidth,
6639 h = this.offsetHeight;
6640 return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none';
6644 return this[this.isDisplayed() ? 'hide' : 'show']();
6650 //IE fails here if the element is not in the dom
6651 d = this.getStyle('display');
6653 if (d == 'none') return this;
6654 return this.store('element:_originalDisplay', d || '').setStyle('display', 'none');
6657 show: function(display){
6658 if (!display && this.isDisplayed()) return this;
6659 display = display || this.retrieve('element:_originalDisplay') || 'block';
6660 return this.setStyle('display', (display == 'none') ? 'block' : display);
6663 swapClass: function(remove, add){
6664 return this.removeClass(remove).addClass(add);
6669 Document.implement({
6671 clearSelection: function(){
6672 if (window.getSelection){
6673 var selection = window.getSelection();
6674 if (selection && selection.removeAllRanges) selection.removeAllRanges();
6675 } else if (document.selection && document.selection.empty){
6677 //IE fails here if selected element is not in dom
6678 document.selection.empty();
6686 // Begin: Source/Forms/OverText.js
6694 description: Shows text over an input that disappears when the user clicks into it. The text remains hidden if the user adds a value.
6696 license: MIT-style license
6704 - Core/Element.Event
6710 provides: [OverText]
6715 var OverText = new Class({
6717 Implements: [Options, Events, Class.Occlude],
6719 Binds: ['reposition', 'assert', 'focus', 'hide'],
6723 onFocus: function(){},
6724 onTextHide: function(textEl, inputEl){},
6725 onTextShow: function(textEl, inputEl){}, */
6727 labelClass: 'overTxtLabel',
6729 position: 'upperLeft',
6741 property: 'OverText',
6743 initialize: function(element, options){
6744 element = this.element = document.id(element);
6746 if (this.occlude()) return this.occluded;
6747 this.setOptions(options);
6749 this.attach(element);
6750 OverText.instances.push(this);
6752 if (this.options.poll) this.poll();
6755 toElement: function(){
6756 return this.element;
6760 var element = this.element,
6761 options = this.options,
6762 value = options.textOverride || element.get('alt') || element.get('title');
6764 if (!value) return this;
6766 var text = this.text = new Element(options.element, {
6767 'class': options.labelClass,
6769 lineHeight: 'normal',
6770 position: 'absolute',
6775 click: this.hide.pass(options.element == 'label', this)
6777 }).inject(element, 'after');
6779 if (options.element == 'label'){
6780 if (!element.get('id')) element.set('id', 'input_' + String.uniqueID());
6781 text.set('for', element.get('id'));
6785 this.textHolder = new Element('div.overTxtWrapper', {
6787 lineHeight: 'normal',
6788 position: 'relative'
6790 }).grab(text).inject(element, 'before');
6793 return this.enable();
6796 destroy: function(){
6797 this.element.eliminate(this.property); // Class.Occlude storage
6799 if (this.text) this.text.destroy();
6800 if (this.textHolder) this.textHolder.destroy();
6804 disable: function(){
6805 this.element.removeEvents({
6810 window.removeEvent('resize', this.reposition);
6811 this.hide(true, true);
6816 this.element.addEvents({
6821 window.addEvent('resize', this.reposition);
6827 if (this.options.element == 'label'){
6828 if (!this.element.get('id')) this.element.set('id', 'input_' + String.uniqueID());
6829 this.text.set('for', this.element.get('id'));
6833 startPolling: function(){
6834 this.pollingPaused = false;
6838 poll: function(stop){
6842 if (this.poller && !stop) return this;
6844 clearInterval(this.poller);
6846 this.poller = (function(){
6847 if (!this.pollingPaused) this.assert(true);
6848 }).periodical(this.options.pollInterval, this);
6854 stopPolling: function(){
6855 this.pollingPaused = true;
6856 return this.poll(true);
6860 if (this.text && (!this.text.isDisplayed() || this.element.get('disabled'))) return this;
6864 hide: function(suppressFocus, force){
6865 if (this.text && (this.text.isDisplayed() && (!this.element.get('disabled') || force))){
6867 this.fireEvent('textHide', [this.text, this.element]);
6868 this.pollingPaused = true;
6869 if (!suppressFocus){
6871 this.element.fireEvent('focus');
6872 this.element.focus();
6873 } catch(e){} //IE barfs if you call focus on hidden elements
6880 if (document.id(this.text) && !this.text.isDisplayed()){
6883 this.fireEvent('textShow', [this.text, this.element]);
6884 this.pollingPaused = false;
6890 return !this.element.get('value');
6893 assert: function(suppressFocus){
6894 return this[this.test() ? 'show' : 'hide'](suppressFocus);
6897 reposition: function(){
6899 if (!this.element.isVisible()) return this.stopPolling().hide();
6900 if (this.text && this.test()){
6901 this.text.position(Object.merge(this.options.positionOptions, {
6902 relativeTo: this.element
6910 OverText.instances = [];
6912 Object.append(OverText, {
6915 return OverText.instances.each(function(ot, i){
6916 if (ot.element && ot.text) fn.call(OverText, ot, i);
6922 return OverText.each(function(ot){
6923 return ot.reposition();
6928 hideAll: function(){
6930 return OverText.each(function(ot){
6931 return ot.hide(true, true);
6936 showAll: function(){
6937 return OverText.each(function(ot){
6946 // Begin: Source/Utilities/IframeShim.js
6950 script: IframeShim.js
6954 description: Defines IframeShim, a class for obscuring select lists and flash objects in IE.
6956 license: MIT-style license
6962 - Core/Element.Event
6963 - Core/Element.Style
6969 provides: [IframeShim]
6974 var IframeShim = new Class({
6976 Implements: [Options, Events, Class.Occlude],
6979 className: 'iframeShim',
6980 src: 'javascript:false;document.write("");',
6984 offset: {x: 0, y: 0},
6985 browsers: (Browser.ie6 || (Browser.firefox && Browser.version < 3 && Browser.Platform.mac))
6988 property: 'IframeShim',
6990 initialize: function(element, options){
6991 this.element = document.id(element);
6992 if (this.occlude()) return this.occluded;
6993 this.setOptions(options);
6998 makeShim: function(){
6999 if (this.options.browsers){
7000 var zIndex = this.element.getStyle('zIndex').toInt();
7004 var pos = this.element.getStyle('position');
7005 if (pos == 'static' || !pos) this.element.setStyle('position', 'relative');
7006 this.element.setStyle('zIndex', zIndex);
7008 zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1;
7009 if (zIndex < 0) zIndex = 1;
7010 this.shim = new Element('iframe', {
7011 src: this.options.src,
7016 position: 'absolute',
7018 filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'
7020 'class': this.options.className
7021 }).store('IframeShim', this);
7022 var inject = (function(){
7023 this.shim.inject(this.element, 'after');
7024 this[this.options.display ? 'show' : 'hide']();
7025 this.fireEvent('inject');
7027 if (!IframeShim.ready) window.addEvent('load', inject);
7030 this.position = this.hide = this.show = this.dispose = Function.from(this);
7034 position: function(){
7035 if (!IframeShim.ready || !this.shim) return this;
7036 var size = this.element.measure(function(){
7037 return this.getSize();
7039 if (this.options.margin != undefined){
7040 size.x = size.x - (this.options.margin * 2);
7041 size.y = size.y - (this.options.margin * 2);
7042 this.options.offset.x += this.options.margin;
7043 this.options.offset.y += this.options.margin;
7045 this.shim.set({width: size.x, height: size.y}).position({
7046 relativeTo: this.element,
7047 offset: this.options.offset
7053 if (this.shim) this.shim.setStyle('display', 'none');
7058 if (this.shim) this.shim.setStyle('display', 'block');
7059 return this.position();
7062 dispose: function(){
7063 if (this.shim) this.shim.dispose();
7067 destroy: function(){
7068 if (this.shim) this.shim.destroy();
7074 window.addEvent('load', function(){
7075 IframeShim.ready = true;
7079 // Begin: Source/Interface/Mask.js
7087 description: Creates a mask element to cover another.
7089 license: MIT-style license
7097 - Core/Element.Event
7107 var Mask = new Class({
7109 Implements: [Options, Events],
7111 Binds: ['position'],
7114 onShow: function(){},
7115 onHide: function(){},
7116 onDestroy: function(){},
7117 onClick: function(event){},
7124 destroyOnHide: false,*/
7128 useIframeShim: true,
7129 iframeShimOptions: {}
7132 initialize: function(target, options){
7133 this.target = document.id(target) || document.id(document.body);
7134 this.target.store('mask', this);
7135 this.setOptions(options);
7141 this.element = new Element('div', {
7142 'class': this.options['class'],
7143 id: this.options.id || 'mask-' + String.uniqueID(),
7144 styles: Object.merge({}, this.options.style, {
7148 click: function(event){
7149 this.fireEvent('click', event);
7150 if (this.options.hideOnClick) this.hide();
7158 toElement: function(){
7159 return this.element;
7162 inject: function(target, where){
7163 where = where || (this.options.inject ? this.options.inject.where : '') || this.target == document.body ? 'inside' : 'after';
7164 target = target || (this.options.inject && this.options.inject.target) || this.target;
7166 this.element.inject(target, where);
7168 if (this.options.useIframeShim){
7169 this.shim = new IframeShim(this.element, this.options.iframeShimOptions);
7172 show: this.shim.show.bind(this.shim),
7173 hide: this.shim.hide.bind(this.shim),
7174 destroy: this.shim.destroy.bind(this.shim)
7179 position: function(){
7180 this.resize(this.options.width, this.options.height);
7182 this.element.position({
7183 relativeTo: this.target,
7184 position: 'topLeft',
7185 ignoreMargins: !this.options.maskMargins,
7186 ignoreScroll: this.target == document.body
7192 resize: function(x, y){
7194 styles: ['padding', 'border']
7196 if (this.options.maskMargins) opt.styles.push('margin');
7198 var dim = this.target.getComputedSize(opt);
7199 if (this.target == document.body){
7200 this.element.setStyles({width: 0, height: 0});
7201 var win = window.getScrollSize();
7202 if (dim.totalHeight < win.y) dim.totalHeight = win.y;
7203 if (dim.totalWidth < win.x) dim.totalWidth = win.x;
7205 this.element.setStyles({
7206 width: Array.pick([x, dim.totalWidth, dim.x]),
7207 height: Array.pick([y, dim.totalHeight, dim.y])
7214 if (!this.hidden) return this;
7216 window.addEvent('resize', this.position);
7218 this.showMask.apply(this, arguments);
7223 showMask: function(){
7224 this.element.setStyle('display', 'block');
7225 this.hidden = false;
7226 this.fireEvent('show');
7230 if (this.hidden) return this;
7232 window.removeEvent('resize', this.position);
7233 this.hideMask.apply(this, arguments);
7234 if (this.options.destroyOnHide) return this.destroy();
7239 hideMask: function(){
7240 this.element.setStyle('display', 'none');
7242 this.fireEvent('hide');
7246 this[this.hidden ? 'show' : 'hide']();
7249 destroy: function(){
7251 this.element.destroy();
7252 this.fireEvent('destroy');
7253 this.target.eliminate('mask');
7258 Element.Properties.mask = {
7260 set: function(options){
7261 var mask = this.retrieve('mask');
7262 if (mask) mask.destroy();
7263 return this.eliminate('mask').store('mask:options', options);
7267 var mask = this.retrieve('mask');
7269 mask = new Mask(this, this.retrieve('mask:options'));
7270 this.store('mask', mask);
7279 mask: function(options){
7280 if (options) this.set('mask', options);
7281 this.get('mask').show();
7286 this.get('mask').hide();
7293 // Begin: Source/Utilities/DOMReady.js
7299 description: Contains the custom event domready.
7301 license: MIT-style license.
7303 requires: [Browser, Element, Element.Event]
7305 provides: [DOMReady, DomReady]
7310 (function(window, document){
7317 testElement = document.createElement('div');
7319 var domready = function(){
7320 clearTimeout(timer);
7322 Browser.loaded = ready = true;
7323 document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
7325 document.fireEvent('domready');
7326 window.fireEvent('domready');
7329 var check = function(){
7330 for (var i = checks.length; i--;) if (checks[i]()){
7337 var poll = function(){
7338 clearTimeout(timer);
7339 if (!check()) timer = setTimeout(poll, 10);
7342 document.addListener('DOMContentLoaded', domready);
7345 // doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
7346 // testElement.doScroll() throws when the DOM is not ready, only in the top window
7347 var doScrollWorks = function(){
7349 testElement.doScroll();
7354 // If doScroll works already, it can't be used to determine domready
7355 // e.g. in an iframe
7356 if (testElement.doScroll && !doScrollWorks()){
7357 checks.push(doScrollWorks);
7362 if (document.readyState) checks.push(function(){
7363 var state = document.readyState;
7364 return (state == 'loaded' || state == 'complete');
7367 if ('onreadystatechange' in document) document.addListener('readystatechange', check);
7368 else shouldPoll = true;
7370 if (shouldPoll) poll();
7372 Element.Events.domready = {
7373 onAdd: function(fn){
7374 if (ready) fn.call(this);
7378 // Make sure that domready fires before load
7379 Element.Events.load = {
7381 onAdd: function(fn){
7382 if (loaded && this == window) fn.call(this);
7384 condition: function(){
7385 if (this == window){
7387 delete Element.Events.load;
7393 // This is based on the custom load event
7394 window.addEvent('load', function(){
7398 })(window, document);
7401 // Begin: Source/Element/Element.Pin.js
7405 script: Element.Pin.js
7409 description: Extends the Element native object to include the pin method useful for fixed positioning for elements.
7411 license: MIT-style license
7417 - Core/Element.Event
7418 - Core/Element.Dimensions
7419 - Core/Element.Style
7422 provides: [Element.Pin]
7428 var supportsPositionFixed = false,
7429 supportTested = false;
7431 var testPositionFixed = function(){
7432 var test = new Element('div').setStyles({
7436 }).inject(document.body);
7437 supportsPositionFixed = (test.offsetTop === 0);
7439 supportTested = true;
7444 pin: function(enable, forceScroll){
7445 if (!supportTested) testPositionFixed();
7446 if (this.getStyle('display') == 'none') return this;
7449 scroll = window.getScroll(),
7453 if (enable !== false){
7454 pinnedPosition = this.getPosition(supportsPositionFixed ? document.body : this.getOffsetParent());
7455 if (!this.retrieve('pin:_pinned')){
7456 var currentPosition = {
7457 top: pinnedPosition.y - scroll.y,
7458 left: pinnedPosition.x - scroll.x
7461 if (supportsPositionFixed && !forceScroll){
7462 this.setStyle('position', 'fixed').setStyles(currentPosition);
7465 parent = this.getOffsetParent();
7466 var position = this.getPosition(parent),
7467 styles = this.getStyles('left', 'top');
7469 if (parent && styles.left == 'auto' || styles.top == 'auto') this.setPosition(position);
7470 if (this.getStyle('position') == 'static') this.setStyle('position', 'absolute');
7473 x: styles.left.toInt() - scroll.x,
7474 y: styles.top.toInt() - scroll.y
7477 scrollFixer = function(){
7478 if (!this.retrieve('pin:_pinned')) return;
7479 var scroll = window.getScroll();
7481 left: position.x + scroll.x,
7482 top: position.y + scroll.y
7486 this.store('pin:_scrollFixer', scrollFixer);
7487 window.addEvent('scroll', scrollFixer);
7489 this.store('pin:_pinned', true);
7493 if (!this.retrieve('pin:_pinned')) return this;
7495 parent = this.getParent();
7496 var offsetParent = (parent.getComputedStyle('position') != 'static' ? parent : parent.getOffsetParent());
7498 pinnedPosition = this.getPosition(offsetParent);
7500 this.store('pin:_pinned', false);
7501 scrollFixer = this.retrieve('pin:_scrollFixer');
7504 position: 'absolute',
7505 top: pinnedPosition.y + scroll.y,
7506 left: pinnedPosition.x + scroll.x
7509 this.store('pin:_scrollFixer', null);
7510 window.removeEvent('scroll', scrollFixer);
7512 this.removeClass('isPinned');
7518 return this.pin(false);
7521 togglePin: function(){
7522 return this.pin(!this.retrieve('pin:_pinned'));
7528 Element.alias('togglepin', 'togglePin');
7534 // Begin: Source/Types/Object.Extras.js
7538 script: Object.Extras.js
7542 description: Extra Object generics, like getFromPath which allows a path notation to child elements.
7544 license: MIT-style license
7553 provides: [Object.Extras]
7560 var defined = function(value){
7561 return value != null;
7564 var hasOwnProperty = Object.prototype.hasOwnProperty;
7568 getFromPath: function(source, parts){
7569 if (typeof parts == 'string') parts = parts.split('.');
7570 for (var i = 0, l = parts.length; i < l; i++){
7571 if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]];
7577 cleanValues: function(object, method){
7578 method = method || defined;
7579 for (var key in object) if (!method(object[key])){
7585 erase: function(object, key){
7586 if (hasOwnProperty.call(object, key)) delete object[key];
7590 run: function(object){
7591 var args = Array.slice(arguments, 1);
7592 for (var key in object) if (object[key].apply){
7593 object[key].apply(object, args);
7603 // Begin: Source/Core/Clientcide.js
7609 description: The Clientcide namespace.
7611 license: MIT-style license.
7613 provides: Clientcide
7619 assetLocation: "http://github.com/anutron/clientcide/raw/master/Assets",
7620 setAssetLocation: function(baseHref) {
7621 Clientcide.assetLocation = baseHref;
7622 if (Clientcide.preloaded) Clientcide.preLoadCss();
7624 preLoadCss: function(){
7625 if (window.StickyWin && StickyWin.ui) StickyWin.ui();
7626 if (window.StickyWin && StickyWin.pointy) StickyWin.pointy();
7627 Clientcide.preloaded = true;
7633 if (!window.addEvent) return;
7634 var preload = function(){
7635 if (window.dbug) dbug.log('preloading clientcide css');
7636 if (!Clientcide.preloaded) Clientcide.preLoadCss();
7638 window.addEvent('domready', preload);
7639 window.addEvent('load', preload);
7641 setCNETAssetBaseHref = Clientcide.setAssetLocation;
7644 // Begin: Source/Core/dbug.js
7650 description: A wrapper for Firebug console.* statements.
7652 license: MIT-style license.
7667 dbug.logged.push(arguments);
7669 nolog: function(msg) {
7670 dbug.logged.push(arguments);
7672 time: function(name){
7673 dbug.timers[name] = new Date().getTime();
7675 timeEnd: function(name){
7676 if (dbug.timers[name]) {
7677 var end = new Date().getTime() - dbug.timers[name];
7678 dbug.timers[name] = false;
7679 dbug.log('%s: %s', name, end);
7680 } else dbug.log('no such timer: %s', name);
7682 enable: function(silent) {
7683 var con = window.firebug ? firebug.d.console.cmd : window.console;
7685 if((!!window.console && !!window.console.warn) || window.firebug) {
7687 dbug.enabled = true;
7688 dbug.log = function(){
7690 (con.debug || con.log).apply(con, arguments);
7692 console.log(Array.slice(arguments));
7695 dbug.time = function(){
7696 con.time.apply(con, arguments);
7698 dbug.timeEnd = function(){
7699 con.timeEnd.apply(con, arguments);
7701 if(!silent) dbug.log('enabling dbug');
7702 for(var i=0;i<dbug.logged.length;i++){ dbug.log.apply(con, dbug.logged[i]); }
7705 dbug.enable.delay(400);
7709 disable: function(){
7710 if(dbug.firebug) dbug.enabled = false;
7711 dbug.log = dbug.nolog;
7712 dbug.time = function(){};
7713 dbug.timeEnd = function(){};
7715 cookie: function(set){
7716 var value = document.cookie.match('(?:^|;)\\s*jsdebug=([^;]*)');
7717 var debugCookie = value ? unescape(value[1]) : false;
7718 if((set == null && debugCookie != 'true') || (set != null && set)) {
7720 dbug.log('setting debugging cookie');
7721 var date = new Date();
7722 date.setTime(date.getTime()+(24*60*60*1000));
7723 document.cookie = 'jsdebug=true;expires='+date.toGMTString()+';path=/;';
7724 } else dbug.disableCookie();
7726 disableCookie: function(){
7727 dbug.log('disabling debugging cookie');
7728 document.cookie = 'jsdebug=false;path=/;';
7730 conditional: function(fn, fnIfError) {
7737 if (fnIfError) fnIfError(e);
7744 var fb = !!window.console || !!window.firebug;
7745 var con = window.firebug ? window.firebug.d.console.cmd : window.console;
7746 var debugMethods = ['debug','info','warn','error','assert','dir','dirxml'];
7747 var otherMethods = ['trace','group','groupEnd','profile','profileEnd','count'];
7748 function set(methodList, defaultFunction) {
7750 var getLogger = function(method) {
7752 con[method].apply(con, arguments);
7756 for(var i = 0; i < methodList.length; i++){
7757 var method = methodList[i];
7758 if (fb && con[method]) {
7759 dbug[method] = getLogger(method);
7761 dbug[method] = defaultFunction;
7765 set(debugMethods, dbug.log);
7766 set(otherMethods, function(){});
7768 if ((!!window.console && !!window.console.warn) || window.firebug){
7769 dbug.firebug = true;
7770 var value = document.cookie.match('(?:^|;)\\s*jsdebug=([^;]*)');
7771 var debugCookie = value ? unescape(value[1]) : false;
7772 if(window.location.href.indexOf("jsdebug=true")>0 || debugCookie=='true') dbug.enable();
7773 if(debugCookie=='true')dbug.log('debugging cookie enabled');
7774 if(window.location.href.indexOf("jsdebugCookie=true")>0){
7776 if(!dbug.enabled)dbug.enable();
7778 if(window.location.href.indexOf("jsdebugCookie=false")>0)dbug.disableCookie();
7782 // Begin: Source/UI/StyleWriter.js
7787 description: Provides a simple method for injecting a css style element into the DOM if it's not already present.
7789 license: MIT-Style License
7791 requires: [Core/Class, Core/DomReady, Core/Element, dbug]
7793 provides: StyleWriter
7798 var StyleWriter = new Class({
7799 createStyle: function(css, id) {
7800 window.addEvent('domready', function(){
7802 if (document.id(id) && id) return;
7803 var style = new Element('style', {id: id||''}).inject($$('head')[0]);
7804 if (Browser.ie) style.styleSheet.cssText = css;
7805 else style.set('text', css);
7806 }catch(e){dbug.log('error: %s',e);}
7811 // Begin: Source/UI/StickyWin.js
7817 description: Creates a div within the page with the specified contents at the location relative to the element you specify; basically an in-page popup maker.
7819 license: MIT-Style License
7824 More/Element.Position,
7826 More/Element.Shortcuts,
7834 provides: [StickyWin, StickyWin.Stacker]
7839 var StickyWin = new Class({
7840 Binds: ['destroy', 'hide', 'togglepin', 'esc'],
7841 Implements: [Options, Events, StyleWriter],
7843 // onDisplay: function(){},
7844 // onClose: function(){},
7845 // onDestroy: function(){},
7846 closeClassName: 'closeSticky',
7847 pinClassName: 'pinSticky',
7851 // id: ... set above in initialize function
7852 /* these are the defaults for Element.position anyway
7853 ************************************************
7854 edge: false, //see Element.position
7855 position: 'center', //center, corner == upperLeft, upperRight, bottomLeft, bottomRight
7857 relativeTo: document.body, */
7861 allowMultipleByClass: true,
7862 allowMultiple: true,
7864 useIframeShim: true,
7865 iframeShimSelector: '',
7866 destroyOnClose: false,
7867 closeOnClickOut: false,
7869 getWindowManager: function(){ return StickyWin.WM; }
7872 css: '.SWclearfix:after {content: "."; display: block; height: 0; clear: both; visibility: hidden;}'+
7873 '.SWclearfix {display: inline-table;} * html .SWclearfix {height: 1%;} .SWclearfix {display: block;}',
7875 initialize: function(options){
7876 this.options.inject = this.options.inject || {
7877 target: document.body,
7880 this.setOptions(options);
7881 this.windowManager = this.options.getWindowManager();
7882 this.id = this.options.id || 'StickyWin_'+new Date().getTime();
7884 if (this.windowManager) this.windowManager.add(this);
7886 if (this.options.content) this.setContent(this.options.content);
7887 if (this.options.timeout > 0) {
7888 this.addEvent('onDisplay', function(){
7889 this.hide.delay(this.options.timeout, this);
7892 //add css for clearfix
7893 this.createStyle(this.css, 'StickyWinClearFix');
7894 if (this.options.closeOnClickOut || this.options.closeOnEsc) this.attach();
7895 if (this.options.destroyOnClose) this.addEvent('close', this.destroy);
7896 if (this.options.showNow) this.show();
7898 toElement: function(){
7899 return this.element;
7901 attach: function(dettach){
7902 var method = dettach ? 'removeEvents' : 'addEvents';
7904 if (this.options.closeOnClickOut) events.click = this.esc;
7905 if (this.options.closeOnEsc) events.keyup = this.esc;
7906 document[method](events);
7909 if (e.key == "esc") this.hide();
7910 if (e.type == "click" && this.element != e.target && !this.element.contains(e.target)) this.hide();
7912 makeWindow: function(){
7913 this.destroyOthers();
7914 if (!document.id(this.id)) {
7915 this.win = new Element('div', {
7917 }).addClass(this.options.className).addClass('StickyWinInstance').addClass('SWclearfix').setStyles({
7919 position: 'absolute',
7920 zIndex: this.options.zIndex
7921 }).inject(this.options.inject.target, this.options.inject.where).store('StickyWin', this);
7922 } else this.win = document.id(this.id);
7923 this.element = this.win;
7924 if (this.options.width && typeOf(this.options.width.toInt())=="number") this.win.setStyle('width', this.options.width.toInt());
7925 if (this.options.height && typeOf(this.options.height.toInt())=="number") this.win.setStyle('height', this.options.height.toInt());
7928 show: function(suppressEvent){
7930 if (!suppressEvent) this.fireEvent('display');
7931 if (this.options.useIframeShim) this.showIframeShim();
7932 this.visible = true;
7935 showWin: function(){
7936 if (this.windowManager) this.windowManager.focus(this);
7937 if (!this.positioned) this.position();
7940 hide: function(suppressEvent){
7941 if (typeOf(suppressEvent) == "event" || !suppressEvent) this.fireEvent('close');
7943 if (this.options.useIframeShim) this.hideIframeShim();
7944 this.visible = false;
7947 hideWin: function(){
7948 this.win.setStyle('display','none');
7950 destroyOthers: function() {
7951 if (!this.options.allowMultipleByClass || !this.options.allowMultiple) {
7952 $$('div.StickyWinInstance').each(function(sw) {
7953 if (!this.options.allowMultiple || (!this.options.allowMultipleByClass && sw.hasClass(this.options.className)))
7954 sw.retrieve('StickyWin').destroy();
7958 setContent: function(html) {
7959 if (this.win.getChildren().length>0) this.win.empty();
7960 if (typeOf(html) == "string") this.win.set('html', html);
7961 else if (document.id(html)) this.win.adopt(html);
7962 this.win.getElements('.'+this.options.closeClassName).each(function(el){
7963 el.addEvent('click', this.hide);
7965 this.win.getElements('.'+this.options.pinClassName).each(function(el){
7966 el.addEvent('click', this.togglepin);
7970 position: function(options){
7971 this.positioned = true;
7972 this.setOptions(options);
7974 Object.cleanValues({
7975 allowNegative: [this.options.allowNegative, this.options.relativeTo != document.body].pick(),
7976 relativeTo: this.options.relativeTo,
7977 position: this.options.position,
7978 offset: this.options.offset,
7979 edge: this.options.edge
7982 if (this.shim) this.shim.position();
7985 pin: function(pin) {
7986 if (!this.win.pin) {
7987 dbug.log('you must include element.pin.js!');
7990 this.pinned = pin != null && pin;
7995 return this.pin(false);
7997 togglepin: function(){
7998 return this.pin(!this.pinned);
8000 makeIframeShim: function(){
8002 var el = (this.options.iframeShimSelector)?this.win.getElement(this.options.iframeShimSelector):this.win;
8003 this.shim = new IframeShim(el, {
8005 name: 'StickyWinShim'
8009 showIframeShim: function(){
8010 if (this.options.useIframeShim) {
8011 this.makeIframeShim();
8015 hideIframeShim: function(){
8016 if (this.shim) this.shim.hide();
8018 destroy: function(){
8019 this.destroyed = true;
8021 if (this.windowManager) this.windowManager.remove(this);
8022 if (this.win) this.win.destroy();
8023 if (this.options.useIframeShim && this.shim) this.shim.destroy();
8024 if (document.id('modalOverlay')) document.id('modalOverlay').destroy();
8025 this.fireEvent('destroy');
8029 StickyWin.Stacker = new Class({
8030 Implements: [Options, Events],
8036 initialize: function(options) {
8037 this.setOptions(options);
8040 this.instances.include(sw);
8041 $(sw).addEvent('mousedown', this.click);
8043 click: function(e) {
8044 this.instances.each(function(sw){
8046 if (el == e.target || el.contains($(e.target))) this.focus(sw);
8049 focus: function(instance){
8050 if (this.focused == instance) return;
8051 this.focused = instance;
8052 if (instance) this.instances.erase(instance).push(instance);
8053 this.instances.each(function(current, i){
8054 $(current).setStyle('z-index', this.options.zIndexBase + i);
8056 this.focused = instance;
8058 remove: function(sw) {
8059 this.instances.erase(sw);
8060 $(sw).removeEvent('click', this.click);
8063 StickyWin.WM = new StickyWin.Stacker();
8065 // Begin: Source/UI/StickyWin.Modal.js
8069 name: StickyWin.Modal
8071 description: This script extends StickyWin and StickyWin.Fx classes to add Mask functionality.
8073 license: MIT-Style License
8075 requires: [More/Mask, StickyWin]
8077 provides: StickyWin.Modal
8080 StickyWin.Modal = new Class({
8088 'background-color':'#333',
8093 getWindowManager: function(){ return StickyWin.ModalWM; }
8096 initialize: function(options) {
8097 this.options.maskTarget = this.options.maskTarget || document.body;
8098 this.setOptions(options);
8099 this.mask = new Mask(this.options.maskTarget, this.options.maskOptions).addEvent('click', function() {
8100 if (this.options.hideOnClick) this.hide();
8102 this.parent(options);
8105 show: function(showModal){
8106 if ([showModal, this.options.modalize].pick()) this.mask.show();
8110 hide: function(hideModal){
8111 if ([hideModal, true].pick()) this.mask.hide();
8115 destroy: function(){
8116 this.mask.destroy();
8117 this.parent.apply(this, arguments);
8122 StickyWin.ModalWM = new StickyWin.Stacker({
8125 if (StickyWin.Fx) StickyWin.Fx.Modal = StickyWin.Modal;
8127 // Begin: Source/Types/String.Extras.js
8131 script: String.Extras.js
8135 description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).
8137 license: MIT-style license
8149 provides: [String.Extras]
8201 ' ': /[\xa0\u2002\u2003\u2009]/g,
8203 '\'': /[\u2018\u2019]/g,
8204 '"': /[\u201c\u201d]/g,
8207 // '--': /[\u2014]/g,
8208 '»': /[\uFFFD]/g
8218 findUnits = /(\d*.?\d+)([msh]+)/;
8220 var walk = function(string, replacements){
8221 var result = string, key;
8222 for (key in replacements) result = result.replace(replacements[key], key);
8226 var getRegexForTag = function(tag, contents){
8228 var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)<\/" + tag + "(?!\\w)>" : "<\/?" + tag + "([^>]+)?>",
8229 reg = new RegExp(regstr, "gi");
8235 standardize: function(){
8236 return walk(this, special);
8239 repeat: function(times){
8240 return new Array(times + 1).join(this);
8243 pad: function(length, str, direction){
8244 if (this.length >= length) return this;
8246 var pad = (str == null ? ' ' : '' + str)
8247 .repeat(length - this.length)
8248 .substr(0, length - this.length);
8250 if (!direction || direction == 'right') return this + pad;
8251 if (direction == 'left') return pad + this;
8253 return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
8256 getTags: function(tag, contents){
8257 return this.match(getRegexForTag(tag, contents)) || [];
8260 stripTags: function(tag, contents){
8261 return this.replace(getRegexForTag(tag, contents), '');
8265 return walk(this, tidy);
8268 truncate: function(max, trail, atChar){
8270 if (trail == null && arguments.length == 1) trail = '…';
8271 if (string.length > max){
8272 string = string.substring(0, max);
8274 var index = string.lastIndexOf(atChar);
8275 if (index != -1) string = string.substr(0, index);
8277 if (trail) string += trail;
8283 // "Borrowed" from https://gist.github.com/1503944
8284 var units = findUnits.exec(this);
8285 if (units == null) return Number(this);
8286 return Number(units[1]) * conversions[units[2]];
8294 // Begin: Source/UI/StickyWin.UI.js
8299 description: Creates an html holder for in-page popups using a default style.
8301 license: MIT-Style License
8303 requires: [Core/Element.Style, More/String.Extras, StyleWriter, StickyWin]
8305 provides: StickyWin.UI
8308 StickyWin.UI = new Class({
8309 Implements: [Options, StyleWriter],
8312 css: "div.DefaultStickyWin {font-family:verdana; font-size:11px; line-height: 13px;position: relative;}"+
8313 "div.DefaultStickyWin div.top{-moz-user-select: none;-khtml-user-select: none;}"+
8314 "div.DefaultStickyWin div.top_ul{background:url({%baseHref%}full.png) top left no-repeat; height:30px; width:15px; float:left}"+
8315 "div.DefaultStickyWin div.top_ur{position:relative; left:0px !important; left:-4px; background:url({%baseHref%}full.png) top right !important; height:30px; margin:0px 0px 0px 15px !important; margin-right:-4px; padding:0px}"+
8316 "div.DefaultStickyWin h1.caption{clear: none !important; margin:0px !important; overflow: hidden; padding:0 !important; font-weight:bold; color:#555; font-size:14px !important; position:relative; top:8px !important; left:5px !important; float: left; height: 22px !important;}"+
8317 "div.DefaultStickyWin div.middle, div.DefaultStickyWin div.closeBody {background:url({%baseHref%}body.png) top left repeat-y; margin:0px 20px 0px 0px !important; margin-bottom: -3px; position: relative; top: 0px !important; top: -3px;}"+
8318 "div.DefaultStickyWin div.body{background:url({%baseHref%}body.png) top right repeat-y; padding:8px 23px 8px 0px !important; margin-left:5px !important; position:relative; right:-20px !important; z-index: 1;}"+
8319 "div.DefaultStickyWin div.bottom{clear:both;}"+
8320 "div.DefaultStickyWin div.bottom_ll{background:url({%baseHref%}full.png) bottom left no-repeat; width:15px; height:15px; float:left}"+
8321 "div.DefaultStickyWin div.bottom_lr{background:url({%baseHref%}full.png) bottom right; position:relative; left:0px !important; left:-4px; margin:0px 0px 0px 15px !important; margin-right:-4px; height:15px}"+
8322 "div.DefaultStickyWin div.closeButtons{text-align: center; background:url({%baseHref%}body.png) top right repeat-y; padding: 4px 30px 8px 0px; margin-left:5px; position:relative; right:-20px}"+
8323 "div.DefaultStickyWin a.button:hover{background:url({%baseHref%}big_button_over.gif) repeat-x}"+
8324 "div.DefaultStickyWin a.button {background:url({%baseHref%}big_button.gif) repeat-x; margin: 2px 8px 2px 8px; padding: 2px 12px; cursor:pointer; border: 1px solid #999 !important; text-decoration:none; color: #000 !important;}"+
8325 "div.DefaultStickyWin div.closeButton{width:13px; height:13px; background:url({%baseHref%}closebtn.gif) no-repeat; position: absolute; right: 0px; margin:10px 15px 0px 0px !important; cursor:pointer;top:0px}"+
8326 "div.DefaultStickyWin div.dragHandle { width: 11px; height: 25px; position: relative; top: 5px; left: -3px; cursor: move; background: url({%baseHref%}drag_corner.gif); float: left;}",
8327 cornerHandle: false,
8330 cssId: 'defaultStickyWinStyle',
8331 cssClassName: 'DefaultStickyWin',
8333 /* These options are deprecated:
8335 onClose: function(){},
8337 onConfirm: function(){} */
8339 initialize: function() {
8340 var args = this.getArgs(arguments);
8341 this.setOptions(args.options);
8343 var css = this.options.css.substitute({baseHref: this.options.baseHref || Clientcide.assetLocation + '/stickyWinHTML/'}, /\\?\{%([^}]+)%\}/g);
8344 if (Browser.ie) css = css.replace(/png/g, 'gif');
8345 this.createStyle(css, this.options.cssId);
8347 if (args.caption || args.body) this.setContent(args.caption, args.body);
8349 toElement: function(){
8350 return this.element;
8352 getArgs: function(){
8353 return StickyWin.UI.getArgs.apply(this, arguments);
8356 var opt = this.options; //saving bytes
8358 if (opt.confirmTxt) opt.buttons.push({text: opt.confirmTxt, onClick: opt.onConfirm || function(){}});
8359 if (opt.closeTxt) opt.buttons.push({text: opt.closeTxt, onClick: opt.onClose || function(){}});
8362 var opt = this.options;
8364 var container = new Element('div', {
8365 'class': opt.cssClassName
8367 if (opt.width) container.setStyle('width', opt.width);
8368 this.element = container;
8369 this.element.store('StickyWinUI', this);
8370 if (opt.cssClass) container.addClass(opt.cssClass);
8373 var bodyDiv = new Element('div').addClass('body');
8374 this.body = bodyDiv;
8376 var top_ur = new Element('div').addClass('top_ur');
8377 this.top_ur = top_ur;
8378 this.top = new Element('div').addClass('top').adopt(
8379 new Element('div').addClass('top_ul')
8381 container.adopt(this.top);
8383 if (opt.cornerHandle) new Element('div').addClass('dragHandle').inject(top_ur, 'top');
8386 container.adopt(new Element('div').addClass('middle').adopt(bodyDiv));
8388 if (opt.buttons.length > 0){
8389 var closeButtons = new Element('div').addClass('closeButtons');
8390 opt.buttons.each(function(button){
8391 if (button.properties && button.properties.className){
8392 button.properties['class'] = button.properties.className;
8393 delete button.properties.className;
8395 var properties = Object.merge({'class': 'closeSticky'}, button.properties);
8396 new Element('a').addEvent('click', button.onClick || function(){})
8397 .appendText(button.text).inject(closeButtons).set(properties).addClass('button');
8399 container.adopt(new Element('div').addClass('closeBody').adopt(closeButtons));
8403 new Element('div').addClass('bottom').adopt(
8404 new Element('div').addClass('bottom_ll')
8406 new Element('div').addClass('bottom_lr')
8409 if (this.options.closeButton) container.adopt(new Element('div').addClass('closeButton').addClass('closeSticky'));
8412 setCaption: function(caption) {
8413 this.caption = caption;
8415 this.makeCaption(caption);
8417 if (document.id(caption)) this.h1.adopt(caption);
8418 else this.h1.set('html', caption);
8422 makeCaption: function(caption) {
8423 if (!caption) return this.destroyCaption();
8424 var opt = this.options;
8425 this.h1 = new Element('h1').addClass('caption');
8426 if (opt.width) this.h1.setStyle('width', (opt.width.toInt()-(opt.cornerHandle?55:40)-(opt.closeButton?10:0)));
8427 this.setCaption(caption);
8428 this.top_ur.adopt(this.h1);
8429 if (!this.options.cornerHandle) this.h1.addClass('dragHandle');
8432 destroyCaption: function(){
8439 setContent: function(){
8440 var args = this.getArgs.apply(this, arguments);
8441 var caption = args.caption;
8442 var body = args.body;
8443 this.setCaption(caption);
8444 if (document.id(body)) this.body.empty().adopt(body);
8445 else this.body.set('html', body);
8449 StickyWin.UI.getArgs = function(){
8450 var input = typeOf(arguments[0]) == "arguments"?arguments[0]:arguments;
8451 if (Browser.opera && 1 === input.length) input = input[0];
8453 var cap = input[0], bod = input[1];
8454 var args = Array.link(input, {options: Type.isObject});
8455 if (input.length == 3 || (!args.options && input.length == 2)) {
8458 } else if ((typeOf(bod) == 'object' || !bod) && cap && typeOf(cap) != 'object'){
8464 StickyWin.ui = function(caption, body, options){
8465 return document.id(new StickyWin.UI(caption, body, options));
8469 // Begin: Source/UI/StickyWin.Alert.js
8473 name: StickyWin.Alert
8475 description: Defines StickyWin.Alert, a simple little alert box with a close button.
8477 license: MIT-Style License
8479 requires: [StickyWin.Modal, StickyWin.UI]
8481 provides: [StickyWin.Alert, StickyWin.Error, StickyWin.alert, StickyWin.error]
8485 StickyWin.Alert = new Class({
8486 Implements: Options,
8487 Extends: StickyWin.Modal,
8489 destroyOnClose: true,
8502 getWindowManager: function(){}
8504 initialize: function(caption, message, options) {
8505 this.message = message;
8506 this.caption = caption;
8507 this.setOptions(options);
8509 content: this.build()
8511 this.parent(options);
8513 makeMessage: function() {
8514 return new Element('p', {
8515 'class': 'errorMsg SWclearfix',
8524 return StickyWin.ui(this.caption, this.makeMessage(), this.options.uiOptions);
8528 StickyWin.Error = new Class({
8529 Extends: StickyWin.Alert,
8530 makeMessage: function(){
8531 var message = this.parent();
8532 new Element('img', {
8533 src: (this.options.baseHref || Clientcide.assetLocation + '/simple.error.popup') + '/icon_problems_sm.gif',
8534 'class': 'bang clearfix',
8539 margin: '3px 5px 5px 0px'
8541 }).inject(message, 'top');
8546 StickyWin.alert = function(caption, message, options) {
8547 if (typeOf(options) == "string") options = {baseHref: options};
8548 return new StickyWin.Alert(caption, message, options);
8551 StickyWin.error = function(caption, message, options) {
8552 return new StickyWin.Error(caption, message, options);
8555 // Begin: Source/UI/StickyWin.Confirm.js
8558 name: StickyWin.Confirm
8560 description: Defines StickyWin.Conferm, a simple confirmation box with an ok and a close button.
8562 license: MIT-Style License
8564 requires: StickyWin.Alert
8566 provides: [StickyWin.Confirm, StickyWin.confirm]
8570 StickyWin.Confirm = new Class({
8571 Extends: StickyWin.Alert,
8577 build: function(callback){
8584 onClick: callback || function(){
8585 this.fireEvent('confirm');
8591 return this.parent();
8595 StickyWin.confirm = function(caption, message, callback, options) {
8596 return new StickyWin.Confirm(caption, message, options).addEvent('confirm', callback);
8599 // Begin: Source/Fx/Fx.Move.js
8607 description: Defines Fx.Move, a class that works with Element.Position.js to transition an element from one location to another.
8609 license: MIT-style license
8623 Fx.Move = new Class({
8628 relativeTo: document.body,
8631 offset: {x: 0, y: 0}
8634 start: function(destination){
8635 var element = this.element,
8636 topLeft = element.getStyles('top', 'left');
8637 if (topLeft.top == 'auto' || topLeft.left == 'auto'){
8638 element.setPosition(element.getPosition(element.getOffsetParent()));
8640 return this.parent(element.position(Object.merge({}, this.options, destination, {returnPos: true})));
8645 Element.Properties.move = {
8647 set: function(options){
8648 this.get('move').cancel().setOptions(options);
8653 var move = this.retrieve('move');
8655 move = new Fx.Move(this, {link: 'cancel'});
8656 this.store('move', move);
8665 move: function(options){
8666 this.get('move').start(options);
8673 // Begin: Source/Fx/Fx.Scroll.js
8677 script: Fx.Scroll.js
8681 description: Effect to smoothly scroll any element, including the window.
8683 license: MIT-style license
8690 - Core/Element.Event
8691 - Core/Element.Dimensions
8694 provides: [Fx.Scroll]
8701 Fx.Scroll = new Class({
8706 offset: {x: 0, y: 0},
8710 initialize: function(element, options){
8711 this.element = this.subject = document.id(element);
8712 this.parent(options);
8714 if (typeOf(this.element) != 'element') this.element = document.id(this.element.getDocument().body);
8716 if (this.options.wheelStops){
8717 var stopper = this.element,
8718 cancel = this.cancel.pass(false, this);
8719 this.addEvent('start', function(){
8720 stopper.addEvent('mousewheel', cancel);
8722 this.addEvent('complete', function(){
8723 stopper.removeEvent('mousewheel', cancel);
8729 var now = Array.flatten(arguments);
8730 if (Browser.firefox) now = [Math.round(now[0]), Math.round(now[1])]; // not needed anymore in newer firefox versions
8731 this.element.scrollTo(now[0], now[1]);
8735 compute: function(from, to, delta){
8736 return [0, 1].map(function(i){
8737 return Fx.compute(from[i], to[i], delta);
8741 start: function(x, y){
8742 if (!this.check(x, y)) return this;
8743 var scroll = this.element.getScroll();
8744 return this.parent([scroll.x, scroll.y], [x, y]);
8747 calculateScroll: function(x, y){
8748 var element = this.element,
8749 scrollSize = element.getScrollSize(),
8750 scroll = element.getScroll(),
8751 size = element.getSize(),
8752 offset = this.options.offset,
8753 values = {x: x, y: y};
8755 for (var z in values){
8756 if (!values[z] && values[z] !== 0) values[z] = scroll[z];
8757 if (typeOf(values[z]) != 'number') values[z] = scrollSize[z] - size[z];
8758 values[z] += offset[z];
8761 return [values.x, values.y];
8765 return this.start.apply(this, this.calculateScroll(false, 0));
8769 return this.start.apply(this, this.calculateScroll(0, false));
8772 toRight: function(){
8773 return this.start.apply(this, this.calculateScroll('right', false));
8776 toBottom: function(){
8777 return this.start.apply(this, this.calculateScroll(false, 'bottom'));
8780 toElement: function(el, axes){
8781 axes = axes ? Array.from(axes) : ['x', 'y'];
8782 var scroll = isBody(this.element) ? {x: 0, y: 0} : this.element.getScroll();
8783 var position = Object.map(document.id(el).getPosition(this.element), function(value, axis){
8784 return axes.contains(axis) ? value + scroll[axis] : false;
8786 return this.start.apply(this, this.calculateScroll(position.x, position.y));
8789 toElementEdge: function(el, axes, offset){
8790 axes = axes ? Array.from(axes) : ['x', 'y'];
8791 el = document.id(el);
8793 position = el.getPosition(this.element),
8794 size = el.getSize(),
8795 scroll = this.element.getScroll(),
8796 containerSize = this.element.getSize(),
8798 x: position.x + size.x,
8799 y: position.y + size.y
8802 ['x', 'y'].each(function(axis){
8803 if (axes.contains(axis)){
8804 if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
8805 if (position[axis] < scroll[axis]) to[axis] = position[axis];
8807 if (to[axis] == null) to[axis] = scroll[axis];
8808 if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
8811 if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
8815 toElementCenter: function(el, axes, offset){
8816 axes = axes ? Array.from(axes) : ['x', 'y'];
8817 el = document.id(el);
8819 position = el.getPosition(this.element),
8820 size = el.getSize(),
8821 scroll = this.element.getScroll(),
8822 containerSize = this.element.getSize();
8824 ['x', 'y'].each(function(axis){
8825 if (axes.contains(axis)){
8826 to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2;
8828 if (to[axis] == null) to[axis] = scroll[axis];
8829 if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
8832 if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
8839 Fx.Scroll.implement({
8840 scrollToCenter: function(){
8841 return this.toElementCenter.apply(this, arguments);
8843 scrollIntoView: function(){
8844 return this.toElementEdge.apply(this, arguments);
8849 function isBody(element){
8850 return (/^(?:body|html)$/i).test(element.tagName);
8856 // Begin: Source/Class/Class.Refactor.js
8860 script: Class.Refactor.js
8862 name: Class.Refactor
8864 description: Extends a class onto itself with new property, preserving any items attached to the class's namespace.
8866 license: MIT-style license
8875 # Some modules declare themselves dependent on Class.Refactor
8876 provides: [Class.refactor, Class.Refactor]
8881 Class.refactor = function(original, refactors){
8883 Object.each(refactors, function(item, name){
8884 var origin = original.prototype[name];
8885 origin = (origin && origin.$origin) || origin || function(){};
8886 original.implement(name, (typeof item == 'function') ? function(){
8887 var old = this.previous;
8888 this.previous = origin;
8889 var value = item.apply(this, arguments);
8890 this.previous = old;
8900 // Begin: Source/Fx/Fx.Tween.js
8906 description: Formerly Fx.Style, effect to transition any CSS property for an element.
8908 license: MIT-style license.
8912 provides: [Fx.Tween, Element.fade, Element.highlight]
8917 Fx.Tween = new Class({
8921 initialize: function(element, options){
8922 this.element = this.subject = document.id(element);
8923 this.parent(options);
8926 set: function(property, now){
8927 if (arguments.length == 1){
8929 property = this.property || this.options.property;
8931 this.render(this.element, property, now, this.options.unit);
8935 start: function(property, from, to){
8936 if (!this.check(property, from, to)) return this;
8937 var args = Array.flatten(arguments);
8938 this.property = this.options.property || args.shift();
8939 var parsed = this.prepare(this.element, this.property, args);
8940 return this.parent(parsed.from, parsed.to);
8945 Element.Properties.tween = {
8947 set: function(options){
8948 this.get('tween').cancel().setOptions(options);
8953 var tween = this.retrieve('tween');
8955 tween = new Fx.Tween(this, {link: 'cancel'});
8956 this.store('tween', tween);
8965 tween: function(property, from, to){
8966 this.get('tween').start(property, from, to);
8970 fade: function(how){
8971 var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle;
8972 if (args[1] == null) args[1] = 'toggle';
8974 case 'in': method = 'start'; args[1] = 1; break;
8975 case 'out': method = 'start'; args[1] = 0; break;
8976 case 'show': method = 'set'; args[1] = 1; break;
8977 case 'hide': method = 'set'; args[1] = 0; break;
8979 var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1);
8981 args[1] = flag ? 0 : 1;
8982 this.store('fade:flag', !flag);
8985 default: method = 'start';
8987 if (!toggle) this.eliminate('fade:flag');
8988 fade[method].apply(fade, args);
8989 var to = args[args.length - 1];
8990 if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible');
8991 else fade.chain(function(){
8992 this.element.setStyle('visibility', 'hidden');
8998 highlight: function(start, end){
9000 end = this.retrieve('highlight:original', this.getStyle('background-color'));
9001 end = (end == 'transparent') ? '#fff' : end;
9003 var tween = this.get('tween');
9004 tween.start('background-color', start || '#ffff88', end).chain(function(){
9005 this.setStyle('background-color', this.retrieve('highlight:original'));
9014 // Begin: Source/UI/StickyWin.Fx.js
9020 description: Extends StickyWin to create popups that fade in and out.
9022 license: MIT-style license.
9024 requires: [More/Class.Refactor, Core/Fx.Tween, StickyWin]
9026 provides: StickyWin.Fx
9031 StickyWin = Class.refactor(StickyWin, {
9033 //fadeTransition: 'sine:in:out',
9037 hideWin: function(){
9038 if (this.options.fade) this.fade(0);
9039 else this.previous();
9041 showWin: function(){
9042 if (this.options.fade) this.fade(1);
9043 else this.previous();
9046 this.previous(this.options.fade);
9049 this.previous(this.options.fade);
9053 this.win.setStyles({
9058 property: 'opacity',
9059 duration: this.options.fadeDuration
9061 if (this.options.fadeTransition) opts.transition = this.options.fadeTransition;
9062 this.fadeFx = new Fx.Tween(this.win, opts);
9065 this.win.setStyle('display','block');
9068 this.fadeFx.clearChain();
9069 this.fadeFx.start(to).chain(function (){
9071 this.win.setStyle('display', 'none');
9072 this.fireEvent('onClose');
9074 this.fireEvent('onDisplay');
9081 StickyWin.Fx = StickyWin;
9084 // Begin: Source/Types/Array.Extras.js
9088 script: Array.Extras.js
9092 description: Extends the Array native object to include useful methods to work with arrays.
9094 license: MIT-style license
9098 - Sebastian Markbåge
9104 provides: [Array.Extras]
9114 return Math.min.apply(null, this);
9118 return Math.max.apply(null, this);
9121 average: function(){
9122 return this.length ? this.sum() / this.length : 0;
9126 var result = 0, l = this.length;
9128 while (l--) result += this[l];
9134 return [].combine(this);
9137 shuffle: function(){
9138 for (var i = this.length; i && --i;){
9139 var temp = this[i], r = Math.floor(Math.random() * ( i + 1 ));
9146 reduce: function(fn, value){
9147 for (var i = 0, l = this.length; i < l; i++){
9148 if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
9153 reduceRight: function(fn, value){
9154 var i = this.length;
9156 if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
9161 pluck: function(prop){
9162 return this.map(function(item){
9172 // Begin: Source/Request/Request.HTML.js
9178 description: Extends the basic Request Class with additional methods for interacting with HTML responses.
9180 license: MIT-style license.
9182 requires: [Element, Request]
9184 provides: Request.HTML
9189 Request.HTML = new Class({
9199 Accept: 'text/html, application/xml, text/xml, */*'
9203 success: function(text){
9204 var options = this.options, response = this.response;
9206 response.html = text.stripScripts(function(script){
9207 response.javascript = script;
9210 var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
9211 if (match) response.html = match[1];
9212 var temp = new Element('div').set('html', response.html);
9214 response.tree = temp.childNodes;
9215 response.elements = temp.getElements(options.filter || '*');
9217 if (options.filter) response.tree = response.elements;
9218 if (options.update){
9219 var update = document.id(options.update).empty();
9220 if (options.filter) update.adopt(response.elements);
9221 else update.set('html', response.html);
9222 } else if (options.append){
9223 var append = document.id(options.append);
9224 if (options.filter) response.elements.reverse().inject(append);
9225 else append.adopt(temp.getChildren());
9227 if (options.evalScripts) Browser.exec(response.javascript);
9229 this.onSuccess(response.tree, response.elements, response.html, response.javascript);
9234 Element.Properties.load = {
9236 set: function(options){
9237 var load = this.get('load').cancel();
9238 load.setOptions(options);
9243 var load = this.retrieve('load');
9245 load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'});
9246 this.store('load', load);
9256 this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString}));
9263 // Begin: Source/Layout/TabSwapper.js
9269 description: Handles the scripting for a common UI layout; the tabbed box.
9271 license: MIT-Style License
9273 requires: [Core/Element.Event, Core/Fx.Tween, Core/Fx.Morph, Core/Element.Dimensions, More/Element.Shortcuts, More/Element.Measure]
9275 provides: TabSwapper
9279 var TabSwapper = new Class({
9280 Implements: [Options, Events],
9284 // smoothSize: false,
9286 // onActive: function(){},
9287 // onActiveAfterFx: function(){},
9288 // onBackground: function(){}
9289 // cookieName: null,
9290 preventDefault: true,
9291 selectedClass: 'tabSelected',
9292 mouseoverClass: 'tabOver',
9293 deselectedClass: '',
9304 initialize: function(options){
9305 this.setOptions(options);
9306 var prev = this.setup();
9307 if (prev) return prev;
9308 if (this.options.initPanel != null) this.show(this.options.initPanel);
9309 else if (this.options.cookieName && this.recall()) this.show(this.recall().toInt());
9314 var opt = this.options,
9315 sections = $$(opt.sections),
9316 tabs = $$(opt.tabs);
9317 if (tabs[0] && tabs[0].retrieve('tabSwapper')) return tabs[0].retrieve('tabSwapper');
9318 var clickers = $$(opt.clickers);
9319 tabs.each(function(tab, index){
9320 this.addTab(tab, sections[index], clickers[index], index);
9323 addTab: function(tab, section, clicker, index){
9324 tab = document.id(tab); clicker = document.id(clicker); section = document.id(section);
9325 //if the tab is already in the interface, just move it
9326 if (this.tabs.indexOf(tab) >= 0 && tab.retrieve('tabbered')
9327 && this.tabs.indexOf(tab) != index && this.options.rearrangeDOM) {
9328 this.moveTab(this.tabs.indexOf(tab), index);
9331 //if the index isn't specified, put the tab at the end
9332 if (index == null) index = this.tabs.length;
9333 //if this isn't the first item, and there's a tab
9334 //already in the interface at the index 1 less than this
9335 //insert this after that one
9336 if (index > 0 && this.tabs[index-1] && this.options.rearrangeDOM) {
9337 tab.inject(this.tabs[index-1], 'after');
9338 section.inject(this.tabs[index-1].retrieve('section'), 'after');
9340 this.tabs.splice(index, 0, tab);
9341 clicker = clicker || tab;
9344 mouseout: function(){
9345 tab.removeClass(this.options.mouseoverClass);
9347 mouseover: function(){
9348 tab.addClass(this.options.mouseoverClass);
9352 clicker.addEvent('click', function(e){
9353 if (this.options.preventDefault) e.preventDefault();
9357 tab.store('tabbered', true);
9358 tab.store('section', section);
9359 tab.store('clicker', clicker);
9360 this.hideSection(index);
9363 removeTab: function(index){
9364 var now = this.tabs[this.now];
9365 if (this.now == index){
9366 if (index > 0) this.show(index - 1);
9367 else if (index < this.tabs.length) this.show(index + 1);
9369 this.now = this.tabs.indexOf(now);
9372 moveTab: function(from, to){
9373 var tab = this.tabs[from];
9374 var clicker = tab.retrieve('clicker');
9375 var section = tab.retrieve('section');
9377 var toTab = this.tabs[to];
9378 var toClicker = toTab.retrieve('clicker');
9379 var toSection = toTab.retrieve('section');
9381 this.tabs.erase(tab).splice(to, 0, tab);
9383 tab.inject(toTab, 'before');
9384 clicker.inject(toClicker, 'before');
9385 section.inject(toSection, 'before');
9389 if (this.now == null) {
9390 this.tabs.each(function(tab, idx){
9392 this.hideSection(idx);
9395 this.showSection(i).save(i);
9398 save: function(index){
9399 if (this.options.cookieName)
9400 Cookie.write(this.options.cookieName, index, {duration:this.options.cookieDays});
9404 return (this.options.cookieName) ? Cookie.read(this.options.cookieName) : false;
9406 hideSection: function(idx) {
9407 var tab = this.tabs[idx];
9408 if (!tab) return this;
9409 var sect = tab.retrieve('section');
9410 if (!sect) return this;
9411 if (sect.getStyle('display') != 'none') {
9412 this.lastHeight = sect.getSize().y;
9413 sect.setStyle('display', 'none');
9414 tab.swapClass(this.options.selectedClass, this.options.deselectedClass);
9415 this.fireEvent('onBackground', [idx, sect, tab]);
9419 showSection: function(idx) {
9420 var tab = this.tabs[idx];
9421 if (!tab) return this;
9422 var sect = tab.retrieve('section');
9423 if (!sect) return this;
9424 var smoothOk = this.options.smooth && !Browser.ie;
9425 if (this.now != idx) {
9426 if (!tab.retrieve('tabFx'))
9427 tab.store('tabFx', new Fx.Morph(sect, this.options.effectOptions));
9428 var overflow = sect.getStyle('overflow');
9433 if (smoothOk) start.opacity = 0;
9436 effect = {opacity: 1};
9437 } else if (sect.getStyle('opacity').toInt() < 1) {
9438 sect.setStyle('opacity', 1);
9439 if (!this.options.smoothSize) this.fireEvent('onActiveAfterFx', [idx, sect, tab]);
9441 if (this.options.smoothSize) {
9442 var size = sect.getDimensions().height;
9443 if (this.options.maxSize != null && this.options.maxSize < size)
9444 size = this.options.maxSize;
9445 if (!effect) effect = {};
9446 effect.height = size;
9448 if (this.now != null) this.hideSection(this.now);
9449 if (this.options.smoothSize && this.lastHeight) start.height = this.lastHeight;
9450 sect.setStyles(start);
9451 var finish = function(){
9452 this.fireEvent('onActiveAfterFx', [idx, sect, tab]);
9454 height: this.options.maxSize == effect.height ? this.options.maxSize : "auto",
9457 sect.getElements('input, textarea').setStyle('opacity', 1);
9460 tab.retrieve('tabFx').start(effect).chain(finish);
9465 this.fireEvent('onActive', [idx, sect, tab]);
9467 tab.swapClass(this.options.deselectedClass, this.options.selectedClass);
9473 // Begin: Source/Element/Element.Forms.js
9477 script: Element.Forms.js
9481 description: Extends the Element native object to include methods useful in managing inputs.
9483 license: MIT-style license
9493 provides: [Element.Forms]
9501 this.set('value', this.get('value').tidy());
9504 getTextInRange: function(start, end){
9505 return this.get('value').substring(start, end);
9508 getSelectedText: function(){
9509 if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd());
9510 return document.selection.createRange().text;
9513 getSelectedRange: function(){
9514 if (this.selectionStart != null){
9516 start: this.selectionStart,
9517 end: this.selectionEnd
9525 var range = this.getDocument().selection.createRange();
9526 if (!range || range.parentElement() != this) return pos;
9527 var duplicate = range.duplicate();
9529 if (this.type == 'text'){
9530 pos.start = 0 - duplicate.moveStart('character', -100000);
9531 pos.end = pos.start + range.text.length;
9533 var value = this.get('value');
9534 var offset = value.length;
9535 duplicate.moveToElementText(this);
9536 duplicate.setEndPoint('StartToEnd', range);
9537 if (duplicate.text.length) offset -= value.match(/[\n\r]*$/)[0].length;
9538 pos.end = offset - duplicate.text.length;
9539 duplicate.setEndPoint('StartToStart', range);
9540 pos.start = offset - duplicate.text.length;
9545 getSelectionStart: function(){
9546 return this.getSelectedRange().start;
9549 getSelectionEnd: function(){
9550 return this.getSelectedRange().end;
9553 setCaretPosition: function(pos){
9554 if (pos == 'end') pos = this.get('value').length;
9555 this.selectRange(pos, pos);
9559 getCaretPosition: function(){
9560 return this.getSelectedRange().start;
9563 selectRange: function(start, end){
9564 if (this.setSelectionRange){
9566 this.setSelectionRange(start, end);
9568 var value = this.get('value');
9569 var diff = value.substr(start, end - start).replace(/\r/g, '').length;
9570 start = value.substr(0, start).replace(/\r/g, '').length;
9571 var range = this.createTextRange();
9572 range.collapse(true);
9573 range.moveEnd('character', start + diff);
9574 range.moveStart('character', start);
9580 insertAtCursor: function(value, select){
9581 var pos = this.getSelectedRange();
9582 var text = this.get('value');
9583 this.set('value', text.substring(0, pos.start) + value + text.substring(pos.end, text.length));
9584 if (select !== false) this.selectRange(pos.start, pos.start + value.length);
9585 else this.setCaretPosition(pos.start + value.length);
9589 insertAroundCursor: function(options, select){
9590 options = Object.append({
9596 var value = this.getSelectedText() || options.defaultMiddle;
9597 var pos = this.getSelectedRange();
9598 var text = this.get('value');
9600 if (pos.start == pos.end){
9601 this.set('value', text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length));
9602 this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length);
9604 var current = text.substring(pos.start, pos.end);
9605 this.set('value', text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length));
9606 var selStart = pos.start + options.before.length;
9607 if (select !== false) this.selectRange(selStart, selStart + current.length);
9608 else this.setCaretPosition(selStart + text.length);
9616 // Begin: Source/Fx/Fx.Reveal.js
9620 script: Fx.Reveal.js
9624 description: Defines Fx.Reveal, a class that shows and hides elements with a transition.
9626 license: MIT-style license
9633 - /Element.Shortcuts
9636 provides: [Fx.Reveal]
9644 var hideTheseOf = function(object){
9645 var hideThese = object.options.hideInputs;
9646 if (window.OverText){
9647 var otClasses = [null];
9648 OverText.each(function(ot){
9649 otClasses.include('.' + ot.options.labelClass);
9651 if (otClasses) hideThese += otClasses.join(', ');
9653 return (hideThese) ? object.element.getElements(hideThese) : null;
9657 Fx.Reveal = new Class({
9662 onShow: function(thisElement){},
9663 onHide: function(thisElement){},
9664 onComplete: function(thisElement){},
9665 heightOverride: null,
9666 widthOverride: null,*/
9668 styles: ['padding', 'border', 'margin'],
9669 transitionOpacity: !Browser.ie6,
9671 display: function(){
9672 return this.element.get('tag') != 'tr' ? 'block' : 'table-row';
9675 hideInputs: Browser.ie ? 'select, input, textarea, object, embed' : null
9678 dissolve: function(){
9679 if (!this.hiding && !this.showing){
9680 if (this.element.getStyle('display') != 'none'){
9682 this.showing = false;
9684 this.cssText = this.element.style.cssText;
9686 var startStyles = this.element.getComputedSize({
9687 styles: this.options.styles,
9688 mode: this.options.mode
9690 if (this.options.transitionOpacity) startStyles.opacity = this.options.opacity;
9693 Object.each(startStyles, function(style, name){
9694 zero[name] = [style, 0];
9697 this.element.setStyles({
9698 display: Function.from(this.options.display).call(this),
9702 var hideThese = hideTheseOf(this);
9703 if (hideThese) hideThese.setStyle('visibility', 'hidden');
9705 this.$chain.unshift(function(){
9707 this.hiding = false;
9708 this.element.style.cssText = this.cssText;
9709 this.element.setStyle('display', 'none');
9710 if (hideThese) hideThese.setStyle('visibility', 'visible');
9712 this.fireEvent('hide', this.element);
9718 this.callChain.delay(10, this);
9719 this.fireEvent('complete', this.element);
9720 this.fireEvent('hide', this.element);
9722 } else if (this.options.link == 'chain'){
9723 this.chain(this.dissolve.bind(this));
9724 } else if (this.options.link == 'cancel' && !this.hiding){
9732 if (!this.showing && !this.hiding){
9733 if (this.element.getStyle('display') == 'none'){
9734 this.hiding = false;
9735 this.showing = true;
9736 this.hidden = false;
9737 this.cssText = this.element.style.cssText;
9740 this.element.measure(function(){
9741 startStyles = this.element.getComputedSize({
9742 styles: this.options.styles,
9743 mode: this.options.mode
9746 if (this.options.heightOverride != null) startStyles.height = this.options.heightOverride.toInt();
9747 if (this.options.widthOverride != null) startStyles.width = this.options.widthOverride.toInt();
9748 if (this.options.transitionOpacity){
9749 this.element.setStyle('opacity', 0);
9750 startStyles.opacity = this.options.opacity;
9755 display: Function.from(this.options.display).call(this)
9757 Object.each(startStyles, function(style, name){
9760 zero.overflow = 'hidden';
9762 this.element.setStyles(zero);
9764 var hideThese = hideTheseOf(this);
9765 if (hideThese) hideThese.setStyle('visibility', 'hidden');
9767 this.$chain.unshift(function(){
9768 this.element.style.cssText = this.cssText;
9769 this.element.setStyle('display', Function.from(this.options.display).call(this));
9770 if (!this.hidden) this.showing = false;
9771 if (hideThese) hideThese.setStyle('visibility', 'visible');
9773 this.fireEvent('show', this.element);
9776 this.start(startStyles);
9779 this.fireEvent('complete', this.element);
9780 this.fireEvent('show', this.element);
9782 } else if (this.options.link == 'chain'){
9783 this.chain(this.reveal.bind(this));
9784 } else if (this.options.link == 'cancel' && !this.showing){
9792 if (this.element.getStyle('display') == 'none'){
9801 this.parent.apply(this, arguments);
9802 if (this.cssText != null) this.element.style.cssText = this.cssText;
9803 this.hiding = false;
9804 this.showing = false;
9810 Element.Properties.reveal = {
9812 set: function(options){
9813 this.get('reveal').cancel().setOptions(options);
9818 var reveal = this.retrieve('reveal');
9820 reveal = new Fx.Reveal(this);
9821 this.store('reveal', reveal);
9828 Element.Properties.dissolve = Element.Properties.reveal;
9832 reveal: function(options){
9833 this.get('reveal').setOptions(options).reveal();
9837 dissolve: function(options){
9838 this.get('reveal').setOptions(options).dissolve();
9842 nix: function(options){
9843 var params = Array.link(arguments, {destroy: Type.isBoolean, options: Type.isObject});
9844 this.get('reveal').setOptions(options).dissolve().chain(function(){
9845 this[params.destroy ? 'destroy' : 'dispose']();
9851 var params = Array.link(arguments, {duration: Type.isNumber, options: Type.isObject});
9852 var reveal = this.get('reveal').setOptions(params.options);
9853 reveal.reveal().chain(function(){
9856 }).delay(params.duration || 2000);
9865 // Begin: Source/Layout/Collapsible.js
9870 description: Enables a dom element to, when clicked, hide or show (it toggles) another dom element. Kind of an Accordion for one item.
9872 license: MIT-Style License
9874 requires: [Core/Element.Event, More/Fx.Reveal]
9876 provides: Collapsible
9879 var Collapsible = new Class({
9881 initialize: function(clicker, section, options) {
9882 this.clicker = document.id(clicker);
9883 this.section = document.id(section);
9884 this.parent(this.section, options);
9885 this.boundtoggle = this.toggle.bind(this);
9889 this.clicker.addEvent('click', this.boundtoggle);
9892 this.clicker.removeEvent('click', this.boundtoggle);
9895 //legacy, this class originated w/ a typo. nice!
9896 var Collapsable = Collapsible;
9898 // Begin: Source/Utilities/Table.js
9902 description: LUA-Style table implementation.
9903 license: MIT-style license
9906 requires: [Core/Array]
9913 var Table = this.Table = function(){
9919 this.set = function(key, value){
9920 var index = keys.indexOf(key);
9922 var length = keys.length;
9924 values[length] = value;
9927 values[index] = value;
9932 this.get = function(key){
9933 var index = keys.indexOf(key);
9934 return (index == -1) ? null : values[index];
9937 this.erase = function(key){
9938 var index = keys.indexOf(key);
9941 keys.splice(index, 1);
9942 return values.splice(index, 1)[0];
9947 this.each = this.forEach = function(fn, bind){
9948 for (var i = 0, l = this.length; i < l; i++) fn.call(bind, keys[i], values[i], this);
9953 if (this.Type) new Type('Table', Table);
9958 // Begin: Source/Element.Data.js
9962 description: Stores data in HTML5 data properties
9963 provides: [Element.Data]
9964 requires: [Core/Element, Core/JSON]
9965 script: Element.Data.js
9971 JSON.isSecure = function(string){
9972 //this verifies that the string is parsable JSON and not malicious (borrowed from JSON.js in MooTools, which in turn borrowed it from Crockford)
9973 //this version is a little more permissive, as it allows single quoted attributes because forcing the use of double quotes
9974 //is a pain when this stuff is used as HTML properties
9975 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '').replace(/'[^'\\\n\r]*'/g, ''));
9980 sets an HTML5 data property.
9982 name - (string) the data name to store; will be automatically prefixed with 'data-'.
9983 value - (string, number) the value to store.
9985 setData: function(name, value){
9986 return this.set('data-' + name.hyphenate(), value);
9989 getData: function(name, defaultValue){
9990 var value = this.get('data-' + name.hyphenate());
9991 if (value != undefined){
9993 } else if (defaultValue != undefined){
9994 this.setData(name, defaultValue);
9995 return defaultValue;
10001 name - (string) the data name to store; will be automatically prefixed with 'data-'
10002 value - (string, array, or object) if an object or array the object will be JSON encoded; otherwise stored as provided.
10004 setJSONData: function(name, value){
10005 return this.setData(name, JSON.encode(value));
10009 retrieves a property from HTML5 data property you specify
10012 name - (retrieve) the data name to store; will be automatically prefixed with 'data-'
10013 strict - (boolean) if true, will set the JSON.decode's secure flag to true; otherwise the value is still tested but allows single quoted attributes.
10014 defaultValue - (string, array, or object) the value to set if no value is found (see storeData above)
10016 getJSONData: function(name, strict, defaultValue){
10017 var value = this.get('data-' + name);
10018 if (value != undefined){
10019 if (value && JSON.isSecure(value)) {
10020 return JSON.decode(value, strict);
10024 } else if (defaultValue != undefined){
10025 this.setJSONData(name, defaultValue);
10026 return defaultValue;
10034 // Begin: Source/BehaviorAPI.js
10038 description: HTML getters for Behavior's API model.
10039 requires: [Core/Class, /Element.Data]
10040 provides: [BehaviorAPI]
10046 //see Docs/BehaviorAPI.md for documentation of public methods.
10048 var reggy = /[^a-z0-9\-]/gi;
10050 window.BehaviorAPI = new Class({
10055 initialize: function(element, prefix){
10056 this.element = element;
10057 this.prefix = prefix.toLowerCase().replace('.', '-', 'g').replace(reggy, '');
10060 /******************
10062 ******************/
10064 get: function(/* name[, name, name, etc] */){
10065 if (arguments.length > 1) return this._getObj(Array.from(arguments));
10066 return this._getValue(arguments[0]);
10069 getAs: function(/*returnType, name, defaultValue OR {name: returnType, name: returnType, etc}*/){
10070 if (typeOf(arguments[0]) == 'object') return this._getValuesAs.apply(this, arguments);
10071 return this._getValueAs.apply(this, arguments);
10074 require: function(/* name[, name, name, etc] */){
10075 for (var i = 0; i < arguments.length; i++){
10076 if (this._getValue(arguments[i]) == undefined) throw new Error('Could not retrieve ' + this.prefix + '-' + arguments[i] + ' option from element.');
10081 requireAs: function(returnType, name /* OR {name: returnType, name: returnType, etc}*/){
10083 if (typeOf(arguments[0]) == 'object'){
10084 for (var objName in arguments[0]){
10085 val = this._getValueAs(arguments[0][objName], objName);
10086 if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + objName + " option from element.");
10089 val = this._getValueAs(returnType, name);
10090 if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + name + " option from element.");
10095 setDefault: function(name, value /* OR {name: value, name: value, etc }*/){
10096 if (typeOf(arguments[0]) == 'object'){
10097 for (var objName in arguments[0]){
10098 this.setDefault(objName, arguments[0][objName]);
10102 name = name.camelCase();
10103 this.defaults[name] = value;
10104 if (this._getValue(name) == null){
10105 var options = this._getOptions();
10106 options[name] = value;
10111 refreshAPI: function(){
10112 delete this.options;
10113 this.setDefault(this.defaults);
10117 /******************
10119 ******************/
10121 //given an array of names, returns an object of key/value pairs for each name
10122 _getObj: function(names){
10124 names.each(function(name){
10125 var value = this._getValue(name);
10126 if (value !== undefined) obj[name] = value;
10130 //gets the data-behaviorname-options object and parses it as JSON
10131 _getOptions: function(){
10133 if (!this.options){
10134 var options = this.element.getData(this.prefix + '-options', '{}');
10135 if (options && options.substring(0,1) != '{') options = '{' + options + '}';
10136 var isSecure = JSON.isSecure(options);
10137 if (!isSecure) throw new Error('warning, options value for element is not parsable, check your JSON format for quotes, etc.');
10138 this.options = isSecure ? JSON.decode(options) : {};
10139 for (option in this.options) {
10140 this.options[option.camelCase()] = this.options[option];
10144 throw new Error('Could not get options from element; check your syntax. ' + this.prefix + '-options: "' + this.element.getData(this.prefix + '-options', '{}') + '"');
10146 return this.options;
10148 //given a name (string) returns the value for it
10149 _getValue: function(name){
10150 name = name.camelCase();
10151 var options = this._getOptions();
10152 if (!options.hasOwnProperty(name)){
10153 var inline = this.element.getData(this.prefix + '-' + name.hyphenate());
10154 if (inline) options[name] = inline;
10156 return options[name];
10158 //given a Type and a name (string) returns the value for it coerced to that type if possible
10159 //else returns the defaultValue or null
10160 _getValueAs: function(returnType, name, defaultValue){
10161 var value = this._getValue(name);
10162 if (value == null || value == undefined) return defaultValue;
10163 var coerced = this._coerceFromString(returnType, value);
10164 if (coerced == null) throw new Error("Could not retrieve value '" + name + "' as the specified type. Its value is: " + value);
10167 //given an object of name/Type pairs, returns those as an object of name/value (as specified Type) pairs
10168 _getValuesAs: function(obj){
10169 var returnObj = {};
10170 for (var name in obj){
10171 returnObj[name] = this._getValueAs(obj[name], name);
10175 //attempts to run a value through the JSON parser. If the result is not of that type returns null.
10176 _coerceFromString: function(toType, value){
10177 if (typeOf(value) == 'string' && toType != String){
10178 if (JSON.isSecure(value)) value = JSON.decode(value);
10180 if (instanceOf(value, toType)) return value;
10187 // Begin: Source/Behavior.js
10191 description: Auto-instantiates widgets/classes based on parsed, declarative HTML.
10192 requires: [Core/Class.Extras, Core/Element.Event, Core/Selectors, More/Table, /Element.Data, /BehaviorAPI]
10193 provides: [Behavior]
10199 var getLog = function(method){
10201 if (window.console && console[method]){
10202 if(console[method].apply) console[method].apply(console, arguments);
10203 else console[method](Array.from(arguments).join(' '));
10208 var PassMethods = new Class({
10209 //pass a method pointer through to a filter
10210 //by default the methods for add/remove events are passed to the filter
10211 //pointed to this instance of behavior. you could use this to pass along
10212 //other methods to your filters. For example, a method to close a popup
10213 //for filters presented inside popups.
10214 passMethod: function(method, fn){
10215 if (this.API.prototype[method]) throw new Error('Cannot overwrite API method ' + method + ' as it already exists');
10216 this.API.implement(method, fn);
10220 passMethods: function(methods){
10221 for (method in methods) this.passMethod(method, methods[method]);
10227 var spaceOrCommaRegex = /\s*,\s*|\s+/g;
10229 BehaviorAPI.implement({
10230 deprecate: function(deprecated, asJSON){
10233 Object.each(deprecated, function(prop, key){
10234 var value = this.element[ asJSON ? 'getJSONData' : 'getData'](prop);
10235 if (value !== undefined){
10237 values[key] = value;
10240 this.setDefault(values);
10245 this.Behavior = new Class({
10247 Implements: [Options, Events, PassMethods],
10250 //by default, errors thrown by filters are caught; the onError event is fired.
10251 //set this to *true* to NOT catch these errors to allow them to be handled by the browser.
10252 // breakOnErrors: false,
10253 // container: document.body,
10255 //default error behavior when a filter cannot be applied
10256 onError: getLog('error'),
10257 onWarn: getLog('warn'),
10258 enableDeprecation: true,
10259 selector: '[data-behavior]'
10262 initialize: function(options){
10263 this.setOptions(options);
10264 this.API = new Class({ Extends: BehaviorAPI });
10266 getDelegator: this.getDelegator.bind(this),
10267 addEvent: this.addEvent.bind(this),
10268 removeEvent: this.removeEvent.bind(this),
10269 addEvents: this.addEvents.bind(this),
10270 removeEvents: this.removeEvents.bind(this),
10271 fireEvent: this.fireEvent.bind(this),
10272 applyFilters: this.apply.bind(this),
10273 applyFilter: this.applyFilter.bind(this),
10274 getContentElement: this.getContentElement.bind(this),
10275 cleanup: this.cleanup.bind(this),
10276 getContainerSize: function(){
10277 return this.getContentElement().measure(function(){
10278 return this.getSize();
10281 error: function(){ this.fireEvent('error', arguments); }.bind(this),
10283 var msg = Array.join(arguments, ' ');
10284 throw new Error(msg);
10287 this.fireEvent('warn', arguments);
10292 getDelegator: function(){
10293 return this.delegator;
10296 setDelegator: function(delegator){
10297 if (!instanceOf(delegator, Delegator)) throw new Error('Behavior.setDelegator only accepts instances of Delegator.');
10298 this.delegator = delegator;
10302 getContentElement: function(){
10303 return this.options.container || document.body;
10306 //Applies all the behavior filters for an element.
10307 //container - (element) an element to apply the filters registered with this Behavior instance to.
10308 //force - (boolean; optional) passed through to applyFilter (see it for docs)
10309 apply: function(container, force){
10310 this._getElements(container).each(function(element){
10312 element.getBehaviors().each(function(name){
10313 var filter = this.getFilter(name);
10315 this.fireEvent('error', ['There is no filter registered with this name: ', name, element]);
10317 var config = filter.config;
10318 if (config.delay !== undefined){
10319 this.applyFilter.delay(filter.config.delay, this, [element, filter, force]);
10320 } else if(config.delayUntil){
10321 this._delayFilterUntil(element, filter, force);
10322 } else if(config.initializer){
10323 this._customInit(element, filter, force);
10325 plugins.append(this.applyFilter(element, filter, force, true));
10329 plugins.each(function(plugin){ plugin(); });
10334 _getElements: function(container){
10335 if (typeOf(this.options.selector) == 'function') return this.options.selector(container);
10336 else return document.id(container).getElements(this.options.selector);
10339 //delays a filter until the event specified in filter.config.delayUntil is fired on the element
10340 _delayFilterUntil: function(element, filter, force){
10341 var events = filter.config.delayUntil.split(','),
10344 var clear = function(){
10345 events.each(function(event){
10346 element.removeEvent(event, attached[event]);
10348 clear = function(){};
10350 events.each(function(event){
10351 var init = function(e){
10353 if (inited) return;
10355 var setup = filter.setup;
10356 filter.setup = function(element, api, _pluginResult){
10358 return setup.apply(filter, [element, api, _pluginResult]);
10360 this.applyFilter(element, filter, force);
10361 filter.setup = setup;
10363 element.addEvent(event, init);
10364 attached[event] = init;
10368 //runs custom initiliazer defined in filter.config.initializer
10369 _customInit: function(element, filter, force){
10370 var api = new this.API(element, filter.name);
10371 api.runSetup = this.applyFilter.pass([element, filter, force], this);
10372 filter.config.initializer(element, api);
10375 //Applies a specific behavior to a specific element.
10376 //element - the element to which to apply the behavior
10377 //filter - (object) a specific behavior filter, typically one registered with this instance or registered globally.
10378 //force - (boolean; optional) apply the behavior to each element it matches, even if it was previously applied. Defaults to *false*.
10379 //_returnPlugins - (boolean; optional; internal) if true, plugins are not rendered but instead returned as an array of functions
10380 //_pluginTargetResult - (obj; optional internal) if this filter is a plugin for another, this is whatever that target filter returned
10381 // (an instance of a class for example)
10382 applyFilter: function(element, filter, force, _returnPlugins, _pluginTargetResult){
10383 var pluginsToReturn = [];
10384 if (this.options.breakOnErrors){
10385 pluginsToReturn = this._applyFilter.apply(this, arguments);
10388 pluginsToReturn = this._applyFilter.apply(this, arguments);
10390 this.fireEvent('error', ['Could not apply the behavior ' + filter.name, e]);
10393 return _returnPlugins ? pluginsToReturn : this;
10396 //see argument list above for applyFilter
10397 _applyFilter: function(element, filter, force, _returnPlugins, _pluginTargetResult){
10398 var pluginsToReturn = [];
10399 element = document.id(element);
10400 //get the filters already applied to this element
10401 var applied = getApplied(element);
10402 //if this filter is not yet applied to the element, or we are forcing the filter
10403 if (!applied[filter.name] || force){
10404 //if it was previously applied, garbage collect it
10405 if (applied[filter.name]) applied[filter.name].cleanup(element);
10406 var api = new this.API(element, filter.name);
10409 api.markForCleanup = filter.markForCleanup.bind(filter);
10410 api.onCleanup = function(fn){
10411 filter.markForCleanup(element, fn);
10414 if (filter.config.deprecated && this.options.enableDeprecation) api.deprecate(filter.config.deprecated);
10415 if (filter.config.deprecateAsJSON && this.options.enableDeprecation) api.deprecate(filter.config.deprecatedAsJSON, true);
10417 //deal with requirements and defaults
10418 if (filter.config.requireAs){
10419 api.requireAs(filter.config.requireAs);
10420 } else if (filter.config.require){
10421 api.require.apply(api, Array.from(filter.config.require));
10424 if (filter.config.defaults) api.setDefault(filter.config.defaults);
10427 var result = filter.setup(element, api, _pluginTargetResult);
10428 if (filter.config.returns && !instanceOf(result, filter.config.returns)){
10429 throw new Error("Filter " + filter.name + " did not return a valid instance.");
10431 element.store('Behavior Filter result:' + filter.name, result);
10432 //and mark it as having been previously applied
10433 applied[filter.name] = filter;
10434 //apply all the plugins for this filter
10435 var plugins = this.getPlugins(filter.name);
10437 for (var name in plugins){
10438 if (_returnPlugins){
10439 pluginsToReturn.push(this.applyFilter.pass([element, plugins[name], force, null, result], this));
10441 this.applyFilter(element, plugins[name], force, null, result);
10446 return pluginsToReturn;
10449 //given a name, returns a registered behavior
10450 getFilter: function(name){
10451 return this._registered[name] || Behavior.getFilter(name);
10454 getPlugins: function(name){
10455 return this._plugins[name] || Behavior._plugins[name];
10458 //Garbage collects all applied filters for an element and its children.
10459 //element - (*element*) container to cleanup
10460 //ignoreChildren - (*boolean*; optional) if *true* only the element will be cleaned, otherwise the element and all the
10461 // children with filters applied will be cleaned. Defaults to *false*.
10462 cleanup: function(element, ignoreChildren){
10463 element = document.id(element);
10464 var applied = getApplied(element);
10465 for (var filter in applied){
10466 applied[filter].cleanup(element);
10467 element.eliminate('Behavior Filter result:' + filter);
10468 delete applied[filter];
10470 if (!ignoreChildren) this._getElements(element).each(this.cleanup, this);
10476 //Export these for use elsewhere (notabily: Delegator).
10477 Behavior.getLog = getLog;
10478 Behavior.PassMethods = PassMethods;
10481 //Returns the applied behaviors for an element.
10482 var getApplied = function(el){
10483 return el.retrieve('_appliedBehaviors', {});
10486 //Registers a behavior filter.
10487 //name - the name of the filter
10488 //fn - a function that applies the filter to the given element
10489 //overwrite - (boolean) if true, will overwrite existing filter if one exists; defaults to false.
10490 var addFilter = function(name, fn, overwrite){
10491 if (!this._registered[name] || overwrite) this._registered[name] = new Behavior.Filter(name, fn);
10492 else throw new Error('Could not add the Behavior filter "' + name +'" as a previous trigger by that same name exists.');
10495 var addFilters = function(obj, overwrite){
10496 for (var name in obj){
10497 addFilter.apply(this, [name, obj[name], overwrite]);
10501 //Registers a behavior plugin
10502 //filterName - (*string*) the filter (or plugin) this is a plugin for
10503 //name - (*string*) the name of this plugin
10504 //setup - a function that applies the filter to the given element
10505 var addPlugin = function(filterName, name, setup, overwrite){
10506 if (!this._plugins[filterName]) this._plugins[filterName] = {};
10507 if (!this._plugins[filterName][name] || overwrite) this._plugins[filterName][name] = new Behavior.Filter(name, setup);
10508 else throw new Error('Could not add the Behavior filter plugin "' + name +'" as a previous trigger by that same name exists.');
10511 var addPlugins = function(obj, overwrite){
10512 for (var name in obj){
10513 addPlugin.apply(this, [obj[name].fitlerName, obj[name].name, obj[name].setup], overwrite);
10517 var setFilterDefaults = function(name, defaults){
10518 var filter = this.getFilter(name);
10519 if (!filter.config.defaults) filter.config.defaults = {};
10520 Object.append(filter.config.defaults, defaults);
10523 //Add methods to the Behavior namespace for global registration.
10524 Object.append(Behavior, {
10527 addGlobalFilter: addFilter,
10528 addGlobalFilters: addFilters,
10529 addGlobalPlugin: addPlugin,
10530 addGlobalPlugins: addPlugins,
10531 setFilterDefaults: setFilterDefaults,
10532 getFilter: function(name){
10533 return this._registered[name];
10536 //Add methods to the Behavior class for instance registration.
10537 Behavior.implement({
10540 addFilter: addFilter,
10541 addFilters: addFilters,
10542 addPlugin: addPlugin,
10543 addPlugins: addPlugins,
10544 setFilterDefaults: setFilterDefaults
10547 //This class is an actual filter that, given an element, alters it with specific behaviors.
10548 Behavior.Filter = new Class({
10553 require: ['req1', 'req2'],
10565 setup: function(element, API){
10566 var kids = element.getElements(API.get('selector'));
10567 //some validation still has to occur here
10568 if (!kids.length) API.fail('there were no child elements found that match ', API.get('selector'));
10569 if (kids.length < 2) API.warn("there weren't more than 2 kids that match", API.get('selector'));
10570 var fooInstance = new Foo(kids, API.get('opt1', 'opt2'));
10571 API.onCleanup(function(){
10572 fooInstance.destroy();
10574 return fooInstance;
10576 delayUntil: 'mouseover',
10580 initializer: function(element, API){
10581 element.addEvent('mouseover', API.runSetup); //same as specifying event
10583 API.runSetup.delay(100); //same as specifying delay
10584 //or something completely esoteric
10585 var timer = (function(){
10586 if (element.hasClass('foo')){
10587 clearInterval(timer);
10590 }).periodical(100);
10592 API.addEvent('someBehaviorEvent', API.runSetup);
10597 //Pass in an object with the following properties:
10598 //name - the name of this filter
10599 //setup - a function that applies the filter to the given element
10600 initialize: function(name, setup){
10602 if (typeOf(setup) == "function"){
10603 this.setup = setup;
10605 Object.append(this.config, setup);
10606 this.setup = this.config.setup;
10608 this._cleanupFunctions = new Table();
10611 //Stores a garbage collection pointer for a specific element.
10612 //Example: if your filter enhances all the inputs in the container
10613 //you might have a function that removes that enhancement for garbage collection.
10614 //You would mark each input matched with its own cleanup function.
10615 //NOTE: this MUST be the element passed to the filter - the element with this filters
10616 // name in its data-behavior property. I.E.:
10617 //<form data-behavior="FormValidator">
10618 // <input type="text" name="email"/>
10620 //If this filter is FormValidator, you can mark the form for cleanup, but not, for example
10621 //the input. Only elements that match this filter can be marked.
10622 markForCleanup: function(element, fn){
10623 var functions = this._cleanupFunctions.get(element);
10624 if (!functions) functions = [];
10625 functions.include(fn);
10626 this._cleanupFunctions.set(element, functions);
10630 //Garbage collect a specific element.
10631 //NOTE: this should be an element that has a data-behavior property that matches this filter.
10632 cleanup: function(element){
10633 var marks = this._cleanupFunctions.get(element);
10635 marks.each(function(fn){ fn(); });
10636 this._cleanupFunctions.erase(element);
10643 Behavior.elementDataProperty = 'behavior';
10645 Element.implement({
10647 addBehaviorFilter: function(name){
10648 return this.setData(Behavior.elementDataProperty, this.getBehaviors().include(name).join(' '));
10651 removeBehaviorFilter: function(name){
10652 return this.setData(Behavior.elementDataProperty, this.getBehaviors().erase(name).join(' '));
10655 getBehaviors: function(){
10656 var filters = this.getData(Behavior.elementDataProperty);
10657 if (!filters) return [];
10658 return filters.trim().split(spaceOrCommaRegex);
10661 hasBehavior: function(name){
10662 return this.getBehaviors().contains(name);
10665 getBehaviorResult: function(name){
10666 return this.retrieve('Behavior Filter result:' + name);
10675 // Begin: Source/Drag/Drag.js
10683 description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
10685 license: MIT-style license
10695 - Core/Element.Event
10696 - Core/Element.Style
10697 - Core/Element.Dimensions
10705 var Drag = new Class({
10707 Implements: [Events, Options],
10710 onBeforeStart: function(thisElement){},
10711 onStart: function(thisElement, event){},
10712 onSnap: function(thisElement){},
10713 onDrag: function(thisElement, event){},
10714 onCancel: function(thisElement){},
10715 onComplete: function(thisElement, event){},*/
10723 preventDefault: false,
10724 stopPropagation: false,
10725 modifiers: {x: 'left', y: 'top'}
10728 initialize: function(){
10729 var params = Array.link(arguments, {
10730 'options': Type.isObject,
10731 'element': function(obj){
10732 return obj != null;
10736 this.element = document.id(params.element);
10737 this.document = this.element.getDocument();
10738 this.setOptions(params.options || {});
10739 var htype = typeOf(this.options.handle);
10740 this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
10741 this.mouse = {'now': {}, 'pos': {}};
10742 this.value = {'start': {}, 'now': {}};
10744 this.selection = (Browser.ie) ? 'selectstart' : 'mousedown';
10747 if (Browser.ie && !Drag.ondragstartFixed){
10748 document.ondragstart = Function.from(false);
10749 Drag.ondragstartFixed = true;
10753 start: this.start.bind(this),
10754 check: this.check.bind(this),
10755 drag: this.drag.bind(this),
10756 stop: this.stop.bind(this),
10757 cancel: this.cancel.bind(this),
10758 eventStop: Function.from(false)
10763 attach: function(){
10764 this.handles.addEvent('mousedown', this.bound.start);
10768 detach: function(){
10769 this.handles.removeEvent('mousedown', this.bound.start);
10773 start: function(event){
10774 var options = this.options;
10776 if (event.rightClick) return;
10778 if (options.preventDefault) event.preventDefault();
10779 if (options.stopPropagation) event.stopPropagation();
10780 this.mouse.start = event.page;
10782 this.fireEvent('beforeStart', this.element);
10784 var limit = options.limit;
10785 this.limit = {x: [], y: []};
10787 var z, coordinates;
10788 for (z in options.modifiers){
10789 if (!options.modifiers[z]) continue;
10791 var style = this.element.getStyle(options.modifiers[z]);
10793 // Some browsers (IE and Opera) don't always return pixels.
10794 if (style && !style.match(/px$/)){
10795 if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
10796 style = coordinates[options.modifiers[z]];
10799 if (options.style) this.value.now[z] = (style || 0).toInt();
10800 else this.value.now[z] = this.element[options.modifiers[z]];
10802 if (options.invert) this.value.now[z] *= -1;
10804 this.mouse.pos[z] = event.page[z] - this.value.now[z];
10806 if (limit && limit[z]){
10809 var limitZI = limit[z][i];
10810 if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
10815 if (typeOf(this.options.grid) == 'number') this.options.grid = {
10816 x: this.options.grid,
10817 y: this.options.grid
10821 mousemove: this.bound.check,
10822 mouseup: this.bound.cancel
10824 events[this.selection] = this.bound.eventStop;
10825 this.document.addEvents(events);
10828 check: function(event){
10829 if (this.options.preventDefault) event.preventDefault();
10830 var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
10831 if (distance > this.options.snap){
10833 this.document.addEvents({
10834 mousemove: this.bound.drag,
10835 mouseup: this.bound.stop
10837 this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
10841 drag: function(event){
10842 var options = this.options;
10844 if (options.preventDefault) event.preventDefault();
10845 this.mouse.now = event.page;
10847 for (var z in options.modifiers){
10848 if (!options.modifiers[z]) continue;
10849 this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
10851 if (options.invert) this.value.now[z] *= -1;
10853 if (options.limit && this.limit[z]){
10854 if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
10855 this.value.now[z] = this.limit[z][1];
10856 } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
10857 this.value.now[z] = this.limit[z][0];
10861 if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);
10863 if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
10864 else this.element[options.modifiers[z]] = this.value.now[z];
10867 this.fireEvent('drag', [this.element, event]);
10870 cancel: function(event){
10871 this.document.removeEvents({
10872 mousemove: this.bound.check,
10873 mouseup: this.bound.cancel
10876 this.document.removeEvent(this.selection, this.bound.eventStop);
10877 this.fireEvent('cancel', this.element);
10881 stop: function(event){
10883 mousemove: this.bound.drag,
10884 mouseup: this.bound.stop
10886 events[this.selection] = this.bound.eventStop;
10887 this.document.removeEvents(events);
10888 if (event) this.fireEvent('complete', [this.element, event]);
10893 Element.implement({
10895 makeResizable: function(options){
10896 var drag = new Drag(this, Object.merge({
10903 this.store('resizer', drag);
10904 return drag.addEvent('drag', function(){
10905 this.fireEvent('resize', drag);
10912 // Begin: Source/Drag/Drag.Move.js
10916 script: Drag.Move.js
10920 description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
10922 license: MIT-style license
10932 - Core/Element.Dimensions
10935 provides: [Drag.Move]
10940 Drag.Move = new Class({
10945 onEnter: function(thisElement, overed){},
10946 onLeave: function(thisElement, overed){},
10947 onDrop: function(thisElement, overed, event){},*/
10950 precalculate: false,
10951 includeMargins: true,
10952 checkDroppables: true
10955 initialize: function(element, options){
10956 this.parent(element, options);
10957 element = this.element;
10959 this.droppables = $$(this.options.droppables);
10960 this.container = document.id(this.options.container);
10962 if (this.container && typeOf(this.container) != 'element')
10963 this.container = document.id(this.container.getDocument().body);
10965 if (this.options.style){
10966 if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){
10967 var parent = element.getOffsetParent(),
10968 styles = element.getStyles('left', 'top');
10969 if (parent && (styles.left == 'auto' || styles.top == 'auto')){
10970 element.setPosition(element.getPosition(parent));
10974 if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute');
10977 this.addEvent('start', this.checkDroppables, true);
10978 this.overed = null;
10981 start: function(event){
10982 if (this.container) this.options.limit = this.calculateLimit();
10984 if (this.options.precalculate){
10985 this.positions = this.droppables.map(function(el){
10986 return el.getCoordinates();
10990 this.parent(event);
10993 calculateLimit: function(){
10994 var element = this.element,
10995 container = this.container,
10997 offsetParent = document.id(element.getOffsetParent()) || document.body,
10998 containerCoordinates = container.getCoordinates(offsetParent),
10999 elementMargin = {},
11000 elementBorder = {},
11001 containerMargin = {},
11002 containerBorder = {},
11003 offsetParentPadding = {};
11005 ['top', 'right', 'bottom', 'left'].each(function(pad){
11006 elementMargin[pad] = element.getStyle('margin-' + pad).toInt();
11007 elementBorder[pad] = element.getStyle('border-' + pad).toInt();
11008 containerMargin[pad] = container.getStyle('margin-' + pad).toInt();
11009 containerBorder[pad] = container.getStyle('border-' + pad).toInt();
11010 offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
11013 var width = element.offsetWidth + elementMargin.left + elementMargin.right,
11014 height = element.offsetHeight + elementMargin.top + elementMargin.bottom,
11017 right = containerCoordinates.right - containerBorder.right - width,
11018 bottom = containerCoordinates.bottom - containerBorder.bottom - height;
11020 if (this.options.includeMargins){
11021 left += elementMargin.left;
11022 top += elementMargin.top;
11024 right += elementMargin.right;
11025 bottom += elementMargin.bottom;
11028 if (element.getStyle('position') == 'relative'){
11029 var coords = element.getCoordinates(offsetParent);
11030 coords.left -= element.getStyle('left').toInt();
11031 coords.top -= element.getStyle('top').toInt();
11033 left -= coords.left;
11035 if (container.getStyle('position') != 'relative'){
11036 left += containerBorder.left;
11037 top += containerBorder.top;
11039 right += elementMargin.left - coords.left;
11040 bottom += elementMargin.top - coords.top;
11042 if (container != offsetParent){
11043 left += containerMargin.left + offsetParentPadding.left;
11044 top += ((Browser.ie6 || Browser.ie7) ? 0 : containerMargin.top) + offsetParentPadding.top;
11047 left -= elementMargin.left;
11048 top -= elementMargin.top;
11049 if (container != offsetParent){
11050 left += containerCoordinates.left + containerBorder.left;
11051 top += containerCoordinates.top + containerBorder.top;
11061 getDroppableCoordinates: function(element){
11062 var position = element.getCoordinates();
11063 if (element.getStyle('position') == 'fixed'){
11064 var scroll = window.getScroll();
11065 position.left += scroll.x;
11066 position.right += scroll.x;
11067 position.top += scroll.y;
11068 position.bottom += scroll.y;
11073 checkDroppables: function(){
11074 var overed = this.droppables.filter(function(el, i){
11075 el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el);
11076 var now = this.mouse.now;
11077 return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
11078 }, this).getLast();
11080 if (this.overed != overed){
11081 if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
11082 if (overed) this.fireEvent('enter', [this.element, overed]);
11083 this.overed = overed;
11087 drag: function(event){
11088 this.parent(event);
11089 if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
11092 stop: function(event){
11093 this.checkDroppables();
11094 this.fireEvent('drop', [this.element, this.overed, event]);
11095 this.overed = null;
11096 return this.parent(event);
11101 Element.implement({
11103 makeDraggable: function(options){
11104 var drag = new Drag.Move(this, options);
11105 this.store('dragger', drag);
11112 // Begin: Source/UI/StickyWin.Drag.js
11116 name: StickyWin.Drag
11118 description: Implements drag and resize functionaity into StickyWin.Fx. See StickyWin.Fx for the options.
11120 license: MIT-Style License
11122 requires: [More/Class.Refactor, More/Drag.Move, StickyWin]
11124 provides: StickyWin.Drag
11128 StickyWin = Class.refactor(StickyWin, {
11132 onComplete: function(){}
11134 dragHandleSelector: '.dragHandle',
11137 onComplete: function(){}
11139 resizeHandleSelector: ''
11141 setContent: function(){
11142 this.previous.apply(this, arguments);
11143 if (this.options.draggable) this.makeDraggable();
11144 if (this.options.resizable) this.makeResizable();
11147 makeDraggable: function(){
11148 var toggled = this.toggleVisible(true);
11149 if (this.options.useIframeShim) {
11150 this.makeIframeShim();
11151 var onComplete = (this.options.dragOptions.onComplete);
11152 this.options.dragOptions.onComplete = function(){
11154 this.shim.position();
11157 if (this.options.dragHandleSelector) {
11158 var handle = this.win.getElement(this.options.dragHandleSelector);
11160 handle.setStyle('cursor','move');
11161 this.options.dragOptions.handle = handle;
11164 this.win.makeDraggable(this.options.dragOptions);
11165 if (toggled) this.toggleVisible(false);
11167 makeResizable: function(){
11168 var toggled = this.toggleVisible(true);
11169 if (this.options.useIframeShim) {
11170 this.makeIframeShim();
11171 var onComplete = (this.options.resizeOptions.onComplete);
11172 this.options.resizeOptions.onComplete = function(){
11174 this.shim.position();
11177 if (this.options.resizeHandleSelector) {
11178 var handle = this.win.getElement(this.options.resizeHandleSelector);
11179 if (handle) this.options.resizeOptions.handle = this.win.getElement(this.options.resizeHandleSelector);
11181 this.win.makeResizable(this.options.resizeOptions);
11182 if (toggled) this.toggleVisible(false);
11184 toggleVisible: function(show){
11185 if (!this.visible && show == null || show) {
11186 this.win.setStyles({
11191 } else if (show != null && !show){
11192 this.win.setStyles({
11201 StickyWin.Fx = StickyWin;
11203 // Begin: Source/Behaviors/Behavior.StickyWin.js
11206 name: Behavior.StickyWin
11207 description: Behaviors for StickyWin instances.
11208 provides: [Behavior.StickyWin]
11209 requires: [Behavior/Behavior, /StickyWin, /StickyWin.Modal, /StickyWin.Fx, /StickyWin.Drag, More/Array.Extras, More/Object.Extras]
11210 script: Behavior.Tabs.js
11215 Behavior.addGlobalFilters({
11217 'StickyWin.Modal': {
11219 destroyOnClose: true,
11220 closeOnClickOut: true,
11225 returns: StickyWin.Modal,
11226 setup: function(element, api) {
11227 var flex = element.getElement('.flex'),
11228 height = api.getAs(Number, 'height') || (window.getSize().y * .9);
11231 element.measure(function(){
11232 var tmp = new Element('span', { styles: { display: 'none' }}).replaces(flex),
11233 remainder = element.getSize().y;
11234 var padding = ['padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'border-top-width', 'border-bottom-width'].map(function(style){
11235 return flex.getStyle(style).toInt();
11237 flex.setStyle('max-height', height - remainder - padding);
11238 flex.replaces(tmp);
11242 var options = Object.merge({
11245 Object.cleanValues(
11247 closeClassName: String,
11248 pinClassName: String,
11253 relativeTo: String,
11257 destroyOnClose: Boolean,
11258 closeOnClickOut: Boolean,
11259 closeOnEsc: Boolean,
11261 maskOptions: Object,
11262 //draggable options
11263 draggable: Boolean,
11264 dragHandleSelector: String,
11265 resizable: Boolean,
11266 resizeHandleSelector: String
11271 if (options.mask) options.closeOnClickOut = false;
11273 var sw = new StickyWin.Modal(options);
11274 api.onCleanup(function(){
11275 if (!sw.destroyed) sw.destroy();
11277 sw.addEvent('destroy', function(){
11278 api.cleanup(element);
11287 // Begin: Source/Utilities/Color.js
11295 description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
11297 license: MIT-style license
11317 var Color = this.Color = new Type('Color', function(color, type){
11318 if (arguments.length >= 3){
11319 type = 'rgb'; color = Array.slice(arguments, 0, 3);
11320 } else if (typeof color == 'string'){
11321 if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true);
11322 else if (color.match(/hsb/)) color = color.hsbToRgb();
11323 else color = color.hexToRgb(true);
11325 type = type || 'rgb';
11329 color = color.hsbToRgb();
11332 case 'hex': color = color.hexToRgb(true); break;
11334 color.rgb = color.slice(0, 3);
11335 color.hsb = color.hsb || color.rgbToHsb();
11336 color.hex = color.rgbToHex();
11337 return Object.append(color, this);
11343 var colors = Array.slice(arguments);
11344 var alpha = (typeOf(colors.getLast()) == 'number') ? colors.pop() : 50;
11345 var rgb = this.slice();
11346 colors.each(function(color){
11347 color = new Color(color);
11348 for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
11350 return new Color(rgb, 'rgb');
11353 invert: function(){
11354 return new Color(this.map(function(value){
11355 return 255 - value;
11359 setHue: function(value){
11360 return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
11363 setSaturation: function(percent){
11364 return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
11367 setBrightness: function(percent){
11368 return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
11373 this.$RGB = function(r, g, b){
11374 return new Color([r, g, b], 'rgb');
11377 this.$HSB = function(h, s, b){
11378 return new Color([h, s, b], 'hsb');
11381 this.$HEX = function(hex){
11382 return new Color(hex, 'hex');
11387 rgbToHsb: function(){
11392 var max = Math.max(red, green, blue),
11393 min = Math.min(red, green, blue);
11394 var delta = max - min;
11395 var brightness = max / 255,
11396 saturation = (max != 0) ? delta / max : 0;
11397 if (saturation != 0){
11398 var rr = (max - red) / delta;
11399 var gr = (max - green) / delta;
11400 var br = (max - blue) / delta;
11401 if (red == max) hue = br - gr;
11402 else if (green == max) hue = 2 + rr - br;
11403 else hue = 4 + gr - rr;
11405 if (hue < 0) hue++;
11407 return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
11410 hsbToRgb: function(){
11411 var br = Math.round(this[2] / 100 * 255);
11413 return [br, br, br];
11415 var hue = this[0] % 360;
11417 var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
11418 var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
11419 var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
11420 switch (Math.floor(hue / 60)){
11421 case 0: return [br, t, p];
11422 case 1: return [q, br, p];
11423 case 2: return [p, br, t];
11424 case 3: return [p, q, br];
11425 case 4: return [t, p, br];
11426 case 5: return [br, p, q];
11436 rgbToHsb: function(){
11437 var rgb = this.match(/\d{1,3}/g);
11438 return (rgb) ? rgb.rgbToHsb() : null;
11441 hsbToRgb: function(){
11442 var hsb = this.match(/\d{1,3}/g);
11443 return (hsb) ? hsb.hsbToRgb() : null;
11452 // Begin: Source/Class/Events.Pseudos.js
11456 name: Events.Pseudos
11458 description: Adds the functionality to add pseudo events
11460 license: MIT-style license
11465 requires: [Core/Class.Extras, Core/Slick.Parser, More/MooTools.More]
11467 provides: [Events.Pseudos]
11474 Events.Pseudos = function(pseudos, addEvent, removeEvent){
11476 var storeKey = '_monitorEvents:';
11478 var storageOf = function(object){
11480 store: object.store ? function(key, value){
11481 object.store(storeKey + key, value);
11482 } : function(key, value){
11483 (object._monitorEvents || (object._monitorEvents = {}))[key] = value;
11485 retrieve: object.retrieve ? function(key, dflt){
11486 return object.retrieve(storeKey + key, dflt);
11487 } : function(key, dflt){
11488 if (!object._monitorEvents) return dflt;
11489 return object._monitorEvents[key] || dflt;
11494 var splitType = function(type){
11495 if (type.indexOf(':') == -1 || !pseudos) return null;
11497 var parsed = Slick.parse(type).expressions[0][0],
11498 parsedPseudos = parsed.pseudos,
11499 l = parsedPseudos.length,
11503 var pseudo = parsedPseudos[l].key,
11504 listener = pseudos[pseudo];
11505 if (listener != null) splits.push({
11507 value: parsedPseudos[l].value,
11513 return splits.length ? splits : null;
11518 addEvent: function(type, fn, internal){
11519 var split = splitType(type);
11520 if (!split) return addEvent.call(this, type, fn, internal);
11522 var storage = storageOf(this),
11523 events = storage.retrieve(type, []),
11524 eventType = split[0].event,
11525 args = Array.slice(arguments, 2),
11529 split.each(function(item){
11530 var listener = item.listener,
11532 if (listener == false) eventType += ':' + item.pseudo + '(' + item.value + ')';
11533 else stack = function(){
11534 listener.call(self, item, stackFn, arguments, stack);
11538 events.include({type: eventType, event: fn, monitor: stack});
11539 storage.store(type, events);
11541 if (type != eventType) addEvent.apply(this, [type, fn].concat(args));
11542 return addEvent.apply(this, [eventType, stack].concat(args));
11545 removeEvent: function(type, fn){
11546 var split = splitType(type);
11547 if (!split) return removeEvent.call(this, type, fn);
11549 var storage = storageOf(this),
11550 events = storage.retrieve(type);
11551 if (!events) return this;
11553 var args = Array.slice(arguments, 2);
11555 removeEvent.apply(this, [type, fn].concat(args));
11556 events.each(function(monitor, i){
11557 if (!fn || monitor.event == fn) removeEvent.apply(this, [monitor.type, monitor.monitor].concat(args));
11561 storage.store(type, events);
11571 once: function(split, fn, args, monitor){
11572 fn.apply(this, args);
11573 this.removeEvent(split.event, monitor)
11574 .removeEvent(split.original, fn);
11577 throttle: function(split, fn, args){
11578 if (!fn._throttled){
11579 fn.apply(this, args);
11580 fn._throttled = setTimeout(function(){
11581 fn._throttled = false;
11582 }, split.value || 250);
11586 pause: function(split, fn, args){
11587 clearTimeout(fn._pause);
11588 fn._pause = fn.delay(split.value || 250, this, args);
11593 Events.definePseudo = function(key, listener){
11594 pseudos[key] = listener;
11598 Events.lookupPseudo = function(key){
11599 return pseudos[key];
11602 var proto = Events.prototype;
11603 Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent));
11605 ['Request', 'Fx'].each(function(klass){
11606 if (this[klass]) this[klass].implement(Events.prototype);
11612 // Begin: Source/Element/Element.Event.Pseudos.js
11616 name: Element.Event.Pseudos
11618 description: Adds the functionality to add pseudo events for Elements
11620 license: MIT-style license
11625 requires: [Core/Element.Event, Core/Element.Delegation, Events.Pseudos]
11627 provides: [Element.Event.Pseudos, Element.Delegation]
11634 var pseudos = {relay: false},
11635 copyFromEvents = ['once', 'throttle', 'pause'],
11636 count = copyFromEvents.length;
11638 while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]);
11640 DOMEvent.definePseudo = function(key, listener){
11641 pseudos[key] = listener;
11645 var proto = Element.prototype;
11646 [Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent));
11651 // Begin: Source/Element/Element.Event.Pseudos.Keys.js
11655 name: Element.Event.Pseudos.Keys
11657 description: Adds functionality fire events if certain keycombinations are pressed
11659 license: MIT-style license
11664 requires: [Element.Event.Pseudos]
11666 provides: [Element.Event.Pseudos.Keys]
11673 var keysStoreKey = '$moo:keys-pressed',
11674 keysKeyupStoreKey = '$moo:keys-keyup';
11677 DOMEvent.definePseudo('keys', function(split, fn, args){
11679 var event = args[0],
11681 pressed = this.retrieve(keysStoreKey, []);
11683 keys.append(split.value.replace('++', function(){
11684 keys.push('+'); // shift++ and shift+++a
11688 pressed.include(event.key);
11690 if (keys.every(function(key){
11691 return pressed.contains(key);
11692 })) fn.apply(this, args);
11694 this.store(keysStoreKey, pressed);
11696 if (!this.retrieve(keysKeyupStoreKey)){
11697 var keyup = function(event){
11699 pressed = this.retrieve(keysStoreKey, []).erase(event.key);
11700 this.store(keysStoreKey, pressed);
11701 }).delay(0, this); // Fix for IE
11703 this.store(keysKeyupStoreKey, keyup).addEvent('keyup', keyup);
11708 DOMEvent.defineKeys({
11718 '145': 'scrolllock',
11730 }).defineKey(Browser.firefox ? 109 : 189, '-');
11735 // Begin: Source/Interface/Keyboard.js
11739 script: Keyboard.js
11743 description: KeyboardEvents used to intercept events on a class for keyboard and format modifiers in a specific order so as to make alt+shift+c the same as shift+alt+c.
11745 license: MIT-style license
11755 - Core/Element.Event
11756 - Element.Event.Pseudos.Keys
11758 provides: [Keyboard]
11765 var Keyboard = this.Keyboard = new Class({
11769 Implements: [Options],
11772 onActivate: function(){},
11773 onDeactivate: function(){},*/
11774 defaultEventType: 'keydown',
11778 nonParsedEvents: ['activate', 'deactivate', 'onactivate', 'ondeactivate', 'changed', 'onchanged']
11781 initialize: function(options){
11782 if (options && options.manager){
11783 this._manager = options.manager;
11784 delete options.manager;
11786 this.setOptions(options);
11790 addEvent: function(type, fn, internal){
11791 return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn, internal);
11794 removeEvent: function(type, fn){
11795 return this.parent(Keyboard.parse(type, this.options.defaultEventType, this.options.nonParsedEvents), fn);
11798 toggleActive: function(){
11799 return this[this.isActive() ? 'deactivate' : 'activate']();
11802 activate: function(instance){
11804 if (instance.isActive()) return this;
11805 //if we're stealing focus, store the last keyboard to have it so the relinquish command works
11806 if (this._activeKB && instance != this._activeKB){
11807 this.previous = this._activeKB;
11808 this.previous.fireEvent('deactivate');
11810 //if we're enabling a child, assign it so that events are now passed to it
11811 this._activeKB = instance.fireEvent('activate');
11812 Keyboard.manager.fireEvent('changed');
11813 } else if (this._manager){
11814 //else we're enabling ourselves, we must ask our parent to do it for us
11815 this._manager.activate(this);
11820 isActive: function(){
11821 return this._manager ? (this._manager._activeKB == this) : (Keyboard.manager == this);
11824 deactivate: function(instance){
11826 if (instance === this._activeKB){
11827 this._activeKB = null;
11828 instance.fireEvent('deactivate');
11829 Keyboard.manager.fireEvent('changed');
11831 } else if (this._manager){
11832 this._manager.deactivate(this);
11837 relinquish: function(){
11838 if (this.isActive() && this._manager && this._manager.previous) this._manager.activate(this._manager.previous);
11839 else this.deactivate();
11844 manage: function(instance){
11845 if (instance._manager) instance._manager.drop(instance);
11846 this._instances.push(instance);
11847 instance._manager = this;
11848 if (!this._activeKB) this.activate(instance);
11852 drop: function(instance){
11853 instance.relinquish();
11854 this._instances.erase(instance);
11855 if (this._activeKB == instance){
11856 if (this.previous && this._instances.contains(this.previous)) this.activate(this.previous);
11857 else this._activeKB = this._instances[0];
11863 Keyboard.trace(this);
11866 each: function(fn){
11867 Keyboard.each(this, fn);
11876 _disable: function(instance){
11877 if (this._activeKB == instance) this._activeKB = null;
11880 _setup: function(){
11881 this.addEvents(this.options.events);
11882 //if this is the root manager, nothing manages it
11883 if (Keyboard.manager && !this._manager) Keyboard.manager.manage(this);
11884 if (this.options.active) this.activate();
11885 else this.relinquish();
11888 _handle: function(event, type){
11889 //Keyboard.stop(event) prevents key propagation
11890 if (event.preventKeyboardPropagation) return;
11892 var bubbles = !!this._manager;
11893 if (bubbles && this._activeKB){
11894 this._activeKB._handle(event, type);
11895 if (event.preventKeyboardPropagation) return;
11897 this.fireEvent(type, event);
11899 if (!bubbles && this._activeKB) this._activeKB._handle(event, type);
11905 var modifiers = ['shift', 'control', 'alt', 'meta'];
11906 var regex = /^(?:shift|control|ctrl|alt|meta)$/;
11908 Keyboard.parse = function(type, eventType, ignore){
11909 if (ignore && ignore.contains(type.toLowerCase())) return type;
11911 type = type.toLowerCase().replace(/^(keyup|keydown):/, function($0, $1){
11916 if (!parsed[type]){
11917 var key, mods = {};
11918 type.split('+').each(function(part){
11919 if (regex.test(part)) mods[part] = true;
11923 mods.control = mods.control || mods.ctrl; // allow both control and ctrl
11926 modifiers.each(function(mod){
11927 if (mods[mod]) keys.push(mod);
11930 if (key) keys.push(key);
11931 parsed[type] = keys.join('+');
11934 return eventType + ':keys(' + parsed[type] + ')';
11937 Keyboard.each = function(keyboard, fn){
11938 var current = keyboard || Keyboard.manager;
11941 current = current._activeKB;
11945 Keyboard.stop = function(event){
11946 event.preventKeyboardPropagation = true;
11949 Keyboard.manager = new Keyboard({
11953 Keyboard.trace = function(keyboard){
11954 keyboard = keyboard || Keyboard.manager;
11955 var hasConsole = window.console && console.log;
11956 if (hasConsole) console.log('the following items have focus: ');
11957 Keyboard.each(keyboard, function(current){
11958 if (hasConsole) console.log(document.id(current.widget) || current.wiget || current);
11962 var handler = function(event){
11964 modifiers.each(function(mod){
11965 if (event[mod]) keys.push(mod);
11968 if (!regex.test(event.key)) keys.push(event.key);
11969 Keyboard.manager._handle(event, event.type + ':keys(' + keys.join('+') + ')');
11972 document.addEvents({
11980 // Begin: Source/Interface/Keyboard.Extras.js
11984 script: Keyboard.Extras.js
11986 name: Keyboard.Extras
11988 description: Enhances Keyboard by adding the ability to name and describe keyboard shortcuts, and the ability to grab shortcuts by name and bind the shortcut to different keys.
11990 license: MIT-style license
11999 provides: [Keyboard.Extras]
12003 Keyboard.prototype.options.nonParsedEvents.combine(['rebound', 'onrebound']);
12005 Keyboard.implement({
12008 shortcut should be in the format of:
12010 'keys': 'shift+s', // the default to add as an event.
12011 'description': 'blah blah blah', // a brief description of the functionality.
12012 'handler': function(){} // the event handler to run when keys are pressed.
12015 addShortcut: function(name, shortcut){
12016 this._shortcuts = this._shortcuts || [];
12017 this._shortcutIndex = this._shortcutIndex || {};
12019 shortcut.getKeyboard = Function.from(this);
12020 shortcut.name = name;
12021 this._shortcutIndex[name] = shortcut;
12022 this._shortcuts.push(shortcut);
12023 if (shortcut.keys) this.addEvent(shortcut.keys, shortcut.handler);
12027 addShortcuts: function(obj){
12028 for (var name in obj) this.addShortcut(name, obj[name]);
12032 removeShortcut: function(name){
12033 var shortcut = this.getShortcut(name);
12034 if (shortcut && shortcut.keys){
12035 this.removeEvent(shortcut.keys, shortcut.handler);
12036 delete this._shortcutIndex[name];
12037 this._shortcuts.erase(shortcut);
12042 removeShortcuts: function(names){
12043 names.each(this.removeShortcut, this);
12047 getShortcuts: function(){
12048 return this._shortcuts || [];
12051 getShortcut: function(name){
12052 return (this._shortcutIndex || {})[name];
12057 Keyboard.rebind = function(newKeys, shortcuts){
12058 Array.from(shortcuts).each(function(shortcut){
12059 shortcut.getKeyboard().removeEvent(shortcut.keys, shortcut.handler);
12060 shortcut.getKeyboard().addEvent(newKeys, shortcut.handler);
12061 shortcut.keys = newKeys;
12062 shortcut.getKeyboard().fireEvent('rebound');
12067 Keyboard.getActiveShortcuts = function(keyboard){
12068 var activeKBS = [], activeSCS = [];
12069 Keyboard.each(keyboard, [].push.bind(activeKBS));
12070 activeKBS.each(function(kb){ activeSCS.extend(kb.getShortcuts()); });
12074 Keyboard.getShortcut = function(name, keyboard, opts){
12076 var shortcuts = opts.many ? [] : null,
12077 set = opts.many ? function(kb){
12078 var shortcut = kb.getShortcut(name);
12079 if (shortcut) shortcuts.push(shortcut);
12081 if (!shortcuts) shortcuts = kb.getShortcut(name);
12083 Keyboard.each(keyboard, set);
12087 Keyboard.getShortcuts = function(name, keyboard){
12088 return Keyboard.getShortcut(name, keyboard, { many: true });
12092 // Begin: Source/Locale/Locale.js
12100 description: Provides methods for localization.
12102 license: MIT-style license
12113 provides: [Locale, Lang]
12120 var current = null,
12124 var getSet = function(set){
12125 if (instanceOf(set, Locale.Set)) return set;
12126 else return locales[set];
12129 var Locale = this.Locale = {
12131 define: function(locale, set, key, value){
12133 if (instanceOf(locale, Locale.Set)){
12134 name = locale.name;
12135 if (name) locales[name] = locale;
12138 if (!locales[name]) locales[name] = new Locale.Set(name);
12139 locale = locales[name];
12142 if (set) locale.define(set, key, value);
12145 if (set == 'cascade') return Locale.inherit(name, key);
12148 if (!current) current = locale;
12153 use: function(locale){
12154 locale = getSet(locale);
12159 this.fireEvent('change', locale);
12162 this.fireEvent('langChange', locale.name);
12169 getCurrent: function(){
12173 get: function(key, args){
12174 return (current) ? current.get(key, args) : '';
12177 inherit: function(locale, inherits, set){
12178 locale = getSet(locale);
12180 if (locale) locale.inherit(inherits, set);
12185 return Object.keys(locales);
12190 Object.append(Locale, new Events);
12192 Locale.Set = new Class({
12201 initialize: function(name){
12202 this.name = name || '';
12205 define: function(set, key, value){
12206 var defineData = this.sets[set];
12207 if (!defineData) defineData = {};
12210 if (typeOf(key) == 'object') defineData = Object.merge(defineData, key);
12211 else defineData[key] = value;
12213 this.sets[set] = defineData;
12218 get: function(key, args, _base){
12219 var value = Object.getFromPath(this.sets, key);
12220 if (value != null){
12221 var type = typeOf(value);
12222 if (type == 'function') value = value.apply(null, Array.from(args));
12223 else if (type == 'object') value = Object.clone(value);
12227 // get value of inherited locales
12228 var index = key.indexOf('.'),
12229 set = index < 0 ? key : key.substr(0, index),
12230 names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
12231 if (!_base) _base = [];
12233 for (var i = 0, l = names.length; i < l; i++){
12234 if (_base.contains(names[i])) continue;
12235 _base.include(names[i]);
12237 var locale = locales[names[i]];
12238 if (!locale) continue;
12240 value = locale.get(key, args, _base);
12241 if (value != null) return value;
12247 inherit: function(names, set){
12248 names = Array.from(names);
12250 if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
12252 var l = names.length;
12253 while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
12261 var lang = MooTools.lang = {};
12263 Object.append(lang, Locale, {
12264 setLanguage: Locale.use,
12265 getCurrentLanguage: function(){
12266 var current = Locale.getCurrent();
12267 return (current) ? current.name : null;
12270 Locale.define.apply(this, arguments);
12273 get: function(set, key, args){
12274 if (key) set += '.' + key;
12275 return Locale.get(set, args);
12283 // Begin: Source/Locale/Locale.en-US.Number.js
12287 name: Locale.en-US.Number
12289 description: Number messages for US English.
12291 license: MIT-style license
12299 provides: [Locale.en-US.Number]
12304 Locale.define('en-US', 'Number', {
12309 /* Commented properties are the defaults for Number.format
12317 // Negative/Currency/percentage will mixin Number
12337 // Begin: Source/Types/Number.Format.js
12340 name: Number.Format
12341 description: Extends the Number Type object to include a number formatting method.
12342 license: MIT-style license
12343 authors: [Arian Stolwijk]
12344 requires: [Core/Number, Locale.en-US.Number]
12345 # Number.Extras is for compatibility
12346 provides: [Number.Format, Number.Extras]
12353 format: function(options){
12354 // Thanks dojo and YUI for some inspiration
12356 options = options ? Object.clone(options) : {};
12357 var getOption = function(key){
12358 if (options[key] != null) return options[key];
12359 return Locale.get('Number.' + key);
12362 var negative = value < 0,
12363 decimal = getOption('decimal'),
12364 precision = getOption('precision'),
12365 group = getOption('group'),
12366 decimals = getOption('decimals');
12369 var negativeLocale = getOption('negative') || {};
12370 if (negativeLocale.prefix == null && negativeLocale.suffix == null) negativeLocale.prefix = '-';
12371 ['prefix', 'suffix'].each(function(key){
12372 if (negativeLocale[key]) options[key] = getOption(key) + negativeLocale[key];
12378 var prefix = getOption('prefix'),
12379 suffix = getOption('suffix');
12381 if (decimals !== '' && decimals >= 0 && decimals <= 20) value = value.toFixed(decimals);
12382 if (precision >= 1 && precision <= 21) value = (+value).toPrecision(precision);
12386 if (getOption('scientific') === false && value.indexOf('e') > -1){
12387 var match = value.split('e'),
12389 value = match[0].replace('.', '');
12392 zeros = -zeros - 1;
12393 index = match[0].indexOf('.');
12394 if (index > -1) zeros -= index - 1;
12395 while (zeros--) value = '0' + value;
12396 value = '0.' + value;
12398 index = match[0].lastIndexOf('.');
12399 if (index > -1) zeros -= match[0].length - index - 1;
12400 while (zeros--) value += '0';
12404 if (decimal != '.') value = value.replace('.', decimal);
12407 index = value.lastIndexOf(decimal);
12408 index = (index > -1) ? index : value.length;
12409 var newOutput = value.substring(index),
12413 if ((index - i - 1) % 3 == 0 && i != (index - 1)) newOutput = group + newOutput;
12414 newOutput = value.charAt(i) + newOutput;
12420 if (prefix) value = prefix + value;
12421 if (suffix) value += suffix;
12426 formatCurrency: function(decimals){
12427 var locale = Locale.get('Number.currency') || {};
12428 if (locale.scientific == null) locale.scientific = false;
12429 locale.decimals = decimals != null ? decimals
12430 : (locale.decimals == null ? 2 : locale.decimals);
12432 return this.format(locale);
12435 formatPercentage: function(decimals){
12436 var locale = Locale.get('Number.percentage') || {};
12437 if (locale.suffix == null) locale.suffix = '%';
12438 locale.decimals = decimals != null ? decimals
12439 : (locale.decimals == null ? 2 : locale.decimals);
12441 return this.format(locale);
12447 // Begin: Source/Request/Request.Periodical.js
12451 script: Request.Periodical.js
12453 name: Request.Periodical
12455 description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load
12457 license: MIT-style license
12466 provides: [Request.Periodical]
12471 Request.implement({
12474 initialDelay: 5000,
12479 startTimer: function(data){
12480 var fn = function(){
12481 if (!this.running) this.send({data: data});
12483 this.lastDelay = this.options.initialDelay;
12484 this.timer = fn.delay(this.lastDelay, this);
12485 this.completeCheck = function(response){
12486 clearTimeout(this.timer);
12487 this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit);
12488 this.timer = fn.delay(this.lastDelay, this);
12490 return this.addEvent('complete', this.completeCheck);
12493 stopTimer: function(){
12494 clearTimeout(this.timer);
12495 return this.removeEvent('complete', this.completeCheck);
12501 // Begin: Source/Request/Request.JSONP.js
12505 script: Request.JSONP.js
12507 name: Request.JSONP
12509 description: Defines Request.JSONP, a class for cross domain javascript via script injection.
12511 license: MIT-style license
12523 provides: [Request.JSONP]
12528 Request.JSONP = new Class({
12530 Implements: [Chain, Events, Options],
12533 onRequest: function(src, scriptElement){},
12534 onComplete: function(data){},
12535 onSuccess: function(data){},
12536 onCancel: function(){},
12537 onTimeout: function(){},
12538 onError: function(){}, */
12539 onRequest: function(src){
12540 if (this.options.log && window.console && console.log){
12541 console.log('JSONP retrieving script with url:' + src);
12544 onError: function(src){
12545 if (this.options.log && window.console && console.warn){
12546 console.warn('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs');
12550 callbackKey: 'callback',
12551 injectScript: document.head,
12558 initialize: function(options){
12559 this.setOptions(options);
12562 send: function(options){
12563 if (!Request.prototype.check.call(this, options)) return this;
12564 this.running = true;
12566 var type = typeOf(options);
12567 if (type == 'string' || type == 'element') options = {data: options};
12568 options = Object.merge(this.options, options || {});
12570 var data = options.data;
12571 switch (typeOf(data)){
12572 case 'element': data = document.id(data).toQueryString(); break;
12573 case 'object': case 'hash': data = Object.toQueryString(data);
12576 var index = this.index = Request.JSONP.counter++;
12578 var src = options.url +
12579 (options.url.test('\\?') ? '&' :'?') +
12580 (options.callbackKey) +
12581 '=Request.JSONP.request_map.request_'+ index +
12582 (data ? '&' + data : '');
12584 if (src.length > 2083) this.fireEvent('error', src);
12586 Request.JSONP.request_map['request_' + index] = function(){
12587 this.success(arguments, index);
12590 var script = this.getScript(src).inject(options.injectScript);
12591 this.fireEvent('request', [src, script]);
12593 if (options.timeout) this.timeout.delay(options.timeout, this);
12598 getScript: function(src){
12599 if (!this.script) this.script = new Element('script', {
12600 type: 'text/javascript',
12604 return this.script;
12607 success: function(args, index){
12608 if (!this.running) return;
12610 .fireEvent('complete', args).fireEvent('success', args)
12614 cancel: function(){
12615 if (this.running) this.clear().fireEvent('cancel');
12619 isRunning: function(){
12620 return !!this.running;
12624 this.running = false;
12626 this.script.destroy();
12627 this.script = null;
12632 timeout: function(){
12634 this.running = false;
12635 this.fireEvent('timeout', [this.script.get('src'), this.script]).fireEvent('failure').cancel();
12642 Request.JSONP.counter = 0;
12643 Request.JSONP.request_map = {};
12646 // Begin: Source/Types/String.QueryString.js
12650 script: String.QueryString.js
12652 name: String.QueryString
12654 description: Methods for dealing with URI query strings.
12656 license: MIT-style license
12659 - Sebastian Markbåge
12669 provides: [String.QueryString]
12676 parseQueryString: function(decodeKeys, decodeValues){
12677 if (decodeKeys == null) decodeKeys = true;
12678 if (decodeValues == null) decodeValues = true;
12680 var vars = this.split(/[&;]/),
12682 if (!vars.length) return object;
12684 vars.each(function(val){
12685 var index = val.indexOf('=') + 1,
12686 value = index ? val.substr(index) : '',
12687 keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val],
12690 if (decodeValues) value = decodeURIComponent(value);
12691 keys.each(function(key, i){
12692 if (decodeKeys) key = decodeURIComponent(key);
12693 var current = obj[key];
12695 if (i < keys.length - 1) obj = obj[key] = current || {};
12696 else if (typeOf(current) == 'array') current.push(value);
12697 else obj[key] = current != null ? [current, value] : value;
12704 cleanQueryString: function(method){
12705 return this.split('&').filter(function(val){
12706 var index = val.indexOf('='),
12707 key = index < 0 ? '' : val.substr(0, index),
12708 value = val.substr(index + 1);
12710 return method ? method.call(null, key, value) : (value || value === 0);
12717 // Begin: Source/Types/URI.js
12725 description: Provides methods useful in managing the window location and uris.
12727 license: MIT-style license
12730 - Sebastian Markbåge
12736 - Core/Class.Extras
12738 - /String.QueryString
12747 var toString = function(){
12748 return this.get('value');
12751 var URI = this.URI = new Class({
12753 Implements: Options,
12759 regex: /^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
12760 parts: ['scheme', 'user', 'password', 'host', 'port', 'directory', 'file', 'query', 'fragment'],
12761 schemes: {http: 80, https: 443, ftp: 21, rtsp: 554, mms: 1755, file: 0},
12763 initialize: function(uri, options){
12764 this.setOptions(options);
12765 var base = this.options.base || URI.base;
12766 if (!uri) uri = base;
12768 if (uri && uri.parsed) this.parsed = Object.clone(uri.parsed);
12769 else this.set('value', uri.href || uri.toString(), base ? new URI(base) : false);
12772 parse: function(value, base){
12773 var bits = value.match(this.regex);
12774 if (!bits) return false;
12776 return this.merge(bits.associate(this.parts), base);
12779 merge: function(bits, base){
12780 if ((!bits || !bits.scheme) && (!base || !base.scheme)) return false;
12782 this.parts.every(function(part){
12783 if (bits[part]) return false;
12784 bits[part] = base[part] || '';
12788 bits.port = bits.port || this.schemes[bits.scheme.toLowerCase()];
12789 bits.directory = bits.directory ? this.parseDirectory(bits.directory, base ? base.directory : '') : '/';
12793 parseDirectory: function(directory, baseDirectory){
12794 directory = (directory.substr(0, 1) == '/' ? '' : (baseDirectory || '/')) + directory;
12795 if (!directory.test(URI.regs.directoryDot)) return directory;
12797 directory.replace(URI.regs.endSlash, '').split('/').each(function(dir){
12798 if (dir == '..' && result.length > 0) result.pop();
12799 else if (dir != '.') result.push(dir);
12801 return result.join('/') + '/';
12804 combine: function(bits){
12805 return bits.value || bits.scheme + '://' +
12806 (bits.user ? bits.user + (bits.password ? ':' + bits.password : '') + '@' : '') +
12807 (bits.host || '') + (bits.port && bits.port != this.schemes[bits.scheme] ? ':' + bits.port : '') +
12808 (bits.directory || '/') + (bits.file || '') +
12809 (bits.query ? '?' + bits.query : '') +
12810 (bits.fragment ? '#' + bits.fragment : '');
12813 set: function(part, value, base){
12814 if (part == 'value'){
12815 var scheme = value.match(URI.regs.scheme);
12816 if (scheme) scheme = scheme[1];
12817 if (scheme && this.schemes[scheme.toLowerCase()] == null) this.parsed = { scheme: scheme, value: value };
12818 else this.parsed = this.parse(value, (base || this).parsed) || (scheme ? { scheme: scheme, value: value } : { value: value });
12819 } else if (part == 'data'){
12820 this.setData(value);
12822 this.parsed[part] = value;
12827 get: function(part, base){
12829 case 'value': return this.combine(this.parsed, base ? base.parsed : false);
12830 case 'data' : return this.getData();
12832 return this.parsed[part] || '';
12836 document.location.href = this.toString();
12843 getData: function(key, part){
12844 var qs = this.get(part || 'query');
12845 if (!(qs || qs === 0)) return key ? null : {};
12846 var obj = qs.parseQueryString();
12847 return key ? obj[key] : obj;
12850 setData: function(values, merge, part){
12851 if (typeof values == 'string'){
12852 var data = this.getData();
12853 data[arguments[0]] = arguments[1];
12856 values = Object.merge(this.getData(), values);
12858 return this.set(part || 'query', Object.toQueryString(values));
12861 clearData: function(part){
12862 return this.set(part || 'query', '');
12865 toString: toString,
12873 directoryDot: /\.\/|\.$/
12876 URI.base = new URI(Array.from(document.getElements('base[href]', true)).getLast(), {base: document.location});
12880 toURI: function(options){
12881 return new URI(this, options);
12889 // Begin: Source/Types/URI.Relative.js
12893 script: URI.Relative.js
12897 description: Extends the URI class to add methods for computing relative and absolute urls.
12899 license: MIT-style license
12902 - Sebastian Markbåge
12909 provides: [URI.Relative]
12914 URI = Class.refactor(URI, {
12916 combine: function(bits, base){
12917 if (!base || bits.scheme != base.scheme || bits.host != base.host || bits.port != base.port)
12918 return this.previous.apply(this, arguments);
12919 var end = bits.file + (bits.query ? '?' + bits.query : '') + (bits.fragment ? '#' + bits.fragment : '');
12921 if (!base.directory) return (bits.directory || (bits.file ? '' : './')) + end;
12923 var baseDir = base.directory.split('/'),
12924 relDir = bits.directory.split('/'),
12929 for (offset = 0; offset < baseDir.length && offset < relDir.length && baseDir[offset] == relDir[offset]; offset++);
12930 for (i = 0; i < baseDir.length - offset - 1; i++) path += '../';
12931 for (i = offset; i < relDir.length - 1; i++) path += relDir[i] + '/';
12933 return (path || (bits.file ? '' : './')) + end;
12936 toAbsolute: function(base){
12937 base = new URI(base);
12938 if (base) base.set('directory', '').set('file', '');
12939 return this.toRelative(base);
12942 toRelative: function(base){
12943 return this.get('value', new URI(base));
12949 // Begin: Source/Utilities/Cookie.js
12955 description: Class for creating, reading, and deleting browser Cookies.
12957 license: MIT-style license.
12960 - Based on the functions by Peter-Paul Koch (http://quirksmode.org).
12962 requires: [Options, Browser]
12969 var Cookie = new Class({
12971 Implements: Options,
12978 document: document,
12982 initialize: function(key, options){
12984 this.setOptions(options);
12987 write: function(value){
12988 if (this.options.encode) value = encodeURIComponent(value);
12989 if (this.options.domain) value += '; domain=' + this.options.domain;
12990 if (this.options.path) value += '; path=' + this.options.path;
12991 if (this.options.duration){
12992 var date = new Date();
12993 date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
12994 value += '; expires=' + date.toGMTString();
12996 if (this.options.secure) value += '; secure';
12997 this.options.document.cookie = this.key + '=' + value;
13002 var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
13003 return (value) ? decodeURIComponent(value[1]) : null;
13006 dispose: function(){
13007 new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write('');
13013 Cookie.write = function(key, value, options){
13014 return new Cookie(key, options).write(value);
13017 Cookie.read = function(key){
13018 return new Cookie(key).read();
13021 Cookie.dispose = function(key, options){
13022 return new Cookie(key, options).dispose();
13026 // Begin: Source/Locale/Locale.en-US.Date.js
13030 name: Locale.en-US.Date
13032 description: Date messages for US English.
13034 license: MIT-style license
13042 provides: [Locale.en-US.Date]
13047 Locale.define('en-US', 'Date', {
13049 months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
13050 months_abbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
13051 days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
13052 days_abbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
13054 // Culture's date order: MM/DD/YYYY
13055 dateOrder: ['month', 'date', 'year'],
13056 shortDate: '%m/%d/%Y',
13057 shortTime: '%I:%M%p',
13063 ordinal: function(dayOfMonth){
13064 // 1st, 2nd, 3rd, etc.
13065 return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)];
13068 lessThanMinuteAgo: 'less than a minute ago',
13069 minuteAgo: 'about a minute ago',
13070 minutesAgo: '{delta} minutes ago',
13071 hourAgo: 'about an hour ago',
13072 hoursAgo: 'about {delta} hours ago',
13073 dayAgo: '1 day ago',
13074 daysAgo: '{delta} days ago',
13075 weekAgo: '1 week ago',
13076 weeksAgo: '{delta} weeks ago',
13077 monthAgo: '1 month ago',
13078 monthsAgo: '{delta} months ago',
13079 yearAgo: '1 year ago',
13080 yearsAgo: '{delta} years ago',
13082 lessThanMinuteUntil: 'less than a minute from now',
13083 minuteUntil: 'about a minute from now',
13084 minutesUntil: '{delta} minutes from now',
13085 hourUntil: 'about an hour from now',
13086 hoursUntil: 'about {delta} hours from now',
13087 dayUntil: '1 day from now',
13088 daysUntil: '{delta} days from now',
13089 weekUntil: '1 week from now',
13090 weeksUntil: '{delta} weeks from now',
13091 monthUntil: '1 month from now',
13092 monthsUntil: '{delta} months from now',
13093 yearUntil: '1 year from now',
13094 yearsUntil: '{delta} years from now'
13099 // Begin: Source/Types/Date.js
13107 description: Extends the Date native object to include methods useful in managing dates.
13109 license: MIT-style license
13113 - Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
13114 - Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
13115 - Scott Kyle - scott [at] appden.com; http://appden.com
13123 - Locale.en-US.Date
13132 var Date = this.Date;
13134 var DateMethods = Date.Methods = {
13135 ms: 'Milliseconds',
13143 ['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset',
13144 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear',
13145 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds', 'UTCMilliseconds'].each(function(method){
13146 Date.Methods[method.toLowerCase()] = method;
13149 var pad = function(n, digits, string){
13150 if (digits == 1) return n;
13151 return n < Math.pow(10, digits - 1) ? (string || '0') + pad(n, digits - 1, string) : n;
13156 set: function(prop, value){
13157 prop = prop.toLowerCase();
13158 var method = DateMethods[prop] && 'set' + DateMethods[prop];
13159 if (method && this[method]) this[method](value);
13161 }.overloadSetter(),
13163 get: function(prop){
13164 prop = prop.toLowerCase();
13165 var method = DateMethods[prop] && 'get' + DateMethods[prop];
13166 if (method && this[method]) return this[method]();
13168 }.overloadGetter(),
13171 return new Date(this.get('time'));
13174 increment: function(interval, times){
13175 interval = interval || 'day';
13176 times = times != null ? times : 1;
13180 return this.increment('month', times * 12);
13182 var d = this.get('date');
13183 this.set('date', 1).set('mo', this.get('mo') + times);
13184 return this.set('date', d.min(this.get('lastdayofmonth')));
13186 return this.increment('day', times * 7);
13188 return this.set('date', this.get('date') + times);
13191 if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval');
13193 return this.set('time', this.get('time') + times * Date.units[interval]());
13196 decrement: function(interval, times){
13197 return this.increment(interval, -1 * (times != null ? times : 1));
13200 isLeapYear: function(){
13201 return Date.isLeapYear(this.get('year'));
13204 clearTime: function(){
13205 return this.set({hr: 0, min: 0, sec: 0, ms: 0});
13208 diff: function(date, resolution){
13209 if (typeOf(date) == 'string') date = Date.parse(date);
13211 return ((date - this) / Date.units[resolution || 'day'](3, 3)).round(); // non-leap year, 30-day month
13214 getLastDayOfMonth: function(){
13215 return Date.daysInMonth(this.get('mo'), this.get('year'));
13218 getDayOfYear: function(){
13219 return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1)
13220 - Date.UTC(this.get('year'), 0, 1)) / Date.units.day();
13223 setDay: function(day, firstDayOfWeek){
13224 if (firstDayOfWeek == null){
13225 firstDayOfWeek = Date.getMsg('firstDayOfWeek');
13226 if (firstDayOfWeek === '') firstDayOfWeek = 1;
13229 day = (7 + Date.parseDay(day, true) - firstDayOfWeek) % 7;
13230 var currentDay = (7 + this.get('day') - firstDayOfWeek) % 7;
13232 return this.increment('day', day - currentDay);
13235 getWeek: function(firstDayOfWeek){
13236 if (firstDayOfWeek == null){
13237 firstDayOfWeek = Date.getMsg('firstDayOfWeek');
13238 if (firstDayOfWeek === '') firstDayOfWeek = 1;
13242 dayOfWeek = (7 + date.get('day') - firstDayOfWeek) % 7,
13246 if (firstDayOfWeek == 1){
13247 // ISO-8601, week belongs to year that has the most days of the week (i.e. has the thursday of the week)
13248 var month = date.get('month'),
13249 startOfWeek = date.get('date') - dayOfWeek;
13251 if (month == 11 && startOfWeek > 28) return 1; // Week 1 of next year
13253 if (month == 0 && startOfWeek < -2){
13254 // Use a date from last year to determine the week
13255 date = new Date(date).decrement('day', dayOfWeek);
13259 firstDayOfYear = new Date(date.get('year'), 0, 1).get('day') || 7;
13260 if (firstDayOfYear > 4) dividend = -7; // First week of the year is not week 1
13262 // In other cultures the first week of the year is always week 1 and the last week always 53 or 54.
13263 // Days in the same week can have a different weeknumber if the week spreads across two years.
13264 firstDayOfYear = new Date(date.get('year'), 0, 1).get('day');
13267 dividend += date.get('dayofyear');
13268 dividend += 6 - dayOfWeek; // Add days so we calculate the current date's week as a full week
13269 dividend += (7 + firstDayOfYear - firstDayOfWeek) % 7; // Make up for first week of the year not being a full week
13271 return (dividend / 7);
13274 getOrdinal: function(day){
13275 return Date.getMsg('ordinal', day || this.get('date'));
13278 getTimezone: function(){
13279 return this.toString()
13280 .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1')
13281 .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3');
13284 getGMTOffset: function(){
13285 var off = this.get('timezoneOffset');
13286 return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
13289 setAMPM: function(ampm){
13290 ampm = ampm.toUpperCase();
13291 var hr = this.get('hr');
13292 if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12);
13293 else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12);
13297 getAMPM: function(){
13298 return (this.get('hr') < 12) ? 'AM' : 'PM';
13301 parse: function(str){
13302 this.set('time', Date.parse(str));
13306 isValid: function(date){
13307 if (!date) date = this;
13308 return typeOf(date) == 'date' && !isNaN(date.valueOf());
13311 format: function(format){
13312 if (!this.isValid()) return 'invalid date';
13314 if (!format) format = '%x %X';
13315 if (typeof format == 'string') format = formats[format.toLowerCase()] || format;
13316 if (typeof format == 'function') return format(this);
13319 return format.replace(/%([a-z%])/gi,
13322 case 'a': return Date.getMsg('days_abbr')[d.get('day')];
13323 case 'A': return Date.getMsg('days')[d.get('day')];
13324 case 'b': return Date.getMsg('months_abbr')[d.get('month')];
13325 case 'B': return Date.getMsg('months')[d.get('month')];
13326 case 'c': return d.format('%a %b %d %H:%M:%S %Y');
13327 case 'd': return pad(d.get('date'), 2);
13328 case 'e': return pad(d.get('date'), 2, ' ');
13329 case 'H': return pad(d.get('hr'), 2);
13330 case 'I': return pad((d.get('hr') % 12) || 12, 2);
13331 case 'j': return pad(d.get('dayofyear'), 3);
13332 case 'k': return pad(d.get('hr'), 2, ' ');
13333 case 'l': return pad((d.get('hr') % 12) || 12, 2, ' ');
13334 case 'L': return pad(d.get('ms'), 3);
13335 case 'm': return pad((d.get('mo') + 1), 2);
13336 case 'M': return pad(d.get('min'), 2);
13337 case 'o': return d.get('ordinal');
13338 case 'p': return Date.getMsg(d.get('ampm'));
13339 case 's': return Math.round(d / 1000);
13340 case 'S': return pad(d.get('seconds'), 2);
13341 case 'T': return d.format('%H:%M:%S');
13342 case 'U': return pad(d.get('week'), 2);
13343 case 'w': return d.get('day');
13344 case 'x': return d.format(Date.getMsg('shortDate'));
13345 case 'X': return d.format(Date.getMsg('shortTime'));
13346 case 'y': return d.get('year').toString().substr(2);
13347 case 'Y': return d.get('year');
13348 case 'z': return d.get('GMTOffset');
13349 case 'Z': return d.get('Timezone');
13356 toISOString: function(){
13357 return this.format('iso8601');
13361 toJSON: 'toISOString',
13366 // The day and month abbreviations are standardized, so we cannot use simply %a and %b because they will get localized
13367 var rfcDayAbbr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
13368 rfcMonthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
13371 db: '%Y-%m-%d %H:%M:%S',
13372 compact: '%Y%m%dT%H%M%S',
13373 'short': '%d %b %H:%M',
13374 'long': '%B %d, %Y %H:%M',
13375 rfc822: function(date){
13376 return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %Z');
13378 rfc2822: function(date){
13379 return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %z');
13381 iso8601: function(date){
13383 date.getUTCFullYear() + '-' +
13384 pad(date.getUTCMonth() + 1, 2) + '-' +
13385 pad(date.getUTCDate(), 2) + 'T' +
13386 pad(date.getUTCHours(), 2) + ':' +
13387 pad(date.getUTCMinutes(), 2) + ':' +
13388 pad(date.getUTCSeconds(), 2) + '.' +
13389 pad(date.getUTCMilliseconds(), 3) + 'Z'
13394 var parsePatterns = [],
13395 nativeParse = Date.parse;
13397 var parseWord = function(type, word, num){
13399 translated = Date.getMsg(type + 's');
13400 switch (typeOf(word)){
13402 ret = translated[word.get(type)];
13405 ret = translated[word];
13406 if (!ret) throw new Error('Invalid ' + type + ' index: ' + word);
13409 var match = translated.filter(function(name){
13410 return this.test(name);
13411 }, new RegExp('^' + word, 'i'));
13412 if (!match.length) throw new Error('Invalid ' + type + ' string');
13413 if (match.length > 1) throw new Error('Ambiguous ' + type);
13417 return (num) ? translated.indexOf(ret) : ret;
13420 var startCentury = 1900,
13425 getMsg: function(key, args){
13426 return Locale.get('Date.' + key, args);
13430 ms: Function.from(1),
13431 second: Function.from(1000),
13432 minute: Function.from(60000),
13433 hour: Function.from(3600000),
13434 day: Function.from(86400000),
13435 week: Function.from(608400000),
13436 month: function(month, year){
13438 return Date.daysInMonth(month != null ? month : d.get('mo'), year != null ? year : d.get('year')) * 86400000;
13440 year: function(year){
13441 year = year || new Date().get('year');
13442 return Date.isLeapYear(year) ? 31622400000 : 31536000000;
13446 daysInMonth: function(month, year){
13447 return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
13450 isLeapYear: function(year){
13451 return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
13454 parse: function(from){
13455 var t = typeOf(from);
13456 if (t == 'number') return new Date(from);
13457 if (t != 'string') return from;
13458 from = from.clean();
13459 if (!from.length) return null;
13462 parsePatterns.some(function(pattern){
13463 var bits = pattern.re.exec(from);
13464 return (bits) ? (parsed = pattern.handler(bits)) : false;
13467 if (!(parsed && parsed.isValid())){
13468 parsed = new Date(nativeParse(from));
13469 if (!(parsed && parsed.isValid())) parsed = new Date(from.toInt());
13474 parseDay: function(day, num){
13475 return parseWord('day', day, num);
13478 parseMonth: function(month, num){
13479 return parseWord('month', month, num);
13482 parseUTC: function(value){
13483 var localDate = new Date(value);
13484 var utcSeconds = Date.UTC(
13485 localDate.get('year'),
13486 localDate.get('mo'),
13487 localDate.get('date'),
13488 localDate.get('hr'),
13489 localDate.get('min'),
13490 localDate.get('sec'),
13491 localDate.get('ms')
13493 return new Date(utcSeconds);
13496 orderIndex: function(unit){
13497 return Date.getMsg('dateOrder').indexOf(unit) + 1;
13500 defineFormat: function(name, format){
13501 formats[name] = format;
13506 parsePatterns: parsePatterns,
13509 defineParser: function(pattern){
13510 parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern));
13514 defineParsers: function(){
13515 Array.flatten(arguments).each(Date.defineParser);
13519 define2DigitYearStart: function(year){
13520 startYear = year % 100;
13521 startCentury = year - startYear;
13526 defineFormats: Date.defineFormat.overloadSetter()
13529 var regexOf = function(type){
13530 return new RegExp('(?:' + Date.getMsg(type).map(function(name){
13531 return name.substr(0, 3);
13532 }).join('|') + ')[a-z]*');
13535 var replacers = function(key){
13539 case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first
13540 return ((Date.orderIndex('month') == 1) ? '%m[-./]%d' : '%d[-./]%m') + '([-./]%y)?';
13542 return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?';
13548 d: /[0-2]?[0-9]|3[01]/,
13549 H: /[01]?[0-9]|2[0-3]/,
13550 I: /0?[1-9]|1[0-2]/,
13557 z: /Z|[+-]\d{2}(?::?\d{2})?/
13563 var currentLanguage;
13565 var recompile = function(language){
13566 currentLanguage = language;
13568 keys.a = keys.A = regexOf('days');
13569 keys.b = keys.B = regexOf('months');
13571 parsePatterns.each(function(pattern, i){
13572 if (pattern.format) parsePatterns[i] = build(pattern.format);
13576 var build = function(format){
13577 if (!currentLanguage) return {format: format};
13580 var re = (format.source || format) // allow format to be regex
13581 .replace(/%([a-z])/gi,
13583 return replacers($1) || $0;
13585 ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing
13586 .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas
13587 .replace(/%([a-z%])/gi,
13592 return '(' + p.source + ')';
13594 ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff;\&]'); // handle unicode words
13598 re: new RegExp('^' + re + '$', 'i'),
13599 handler: function(bits){
13600 bits = bits.slice(1).associate(parsed);
13601 var date = new Date().clearTime(),
13602 year = bits.y || bits.Y;
13604 if (year != null) handle.call(date, 'y', year); // need to start in the right year
13605 if ('d' in bits) handle.call(date, 'd', 1);
13606 if ('m' in bits || bits.b || bits.B) handle.call(date, 'm', 1);
13608 for (var key in bits) handle.call(date, key, bits[key]);
13614 var handle = function(key, value){
13615 if (!value) return this;
13618 case 'a': case 'A': return this.set('day', Date.parseDay(value, true));
13619 case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true));
13620 case 'd': return this.set('date', value);
13621 case 'H': case 'I': return this.set('hr', value);
13622 case 'm': return this.set('mo', value - 1);
13623 case 'M': return this.set('min', value);
13624 case 'p': return this.set('ampm', value.replace(/\./g, ''));
13625 case 'S': return this.set('sec', value);
13626 case 's': return this.set('ms', ('0.' + value) * 1000);
13627 case 'w': return this.set('day', value);
13628 case 'Y': return this.set('year', value);
13631 if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
13632 return this.set('year', value);
13634 if (value == 'Z') value = '+00';
13635 var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
13636 offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
13637 return this.set('time', this - offset * 60000);
13643 Date.defineParsers(
13644 '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601
13645 '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact
13646 '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM"
13647 '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm"
13648 '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched
13649 '%Y %b( %d%o( %X)?)?', // Same as above with year coming first
13650 '%o %b %d %X %z %Y', // "Thu Oct 22 08:11:23 +0000 2009"
13652 '%H:%M( ?%p)?' // "11:05pm", "11:05 am" and "11:05"
13655 Locale.addEvent('change', function(language){
13656 if (Locale.get('Date')) recompile(language);
13657 }).fireEvent('change', Locale.getCurrent());
13662 // Begin: Source/Types/Date.Extras.js
13666 script: Date.Extras.js
13670 description: Extends the Date native object to include extra methods (on top of those in Date.js).
13672 license: MIT-style license
13681 provides: [Date.Extras]
13688 timeDiffInWords: function(to){
13689 return Date.distanceOfTimeInWords(this, to || new Date);
13692 timeDiff: function(to, separator){
13693 if (to == null) to = new Date;
13694 var delta = ((to - this) / 1000).floor().abs();
13697 durations = [60, 60, 24, 365, 0],
13698 names = ['s', 'm', 'h', 'd', 'y'],
13701 for (var item = 0; item < durations.length; item++){
13702 if (item && !delta) break;
13704 if ((duration = durations[item])){
13705 value = (delta % duration);
13706 delta = (delta / duration).floor();
13708 vals.unshift(value + (names[item] || ''));
13711 return vals.join(separator || ':');
13716 distanceOfTimeInWords: function(from, to){
13717 return Date.getTimePhrase(((to - from) / 1000).toInt());
13720 getTimePhrase: function(delta){
13721 var suffix = (delta < 0) ? 'Until' : 'Ago';
13722 if (delta < 0) delta *= -1;
13734 var msg = 'lessThanMinute';
13736 for (var unit in units){
13737 var interval = units[unit];
13738 if (delta < 1.5 * interval){
13739 if (delta > 0.75 * interval) msg = unit;
13746 delta = delta.round();
13747 return Date.getMsg(msg + suffix, delta).substitute({delta: delta});
13753 // "today", "tomorrow", "yesterday"
13754 re: /^(?:tod|tom|yes)/i,
13755 handler: function(bits){
13756 var d = new Date().clearTime();
13758 case 'tom': return d.increment();
13759 case 'yes': return d.decrement();
13766 // "next Wednesday", "last Thursday"
13767 re: /^(next|last) ([a-z]+)$/i,
13768 handler: function(bits){
13769 var d = new Date().clearTime();
13770 var day = d.getDay();
13771 var newDay = Date.parseDay(bits[2], true);
13772 var addDays = newDay - day;
13773 if (newDay <= day) addDays += 7;
13774 if (bits[1] == 'last') addDays -= 7;
13775 return d.set('date', d.getDate() + addDays);
13779 ).alias('timeAgoInWords', 'timeDiffInWords');
13782 // Begin: Source/Fx/Fx.Elements.js
13786 script: Fx.Elements.js
13790 description: Effect to change any number of CSS properties of any number of Elements.
13792 license: MIT-style license
13801 provides: [Fx.Elements]
13806 Fx.Elements = new Class({
13810 initialize: function(elements, options){
13811 this.elements = this.subject = $$(elements);
13812 this.parent(options);
13815 compute: function(from, to, delta){
13818 for (var i in from){
13819 var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
13820 for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
13826 set: function(now){
13827 for (var i in now){
13828 if (!this.elements[i]) continue;
13831 for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
13837 start: function(obj){
13838 if (!this.check(obj)) return this;
13839 var from = {}, to = {};
13841 for (var i in obj){
13842 if (!this.elements[i]) continue;
13844 var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
13846 for (var p in iProps){
13847 var parsed = this.prepare(this.elements[i], p, iProps[p]);
13848 iFrom[p] = parsed.from;
13849 iTo[p] = parsed.to;
13853 return this.parent(from, to);
13859 // Begin: Source/Fx/Fx.Accordion.js
13863 script: Fx.Accordion.js
13867 description: An Fx.Elements extension which allows you to easily create accordion type controls.
13869 license: MIT-style license
13875 - Core/Element.Event
13878 provides: [Fx.Accordion]
13883 Fx.Accordion = new Class({
13885 Extends: Fx.Elements,
13888 onActive: function(toggler, section){},
13889 onBackground: function(toggler, section){},*/
13890 fixedHeight: false,
13899 initialDisplayFx: true,
13903 initialize: function(){
13904 var defined = function(obj){
13905 return obj != null;
13908 var params = Array.link(arguments, {
13909 'container': Type.isElement, //deprecated
13910 'options': Type.isObject,
13911 'togglers': defined,
13912 'elements': defined
13914 this.parent(params.elements, params.options);
13916 var options = this.options,
13917 togglers = this.togglers = $$(params.togglers);
13919 this.previous = -1;
13920 this.internalChain = new Chain();
13922 if (options.alwaysHide) this.options.link = 'chain';
13924 if (options.show || this.options.show === 0){
13925 options.display = false;
13926 this.previous = options.show;
13929 if (options.start){
13930 options.display = false;
13931 options.show = false;
13934 var effects = this.effects = {};
13936 if (options.opacity) effects.opacity = 'fullOpacity';
13937 if (options.width) effects.width = options.fixedWidth ? 'fullWidth' : 'offsetWidth';
13938 if (options.height) effects.height = options.fixedHeight ? 'fullHeight' : 'scrollHeight';
13940 for (var i = 0, l = togglers.length; i < l; i++) this.addSection(togglers[i], this.elements[i]);
13942 this.elements.each(function(el, i){
13943 if (options.show === i){
13944 this.fireEvent('active', [togglers[i], el]);
13946 for (var fx in effects) el.setStyle(fx, 0);
13950 if (options.display || options.display === 0 || options.initialDisplayFx === false){
13951 this.display(options.display, options.initialDisplayFx);
13954 if (options.fixedHeight !== false) options.resetHeight = false;
13955 this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain));
13958 addSection: function(toggler, element){
13959 toggler = document.id(toggler);
13960 element = document.id(element);
13961 this.togglers.include(toggler);
13962 this.elements.include(element);
13964 var togglers = this.togglers,
13965 options = this.options,
13966 test = togglers.contains(toggler),
13967 idx = togglers.indexOf(toggler),
13968 displayer = this.display.pass(idx, this);
13970 toggler.store('accordion:display', displayer)
13971 .addEvent(options.trigger, displayer);
13973 if (options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
13974 if (options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
13976 element.fullOpacity = 1;
13977 if (options.fixedWidth) element.fullWidth = options.fixedWidth;
13978 if (options.fixedHeight) element.fullHeight = options.fixedHeight;
13979 element.setStyle('overflow', 'hidden');
13981 if (!test) for (var fx in this.effects){
13982 element.setStyle(fx, 0);
13987 removeSection: function(toggler, displayIndex){
13988 var togglers = this.togglers,
13989 idx = togglers.indexOf(toggler),
13990 element = this.elements[idx];
13992 var remover = function(){
13993 togglers.erase(toggler);
13994 this.elements.erase(element);
13995 this.detach(toggler);
13998 if (this.now == idx || displayIndex != null){
13999 this.display(displayIndex != null ? displayIndex : (idx - 1 >= 0 ? idx - 1 : 0)).chain(remover);
14006 detach: function(toggler){
14007 var remove = function(toggler){
14008 toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display'));
14011 if (!toggler) this.togglers.each(remove);
14012 else remove(toggler);
14016 display: function(index, useFx){
14017 if (!this.check(index, useFx)) return this;
14020 elements = this.elements,
14021 options = this.options,
14022 effects = this.effects;
14024 if (useFx == null) useFx = true;
14025 if (typeOf(index) == 'element') index = elements.indexOf(index);
14026 if (index == this.previous && !options.alwaysHide) return this;
14028 if (options.resetHeight){
14029 var prev = elements[this.previous];
14030 if (prev && !this.selfHidden){
14031 for (var fx in effects) prev.setStyle(fx, prev[effects[fx]]);
14035 if ((this.timer && options.link == 'chain') || (index === this.previous && !options.alwaysHide)) return this;
14037 this.previous = index;
14038 this.selfHidden = false;
14040 elements.each(function(el, i){
14045 } else if (options.alwaysHide && ((el.offsetHeight > 0 && options.height) || el.offsetWidth > 0 && options.width)){
14047 this.selfHidden = true;
14049 this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]);
14050 for (var fx in effects) obj[i][fx] = hide ? 0 : el[effects[fx]];
14051 if (!useFx && !hide && options.resetHeight) obj[i].height = 'auto';
14054 this.internalChain.clearChain();
14055 this.internalChain.chain(function(){
14056 if (options.resetHeight && !this.selfHidden){
14057 var el = elements[index];
14058 if (el) el.setStyle('height', 'auto');
14062 return useFx ? this.start(obj) : this.set(obj).internalChain.callChain();
14069 Compatibility with 1.2.0
14071 var Accordion = new Class({
14073 Extends: Fx.Accordion,
14075 initialize: function(){
14076 this.parent.apply(this, arguments);
14077 var params = Array.link(arguments, {'container': Type.isElement});
14078 this.container = params.container;
14081 addSection: function(toggler, element, pos){
14082 toggler = document.id(toggler);
14083 element = document.id(element);
14085 var test = this.togglers.contains(toggler);
14086 var len = this.togglers.length;
14087 if (len && (!test || pos)){
14088 pos = pos != null ? pos : len - 1;
14089 toggler.inject(this.togglers[pos], 'before');
14090 element.inject(toggler, 'after');
14091 } else if (this.container && !test){
14092 toggler.inject(this.container);
14093 element.inject(this.container);
14095 return this.parent.apply(this, arguments);
14102 // Begin: Source/Types/Hash.js
14108 description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
14110 license: MIT-style license.
14123 if (this.Hash) return;
14125 var Hash = this.Hash = new Type('Hash', function(object){
14126 if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
14127 for (var key in object) this[key] = object[key];
14131 this.$H = function(object){
14132 return new Hash(object);
14137 forEach: function(fn, bind){
14138 Object.forEach(this, fn, bind);
14141 getClean: function(){
14143 for (var key in this){
14144 if (this.hasOwnProperty(key)) clean[key] = this[key];
14149 getLength: function(){
14151 for (var key in this){
14152 if (this.hasOwnProperty(key)) length++;
14159 Hash.alias('each', 'forEach');
14163 has: Object.prototype.hasOwnProperty,
14165 keyOf: function(value){
14166 return Object.keyOf(this, value);
14169 hasValue: function(value){
14170 return Object.contains(this, value);
14173 extend: function(properties){
14174 Hash.each(properties || {}, function(value, key){
14175 Hash.set(this, key, value);
14180 combine: function(properties){
14181 Hash.each(properties || {}, function(value, key){
14182 Hash.include(this, key, value);
14187 erase: function(key){
14188 if (this.hasOwnProperty(key)) delete this[key];
14192 get: function(key){
14193 return (this.hasOwnProperty(key)) ? this[key] : null;
14196 set: function(key, value){
14197 if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
14202 Hash.each(this, function(value, key){
14208 include: function(key, value){
14209 if (this[key] == undefined) this[key] = value;
14213 map: function(fn, bind){
14214 return new Hash(Object.map(this, fn, bind));
14217 filter: function(fn, bind){
14218 return new Hash(Object.filter(this, fn, bind));
14221 every: function(fn, bind){
14222 return Object.every(this, fn, bind);
14225 some: function(fn, bind){
14226 return Object.some(this, fn, bind);
14229 getKeys: function(){
14230 return Object.keys(this);
14233 getValues: function(){
14234 return Object.values(this);
14237 toQueryString: function(base){
14238 return Object.toQueryString(this, base);
14243 Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
14250 // Begin: Source/Utilities/Hash.Cookie.js
14254 script: Hash.Cookie.js
14258 description: Class for creating, reading, and deleting Cookies in JSON format.
14260 license: MIT-style license
14272 provides: [Hash.Cookie]
14277 Hash.Cookie = new Class({
14285 initialize: function(name, options){
14286 this.parent(name, options);
14291 var value = JSON.encode(this.hash);
14292 if (!value || value.length > 4096) return false; //cookie would be truncated!
14293 if (value == '{}') this.dispose();
14294 else this.write(value);
14299 this.hash = new Hash(JSON.decode(this.read(), true));
14305 Hash.each(Hash.prototype, function(method, name){
14306 if (typeof method == 'function') Hash.Cookie.implement(name, function(){
14307 var value = method.apply(this.hash, arguments);
14308 if (this.options.autoSave) this.save();
14314 // Begin: Source/Utilities/Assets.js
14322 description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
14324 license: MIT-style license
14330 - Core/Element.Event
14340 javascript: function(source, properties){
14341 if (!properties) properties = {};
14343 var script = new Element('script', {src: source, type: 'text/javascript'}),
14344 doc = properties.document || document,
14345 load = properties.onload || properties.onLoad;
14347 delete properties.onload;
14348 delete properties.onLoad;
14349 delete properties.document;
14352 if (!script.addEventListener){
14353 script.addEvent('readystatechange', function(){
14354 if (['loaded', 'complete'].contains(this.readyState)) load.call(this);
14357 script.addEvent('load', load);
14361 return script.set(properties).inject(doc.head);
14364 css: function(source, properties){
14365 if (!properties) properties = {};
14367 var link = new Element('link', {
14374 var load = properties.onload || properties.onLoad,
14375 doc = properties.document || document;
14377 delete properties.onload;
14378 delete properties.onLoad;
14379 delete properties.document;
14381 if (load) link.addEvent('load', load);
14382 return link.set(properties).inject(doc.head);
14385 image: function(source, properties){
14386 if (!properties) properties = {};
14388 var image = new Image(),
14389 element = document.id(image) || new Element('img');
14391 ['load', 'abort', 'error'].each(function(name){
14392 var type = 'on' + name,
14393 cap = 'on' + name.capitalize(),
14394 event = properties[type] || properties[cap] || function(){};
14396 delete properties[cap];
14397 delete properties[type];
14399 image[type] = function(){
14400 if (!image) return;
14401 if (!element.parentNode){
14402 element.width = image.width;
14403 element.height = image.height;
14405 image = image.onload = image.onabort = image.onerror = null;
14406 event.delay(1, element, element);
14407 element.fireEvent(name, element, 1);
14411 image.src = element.src = source;
14412 if (image && image.complete) image.onload.delay(1);
14413 return element.set(properties);
14416 images: function(sources, options){
14417 sources = Array.from(sources);
14419 var fn = function(){},
14422 options = Object.merge({
14429 return new Elements(sources.map(function(source, index){
14430 return Asset.image(source, Object.append(options.properties, {
14431 onload: function(){
14433 options.onProgress.call(this, counter, index, source);
14434 if (counter == sources.length) options.onComplete();
14436 onerror: function(){
14438 options.onError.call(this, counter, index, source);
14439 if (counter == sources.length) options.onComplete();
14448 // Begin: Source/Interface/Spinner.js
14456 description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon.
14458 license: MIT-style license
14469 provides: [Spinner]
14474 var Spinner = new Class({
14482 'class': 'spinner',
14483 containerPosition: {},
14485 'class': 'spinner-content'
14487 messageContainer: {
14488 'class': 'spinner-msg'
14491 'class': 'spinner-img'
14498 initialize: function(target, options){
14499 this.target = document.id(target) || document.id(document.body);
14500 this.target.store('spinner', this);
14501 this.setOptions(options);
14505 // Add this to events for when noFx is true; parent methods handle hide/show.
14506 var deactivate = function(){ this.active = false; }.bind(this);
14513 render: function(){
14516 this.element.set('id', this.options.id || 'spinner-' + String.uniqueID());
14518 this.content = document.id(this.options.content) || new Element('div', this.options.content);
14519 this.content.inject(this.element);
14521 if (this.options.message){
14522 this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message);
14523 this.msg.inject(this.content);
14526 if (this.options.img){
14527 this.img = document.id(this.options.img) || new Element('div', this.options.img);
14528 this.img.inject(this.content);
14531 this.element.set('tween', this.options.fxOptions);
14534 show: function(noFx){
14535 if (this.active) return this.chain(this.show.bind(this));
14537 this.callChain.delay(20, this);
14541 this.active = true;
14543 return this.parent(noFx);
14546 showMask: function(noFx){
14547 var pos = function(){
14548 this.content.position(Object.merge({
14549 relativeTo: this.element
14550 }, this.options.containerPosition));
14557 if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat();
14558 this.element.setStyles({
14561 }).tween('opacity', this.options.style.opacity);
14563 this.hidden = false;
14564 this.fireEvent('show');
14569 hide: function(noFx){
14570 if (this.active) return this.chain(this.hide.bind(this));
14572 this.callChain.delay(20, this);
14575 this.active = true;
14576 return this.parent(noFx);
14579 hideMask: function(noFx){
14580 if (noFx) return this.parent();
14581 this.element.tween('opacity', 0).get('tween').chain(function(){
14582 this.element.setStyle('display', 'none');
14583 this.hidden = true;
14584 this.fireEvent('hide');
14589 destroy: function(){
14590 this.content.destroy();
14592 this.target.eliminate('spinner');
14597 Request = Class.refactor(Request, {
14601 spinnerOptions: {},
14602 spinnerTarget: false
14605 initialize: function(options){
14606 this._send = this.send;
14607 this.send = function(options){
14608 var spinner = this.getSpinner();
14609 if (spinner) spinner.chain(this._send.pass(options, this)).show();
14610 else this._send(options);
14613 this.previous(options);
14616 getSpinner: function(){
14617 if (!this.spinner){
14618 var update = document.id(this.options.spinnerTarget) || document.id(this.options.update);
14619 if (this.options.useSpinner && update){
14620 update.set('spinner', this.options.spinnerOptions);
14621 var spinner = this.spinner = update.get('spinner');
14622 ['complete', 'exception', 'cancel'].each(function(event){
14623 this.addEvent(event, spinner.hide.bind(spinner));
14627 return this.spinner;
14632 Element.Properties.spinner = {
14634 set: function(options){
14635 var spinner = this.retrieve('spinner');
14636 if (spinner) spinner.destroy();
14637 return this.eliminate('spinner').store('spinner:options', options);
14641 var spinner = this.retrieve('spinner');
14643 spinner = new Spinner(this, this.retrieve('spinner:options'));
14644 this.store('spinner', spinner);
14651 Element.implement({
14653 spin: function(options){
14654 if (options) this.set('spinner', options);
14655 this.get('spinner').show();
14659 unspin: function(){
14660 this.get('spinner').hide();
14667 // Begin: Source/Fx/Fx.Slide.js
14671 script: Fx.Slide.js
14675 description: Effect to slide an element in and out of view.
14677 license: MIT-style license
14684 - Core/Element.Style
14687 provides: [Fx.Slide]
14692 Fx.Slide = new Class({
14699 hideOverflow: true,
14703 initialize: function(element, options){
14704 element = this.element = this.subject = document.id(element);
14705 this.parent(options);
14706 options = this.options;
14708 var wrapper = element.retrieve('wrapper'),
14709 styles = element.getStyles('margin', 'position', 'overflow');
14711 if (options.hideOverflow) styles = Object.append(styles, {overflow: 'hidden'});
14712 if (options.wrapper) wrapper = document.id(options.wrapper).setStyles(styles);
14714 if (!wrapper) wrapper = new Element('div', {
14718 element.store('wrapper', wrapper).setStyle('margin', 0);
14719 if (element.getStyle('overflow') == 'visible') element.setStyle('overflow', 'hidden');
14723 this.wrapper = wrapper;
14725 this.addEvent('complete', function(){
14726 this.open = (wrapper['offset' + this.layout.capitalize()] != 0);
14727 if (this.open && this.options.resetHeight) wrapper.setStyle('height', '');
14731 vertical: function(){
14732 this.margin = 'margin-top';
14733 this.layout = 'height';
14734 this.offset = this.element.offsetHeight;
14737 horizontal: function(){
14738 this.margin = 'margin-left';
14739 this.layout = 'width';
14740 this.offset = this.element.offsetWidth;
14743 set: function(now){
14744 this.element.setStyle(this.margin, now[0]);
14745 this.wrapper.setStyle(this.layout, now[1]);
14749 compute: function(from, to, delta){
14750 return [0, 1].map(function(i){
14751 return Fx.compute(from[i], to[i], delta);
14755 start: function(how, mode){
14756 if (!this.check(how, mode)) return this;
14757 this[mode || this.options.mode]();
14759 var margin = this.element.getStyle(this.margin).toInt(),
14760 layout = this.wrapper.getStyle(this.layout).toInt(),
14761 caseIn = [[margin, layout], [0, this.offset]],
14762 caseOut = [[margin, layout], [-this.offset, 0]],
14766 case 'in': start = caseIn; break;
14767 case 'out': start = caseOut; break;
14768 case 'toggle': start = (layout == 0) ? caseIn : caseOut;
14770 return this.parent(start[0], start[1]);
14773 slideIn: function(mode){
14774 return this.start('in', mode);
14777 slideOut: function(mode){
14778 return this.start('out', mode);
14781 hide: function(mode){
14782 this[mode || this.options.mode]();
14784 return this.set([-this.offset, 0]);
14787 show: function(mode){
14788 this[mode || this.options.mode]();
14790 return this.set([0, this.offset]);
14793 toggle: function(mode){
14794 return this.start('toggle', mode);
14799 Element.Properties.slide = {
14801 set: function(options){
14802 this.get('slide').cancel().setOptions(options);
14807 var slide = this.retrieve('slide');
14809 slide = new Fx.Slide(this, {link: 'cancel'});
14810 this.store('slide', slide);
14817 Element.implement({
14819 slide: function(how, mode){
14820 how = how || 'toggle';
14821 var slide = this.get('slide'), toggle;
14823 case 'hide': slide.hide(mode); break;
14824 case 'show': slide.show(mode); break;
14826 var flag = this.retrieve('slide:flag', slide.open);
14827 slide[flag ? 'slideOut' : 'slideIn'](mode);
14828 this.store('slide:flag', !flag);
14831 default: slide.start(how, mode);
14833 if (!toggle) this.eliminate('slide:flag');
14840 // Begin: Source/UI/StickyWin.UI.Pointy.js
14843 name: StickyWin.UI.Pointy
14845 description: Creates an html holder for in-page popups using a default style - this one including a pointer in the specified direction.
14847 license: MIT-Style License
14849 requires: [More/Element.Shortcuts, More/Element.Position, StickyWin.UI]
14851 provides: [StickyWin.UI.Pointy, StickyWin.UI.pointy]
14854 StickyWin.UI.Pointy = new Class({
14855 Extends: StickyWin.UI,
14870 css: "div.DefaultPointyTip {vertical-align: auto; position: relative;}"+
14871 "div.DefaultPointyTip * {text-align:left !important}"+
14872 "div.DefaultPointyTip .pointyWrapper div.body{background: {%bgColor%}; color: {%fgColor%}; left: 0px; right: 0px !important;padding: 0px 10px !important;margin-left: 0px !important;font-family: verdana;font-size: 11px;line-height: 13px;position: relative;}"+
14873 "div.DefaultPointyTip .pointyWrapper div.top {position: relative;height: 25px; overflow: visible;}"+
14874 "div.DefaultPointyTip .pointyWrapper div.top_ul{background: url({%baseHref%}{%imgset%}_back.png) top left no-repeat;width: 8px;height: 25px; position: absolute; left: 0px;}"+
14875 "div.DefaultPointyTip .pointyWrapper div.top_ur{background: url({%baseHref%}{%imgset%}_back.png) top right !important;margin: 0 0 0 8px !important;height: 25px;position: relative;left: 0px !important;padding: 0;}"+
14876 "div.DefaultPointyTip .pointyWrapper h1.caption{color: {%fgColor%};left: 0px !important;top: 4px !important;clear: none !important;overflow: hidden;font-weight: 700;font-size: 12px !important;position: relative;float: left;height: 22px !important;margin: 0 !important;padding: 0 !important;}"+
14877 "div.DefaultPointyTip .pointyWrapper div.middle, div.DefaultPointyTip .pointyWrapper div.closeBody{background: {%bgColor%};margin: 0 0px 0 0 !important;position: relative;top: 0 !important;}"+
14878 "div.DefaultPointyTip .pointyWrapper div.middle {min-height: 16px; background: {%bgColor%};margin: 0 0px 0 0 !important;position: relative;top: 0 !important;}"+
14879 "div.DefaultPointyTip .pointyWrapper div.bottom {clear: both; width: 100% !important; background: none; height: 6px} "+
14880 "div.DefaultPointyTip .pointyWrapper div.bottom_ll{font-size:1; background: url({%baseHref%}{%imgset%}_back.png) bottom left no-repeat;width: 6px;height: 6px;position: absolute; left: 0px;}"+
14881 "div.DefaultPointyTip .pointyWrapper div.bottom_lr{font-size:1; background: url({%baseHref%}{%imgset%}_back.png) bottom right;height: 6px;margin: 0 0 0 6px !important;position: relative;left: 0 !important;}"+
14882 "div.DefaultPointyTip .pointyWrapper div.noCaption{ height: 6px; overflow: hidden}"+
14883 "div.DefaultPointyTip .pointyWrapper div.closeButton{width:13px; height:13px; background:url({%baseHref%}{%imgset%}_x.png) no-repeat; position: absolute; right: 0px; margin:0px !important; cursor:pointer; z-index: 1; top: 4px;}"+
14884 "div.DefaultPointyTip .pointyWrapper div.pointyDivot {background: url({%divot%}) no-repeat;}",
14885 divot: '{%baseHref%}{%imgset%}_divot.png',
14888 cssId: 'defaultPointyTipStyle',
14889 cssClassName: 'DefaultPointyTip'
14891 initialize: function() {
14892 var args = this.getArgs(arguments);
14893 this.setOptions(args.options);
14894 Object.append(this.options, this.options.themes[this.options.theme]);
14895 this.options.baseHref = this.options.baseHref || Clientcide.assetLocation + '/PointyTip/';
14896 this.options.divot = this.options.divot.substitute(this.options, /\\?\{%([^}]+)%\}/g);
14897 if (Browser.ie) this.options.divot = this.options.divot.replace(/png/g, 'gif');
14898 this.options.css = this.options.css.substitute(this.options, /\\?\{%([^}]+)%\}/g);
14899 if (args.options && args.options.theme) {
14901 var id = Number.random(0, 999999999);
14902 if (!StickyWin.UI.Pointy[id]) {
14903 StickyWin.UI.Pointy[id] = this;
14907 this.options.css = this.options.css.replace(/div\.DefaultPointyTip/g, "div#pointy_"+this.id);
14908 this.options.cssId = "pointyTipStyle_" + this.id;
14910 if (typeOf(this.options.direction) == 'string') {
14917 this.options.direction = map[this.options.direction];
14920 this.parent(args.caption, args.body, this.options);
14921 if (this.id) document.id(this).set('id', "pointy_"+this.id);
14925 var opt = this.options;
14926 this.pointyWrapper = new Element('div', {
14927 'class': 'pointyWrapper'
14928 }).inject(document.id(this));
14929 document.id(this).getChildren().each(function(el){
14930 if (el != this.pointyWrapper) this.pointyWrapper.grab(el);
14933 var w = opt.divotSize;
14935 var left = (opt.width.toInt() - opt.divotSize)/2;
14936 var orient = function(){
14937 switch(opt.direction) {
14938 case 12: case 1: case 11:
14942 case 5: case 6: case 7:
14945 backgroundPosition: '0 -'+h/2+'px'
14947 case 8: case 9: case 10:
14951 case 2: case 3: case 4:
14954 backgroundPosition: '100%'
14958 this.pointer = new Element('div', {
14959 styles: Object.append({
14964 'class': 'pointyDivot pointy_'+opt.direction
14965 }).inject(this.pointyWrapper);
14967 expose: function(){
14968 if (document.id(this).getStyle('display') != 'none' &&
14969 document.body != document.id(this) &&
14970 document.id(document.body).contains(document.id(this))) return function(){};
14971 document.id(this).setStyles({
14972 visibility: 'hidden',
14973 position: 'absolute'
14976 if (document.body != document.id(this) && !document.body.contains(document.id(this))) {
14977 document.id(this).inject(document.body);
14980 return (function(){
14981 if (dispose) document.id(this).dispose();
14982 document.id(this).setStyles({
14983 visibility: 'visible',
14984 position: 'relative'
14988 positionPointer: function(options){
14989 if (!this.pointer) return;
14990 var opt = options || this.options;
14992 var d = opt.direction;
14994 case 12: case 1: case 11:
14996 edge: {x: 'center', y: 'bottom'},
14998 x: d==12?'center':d==1?'right':'left',
15002 x: (d==12?0:d==1?-1:1)*opt.divotSize,
15007 case 2: case 3: case 4:
15009 edge: {x: 'left', y: 'center'},
15012 y: d==3?'center':d==2?'top':'bottom'
15016 y: (d==3?0:d==4?-1:1)*opt.divotSize
15020 case 5: case 6: case 7:
15022 edge: {x: 'center', y: 'top'},
15024 x: d==6?'center':d==5?'right':'left',
15028 x: (d==6?0:d==5?-1:1)*opt.divotSize,
15033 case 8: case 9: case 10:
15035 edge: {x: 'right', y: 'center'},
15038 y: d==9?'center':d==10?'top':'bottom'
15042 y: (d==9?0:d==8?-1:1)*opt.divotSize
15047 var putItBack = this.expose();
15048 this.pointer.position(Object.append({
15049 relativeTo: this.pointyWrapper,
15050 allowNegative: true
15054 setContent: function(a1, a2){
15055 this.parent(a1, a2);
15056 this.top[this.h1?'removeClass':'addClass']('noCaption');
15057 if (Browser.ie) document.id(this).getElements('.bottom_ll, .bottom_lr').setStyle('font-size', 1); //IE6 bullshit
15058 if (this.options.closeButton) this.body.setStyle('margin-right', 6);
15059 this.positionPointer();
15062 makeCaption: function(caption){
15063 this.parent(caption);
15064 if (this.options.width && this.h1) this.h1.setStyle('width', (this.options.width.toInt()-(this.options.closeButton?25:15)));
15068 StickyWin.UI.pointy = function(caption, body, options){
15069 return document.id(new StickyWin.UI.Pointy(caption, body, options));
15071 StickyWin.ui.pointy = StickyWin.UI.pointy;
15073 // Begin: Source/UI/StickyWin.PointyTip.js
15076 name: StickyWin.PointyTip
15078 description: Positions a pointy tip relative to the element you specify.
15080 license: MIT-Style License
15082 requires: StickyWin.UI.Pointy
15084 provides: StickyWin.PointyTip
15088 StickyWin.PointyTip = new Class({
15089 Extends: StickyWin,
15094 initialize: function(){
15095 var args = this.getArgs(arguments);
15096 this.setOptions(args.options);
15097 var popts = this.options.pointyOptions;
15098 var d = popts.direction;
15106 d = map[this.options.point];
15107 if (!d) d = this.options.point;
15108 popts.direction = d;
15110 if (!popts.width) popts.width = this.options.width;
15111 this.pointy = new StickyWin.UI.Pointy(args.caption, args.body, popts);
15112 this.options.content = null;
15113 this.setOptions(args.options, this.getPositionSettings());
15114 this.parent(this.options);
15115 this.win.empty().adopt(document.id(this.pointy));
15116 this.attachHandlers(this.win);
15117 if (this.options.showNow) this.position();
15119 getArgs: function(){
15120 return StickyWin.UI.getArgs.apply(this, arguments);
15122 getPositionSettings: function(){
15123 var s = this.pointy.options.divotSize;
15124 var d = this.options.point;
15125 var offset = this.options.offset || {};
15127 case "left": case 8: case 9: case 10:
15131 y: d==10?'top':d==8?'bottom':'center'
15133 position: {x: 'right', y: 'center'},
15135 x: s + (offset.x || 0),
15139 case "right": case 2: case 3: case 4:
15143 y: (d==2?'top':d==4?'bottom':'center') + (offset.y || 0)
15145 position: {x: 'left', y: 'center'},
15147 x: -s + (offset.x || 0),
15151 case "up": case 11: case 12: case 1:
15154 x: d==11?'left':d==1?'right':'center',
15157 position: { x: 'center', y: 'bottom' },
15159 y: s + (offset.y || 0),
15160 x: (d==11?-s:d==1?s:0) + (offset.x || 0)
15163 case "down": case 5: case 6: case 7:
15166 x: (d==7?'left':d==5?'right':'center') + (offset.x || 0),
15169 position: {x: 'center', y: 'top'},
15171 y: -s + (offset.y || 0),
15172 x: (d==7?-s:d==5?s:0) + (offset.x || 0)
15177 setContent: function() {
15178 var args = this.getArgs(arguments);
15179 this.pointy.setContent(args.caption, args.body);
15180 [this.pointy.h1, this.pointy.body].each(this.attachHandlers, this);
15181 if (this.visible) this.position();
15184 showWin: function(){
15186 this.pointy.positionPointer();
15188 position: function(options){
15189 this.parent(options);
15190 this.pointy.positionPointer();
15192 attachHandlers: function(content) {
15193 if (!content) return;
15194 content.getElements('.'+this.options.closeClassName).addEvent('click', function(){ this.hide(); }.bind(this));
15195 content.getElements('.'+this.options.pinClassName).addEvent('click', function(){ this.togglepin(); }.bind(this));
15199 // Begin: Source/UI/StickyWin.Ajax.js
15203 name: StickyWin.Ajax
15205 description: Adds ajax functionality to all the StickyWin classes.
15207 license: MIT-Style License
15209 requires: [Core/Request, StickyWin, StickyWin.UI, StickyWin.PointyTip]
15211 provides: [StickyWin.Ajax, StickyWin.Modal.Ajax, StickyWin.PointyTip.Ajax]
15216 var SWA = function(extend){
15220 //onUpdate: function(){},
15223 cacheRequest: false,
15231 cacheRequest: false,
15232 handleResponse: function(response){
15233 if(this.options.cacheRequest) {
15234 this.element.store(this.Request.options.url, response);
15236 var responseScript = "";
15237 this.Request.response.text.stripScripts(function(script){ responseScript += script; });
15238 if (this.options.wrapWithUi) response = StickyWin.ui(this.options.caption, response, this.options.uiOptions);
15239 this.setContent(response);
15241 if (this.evalScripts) Browser.exec(responseScript);
15242 this.fireEvent('update');
15245 initialize: function(options){
15247 if (options && options.showNow) {
15249 options.showNow = false;
15251 this.parent(options);
15252 this.evalScripts = this.options.requestOptions.evalScripts;
15253 this.options.requestOptions.evalScripts = false;
15254 this.createRequest();
15255 if (showNow) this.update();
15257 createRequest: function(){
15258 this.Request = new Request(this.options.requestOptions).addEvent('onSuccess',
15259 this.options.handleResponse.bind(this));
15261 update: function(url, options){
15262 this.Request.options.url = url || options.url;
15263 var cachedResponse;
15264 if(this.options.cacheRequest) {
15265 cachedResponse = this.element.retrieve(url);
15267 if(!cachedResponse) {
15268 this.Request.setOptions(options).send({url: url||this.options.url});
15271 this.Request.fireEvent('onSuccess', cachedResponse);
15277 try { StickyWin.Ajax = new Class(SWA(StickyWin)); } catch(e){}
15278 try { StickyWin.Modal.Ajax = new Class(SWA(StickyWin.Modal)); } catch(e){}
15279 try { StickyWin.PointyTip.Ajax = new Class(SWA(StickyWin.PointyTip)); } catch(e){}
15282 // Begin: Source/Layout/MultipleOpenAccordion.js
15285 name: MultipleOpenAccordion
15287 description: Creates a Mootools Fx.Accordion that allows the user to open more than one element.
15289 license: MIT-Style License
15291 requires: [Core/Element.Event, More/Fx.Reveal]
15293 provides: MultipleOpenAccordion
15297 var MultipleOpenAccordion = new Class({
15298 Implements: [Options, Events, Chain],
15303 firstElementsOpen: [0],
15309 //onActive: function(){},
15310 //onBackground: function(){}
15314 initialize: function(options){
15315 var args = Array.link(arguments, {options: Type.isObject, elements: Type.isElements});
15316 this.setOptions(args.options);
15317 elements = $$(this.options.elements);
15318 $$(this.options.togglers).each(function(toggler, idx){
15319 this.addSection(toggler, elements[idx], idx);
15321 if (this.togglers.length) {
15322 if (this.options.openAll) this.showAll();
15323 else this.toggleSections(this.options.firstElementsOpen, false, true);
15325 this.openSections = this.showSections.bind(this);
15326 this.closeSections = this.hideSections.bind(this);
15328 addSection: function(toggler, element){
15329 toggler = document.id(toggler);
15330 element = document.id(element);
15331 var test = this.togglers.contains(toggler);
15332 var len = this.togglers.length;
15333 this.togglers.include(toggler);
15334 this.elements.include(element);
15335 var idx = this.togglers.indexOf(toggler);
15336 var displayer = this.toggleSection.bind(this, idx);
15337 toggler.addEvent('click', displayer).store('multipleOpenAccordion:display', displayer);
15339 if (this.options.height && this.options.width) mode = "both";
15340 else mode = (this.options.height)?"vertical":"horizontal";
15341 element.store('moa:reveal', new Fx.Reveal(element, {
15342 transitionOpacity: this.options.opacity,
15344 heightOverride: this.options.fixedHeight,
15345 widthOverride: this.options.fixedWidth
15349 removeSection: function(toggler) {
15350 var idx = this.togglers.indexOf(toggler);
15351 var element = this.elements[idx];
15352 element.dissolve();
15353 this.togglers.erase(toggler);
15354 this.elements.erase(element);
15355 this.detach(toggler);
15358 detach: function(toggler){
15359 var remove = function(toggler) {
15360 toggler.removeEvent(this.options.trigger, toggler.retrieve('multipleOpenAccordion:display'));
15362 if (!toggler) this.togglers.each(remove);
15363 else remove(toggler);
15366 onComplete: function(idx, callChain){
15367 this.fireEvent(this.elements[idx].isDisplayed()?'onActive':'onBackground', [this.togglers[idx], this.elements[idx]]);
15371 showSection: function(idx, useFx){
15372 this.toggleSection(idx, useFx, true);
15374 hideSection: function(idx, useFx){
15375 this.toggleSection(idx, useFx, false);
15377 toggleSection: function(idx, useFx, show, callChain){
15378 var method = show?'reveal':show != null?'dissolve':'toggle';
15379 callChain = [callChain, true].pick();
15380 var el = this.elements[idx];
15381 if (useFx != null ? useFx : true) {
15382 el.retrieve('moa:reveal')[method]().chain(
15383 this.onComplete.bind(this, idx, callChain)
15386 if (method == "toggle") el.toggle();
15387 else el[method == "reveal"?'show':'hide']();
15388 this.onComplete(idx, callChain);
15392 toggleAll: function(useFx, show){
15393 var method = show?'reveal':(show!=null)?'disolve':'toggle';
15394 var last = this.elements.getLast();
15395 this.elements.each(function(el, idx){
15396 this.toggleSection(idx, useFx, show, el == last);
15400 toggleSections: function(sections, useFx, show) {
15401 last = sections.getLast();
15402 this.elements.each(function(el,idx){
15403 this.toggleSection(idx, useFx, sections.contains(idx)?show:!show, idx == last);
15407 showSections: function(sections, useFx){
15408 sections.each(function(i){
15409 this.showSection(i, useFx);
15412 hideSections: function(sections, useFx){
15413 sections.each(function(i){
15414 this.hideSection(i, useFx);
15417 showAll: function(useFx){
15418 return this.toggleAll(useFx, true);
15420 hideAll: function(useFx){
15421 return this.toggleAll(useFx, false);