JAVASCRIPT   49

mootools

Guest on 3rd May 2022 09:50:07 AM

  1. //MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
  2. var Class = function(properties) {
  3.     var klass = function() {
  4.         if (this.initialize && arguments[0] != 'noinit') return this.initialize.apply(this, arguments);
  5.         else return this
  6.     };
  7.     for (var property in this) klass[property] = this[property];
  8.     klass.prototype = properties;
  9.     return klass
  10. };
  11. Class.empty = function() {};
  12. Class.prototype = {
  13.     extend: function(properties) {
  14.         var pr0t0typ3 = new this('noinit');
  15.         var parentize = function(previous, current) {
  16.             if (!previous.apply || !current.apply) return false;
  17.             return function() {
  18.                 this.parent = previous;
  19.                 return current.apply(this, arguments)
  20.             }
  21.         };
  22.         for (var property in properties) {
  23.             var previous = pr0t0typ3[property];
  24.             var current = properties[property];
  25.             if (previous && previous != current) current = parentize(previous, current) || current;
  26.             pr0t0typ3[property] = current
  27.         }
  28.         return new Class(pr0t0typ3)
  29.     },
  30.     implement: function(properties) {
  31.         for (var property in properties) this.prototype[property] = properties[property]
  32.     }
  33. };
  34. Object.extend = function() {
  35.     var args = arguments;
  36.     args = (args[1]) ? [args[0], args[1]] : [this, args[0]];
  37.     for (var property in args[1]) args[0][property] = args[1][property];
  38.     return args[0]
  39. };
  40. Object.Native = function() {
  41.     for (var i = 0; i < arguments.length; i++) arguments[i].extend = Class.prototype.implement
  42. };
  43. new Object.Native(Function, Array, String, Number, Class);
  44. if (typeof HTMLElement == 'undefined') {
  45.     var HTMLElement = Class.empty;
  46.     HTMLElement.prototype = {}
  47. } else {
  48.     HTMLElement.prototype.htmlElement = true
  49. }
  50. window.extend = document.extend = Object.extend;
  51. var Window = window;
  52.  
  53. function $type(obj) {
  54.     if (obj === null || obj === undefined) return false;
  55.     var type = typeof obj;
  56.     if (type == 'object') {
  57.         if (obj.htmlElement) return 'element';
  58.         if (obj.push) return 'array';
  59.         if (obj.nodeName) {
  60.             switch (obj.nodeType) {
  61.                 case 1:
  62.                     return 'element';
  63.                 case 3:
  64.                     return obj.nodeValue.test(/\S/) ? 'textnode' : 'whitespace'
  65.             }
  66.         }
  67.     }
  68.     return type
  69. };
  70.  
  71. function $chk(obj) {
  72.     return !!(obj || obj === 0)
  73. };
  74.  
  75. function $pick(obj, picked) {
  76.     return ($type(obj)) ? obj : picked
  77. };
  78.  
  79. function $random(min, max) {
  80.     return Math.floor(Math.random() * (max - min + 1) + min)
  81. };
  82.  
  83. function $clear(timer) {
  84.     clearTimeout(timer);
  85.     clearInterval(timer);
  86.     return null
  87. };
  88. if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
  89. else if (document.childNodes && !document.all && !navigator.taintEnabled) window.khtml = true;
  90. else if (document.getBoxObjectFor != null) window.gecko = true;
  91. if (window.ie6) try {
  92.     document.execCommand("BackgroundImageCache", false, true)
  93. } catch (e) {};
  94. Array.prototype.forEach = Array.prototype.forEach || function(fn, bind) {
  95.     for (var i = 0; i < this.length; i++) fn.call(bind, this[i], i, this)
  96. };
  97. Array.prototype.filter = Array.prototype.filter || function(fn, bind) {
  98.     var results = [];
  99.     for (var i = 0; i < this.length; i++) {
  100.         if (fn.call(bind, this[i], i, this)) results.push(this[i])
  101.     }
  102.     return results
  103. };
  104. Array.prototype.map = Array.prototype.map || function(fn, bind) {
  105.     var results = [];
  106.     for (var i = 0; i < this.length; i++) results[i] = fn.call(bind, this[i], i, this);
  107.     return results
  108. };
  109. Array.prototype.every = Array.prototype.every || function(fn, bind) {
  110.     for (var i = 0; i < this.length; i++) {
  111.         if (!fn.call(bind, this[i], i, this)) return false
  112.     }
  113.     return true
  114. };
  115. Array.prototype.some = Array.prototype.some || function(fn, bind) {
  116.     for (var i = 0; i < this.length; i++) {
  117.         if (fn.call(bind, this[i], i, this)) return true
  118.     }
  119.     return false
  120. };
  121. Array.prototype.indexOf = Array.prototype.indexOf || function(item, from) {
  122.     from = from || 0;
  123.     if (from < 0) from = Math.max(0, this.length + from);
  124.     while (from < this.length) {
  125.         if (this[from] === item) return from;
  126.         from++
  127.     }
  128.     return -1
  129. };
  130. Array.extend({
  131.     each: Array.prototype.forEach,
  132.     copy: function(start, length) {
  133.         start = start || 0;
  134.         if (start < 0) start = this.length + start;
  135.         length = length || (this.length - start);
  136.         var newArray = [];
  137.         for (var i = 0; i < length; i++) newArray[i] = this[start++];
  138.         return newArray
  139.     },
  140.     remove: function(item) {
  141.         var i = 0;
  142.         while (i < this.length) {
  143.             if (this[i] === item) this.splice(i, 1);
  144.             else i++
  145.         }
  146.         return this
  147.     },
  148.     test: function(item, from) {
  149.         return this.indexOf(item, from) != -1
  150.     },
  151.     extend: function(newArray) {
  152.         for (var i = 0; i < newArray.length; i++) this.push(newArray[i]);
  153.         return this
  154.     },
  155.     associate: function(keys) {
  156.         var obj = {},
  157.             length = Math.min(this.length, keys.length);
  158.         for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
  159.         return obj
  160.     }
  161. });
  162.  
  163. function $A(array, start, length) {
  164.     return Array.prototype.copy.call(array, start, length)
  165. };
  166.  
  167. function $each(iterable, fn, bind) {
  168.     return Array.prototype.forEach.call(iterable, fn, bind)
  169. };
  170. String.extend({
  171.     test: function(regex, params) {
  172.         return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this)
  173.     },
  174.     toInt: function() {
  175.         return parseInt(this)
  176.     },
  177.     toFloat: function() {
  178.         return parseFloat(this)
  179.     },
  180.     camelCase: function() {
  181.         return this.replace(/-\D/g, function(match) {
  182.             return match.charAt(1).toUpperCase()
  183.         })
  184.     },
  185.     hyphenate: function() {
  186.         return this.replace(/\w[A-Z]/g, function(match) {
  187.             return (match.charAt(0) + '-' + match.charAt(1).toLowerCase())
  188.         })
  189.     },
  190.     capitalize: function() {
  191.         return this.toLowerCase().replace(/\b[a-z]/g, function(match) {
  192.             return match.toUpperCase()
  193.         })
  194.     },
  195.     trim: function() {
  196.         return this.replace(/^\s+|\s+$/g, '')
  197.     },
  198.     clean: function() {
  199.         return this.replace(/\s{2,}/g, ' ').trim()
  200.     },
  201.     rgbToHex: function(array) {
  202.         var rgb = this.match(/\d{1,3}/g);
  203.         return (rgb) ? rgb.rgbToHex(array) : false
  204.     },
  205.     hexToRgb: function(array) {
  206.         var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
  207.         return (hex) ? hex.slice(1).hexToRgb(array) : false
  208.     }
  209. });
  210. Array.extend({
  211.     rgbToHex: function(array) {
  212.         if (this.length < 3) return false;
  213.         if (this[3] && (this[3] == 0) && !array) return 'transparent';
  214.         var hex = [];
  215.         for (var i = 0; i < 3; i++) {
  216.             var bit = (this[i] - 0).toString(16);
  217.             hex.push((bit.length == 1) ? '0' + bit : bit)
  218.         }
  219.         return array ? hex : '#' + hex.join('')
  220.     },
  221.     hexToRgb: function(array) {
  222.         if (this.length != 3) return false;
  223.         var rgb = [];
  224.         for (var i = 0; i < 3; i++) {
  225.             rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16))
  226.         }
  227.         return array ? rgb : 'rgb(' + rgb.join(',') + ')'
  228.     }
  229. });
  230. Number.extend({
  231.     toInt: function() {
  232.         return parseInt(this)
  233.     },
  234.     toFloat: function() {
  235.         return parseFloat(this)
  236.     }
  237. });
  238. Function.extend({
  239.     create: function(options) {
  240.         var fn = this;
  241.         options = Object.extend({
  242.             'bind': fn,
  243.             'event': false,
  244.             'arguments': null,
  245.             'delay': false,
  246.             'periodical': false,
  247.             'attempt': false
  248.         }, options || {});
  249.         if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments];
  250.         return function(event) {
  251.             var args;
  252.             if (options.event) {
  253.                 event = event || window.event;
  254.                 args = [(options.event === true) ? event : new options.event(event)];
  255.                 if (options.arguments) args = args.concat(options.arguments)
  256.             } else args = options.arguments || arguments;
  257.             var returns = function() {
  258.                 return fn.apply(options.bind, args)
  259.             };
  260.             if (options.delay) return setTimeout(returns, options.delay);
  261.             if (options.periodical) return setInterval(returns, options.periodical);
  262.             if (options.attempt) {
  263.                 try {
  264.                     return returns()
  265.                 } catch (err) {
  266.                     return err
  267.                 }
  268.             }
  269.             return returns()
  270.         }
  271.     },
  272.     pass: function(args, bind) {
  273.         return this.create({
  274.             'arguments': args,
  275.             'bind': bind
  276.         })
  277.     },
  278.     attempt: function(args, bind) {
  279.         return this.create({
  280.             'arguments': args,
  281.             'bind': bind,
  282.             'attempt': true
  283.         })()
  284.     },
  285.     bind: function(bind, args) {
  286.         return this.create({
  287.             'bind': bind,
  288.             'arguments': args
  289.         })
  290.     },
  291.     bindAsEventListener: function(bind, args) {
  292.         return this.create({
  293.             'bind': bind,
  294.             'event': true,
  295.             'arguments': args
  296.         })
  297.     },
  298.     delay: function(ms, bind, args) {
  299.         return this.create({
  300.             'delay': ms,
  301.             'bind': bind,
  302.             'arguments': args
  303.         })()
  304.     },
  305.     periodical: function(ms, bind, args) {
  306.         return this.create({
  307.             'periodical': ms,
  308.             'bind': bind,
  309.             'arguments': args
  310.         })()
  311.     }
  312. });
  313. var Element = new Class({
  314.     initialize: function(el) {
  315.         if ($type(el) == 'string') el = document.createElement(el);
  316.         return $(el)
  317.     }
  318. });
  319.  
  320. function $(el) {
  321.     if (!el) return false;
  322.     if (el._element_extended_ || [window, document].test(el)) return el;
  323.     if ($type(el) == 'string') el = document.getElementById(el);
  324.     if ($type(el) != 'element') return false;
  325.     if (['object', 'embed'].test(el.tagName.toLowerCase()) || el.extend) return el;
  326.     el._element_extended_ = true;
  327.     Garbage.collect(el);
  328.     el.extend = Object.extend;
  329.     if (!(el.htmlElement)) el.extend(Element.prototype);
  330.     return el
  331. };
  332. var Elements = new Class({});
  333. new Object.Native(Elements);
  334. document.getElementsBySelector = document.getElementsByTagName;
  335.  
  336. function $$() {
  337.     if (!arguments) return false;
  338.     if (arguments.length == 1) {
  339.         if (!arguments[0]) return false;
  340.         if (arguments[0]._elements_extended_) return arguments[0]
  341.     }
  342.     var elements = [];
  343.     $each(arguments, function(selector) {
  344.         switch ($type(selector)) {
  345.             case 'element':
  346.                 elements.push($(selector));
  347.                 break;
  348.             case 'string':
  349.                 selector = document.getElementsBySelector(selector);
  350.             default:
  351.                 if (selector.length) {
  352.                     $each(selector, function(el) {
  353.                         if ($(el)) elements.push(el)
  354.                     })
  355.                 }
  356.         }
  357.     });
  358.     elements._elements_extended_ = true;
  359.     return Object.extend(elements, new Elements)
  360. };
  361. Elements.Multi = function(property) {
  362.     return function() {
  363.         var args = arguments;
  364.         var items = [];
  365.         var elements = true;
  366.         $each(this, function(el) {
  367.             var returns = el[property].apply(el, args);
  368.             if ($type(returns) != 'element') elements = false;
  369.             items.push(returns)
  370.         });
  371.         if (elements) items = $$(items);
  372.         return items
  373.     }
  374. };
  375. Element.extend = function(properties) {
  376.     for (var property in properties) {
  377.         HTMLElement.prototype[property] = properties[property];
  378.         Element.prototype[property] = properties[property];
  379.         Elements.prototype[property] = Elements.Multi(property)
  380.     }
  381. };
  382. Element.extend({
  383.     inject: function(el, where) {
  384.         el = $(el) || new Element(el);
  385.         switch (where) {
  386.             case "before":
  387.                 $(el.parentNode).insertBefore(this, el);
  388.                 break;
  389.             case "after":
  390.                 if (!el.getNext()) $(el.parentNode).appendChild(this);
  391.                 else $(el.parentNode).insertBefore(this, el.getNext());
  392.                 break;
  393.             case "inside":
  394.                 el.appendChild(this)
  395.         }
  396.         return this
  397.     },
  398.     injectBefore: function(el) {
  399.         return this.inject(el, 'before')
  400.     },
  401.     injectAfter: function(el) {
  402.         return this.inject(el, 'after')
  403.     },
  404.     injectInside: function(el) {
  405.         return this.inject(el, 'inside')
  406.     },
  407.     adopt: function(el) {
  408.         this.appendChild($(el) || new Element(el));
  409.         return this
  410.     },
  411.     remove: function() {
  412.         this.parentNode.removeChild(this);
  413.         return this
  414.     },
  415.     clone: function(contents) {
  416.         var el = this.cloneNode(contents !== false);
  417.         return $(el)
  418.     },
  419.     replaceWith: function(el) {
  420.         el = $(el) || new Element(el);
  421.         this.parentNode.replaceChild(el, this);
  422.         return el
  423.     },
  424.     appendText: function(text) {
  425.         if (window.ie) {
  426.             switch (this.getTag()) {
  427.                 case 'style':
  428.                     this.styleSheet.cssText = text;
  429.                     return this;
  430.                 case 'script':
  431.                     this.setProperty('text', text);
  432.                     return this
  433.             }
  434.         }
  435.         this.appendChild(document.createTextNode(text));
  436.         return this
  437.     },
  438.     hasClass: function(className) {
  439.         return this.className.test('(?:^|\\s)' + className + '(?:\\s|$)')
  440.     },
  441.     addClass: function(className) {
  442.         if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
  443.         return this
  444.     },
  445.     removeClass: function(className) {
  446.         this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
  447.         return this
  448.     },
  449.     toggleClass: function(className) {
  450.         return this.hasClass(className) ? this.removeClass(className) : this.addClass(className)
  451.     },
  452.     setStyle: function(property, value) {
  453.         if (property == 'opacity') this.setOpacity(parseFloat(value));
  454.         else this.style[property.camelCase()] = (value.push) ? 'rgb(' + value.join(',') + ')' : value;
  455.         return this
  456.     },
  457.     setStyles: function(source) {
  458.         switch ($type(source)) {
  459.             case 'object':
  460.                 for (var property in source) this.setStyle(property, source[property]);
  461.                 break;
  462.             case 'string':
  463.                 this.style.cssText = source
  464.         }
  465.         return this
  466.     },
  467.     setOpacity: function(opacity) {
  468.         if (opacity == 0) {
  469.             if (this.style.visibility != "hidden") this.style.visibility = "hidden"
  470.         } else {
  471.             if (this.style.visibility != "visible") this.style.visibility = "visible"
  472.         }
  473.         if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
  474.         if (window.ie) this.style.filter = "alpha(opacity=" + opacity * 100 + ")";
  475.         this.style.opacity = this.opacity = opacity;
  476.         return this
  477.     },
  478.     getStyle: function(property) {
  479.         property = property.camelCase();
  480.         var style = this.style[property] || false;
  481.         if (!$chk(style)) {
  482.             if (property == 'opacity') return $chk(this.opacity) ? this.opacity : 1;
  483.             if (['margin', 'padding'].test(property)) {
  484.                 return [this.getStyle(property + '-top') || 0, this.getStyle(property + '-right') || 0, this.getStyle(property + '-bottom') || 0, this.getStyle(property + '-left') || 0].join(' ')
  485.             }
  486.             if (document.defaultView) style = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
  487.             else if (this.currentStyle) style = this.currentStyle[property]
  488.         }
  489.         if (style == 'auto' && ['height', 'width'].test(property)) return this['offset' + property.capitalize()] + 'px';
  490.         return (style && property.test(/color/i) && style.test(/rgb/)) ? style.rgbToHex() : style
  491.     },
  492.     addEvent: function(type, fn) {
  493.         this.events = this.events || {};
  494.         this.events[type] = this.events[type] || {
  495.             'keys': [],
  496.             'values': []
  497.         };
  498.         if (!this.events[type].keys.test(fn)) {
  499.             this.events[type].keys.push(fn);
  500.             if (this.addEventListener) {
  501.                 this.addEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, fn, false)
  502.             } else {
  503.                 fn = fn.bind(this);
  504.                 this.attachEvent('on' + type, fn);
  505.                 this.events[type].values.push(fn)
  506.             }
  507.         }
  508.         return this
  509.     },
  510.     addEvents: function(source) {
  511.         if (source) {
  512.             for (var type in source) this.addEvent(type, source[type])
  513.         }
  514.         return this
  515.     },
  516.     removeEvent: function(type, fn) {
  517.         if (this.events && this.events[type]) {
  518.             var pos = this.events[type].keys.indexOf(fn);
  519.             if (pos == -1) return this;
  520.             var key = this.events[type].keys.splice(pos, 1)[0];
  521.             if (this.removeEventListener) {
  522.                 this.removeEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, key, false)
  523.             } else {
  524.                 this.detachEvent('on' + type, this.events[type].values.splice(pos, 1)[0])
  525.             }
  526.         }
  527.         return this
  528.     },
  529.     removeEvents: function(type) {
  530.         if (this.events) {
  531.             if (type) {
  532.                 if (this.events[type]) {
  533.                     this.events[type].keys.each(function(fn) {
  534.                         this.removeEvent(type, fn)
  535.                     }, this);
  536.                     this.events[type] = null
  537.                 }
  538.             } else {
  539.                 for (var evType in this.events) this.removeEvents(evType);
  540.                 this.events = null
  541.             }
  542.         }
  543.         return this
  544.     },
  545.     fireEvent: function(type, args) {
  546.         if (this.events && this.events[type]) {
  547.             this.events[type].keys.each(function(fn) {
  548.                 fn.bind(this, args)()
  549.             }, this)
  550.         }
  551.     },
  552.     getBrother: function(what) {
  553.         var el = this[what + 'Sibling'];
  554.         while ($type(el) == 'whitespace') el = el[what + 'Sibling'];
  555.         return $(el)
  556.     },
  557.     getPrevious: function() {
  558.         return this.getBrother('previous')
  559.     },
  560.     getNext: function() {
  561.         return this.getBrother('next')
  562.     },
  563.     getFirst: function() {
  564.         var el = this.firstChild;
  565.         while ($type(el) == 'whitespace') el = el.nextSibling;
  566.         return $(el)
  567.     },
  568.     getLast: function() {
  569.         var el = this.lastChild;
  570.         while ($type(el) == 'whitespace') el = el.previousSibling;
  571.         return $(el)
  572.     },
  573.     getParent: function() {
  574.         return $(this.parentNode)
  575.     },
  576.     getChildren: function() {
  577.         return $$(this.childNodes)
  578.     },
  579.     setProperty: function(property, value) {
  580.         switch (property) {
  581.             case 'class':
  582.                 this.className = value;
  583.                 break;
  584.             case 'style':
  585.                 this.setStyles(value);
  586.                 break;
  587.             case 'name':
  588.                 if (window.ie6) {
  589.                     var el = $(document.createElement('<' + this.getTag() + ' name="' + value + '" />'));
  590.                     $each(this.attributes, function(attribute) {
  591.                         if (attribute.name != 'name') el.setProperty(attribute.name, attribute.value)
  592.                     });
  593.                     if (this.parentNode) this.replaceWith(el);
  594.                     return el
  595.                 }
  596.             default:
  597.                 this.setAttribute(property, value)
  598.         }
  599.         return this
  600.     },
  601.     setProperties: function(source) {
  602.         for (var property in source) this.setProperty(property, source[property]);
  603.         return this
  604.     },
  605.     setHTML: function() {
  606.         this.innerHTML = $A(arguments).join('');
  607.         return this
  608.     },
  609.     getProperty: function(property) {
  610.         return (property == 'class') ? this.className : this.getAttribute(property)
  611.     },
  612.     getTag: function() {
  613.         return this.tagName.toLowerCase()
  614.     },
  615.     scrollTo: function(x, y) {
  616.         this.scrollLeft = x;
  617.         this.scrollTop = y
  618.     },
  619.     getValue: function() {
  620.         switch (this.getTag()) {
  621.             case 'select':
  622.                 if (this.selectedIndex != -1) {
  623.                     var opt = this.options[this.selectedIndex];
  624.                     return opt.value || opt.text
  625.                 }
  626.                 break;
  627.             case 'input':
  628.                 if (!(this.checked && ['checkbox', 'radio'].test(this.type)) && !['hidden', 'text', 'password'].test(this.type)) break;
  629.             case 'textarea':
  630.                 return this.value
  631.         }
  632.         return false
  633.     },
  634.     getSize: function() {
  635.         return {
  636.             'scroll': {
  637.                 'x': this.scrollLeft,
  638.                 'y': this.scrollTop
  639.             },
  640.             'size': {
  641.                 'x': this.offsetWidth,
  642.                 'y': this.offsetHeight
  643.             },
  644.             'scrollSize': {
  645.                 'x': this.scrollWidth,
  646.                 'y': this.scrollHeight
  647.             }
  648.         }
  649.     },
  650.     getPosition: function(overflown) {
  651.         overflown = overflown || [];
  652.         var el = this,
  653.             left = 0,
  654.             top = 0;
  655.         do {
  656.             left += el.offsetLeft || 0;
  657.             top += el.offsetTop || 0;
  658.             el = el.offsetParent
  659.         } while (el);
  660.         overflown.each(function(element) {
  661.             left -= element.scrollLeft || 0;
  662.             top -= element.scrollTop || 0
  663.         });
  664.         return {
  665.             'x': left,
  666.             'y': top
  667.         }
  668.     },
  669.     getTop: function() {
  670.         return this.getPosition().y
  671.     },
  672.     getLeft: function() {
  673.         return this.getPosition().x
  674.     },
  675.     getCoordinates: function(overflown) {
  676.         var position = this.getPosition(overflown);
  677.         var obj = {
  678.             'width': this.offsetWidth,
  679.             'height': this.offsetHeight,
  680.             'left': position.x,
  681.             'top': position.y
  682.         };
  683.         obj.right = obj.left + obj.width;
  684.         obj.bottom = obj.top + obj.height;
  685.         return obj
  686.     }
  687. });
  688. window.addEvent = document.addEvent = Element.prototype.addEvent;
  689. window.removeEvent = document.removeEvent = Element.prototype.removeEvent;
  690. window.removeEvents = document.removeEvents = Element.prototype.removeEvents;
  691. var Garbage = {
  692.     elements: [],
  693.     collect: function(element) {
  694.         Garbage.elements.push(element)
  695.     },
  696.     trash: function() {
  697.         Garbage.collect(window);
  698.         Garbage.collect(document);
  699.         Garbage.elements.each(function(el) {
  700.             el.removeEvents();
  701.             for (var p in Element.prototype) el[p] = null;
  702.             el.extend = null
  703.         })
  704.     }
  705. };
  706. window.addEvent('unload', Garbage.trash);
  707. var Chain = new Class({
  708.     chain: function(fn) {
  709.         this.chains = this.chains || [];
  710.         this.chains.push(fn);
  711.         return this
  712.     },
  713.     callChain: function() {
  714.         if (this.chains && this.chains.length) this.chains.shift().delay(10, this)
  715.     },
  716.     clearChain: function() {
  717.         this.chains = []
  718.     }
  719. });
  720. var Events = new Class({
  721.     addEvent: function(type, fn) {
  722.         if (fn != Class.empty) {
  723.             this.events = this.events || {};
  724.             this.events[type] = this.events[type] || [];
  725.             if (!this.events[type].test(fn)) this.events[type].push(fn)
  726.         }
  727.         return this
  728.     },
  729.     fireEvent: function(type, args, delay) {
  730.         if (this.events && this.events[type]) {
  731.             this.events[type].each(function(fn) {
  732.                 fn.create({
  733.                     'bind': this,
  734.                     'delay': delay,
  735.                     'arguments': args
  736.                 })()
  737.             }, this)
  738.         }
  739.         return this
  740.     },
  741.     removeEvent: function(type, fn) {
  742.         if (this.events && this.events[type]) this.events[type].remove(fn);
  743.         return this
  744.     }
  745. });
  746. var Options = new Class({
  747.     setOptions: function(defaults, options) {
  748.         this.options = Object.extend(defaults, options);
  749.         if (this.addEvent) {
  750.             for (var option in this.options) {
  751.                 if (($type(this.options[option]) == 'function') && option.test(/^on[A-Z]/)) this.addEvent(option, this.options[option])
  752.             }
  753.         }
  754.         return this
  755.     }
  756. });
  757. var Group = new Class({
  758.     initialize: function() {
  759.         this.instances = $A(arguments);
  760.         this.events = {};
  761.         this.checker = {}
  762.     },
  763.     addEvent: function(type, fn) {
  764.         this.checker[type] = this.checker[type] || {};
  765.         this.events[type] = this.events[type] || [];
  766.         if (this.events[type].test(fn)) return false;
  767.         else this.events[type].push(fn);
  768.         this.instances.each(function(instance, i) {
  769.             instance.addEvent(type, this.check.bind(this, [type, instance, i]))
  770.         }, this);
  771.         return this
  772.     },
  773.     check: function(type, instance, i) {
  774.         this.checker[type][i] = true;
  775.         var every = this.instances.every(function(current, j) {
  776.             return this.checker[type][j] || false
  777.         }, this);
  778.         if (!every) return;
  779.         this.instances.each(function(current, j) {
  780.             this.checker[type][j] = false
  781.         }, this);
  782.         this.events[type].each(function(event) {
  783.             event.call(this, this.instances, instance)
  784.         }, this)
  785.     }
  786. });
  787. var Fx = {};
  788. Fx.Base = new Class({
  789.     getOptions: function() {
  790.         return {
  791.             onStart: Class.empty,
  792.             onComplete: Class.empty,
  793.             onCancel: Class.empty,
  794.             transition: Fx.Transitions.sineInOut,
  795.             duration: 500,
  796.             unit: 'px',
  797.             wait: true,
  798.             fps: 50
  799.         }
  800.     },
  801.     initialize: function(options) {
  802.         this.element = this.element || null;
  803.         this.setOptions(this.getOptions(), options);
  804.         if (this.options.initialize) this.options.initialize.call(this)
  805.     },
  806.     step: function() {
  807.         var time = new Date().getTime();
  808.         if (time < this.time + this.options.duration) {
  809.             this.cTime = time - this.time;
  810.             this.setNow();
  811.             this.increase()
  812.         } else {
  813.             this.stop(true);
  814.             this.now = this.to;
  815.             this.increase();
  816.             this.fireEvent('onComplete', this.element, 10);
  817.             this.callChain()
  818.         }
  819.     },
  820.     set: function(to) {
  821.         this.now = to;
  822.         this.increase();
  823.         return this
  824.     },
  825.     setNow: function() {
  826.         this.now = this.compute(this.from, this.to)
  827.     },
  828.     compute: function(from, to) {
  829.         return this.options.transition(this.cTime, from, (to - from), this.options.duration)
  830.     },
  831.     start: function(from, to) {
  832.         if (!this.options.wait) this.stop();
  833.         else if (this.timer) return this;
  834.         this.from = from;
  835.         this.to = to;
  836.         this.time = new Date().getTime();
  837.         this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
  838.         this.fireEvent('onStart', this.element);
  839.         return this
  840.     },
  841.     stop: function(end) {
  842.         if (!this.timer) return this;
  843.         this.timer = $clear(this.timer);
  844.         if (!end) this.fireEvent('onCancel', this.element);
  845.         return this
  846.     },
  847.     custom: function(from, to) {
  848.         return this.start(from, to)
  849.     },
  850.     clearTimer: function(end) {
  851.         return this.stop(end)
  852.     }
  853. });
  854. Fx.Base.implement(new Chain);
  855. Fx.Base.implement(new Events);
  856. Fx.Base.implement(new Options);
  857. Fx.Transitions = {
  858.     linear: function(t, b, c, d) {
  859.         return c * t / d + b
  860.     },
  861.     sineInOut: function(t, b, c, d) {
  862.         return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b
  863.     }
  864. };
  865. Fx.CSS = {
  866.     select: function(property, to) {
  867.         if (property.test(/color/i)) return this.Color;
  868.         if (to.test && to.test(' ')) return this.Multi;
  869.         return this.Single
  870.     },
  871.     parse: function(el, property, fromTo) {
  872.         if (!fromTo.push) fromTo = [fromTo];
  873.         var from = fromTo[0],
  874.             to = fromTo[1];
  875.         if (!to && to != 0) {
  876.             to = from;
  877.             from = el.getStyle(property)
  878.         }
  879.         var css = this.select(property, to);
  880.         return {
  881.             from: css.parse(from),
  882.             to: css.parse(to),
  883.             css: css
  884.         }
  885.     }
  886. };
  887. Fx.CSS.Single = {
  888.     parse: function(value) {
  889.         return parseFloat(value)
  890.     },
  891.     getNow: function(from, to, fx) {
  892.         return fx.compute(from, to)
  893.     },
  894.     getValue: function(value, unit) {
  895.         return value + unit
  896.     }
  897. };
  898. Fx.CSS.Multi = {
  899.     parse: function(value) {
  900.         return value.push ? value : value.split(' ').map(function(v) {
  901.             return parseFloat(v)
  902.         })
  903.     },
  904.     getNow: function(from, to, fx) {
  905.         var now = [];
  906.         for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
  907.         return now
  908.     },
  909.     getValue: function(value, unit) {
  910.         return value.join(unit + ' ') + unit
  911.     }
  912. };
  913. Fx.CSS.Color = {
  914.     parse: function(value) {
  915.         return value.push ? value : value.hexToRgb(true)
  916.     },
  917.     getNow: function(from, to, fx) {
  918.         var now = [];
  919.         for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
  920.         return now
  921.     },
  922.     getValue: function(value) {
  923.         return 'rgb(' + value.join(',') + ')'
  924.     }
  925. };
  926. Fx.Styles = Fx.Base.extend({
  927.     initialize: function(el, options) {
  928.         this.element = $(el);
  929.         this.parent(options)
  930.     },
  931.     setNow: function() {
  932.         for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this)
  933.     },
  934.     set: function(to) {
  935.         var parsed = {};
  936.         this.css = {};
  937.         for (var p in to) {
  938.             this.css[p] = Fx.CSS.select(p, to[p]);
  939.             parsed[p] = this.css[p].parse(to[p])
  940.         }
  941.         return this.parent(parsed)
  942.     },
  943.     start: function(obj) {
  944.         if (this.timer && this.options.wait) return this;
  945.         this.now = {};
  946.         this.css = {};
  947.         var from = {},
  948.             to = {};
  949.         for (var p in obj) {
  950.             var parsed = Fx.CSS.parse(this.element, p, obj[p]);
  951.             from[p] = parsed.from;
  952.             to[p] = parsed.to;
  953.             this.css[p] = parsed.css
  954.         }
  955.         return this.parent(from, to)
  956.     },
  957.     increase: function() {
  958.         for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit))
  959.     }
  960. });
  961. Element.extend({
  962.     effects: function(options) {
  963.         return new Fx.Styles(this, options)
  964.     }
  965. });

Raw Paste


Login or Register to edit or fork this paste. It's free.