source: trunk/spip/esqueleto-redcta/plugins/magusine/javascript/mootools.js @ 133

Last change on this file since 133 was 80, checked in by guille, 16 years ago

el plugin completo

  • Property svn:executable set to *
File size: 100.8 KB
Line 
1/*
2Script: Moo.js
3        My Object Oriented javascript.
4
5Author:
6        Valerio Proietti, <http://mad4milk.net>
7
8License:
9        MIT-style license.
10
11Credits:
12        - Class is slightly based on Base.js <http://dean.edwards.name/weblog/2006/03/base/> (c) 2006 Dean Edwards, License <http://creativecommons.org/licenses/LGPL/2.1/>
13        - Some functions are based on those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
14        - Documentation by Aaron Newton (aaron.newton [at] cnet [dot] com) and Valerio Proietti.
15*/
16
17/*
18Class: Class
19        The base class object of the <http://mootools.net> framework.
20
21Arguments:
22        properties - the collection of properties that apply to the class. Creates a new class, its initialize method will fire upon class instantiation.
23
24Example:
25        (start code)
26        var Cat = new Class({
27                initialize: function(name){
28                        this.name = name;
29                }
30        });
31        var myCat = new Cat('Micia');
32        alert myCat.name; //alerts 'Micia'
33        (end)
34*/
35
36var Class = function(properties){
37        var klass = function(){
38                if (this.initialize && arguments[0] != 'noinit') return this.initialize.apply(this, arguments);
39                else return this;
40        };
41        for (var property in this) klass[property] = this[property];
42        klass.prototype = properties;
43        return klass;
44};
45
46/*
47Property: empty
48        Returns an empty function
49*/
50
51Class.empty = function(){};
52
53Class.prototype = {
54
55        /*
56        Property: extend
57                Returns the copy of the Class extended with the passed in properties.
58
59        Arguments:
60                properties - the properties to add to the base class in this new Class.
61
62        Example:
63                (start code)
64                var Animal = new Class({
65                        initialize: function(age){
66                                this.age = age;
67                        }
68                });
69                var Cat = Animal.extend({
70                        initialize: function(name, age){
71                                this.parent(age); //will call the previous initialize;
72                                this.name = name;
73                        }
74                });
75                var myCat = new Cat('Micia', 20);
76                alert myCat.name; //alerts 'Micia'
77                alert myCat.age; //alerts 20
78                (end)
79        */
80
81        extend: function(properties){
82                var pr0t0typ3 = new this('noinit');
83
84                var parentize = function(previous, current){
85                        if (!previous.apply || !current.apply) return false;
86                        return function(){
87                                this.parent = previous;
88                                return current.apply(this, arguments);
89                        };
90                };
91
92                for (var property in properties){
93                        var previous = pr0t0typ3[property];
94                        var current = properties[property];
95                        if (previous && previous != current) current = parentize(previous, current) || current;
96                        pr0t0typ3[property] = current;
97                }
98                return new Class(pr0t0typ3);
99        },
100
101        /*
102        Property: implement
103                Implements the passed in properties to the base Class prototypes, altering the base class, unlike <Class.extend>.
104
105        Arguments:
106                properties - the properties to add to the base class.
107
108        Example:
109                (start code)
110                var Animal = new Class({
111                        initialize: function(age){
112                                this.age = age;
113                        }
114                });
115                Animal.implement({
116                        setName: function(name){
117                                this.name = name
118                        }
119                });
120                var myAnimal = new Animal(20);
121                myAnimal.setName('Micia');
122                alert(myAnimal.name); //alerts 'Micia'
123                (end)
124        */
125
126        implement: function(properties){
127                for (var property in properties) this.prototype[property] = properties[property];
128        }
129
130};
131
132/* Section: Object related Functions */
133
134/*
135Function: Object.extend
136        Copies all the properties from the second passed object to the first passed Object.
137        If you do myWhatever.extend = Object.extend the first parameter will become myWhatever, and your extend function will only need one parameter.
138
139Example:
140        (start code)
141        var firstOb = {
142                'name': 'John',
143                'lastName': 'Doe'
144        };
145        var secondOb = {
146                'age': '20',
147                'sex': 'male',
148                'lastName': 'Dorian'
149        };
150        Object.extend(firstOb, secondOb);
151        //firstOb will become:
152        {
153                'name': 'John',
154                'lastName': 'Dorian',
155                'age': '20',
156                'sex': 'male'
157        };
158        (end)
159
160Returns:
161        The first object, extended.
162*/
163
164Object.extend = function(){
165        var args = arguments;
166        args = (args[1]) ? [args[0], args[1]] : [this, args[0]];
167        for (var property in args[1]) args[0][property] = args[1][property];
168        return args[0];
169};
170
171/*
172Function: Object.Native
173        Will add a .extend method to the objects passed as a parameter, equivalent to <Class.implement>
174
175Arguments:
176        a number of classes/native javascript objects
177
178*/
179
180Object.Native = function(){
181        for (var i = 0; i < arguments.length; i++) arguments[i].extend = Class.prototype.implement;
182};
183
184new Object.Native(Function, Array, String, Number, Class);
185
186/*
187Script: Utility.js
188        Contains Utility functions
189
190Author:
191        Valerio Proietti, <http://mad4milk.net>
192
193License:
194        MIT-style license.
195*/
196
197//htmlelement mapping
198
199if (typeof HTMLElement == 'undefined'){
200        var HTMLElement = Class.empty;
201        HTMLElement.prototype = {};
202}
203
204/*
205Function: $type
206        Returns the type of object that matches the element passed in.
207
208Arguments:
209        obj - the object to inspect.
210
211Example:
212        >var myString = 'hello';
213        >$type(myString); //returns "string"
214
215Returns:
216        'element' - if obj is a DOM element node
217        'textnode' - if obj is a DOM text node
218        'whitespace' - if obj is a DOM whitespace node
219        'array' - if obj is an array
220        'object' - if obj is an object
221        'string' - if obj is a string
222        'number' - if obj is a number
223        'boolean' - if obj is a boolean
224        'function' - if obj is a function
225        false - (boolean) if the object is not defined or none of the above.
226*/
227
228function $type(obj){
229        if (obj === null || obj === undefined) return false;
230        var type = typeof obj;
231        if (type == 'object'){
232                if (obj instanceof HTMLElement) return 'element';
233                if (obj instanceof Array) return 'array';
234                if (obj.nodeName){
235                        switch (obj.nodeType){
236                                case 1: return 'element';
237                                case 3: return obj.nodeValue.test('\\S') ? 'textnode' : 'whitespace';
238                        }
239                }
240        }
241        return type;
242};
243
244/*
245Function: $chk
246        Returns true if the passed in value/object exists or is 0, otherwise returns false.
247        Useful to accept zeroes.
248*/
249
250function $chk(obj){
251        return !!(obj || obj === 0);
252};
253
254/*
255Function: $pick
256        Returns the first object if defined, otherwise returns the second.
257*/
258
259function $pick(obj, picked){
260        return ($type(obj)) ? obj : picked;
261};
262
263/*
264Function: $random
265        Returns a random integer number between the two passed in values.
266
267Arguments:
268        min - integer, the minimum value (inclusive).
269        max - integer, the maximum value (inclusive).
270
271Returns:
272        a random integer between min and max.
273*/
274
275function $random(min, max){
276        return Math.floor(Math.random() * (max - min + 1) + min);
277};
278
279/*
280Function: $clear
281        clears a timeout or an Interval.
282
283Returns:
284        null
285
286Arguments:
287        timer - the setInterval or setTimeout to clear.
288
289Example:
290        >var myTimer = myFunction.delay(5000); //wait 5 seconds and execute my function.
291        >myTimer = $clear(myTimer); //nevermind
292
293See also:
294        <Function.delay>, <Function.periodical>
295*/
296
297function $clear(timer){
298        clearTimeout(timer);
299        clearInterval(timer);
300        return null;
301};
302
303/* Section: Browser Detection */
304
305/*
306Properties:
307        window.ie - will be set to true if the current browser is internet explorer (any).
308        window.ie6 - will be set to true if the current browser is internet explorer 6.
309        window.ie7 - will be set to true if the current browser is internet explorer 7.
310        window.khtml - will be set to true if the current browser is Safari/Konqueror.
311        window.gecko - will be set to true if the current browser is Mozilla/Gecko.
312*/
313
314if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
315else if (document.childNodes && !document.all && !navigator.taintEnabled) window.khtml = true;
316else if (document.getBoxObjectFor != null) window.gecko = true;
317
318/*
319Script: Array.js
320        Contains Array prototypes and the function <$A>;
321
322Author:
323        Valerio Proietti, <http://mad4milk.net>
324
325License:
326        MIT-style license.
327*/
328
329/*
330Class: Array
331        A collection of The Array Object prototype methods.
332*/
333
334//emulated methods
335
336/*
337Property: forEach
338        Iterates through an array; This method is only available for browsers without native *forEach* support.
339        For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
340*/
341
342Array.prototype.forEach = Array.prototype.forEach || function(fn, bind){
343        for (var i = 0; i < this.length; i++) fn.call(bind, this[i], i, this);
344};
345
346/*
347Property: map
348        This method is provided only for browsers without native *map* support.
349        For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map>
350*/
351
352Array.prototype.map = Array.prototype.map || function(fn, bind){
353        var results = [];
354        for (var i = 0; i < this.length; i++) results[i] = fn.call(bind, this[i], i, this);
355        return results;
356};
357
358/*
359Property: every
360        This method is provided only for browsers without native *every* support.
361        For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every>
362*/
363
364Array.prototype.every = Array.prototype.every || function(fn, bind){
365        for (var i = 0; i < this.length; i++){
366                if (!fn.call(bind, this[i], i, this)) return false;
367        }
368        return true;
369};
370
371/*
372Property: some
373        This method is provided only for browsers without native *some* support.
374        For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some>
375*/
376
377Array.prototype.some = Array.prototype.some || function(fn, bind){
378        for (var i = 0; i < this.length; i++){
379                if (fn.call(bind, this[i], i, this)) return true;
380        }
381        return false;
382};
383
384/*
385Property: indexOf
386        This method is provided only for browsers without native *indexOf* support.
387        For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf>
388*/
389
390Array.prototype.indexOf = Array.prototype.indexOf || function(item, from){
391        from = from || 0;
392        if (from < 0) from = Math.max(0, this.length + from);
393        while (from < this.length){
394                if(this[from] === item) return from;
395                from++;
396        }
397        return -1;
398};
399
400//custom methods
401
402Array.extend({
403
404        /*
405        Property: each
406                Same as <Array.forEach>.
407
408        Arguments:
409                fn - the function to execute with each item in the array
410                bind - optional, the object that the "this" of the function will refer to.
411
412        Example:
413                >var Animals = ['Cat', 'Dog', 'Coala'];
414                >Animals.forEach(function(animal){
415                >       document.write(animal)
416                >});
417        */
418
419        each: Array.prototype.forEach,
420
421        /*
422        Property: copy
423                Copy the array and returns it.
424
425        Returns:
426                an Array
427
428        Example:
429                >var letters = ["a","b","c"];
430                >var copy = ["a","b","c"].copy();
431        */
432
433        copy: function(){
434                var newArray = [];
435                for (var i = 0; i < this.length; i++) newArray[i] = this[i];
436                return newArray;
437        },
438
439        /*
440        Property: remove
441                Removes all occurrences of an item from the array.
442
443        Arguments:
444                item - the item to remove
445
446        Returns:
447                the Array with all occurrences of the item removed.
448
449        Example:
450                >["1","2","3","2"].remove("2") // ["1","3"];
451        */
452
453        remove: function(item){
454                var i = 0;
455                while (i < this.length){
456                        if (this[i] == item) this.splice(i, 1);
457                        else i++;
458                }
459                return this;
460        },
461
462        /*
463        Property: test
464                Tests an array for the presence of an item.
465
466        Arguments:
467                item - the item to search for in the array.
468                from - optional, the index at which to begin the search, default is 0. If negative, it is taken as the offset from the end of the array.
469
470        Returns:
471                true - the item was found
472                false - it wasn't
473
474        Example:
475                >["a","b","c"].test("a"); // true
476                >["a","b","c"].test("d"); // false
477        */
478
479        test: function(item, from){
480                return this.indexOf(item, from) != -1;
481        },
482
483        /*
484        Property: extend
485                Extends an array with another
486
487        Arguments:
488                newArray - the array to extend ours with
489
490        Example:
491                >var Animals = ['Cat', 'Dog', 'Coala'];
492                >Animals.extend(['Lizard']);
493                >//Animals is now: ['Cat', 'Dog', 'Coala', 'Lizard'];
494        */
495
496        extend: function(newArray){
497                for (var i = 0; i < newArray.length; i++) this.push(newArray[i]);
498                return this;
499        },
500
501        /*
502        Property: associate
503                Creates an object with key-value pairs based on the array of keywords passed in
504                and the current content of the array.
505
506        Arguments:
507                keys - the array of keywords.
508
509        Example:
510                (start code)
511                var Animals = ['Cat', 'Dog', 'Coala', 'Lizard'];
512                var Speech = ['Miao', 'Bau', 'Fruuu', 'Mute'];
513                var Speeches = Animals.associate(speech);
514                //Speeches['Miao'] is now Cat.
515                //Speeches['Bau'] is now Dog.
516                //...
517                (end)
518        */
519
520        associate: function(keys){
521                var obj = {}, length = Math.min(this.length, keys.length);
522                for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
523                return obj;
524        }
525
526});
527
528/* Section: Utility Functions */
529
530/*
531Function: $A()
532        Same as <Array.copy>, but as function.
533        Useful to apply Array prototypes to iterable objects, as a collection of DOM elements or the arguments object.
534
535Example:
536        (start code)
537        function myFunction(){
538                $A(arguments).each(argument, function(){
539                        alert(argument);
540                });
541        };
542        //the above will alert all the arguments passed to the function myFunction.
543        (end)
544*/
545
546function $A(array){
547        return Array.prototype.copy.call(array);
548};
549
550/*
551Function: $each
552        use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, or arguments of a function.
553
554Arguments:
555        iterable - an iterable element.
556        function - function to apply to the iterable.
557        bind - optional, the 'this' of the function will refer to this object.
558*/
559
560function $each(iterable, fn, bind){
561        return Array.prototype.forEach.call(iterable, fn, bind);
562};
563
564/*
565Script: String.js
566        Contains String prototypes and Number prototypes.
567
568Author:
569        Valerio Proietti, <http://mad4milk.net>
570
571License:
572        MIT-style license.
573*/
574
575/*
576Class: String
577        A collection of The String Object prototype methods.
578*/
579
580String.extend({
581
582        /*
583        Property: test
584                Tests a string with a regular expression.
585
586        Arguments:
587                regex - the regular expression you want to match the string with
588                params - optional, any parameters you want to pass to the regex ('g' has no effect)
589
590        Returns:
591                true if a match for the regular expression is found in the string, false if not.
592                See <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test>
593
594        Example:
595                >"I like cookies".test("cookie"); // returns true
596                >"I like cookies".test("COOKIE", "i") // ignore case, returns true
597                >"I like cookies".test("cake"); // returns false
598        */
599
600        test: function(regex, params){
601                return new RegExp(regex, params).test(this);
602        },
603
604        /*
605        Property: toInt
606                parses a string to an integer.
607
608        Returns:
609                either an int or "NaN" if the string is not a number.
610
611        Example:
612                >var value = "10px".toInt(); // value is 10
613        */
614
615        toInt: function(){
616                return parseInt(this);
617        },
618
619        toFloat: function(){
620                return parseFloat(this);
621        },
622
623        /*
624        Property: camelCase
625                Converts a hiphenated string to a camelcase string.
626
627        Example:
628                >"I-like-cookies".camelCase(); //"ILikeCookies"
629
630        Returns:
631                the camel cased string
632        */
633
634        camelCase: function(){
635                return this.replace(/-\D/g, function(match){
636                        return match.charAt(1).toUpperCase();
637                });
638        },
639
640        /*
641        Property: hyphenate
642                Converts a camelCased string to a hyphen-ated string.
643
644        Example:
645                >"ILikeCookies".hyphenate(); //"I-like-cookies"
646        */
647
648        hyphenate: function(){
649                return this.replace(/\w[A-Z]/g, function(match){
650                        return (match.charAt(0)+'-'+match.charAt(1).toLowerCase());
651                });
652        },
653
654        /*
655        Property: capitalize
656                Converts the first letter in each word of a string to Uppercase.
657
658        Example:
659                >"i like cookies".capitalize(); //"I Like Cookies"
660
661        Returns:
662                the capitalized string
663        */
664
665        capitalize: function(){
666                return this.toLowerCase().replace(/\b[a-z]/g, function(match){
667                        return match.toUpperCase();
668                });
669        },
670
671        /*
672        Property: trim
673                Trims the leading and trailing spaces off a string.
674
675        Example:
676                >"    i like cookies     ".trim() //"i like cookies"
677
678        Returns:
679                the trimmed string
680        */
681
682        trim: function(){
683                return this.replace(/^\s+|\s+$/g, '');
684        },
685
686        /*
687        Property: clean
688                trims (<String.trim>) a string AND removes all the double spaces in a string.
689
690        Returns:
691                the cleaned string
692
693        Example:
694                >" i      like     cookies      \n\n".clean() //"i like cookies"
695        */
696
697        clean: function(){
698                return this.replace(/\s{2,}/g, ' ').trim();
699        },
700
701        /*
702        Property: rgbToHex
703                Converts an RGB value to hexidecimal. The string must be in the format of "rgb(255, 255, 255)" or "rgba(255, 255, 255, 1)";
704
705        Arguments:
706                array - boolean value, defaults to false. Use true if you want the array ['FF', '33', '00'] as output instead of #FF3300
707
708        Returns:
709                hex string or array. returns transparent if the fourth value of rgba in input string is 0,
710
711        Example:
712                >"rgb(17,34,51)".rgbToHex(); //"#112233"
713                >"rgba(17,34,51,0)".rgbToHex(); //"transparent"
714                >"rgb(17,34,51)".rgbToHex(true); //[11,22,33]
715        */
716
717        rgbToHex: function(array){
718                var rgb = this.match(/\d{1,3}/g);
719                return (rgb) ? rgb.rgbToHex(array) : false;
720        },
721
722        /*
723        Property: hexToRgb
724                Converts a hexidecimal color value to RGB. Input string must be the hex color value (with or without the hash). Also accepts triplets ('333');
725
726        Arguments:
727                array - boolean value, defaults to false. Use true if you want the array ['255', '255', '255'] as output instead of "rgb(255,255,255)";
728
729        Returns:
730                rgb string or array.
731
732        Example:
733                >"#112233".hexToRgb(); //"rgb(17,34,51)"
734                >"#112233".hexToRgb(true); //[17,34,51]
735        */
736
737        hexToRgb: function(array){
738                var hex = this.match('^#?(\\w{1,2})(\\w{1,2})(\\w{1,2})$');
739                return (hex) ? hex.hexToRgb(array) : false;
740        }
741
742});
743
744Array.extend({
745       
746        rgbToHex: function(array){
747                if (this.length < 3) return false;
748                if (this[3] && this[3] == 0) return 'transparent';
749                var hex = [];
750                for (var i = 0; i < 3; i++){
751                        var bit = (this[i]-0).toString(16);
752                        hex.push(bit.length == 1 ? '0'+bit : bit);
753                }
754                return array ? hex : '#'+hex.join('');
755        },
756       
757        hexToRgb: function(array){
758                if (this.length != 4) return false;
759                var rgb = [];
760                for (var i = 1; i < 4; i++){
761                        if (this[i].length == 1) this[i] += this[i];
762                        rgb.push(parseInt(this[i], 16));
763                }
764                return array ? rgb : 'rgb('+rgb.join(',')+')';
765        }
766
767});
768
769/*
770Class: Number
771        contains the internal method toInt.
772*/
773
774Number.extend({
775
776        /*
777        Property: toInt
778                Returns this number; useful because toInt must work on both Strings and Numbers.
779        */
780
781        toInt: function(){
782                return parseInt(this);
783        },
784
785        toFloat: function(){
786                return parseFloat(this);
787        }
788
789});
790
791/*
792Script: Function.js
793        Contains Function prototypes and utility functions .
794
795Author:
796        Valerio Proietti, <http://mad4milk.net>
797
798License:
799        MIT-style license.
800
801Credits:
802        - Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
803*/
804
805/*
806Class: Function
807        A collection of The Function Object prototype methods.
808*/
809
810Function.extend({
811
812        create: function(options){
813                var fn = this;
814                options = Object.extend({
815                        'bind': fn,
816                        'event': false,
817                        'arguments': null,
818                        'delay': false,
819                        'periodical': false,
820                        'attempt': false
821                }, options || {});
822                if (options.arguments != null && typeof options.arguments != 'undefined' && !(options.arguments instanceof Array))
823                        options.arguments = [options.arguments];
824                return function(event){
825                        var args = options.arguments || arguments;
826                        if (options.event){
827                                event = (options.event === true) ? event || window.event : new options.event(event);
828                                args = [event].concat(args);
829                        }
830                        var returns = function(){
831                                return fn.apply(options.bind, args);
832                        };
833                        if (options.delay) return setTimeout(returns, options.delay);
834                        if (options.periodical) return setInterval(returns, options.periodical);
835                        if (options.attempt){
836                                try {
837                                        var result = returns();
838                                } catch(err){
839                                        result = err;
840                                } finally {
841                                        return result;
842                                }
843                        } else return returns();
844                };
845        },
846
847        /*
848        Property: pass
849                Shortcut to create closures with arguments and bind.
850
851        Returns:
852                a function.
853
854        Arguments:
855                args - the arguments passed. must be an array if arguments > 1
856                bind - optional, the object that the "this" of the function will refer to.
857
858        Example:
859                >myFunction.pass([arg1, arg2], myElement);
860        */
861
862        pass: function(args, bind){
863                return this.create({'arguments': args, 'bind': bind});
864        },
865       
866        /*
867        Property: attempt
868                Tries to execute the function, returns either the function results or the error.
869
870        Arguments:
871                args - the arguments passed. must be an array if arguments > 1
872                bind - optional, the object that the "this" of the function will refer to.
873
874        Example:
875                >myFunction.attempt([arg1, arg2], myElement);
876        */
877
878        attempt: function(args, bind){
879                return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
880        },
881
882        /*
883        Property: bind
884                method to easily create closures with "this" altered.
885
886        Arguments:
887                bind - optional, the object that the "this" of the function will refer to.
888                args - optional, the arguments passed. must be an array if arguments > 1
889
890        Returns:
891                a function.
892
893        Example:
894                >function myFunction(){
895                >       this.setStyle('color', 'red');
896                >       // note that 'this' here refers to myFunction, not an element
897                >       // we'll need to bind this function to the element we want to alter
898                >};
899                >var myBoundFunction = myFunction.bind(myElement);
900                >myBoundFunction(); // this will make the element myElement red.
901        */
902
903        bind: function(bind, args){
904                return this.create({'bind': bind, 'arguments': args});
905        },
906
907        /*
908        Property: bindAsEventListener
909                cross browser method to pass event firer
910
911        Arguments:
912                bind - optional, the object that the "this" of the function will refer to.
913                args - optional, the arguments passed. must be an array if arguments > 1
914
915        Returns:
916                a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
917
918        Example:
919                >function myFunction(event){
920                >       alert(event.clientx) //returns the coordinates of the mouse..
921                >};
922                >myElement.onclick = myFunction.bindAsEventListener(myElement);
923        */
924
925        bindAsEventListener: function(bind, args){
926                return this.create({'bind': bind, 'event': true, 'arguments': args});
927        },
928
929        /*
930        Property: delay
931                Delays the execution of a function by a specified duration.
932
933        Arguments:
934                ms - the duration to wait in milliseconds
935                bind - optional, the object that the "this" of the function will refer to.
936                args - optional, the arguments passed. must be an array if arguments > 1
937
938        Example:
939                >myFunction.delay(50, myElement) //wait 50 milliseconds, then call myFunction and bind myElement to it
940                >(function(){alert('one second later...')}).delay(1000); //wait a second and alert
941        */
942
943        delay: function(ms, bind, args){
944                return this.create({'delay': ms, 'bind': bind, 'arguments': args})();
945        },
946
947        /*
948        Property: periodical
949                Executes a function in the specified intervals of time
950
951        Arguments:
952                ms - the duration of the intervals between executions.
953                bind - optional, the object that the "this" of the function will refer to.
954                args - optional, the arguments passed. must be an array if arguments > 1
955        */
956
957        periodical: function(ms, bind, args){
958                return this.create({'periodical': ms, 'bind': bind, 'arguments': args})();
959        }
960
961});
962
963/*
964Script: Element.js
965        Contains useful Element prototypes, to be used with the dollar function <$>.
966
967Author:
968        Valerio Proietti, <http://mad4milk.net>
969
970License:
971        MIT-style license.
972
973Credits:
974        - Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
975*/
976
977/*
978Class: Element
979        Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
980*/
981
982var Element = new Class({
983
984        /*
985        Property: initialize
986                Creates a new element of the type passed in.
987
988        Arguments:
989                el - the tag name for the element you wish to create.
990
991        Example:
992                >var div = new Element('div');
993        */
994
995        initialize: function(el){
996                if ($type(el) == 'string') el = document.createElement(el);
997                return $(el);
998        }
999
1000});
1001
1002/*
1003Function: $()
1004        returns the element passed in with all the Element prototypes applied.
1005
1006Arguments:
1007        el - a reference to an actual element or a string representing the id of an element
1008
1009Example:
1010        >$('myElement') // gets a DOM element by id with all the Element prototypes applied.
1011        >var div = document.getElementById('myElement');
1012        >$(div) //returns an Element also with all the mootools extentions applied.
1013
1014        You'll use this when you aren't sure if a variable is an actual element or an id, as
1015        well as just shorthand for document.getElementById().
1016
1017Returns:
1018        a DOM element or false (if no id was found).
1019
1020Note:
1021        you need to call $ on an element only once to get all the prototypes.
1022        But its no harm to call it multiple times, as it will detect if it has been already extended.
1023*/
1024
1025function $(el){
1026        if (!el) return false;
1027        if (el._element_extended_ || [window, document].test(el)) return el;
1028        if ($type(el) == 'string') el = document.getElementById(el);
1029        if ($type(el) != 'element') return false;
1030        if (['object', 'embed'].test(el.tagName.toLowerCase()) || el.extend) return el;
1031        el._element_extended_ = true;
1032        Garbage.collect(el);
1033        el.extend = Object.extend;
1034        if (!(el instanceof HTMLElement)) el.extend(Element.prototype);
1035        return el;
1036};
1037
1038//elements class
1039
1040var Elements = new Class({});
1041
1042new Object.Native(Elements);
1043
1044document.getElementsBySelector = document.getElementsByTagName;
1045
1046/*
1047Function: $$()
1048        Selects, and extends DOM elements.
1049
1050Arguments:
1051        HTMLCollection(document.getElementsByTagName, element.childNodes), an array of elements, a string.
1052
1053Note:
1054        if you loaded <Dom.js>, $$ will also accept CSS Selectors.
1055
1056Example:
1057        >$$('a') //an array of all anchor tags on the page
1058        >$$('a', 'b') //an array of all anchor and bold tags on the page
1059        >$$('#myElement') //array containing only the element with id = myElement. (only with <Dom.js>)
1060        >$$('#myElement a.myClass') //an array of all anchor tags with the class "myClass" within the DOM element with id "myElement" (only with <Dom.js>)
1061
1062Returns:
1063        array - array of all the dom elements matched
1064*/
1065
1066function $$(){
1067        if (!arguments) return false;
1068        if (arguments.length == 1){
1069                if (!arguments[0]) return false;
1070                if (arguments[0]._elements_extended_) return arguments[0];
1071        }
1072        var elements = [];
1073        $each(arguments, function(selector){
1074                switch ($type(selector)){
1075                        case 'element': elements.push($(selector)); break;
1076                        case 'string': selector = document.getElementsBySelector(selector);
1077                        default:
1078                        if (selector.length){
1079                                $each(selector, function(el){
1080                                        if ($(el)) elements.push(el);
1081                                });
1082                        }
1083                }
1084        });
1085        elements._elements_extended_ = true;
1086        return Object.extend(elements, new Elements);
1087};
1088
1089Elements.Multi = function(property){
1090        return function(){
1091                var args = arguments;
1092                var items = [];
1093                var elements = true;
1094                $each(this, function(el){
1095                        var returns = el[property].apply(el, args);
1096                        if ($type(returns) != 'element') elements = false;
1097                        items.push(returns);
1098                });
1099                if (elements) items = $$(items);
1100                return items;
1101        };
1102};
1103
1104Element.extend = function(properties){
1105        for (var property in properties){
1106                HTMLElement.prototype[property] = properties[property];
1107                Element.prototype[property] = properties[property];
1108                Elements.prototype[property] = Elements.Multi(property);
1109        }
1110};
1111
1112Element.extend({
1113
1114        inject: function(el, where){
1115                el = $(el) || new Element(el);
1116                switch (where){
1117                        case "before": $(el.parentNode).insertBefore(this, el); break;
1118                        case "after":
1119                                if (!el.getNext()) $(el.parentNode).appendChild(this);
1120                                else $(el.parentNode).insertBefore(this, el.getNext());
1121                                break;
1122                        case "inside": el.appendChild(this);
1123                }
1124                return this;
1125        },
1126
1127        /*
1128        Property: injectBefore
1129                Inserts the Element before the passed element.
1130
1131        Parameteres:
1132                el - a string representing the element to be injected in (myElementId, or div), or an element reference.
1133                If you pass div or another tag, the element will be created.
1134
1135        Example:
1136                >html:
1137                ><div id="myElement"></div>
1138                ><div id="mySecondElement"></div>
1139                >js:
1140                >$('mySecondElement').injectBefore('myElement');
1141                >resulting html:
1142                ><div id="mySecondElement"></div>
1143                ><div id="myElement"></div>
1144
1145        */
1146
1147        injectBefore: function(el){
1148                return this.inject(el, 'before');
1149        },
1150
1151        /*
1152        Property: injectAfter
1153                Same as <Element.injectBefore>, but inserts the element after.
1154        */
1155
1156        injectAfter: function(el){
1157                return this.inject(el, 'after');
1158        },
1159
1160        /*
1161        Property: injectInside
1162                Same as <Element.injectBefore>, but inserts the element inside.
1163        */
1164
1165        injectInside: function(el){
1166                return this.inject(el, 'inside');
1167        },
1168
1169        /*
1170        Property: adopt
1171                Inserts the passed element inside the Element. Works as <Element.injectInside> but in reverse.
1172
1173        Parameteres:
1174                el - a string representing the element to be injected in (myElementId, or div), or an element reference.
1175                If you pass div or another tag, the element will be created.
1176        */
1177
1178        adopt: function(el){
1179                this.appendChild($(el) || new Element(el));
1180                return this;
1181        },
1182
1183        /*
1184        Property: remove
1185                Removes the Element from the DOM.
1186
1187        Example:
1188                >$('myElement').remove() //bye bye
1189        */
1190
1191        remove: function(){
1192                this.parentNode.removeChild(this);
1193                return this;
1194        },
1195
1196        /*
1197        Property: clone
1198                Clones the Element and returns the cloned one.
1199
1200        Returns:
1201                the cloned element
1202
1203        Example:
1204                >var clone = $('myElement').clone().injectAfter('myElement');
1205                >//clones the Element and append the clone after the Element.
1206        */
1207
1208        clone: function(contents){
1209                var el = this.cloneNode(contents !== false);
1210                return $(el);
1211        },
1212
1213        /*
1214        Property: replaceWith
1215                Replaces the Element with an element passed.
1216
1217        Parameteres:
1218                el - a string representing the element to be injected in (myElementId, or div), or an element reference.
1219                If you pass div or another tag, the element will be created.
1220
1221        Returns:
1222                the passed in element
1223
1224        Example:
1225                >$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place.
1226        */
1227
1228        replaceWith: function(el){
1229                el = $(el) || new Element(el);
1230                this.parentNode.replaceChild(el, this);
1231                return el;
1232        },
1233
1234        /*
1235        Property: appendText
1236                Appends text node to a DOM element.
1237
1238        Arguments:
1239                text - the text to append.
1240
1241        Example:
1242                ><div id="myElement">hey</div>
1243                >$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy"
1244        */
1245
1246        appendText: function(text){
1247                if (window.ie){
1248                        switch(this.getTag()){
1249                                case 'style': this.styleSheet.cssText = text; return this;
1250                                case 'script': this.setProperty('text', text); return this;
1251                        }
1252                }
1253                this.appendChild(document.createTextNode(text));
1254                return this;
1255        },
1256
1257        /*
1258        Property: hasClass
1259                Tests the Element to see if it has the passed in className.
1260
1261        Returns:
1262                true - the Element has the class
1263                false - it doesn't
1264         
1265        Arguments:
1266                className - the class name to test.
1267         
1268        Example:
1269                ><div id="myElement" class="testClass"></div>
1270                >$('myElement').hasClass('testClass'); //returns true
1271        */
1272
1273        hasClass: function(className){
1274                return this.className.test('(?:^|\\s+)' + className + '(?:\\s+|$)');
1275        },
1276
1277        /*
1278        Property: addClass
1279                Adds the passed in class to the Element, if the element doesnt already have it.
1280
1281        Arguments:
1282                className - the class name to add
1283
1284        Example:
1285                ><div id="myElement" class="testClass"></div>
1286                >$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div>
1287        */
1288
1289        addClass: function(className){
1290                if (!this.hasClass(className)) this.className = (this.className+' '+className).clean();
1291                return this;
1292        },
1293
1294        /*
1295        Property: removeClass
1296                works like <Element.addClass>, but removes the class from the element.
1297        */
1298
1299        removeClass: function(className){
1300                if (this.hasClass(className)) this.className = this.className.replace(className, '').clean();
1301                return this;
1302        },
1303
1304        /*
1305        Property: toggleClass
1306                Adds or removes the passed in class name to the element, depending on if it's present or not.
1307
1308        Arguments:
1309                className - the class to add or remove
1310
1311        Example:
1312                ><div id="myElement" class="myClass"></div>
1313                >$('myElement').toggleClass('myClass');
1314                ><div id="myElement" class=""></div>
1315                >$('myElement').toggleClass('myClass');
1316                ><div id="myElement" class="myClass"></div>
1317        */
1318
1319        toggleClass: function(className){
1320                return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
1321        },
1322
1323        /*
1324        Property: setStyle
1325                Sets a css property to the Element.
1326
1327                Arguments:
1328                        property - the property to set
1329                        value - the value to which to set it
1330
1331                Example:
1332                        >$('myElement').setStyle('width', '300px'); //the width is now 300px
1333        */
1334
1335        setStyle: function(property, value){
1336                if (property == 'opacity') this.setOpacity(parseFloat(value));
1337                else this.style[property.camelCase()] = (value.push) ? value.rgbToHex() : value;
1338                return this;
1339        },
1340
1341        /*
1342        Property: setStyles
1343                Applies a collection of styles to the Element.
1344
1345        Arguments:
1346                source - an object or string containing all the styles to apply
1347
1348        Examples:
1349                >$('myElement').setStyles({
1350                >       border: '1px solid #000',
1351                >       width: '300px',
1352                >       height: '400px'
1353                >});
1354
1355                OR
1356
1357                >$('myElement').setStyle('border: 1px solid #000; width: 300px; height: 400px;');
1358        */
1359
1360        setStyles: function(source){
1361                switch ($type(source)){
1362                        case 'object':
1363                                for (var property in source) this.setStyle(property, source[property]);
1364                                break;
1365                        case 'string':
1366                                if (window.ie) this.cssText = source;
1367                                else this.setAttribute('style', source);
1368                }
1369                return this;
1370        },
1371
1372        /*
1373        Property: setOpacity
1374                Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity == 1.
1375
1376        Arguments:
1377                opacity - Accepts numbers from 0 to 1.
1378
1379        Example:
1380                >$('myElement').setOpacity(0.5) //make it 50% transparent
1381        */
1382
1383        setOpacity: function(opacity){
1384                if (opacity == 0){
1385                        if(this.style.visibility != "hidden") this.style.visibility = "hidden";
1386                } else {
1387                        if(this.style.visibility != "visible") this.style.visibility = "visible";
1388                }
1389                if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
1390                if (window.ie) this.style.filter = "alpha(opacity=" + opacity*100 + ")";
1391                this.style.opacity = this.opacity = opacity;
1392                return this;
1393        },
1394
1395        /*
1396        Property: getStyle
1397                Returns the style of the Element given the property passed in.
1398
1399        Arguments:
1400                property - the css style property you want to retrieve
1401
1402        Example:
1403                >$('myElement').getStyle('width'); //returns "400px"
1404                >//but you can also use
1405                >$('myElement').getStyle('width').toInt(); //returns "400"
1406
1407        Returns:
1408                the style as a string
1409        */
1410
1411        getStyle: function(property){
1412                property = property.camelCase();
1413                var style = this.style[property] || false;
1414                if (!$chk(style)){
1415                        if (property == 'opacity') return $chk(this.opacity) ? this.opacity : 1;
1416                        if (['margin', 'padding'].test(property)){
1417                                return [this.getStyle(property+'-top') || 0, this.getStyle(property+'-right') || 0,
1418                                                this.getStyle(property+'-bottom') || 0, this.getStyle(property+'-left') || 0].join(' ');
1419                        }
1420                        if (document.defaultView) style = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
1421                        else if (this.currentStyle) style = this.currentStyle[property];
1422                }
1423                return (style && property.test('color', 'i') && style.test('rgb')) ? style.rgbToHex() : style;
1424        },
1425
1426        /*
1427        Property: addEvent
1428                Attaches an event listener to a DOM element.
1429
1430        Arguments:
1431                type - the event to monitor ('click', 'load', etc) without the prefix 'on'.
1432                fn - the function to execute
1433
1434        Example:
1435                >$('myElement').addEvent('click', function(){alert('clicked!')});
1436        */
1437
1438        addEvent: function(type, fn){
1439                this.events = this.events || {};
1440                this.events[type] = this.events[type] || {'keys': [], 'values': []};
1441                if (!this.events[type].keys){
1442                        this.events[type].keys = [];
1443                }
1444                if (!this.events[type].values){
1445                        this.events[type].values = [];
1446                }
1447                if (!this.events[type].keys.test(fn)){
1448                        this.events[type].keys.push(fn);
1449                        if (this.addEventListener){
1450                                this.addEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, fn, false);
1451                        } else {
1452                                fn = fn.bind(this);
1453                                this.attachEvent('on'+type, fn);
1454                                this.events[type].values.push(fn);
1455                        }
1456                }
1457                return this;
1458        },
1459
1460        addEvents: function(source){
1461                if (source){
1462                        for (var type in source) this.addEvent(type, source[type]);
1463                }
1464                return this;
1465        },
1466
1467        /*
1468        Property: removeEvent
1469                Works as Element.addEvent, but instead removes the previously added event listener.
1470        */
1471
1472        removeEvent: function(type, fn){
1473                if (this.events && this.events[type]){
1474                        var pos = this.events[type].keys.indexOf(fn);
1475                        if (pos == -1) return this;
1476                        var key = this.events[type].keys.splice(pos,1)[0];
1477                        if (this.removeEventListener){
1478                                this.removeEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, key, false);
1479                        } else {
1480                                this.detachEvent('on'+type, this.events[type].values.splice(pos,1)[0]);
1481                        }
1482                }
1483                return this;
1484        },
1485
1486        /*
1487        Property: removeEvents
1488                removes all events of a certain type from an element. if no argument is passed in, removes all events.
1489        */
1490
1491        removeEvents: function(type){
1492                if (this.events){
1493                        if (type){
1494                                if (this.events[type]){
1495                                        this.events[type].keys.each(function(fn){
1496                                                this.removeEvent(type, fn);
1497                                        }, this);
1498                                        this.events[type] = null;
1499                                }
1500                        } else {
1501                                for (var evType in this.events) this.removeEvents(evType);
1502                                this.events = null;
1503                        }
1504                }
1505                return this;
1506        },
1507
1508        /*
1509        Property: fireEvent
1510                executes all events of the specified type present in the element.
1511        */
1512
1513        fireEvent: function(type, args){
1514                if (this.events && this.events[type]){
1515                        args = args || [];
1516                        if ($type(args) != 'array') args = [args];
1517                        this.events[type].keys.each(function(fn){
1518                                fn.apply(this, args);
1519                        }, this);
1520                }
1521        },
1522
1523        getBrother: function(what){
1524                var el = this[what+'Sibling'];
1525                while ($type(el) == 'whitespace') el = el[what+'Sibling'];
1526                return $(el);
1527        },
1528
1529        /*
1530        Property: getPrevious
1531                Returns the previousSibling of the Element, excluding text nodes.
1532
1533        Example:
1534                >$('myElement').getPrevious(); //get the previous DOM element from myElement
1535
1536        Returns:
1537                the sibling element or undefined if none found.
1538        */
1539
1540        getPrevious: function(){
1541                return this.getBrother('previous');
1542        },
1543
1544        /*
1545        Property: getNext
1546                Works as Element.getPrevious, but tries to find the nextSibling.
1547        */
1548
1549        getNext: function(){
1550                return this.getBrother('next');
1551        },
1552
1553        /*
1554        Property: getFirst
1555                Works as <Element.getPrevious>, but tries to find the firstChild.
1556        */
1557
1558        getFirst: function(){
1559                var el = this.firstChild;
1560                while ($type(el) == 'whitespace') el = el.nextSibling;
1561                return $(el);
1562        },
1563
1564        /*
1565        Property: getLast
1566                Works as <Element.getPrevious>, but tries to find the lastChild.
1567        */
1568
1569        getLast: function(){
1570                var el = this.lastChild;
1571                while ($type(el) == 'whitespace') el = el.previousSibling;
1572                return $(el);
1573        },
1574       
1575        /*
1576        Property: getParent
1577                returns the $(element.parentNode)
1578        */
1579
1580        getParent: function(){
1581                return $(this.parentNode);
1582        },
1583       
1584        /*
1585        Property: getChildren
1586                returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>.
1587        */
1588
1589        getChildren: function(){
1590                return $$(this.childNodes);
1591        },
1592
1593        /*
1594        Property: setProperty
1595                Sets an attribute for the Element.
1596
1597        Arguments:
1598                property - the property to assign the value passed in
1599                value - the value to assign to the property passed in
1600
1601        Example:
1602                >$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source
1603        */
1604
1605        setProperty: function(property, value){
1606                switch (property){
1607                        case 'class': this.className = value; break;
1608                        case 'style': this.setStyles(value); break;
1609                        case 'name': if (window.ie6){
1610                                var el = $(document.createElement('<'+this.getTag()+' name="'+value+'" />'));
1611                                $each(this.attributes, function(attribute){
1612                                        if (attribute.name != 'name') el.setProperty(attribute.name, attribute.value);
1613                                });
1614                                if (this.parentNode) this.replaceWith(el);
1615                                return el;
1616                        }
1617                        default: this.setAttribute(property, value);
1618                }
1619                return this;
1620        },
1621
1622        /*
1623        Property: setProperties
1624                Sets numerous attributes for the Element.
1625
1626        Arguments:
1627                source - an object with key/value pairs.
1628
1629        Example:
1630                >$('myElement').setProperties({
1631                >       src: 'whatever.gif',
1632                >       alt: 'whatever dude'
1633                >});
1634                ><img src="whatever.gif" alt="whatever dude">
1635        */
1636
1637        setProperties: function(source){
1638                for (var property in source) this.setProperty(property, source[property]);
1639                return this;
1640        },
1641
1642        /*
1643        Property: setHTML
1644                Sets the innerHTML of the Element.
1645
1646        Arguments:
1647                html - the new innerHTML for the element.
1648
1649        Example:
1650                >$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML
1651        */
1652
1653        setHTML: function(html){
1654                this.innerHTML = html;
1655                return this;
1656        },
1657
1658        /*
1659        Property: getProperty
1660                Gets the an attribute of the Element.
1661
1662        Arguments:
1663                property - the attribute to retrieve
1664
1665        Example:
1666                >$('myImage').getProperty('src') // returns whatever.gif
1667
1668        Returns:
1669                the value, or an empty string
1670        */
1671
1672        getProperty: function(property){
1673                return (property == 'class') ? this.className : this.getAttribute(property);
1674        },
1675
1676        /*
1677        Property: getTag
1678                Returns the tagName of the element in lower case.
1679
1680        Example:
1681                >$('myImage').getTag() // returns 'img'
1682
1683        Returns:
1684                The tag name in lower case
1685        */
1686
1687        getTag: function(){
1688                return this.tagName.toLowerCase();
1689        },
1690
1691        getOffsets: function(){
1692                var el = this, offsetLeft = 0, offsetTop = 0;
1693                do {
1694                        offsetLeft += el.offsetLeft || 0;
1695                        offsetTop += el.offsetTop || 0;
1696                        el = el.offsetParent;
1697                } while (el);
1698                return {'x': offsetLeft, 'y': offsetTop};
1699        },
1700
1701        /*
1702        Property: scrollTo
1703                scrolls the element to the specified coordinated (if the element has an overflow)
1704
1705        Arguments:
1706                x - the x coordinate
1707                y - the y coordinate
1708
1709        Example:
1710                >$('myElement').scrollTo(0, 100)
1711        */
1712
1713        scrollTo: function(x, y){
1714                this.scrollLeft = x;
1715                this.scrollTop = y;
1716        },
1717
1718        /*
1719        Property: getSize
1720                return an Object representing the size/scroll values of the element.
1721
1722        Example:
1723                (start code)
1724                $('myElement').getSize();
1725                (end)
1726
1727        Returns:
1728                (start code)
1729                {
1730                        'scroll': {'x': 100, 'y': 100},
1731                        'size': {'x': 200, 'y': 400},
1732                        'scrollSize': {'x': 300, 'y': 500}
1733                }
1734                (end)
1735        */
1736
1737        getSize: function(){
1738                return {
1739                        'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
1740                        'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
1741                        'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
1742                };
1743        },
1744
1745        /*
1746        Property: getTop
1747                Returns the distance from the top of the window to the Element.
1748        */
1749
1750        getTop: function(){
1751                return this.getOffsets().y;
1752        },
1753
1754        /*
1755        Property: getLeft
1756                Returns the distance from the left of the window to the Element.
1757        */
1758
1759        getLeft: function(){
1760                return this.getOffsets().x;
1761        },
1762
1763        /*
1764        Property: getPosition
1765                Returns an object with width, height, left, right, top, and bottom, representing the values of the Element
1766
1767        Example:
1768                (start code)
1769                var myValues = $('myElement').getPosition();
1770                (end)
1771
1772        Returns:
1773                (start code)
1774                {
1775                        width: 200,
1776                        height: 300,
1777                        left: 100,
1778                        top: 50,
1779                        right: 300,
1780                        bottom: 350
1781                }
1782                (end)
1783        */
1784
1785        getPosition: function(){
1786                var offs = this.getOffsets();
1787                var obj = {
1788                        'width': this.offsetWidth,
1789                        'height': this.offsetHeight,
1790                        'left': offs.x,
1791                        'top': offs.y
1792                };
1793                obj.right = obj.left + obj.width;
1794                obj.bottom = obj.top + obj.height;
1795                return obj;
1796        },
1797
1798        /*
1799        Property: getValue
1800                Returns the value of the Element, if its tag is textarea, select or input. no multiple select support.
1801        */
1802
1803        getValue: function(){
1804                switch (this.getTag()){
1805                        case 'select': if (this.selectedIndex != -1) return this.options[this.selectedIndex].value; break;
1806                        case 'input': if (!(this.checked && ['checkbox', 'radio'].test(this.type)) && !['hidden', 'text', 'password'].test(this.type)) break;
1807                        case 'textarea': return this.value;
1808                }
1809                return false;
1810        }
1811
1812});
1813
1814var Window = window;
1815
1816window.addEvent = document.addEvent = Element.prototype.addEvent;
1817window.removeEvent = document.removeEvent = Element.prototype.removeEvent;
1818
1819var Garbage = {
1820
1821        elements: [],
1822
1823        collect: function(element){
1824                Garbage.elements.push(element);
1825        },
1826
1827        trash: function(){
1828                window.removeEvent('unload', Garbage.trash);
1829                Garbage.elements.each(function(el){
1830                        el.removeEvents();
1831                        for (var p in Element.prototype) HTMLElement[p] = window[p] = document[p] = el[p] = null;
1832                        el.extend = null;
1833                });
1834        }
1835
1836};
1837
1838window.addEvent('unload', Garbage.trash);
1839
1840/*
1841Script: Event.js
1842        Event class
1843
1844Author:
1845        Valerio Proietti, <http://mad4milk.net>, Michael Jackson, <http://ajaxon.com/michael>
1846
1847License:
1848        MIT-style license.
1849*/
1850
1851/*
1852Class: Event
1853        Cross browser methods to manage events.
1854
1855Arguments:
1856        event - the event
1857
1858Properties:
1859        shift - true if the user pressed the shift
1860        control - true if the user pressed the control
1861        alt - true if the user pressed the alt
1862        meta - true if the user pressed the meta key
1863        code - the keycode of the key pressed
1864        page.x - the x position of the mouse, relative to the full window
1865        page.y - the y position of the mouse, relative to the full window
1866        client.x - the x position of the mouse, relative to the viewport
1867        client.y - the y position of the mouse, relative to the viewport
1868        key - the key pressed as a lowercase string. key also returns 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', 'esc'. Handy for these special keys.
1869        target - the event target
1870        relatedTarget - the event related target
1871
1872Example:
1873        (start code)
1874        $('myLink').onkeydown = function(event){
1875                var event = new Event(event);
1876                //event is now the Event class.
1877                alert(event.key); //returns the lowercase letter pressed
1878                alert(event.shift); //returns true if the key pressed is shift
1879                if (event.key == 's' && event.control) alert('document saved');
1880        };
1881        (end)
1882*/
1883
1884var Event = new Class({
1885
1886        initialize: function(event){
1887                this.event = event || window.event;
1888                this.type = this.event.type;
1889                this.target = this.event.target || this.event.srcElement;
1890                if (this.target.nodeType == 3) this.target = this.target.parentNode; // Safari
1891                this.shift = this.event.shiftKey;
1892                this.control = this.event.ctrlKey;
1893                this.alt = this.event.altKey;
1894                this.meta = this.event.metaKey;
1895                if (['DOMMouseScroll', 'mousewheel'].test(this.type)){
1896                        this.wheel = this.event.wheelDelta ? (this.event.wheelDelta / (window.opera ? -120 : 120)) : -(this.event.detail || 0) / 3;
1897                } else if (this.type.test('key')){
1898                        this.code = this.event.which || this.event.keyCode;
1899                        for (var name in Event.keys){
1900                                if (Event.keys[name] == this.code) var special = name;
1901                        }
1902                        this.key = special || String.fromCharCode(this.code).toLowerCase();
1903
1904                } else if (this.type.test('mouse') || this.type == 'click'){
1905                        this.page = {
1906                                'x': this.event.pageX || this.event.clientX + document.documentElement.scrollLeft,
1907                                'y': this.event.pageY || this.event.clientY + document.documentElement.scrollTop
1908                        };
1909                        this.client = {
1910                                'x': this.event.pageX ? this.event.pageX - window.pageXOffset : this.event.clientX,
1911                                'y': this.event.pageY ? this.event.pageY - window.pageYOffset : this.event.clientY
1912                        };
1913                        this.rightClick = (this.event.which == 3) || (this.event.button == 2);
1914                        switch (this.type){
1915                                case 'mouseover': this.relatedTarget = this.event.relatedTarget || this.event.fromElement; break;
1916                                case 'mouseout': this.relatedTarget = this.event.relatedTarget || this.event.toElement;
1917                        }
1918                }
1919        },
1920
1921        /*
1922        Property: stop
1923                cross browser method to stop an event
1924        */
1925
1926        stop: function() {
1927                this.stopPropagation();
1928                this.preventDefault();
1929                return this;
1930        },
1931
1932        /*
1933        Property: stopPropagation
1934                cross browser method to stop the propagation of an event
1935        */
1936
1937        stopPropagation: function(){
1938                if (this.event.stopPropagation) this.event.stopPropagation();
1939                else this.event.cancelBubble = true;
1940                return this;
1941    },
1942
1943        /*
1944        Property: preventDefault
1945                cross browser method to prevent the default action of the event
1946        */
1947
1948        preventDefault: function(){
1949                if (this.event.preventDefault) this.event.preventDefault();
1950                else this.event.returnValue = false;
1951                return this;
1952        }
1953
1954});
1955
1956Event.keys = {
1957        'enter': 13,
1958        'up': 38,
1959        'down': 40,
1960        'left': 37,
1961        'right': 39,
1962        'esc': 27,
1963        'space': 32,
1964        'backspace': 8,
1965        'delete': 46
1966};
1967
1968Function.extend({
1969
1970        /*
1971        Property: bindWithEvent
1972                automatically passes mootools Event Class.
1973
1974        Arguments:
1975                bind - optional, the object that the "this" of the function will refer to.
1976
1977        Returns:
1978                a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
1979
1980        Example:
1981                >function myFunction(event){
1982                >       alert(event.clientx) //returns the coordinates of the mouse..
1983                >};
1984                >myElement.onclick = myFunction.bindWithEvent(myElement);
1985        */
1986
1987        bindWithEvent: function(bind, args){
1988                return this.create({'bind': bind, 'arguments': args, 'event': Event});
1989        }
1990
1991});
1992
1993
1994/*
1995Script: Common.js
1996        Contains common implementations for custom classes. In Mootools is implemented in <Ajax> and <Fx>.
1997
1998Author:
1999        Valerio Proietti, <http://mad4milk.net>
2000
2001License:
2002        MIT-style license.
2003*/
2004
2005/*
2006Class: Chain
2007        An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
2008        Currently implemented in <Fx> and <Ajax>. In <Fx> for example, is used to execute a list of function, one after another, once the effect is completed.
2009        The functions will not be fired all togheter, but one every completion, to create custom complex animations.
2010
2011Example:
2012        (start code)
2013        var myFx = new Fx.Style('element', 'opacity');
2014
2015        myFx.start(1,0).chain(function(){
2016                myFx.start(0,1);
2017        }).chain(function(){
2018                myFx.start(1,0);
2019        }).chain(function(){
2020                myFx.start(0,1);
2021        });
2022        //the element will appear and disappear three times
2023        (end)
2024*/
2025
2026var Chain = new Class({
2027
2028        /*
2029        Property: chain
2030                adds a function to the Chain instance stack.
2031
2032        Arguments:
2033                fn - the function to append.
2034        */
2035
2036        chain: function(fn){
2037                this.chains = this.chains || [];
2038                this.chains.push(fn);
2039                return this;
2040        },
2041
2042        /*
2043        Property: callChain
2044                Executes the first function of the Chain instance stack, then removes it. The first function will then become the second.
2045        */
2046
2047        callChain: function(){
2048                if (this.chains && this.chains.length) this.chains.splice(0, 1)[0].delay(10, this);
2049        },
2050
2051        /*
2052        Property: clearChain
2053                Clears the stack of a Chain instance.
2054        */
2055
2056        clearChain: function(){
2057                this.chains = [];
2058        }
2059
2060});
2061
2062/*
2063Class: Events
2064        An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
2065        In <Fx> Class, for example, is used to give the possibility add any number of functions to the Effects events, like onComplete, onStart, onCancel
2066
2067Example:
2068        (start code)
2069        var myFx = new Fx.Style('element', 'opacity').addEvent('onComplete', function(){
2070                alert('the effect is completed');
2071        }).addEvent('onComplete', function(){
2072                alert('I told you the effect is completed');
2073        });
2074
2075        myFx.start(0,1);
2076        //upon completion it will display the 2 alerts, in order.
2077        (end)
2078*/
2079
2080var Events = new Class({
2081
2082        /*
2083        Property: addEvent
2084                adds an event to the stack of events of the Class instance.
2085        */
2086
2087        addEvent: function(type, fn){
2088                if (fn != Class.empty){
2089                        this.events = this.events || {};
2090                        this.events[type] = this.events[type] || [];
2091                        if (!this.events[type].test(fn)) this.events[type].push(fn);
2092                }
2093                return this;
2094        },
2095
2096        /*
2097        Property: fireEvent
2098                fires all events of the specified type in the Class instance.
2099        */
2100
2101        fireEvent: function(type, args, delay){
2102                if (this.events && this.events[type]){
2103                        this.events[type].each(function(fn){
2104                                fn.create({'bind': this, 'delay': delay, 'arguments': args})();
2105                        }, this);
2106                }
2107                return this;
2108        },
2109
2110        /*
2111        Property: removeEvent
2112                removes an event from the stack of events of the Class instance.
2113        */
2114
2115        removeEvent: function(type, fn){
2116                if (this.events && this.events[type]) this.events[type].remove(fn);
2117                return this;
2118        }
2119
2120});
2121
2122/*
2123Class: Options
2124        An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
2125        Used to automate the options settings, also adding Class <Events> when the option begins with on.
2126*/
2127
2128var Options = new Class({
2129
2130        /*
2131        Property: setOptions
2132                sets this.options
2133
2134        Arguments:
2135                defaults - the default set of options
2136                options - the user entered options. can be empty too.
2137
2138        Note:
2139                if your Class has <Events> implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event.
2140        */
2141
2142        setOptions: function(defaults, options){
2143                this.options = Object.extend(defaults, options);
2144                if (this.addEvent){
2145                        for (var option in this.options){
2146                                if (($type(this.options[option]) == 'function') && option.test('^on[A-Z]')) this.addEvent(option, this.options[option]);
2147                        }
2148                }
2149                return this;
2150        }
2151
2152});
2153
2154/*
2155Script: Dom.js
2156        Css Query related function and <Element> extensions
2157
2158Author:
2159        Valerio Proietti, <http://mad4milk.net>
2160
2161License:
2162        MIT-style license.
2163*/
2164
2165/* Section: Utility Functions */
2166
2167/*
2168Function: $E
2169        Selects a single (i.e. the first found) Element based on the selector passed in and an optional filter element.
2170
2171Arguments:
2172        selector - the css selector to match
2173        filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
2174
2175Example:
2176        >$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement'
2177
2178Returns:
2179        a DOM element - the first element that matches the selector
2180*/
2181
2182function $E(selector, filter){
2183        return ($(filter) || document).getElement(selector);
2184};
2185
2186/*
2187Function: $ES
2188        Returns a collection of Elements that match the selector passed in limited to the scope of the optional filter.
2189        See Also: <Element.getElements> for an alternate syntax.
2190
2191Returns:
2192        an array of dom elements that match the selector within the filter
2193
2194Arguments:
2195        selector - css selector to match
2196        filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
2197
2198Examples:
2199        >$ES("a") //gets all the anchor tags; synonymous with $$("a")
2200        >$ES('a','myElement') //get all the anchor tags within $('myElement')
2201*/
2202
2203function $ES(selector, filter){
2204        return ($(filter) || document).getElementsBySelector(selector);
2205};
2206
2207/*
2208Class: Element
2209        Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
2210*/
2211
2212Element.extend({
2213
2214        /*
2215        Property: getElements
2216                Gets all the elements within an element that match the given (single) selector.
2217
2218        Arguments:
2219                selector - the css selector to match
2220
2221        Example:
2222                >$('myElement').getElements('a'); // get all anchors within myElement
2223
2224        Credits:
2225                Say thanks to Christophe Beyls <http://digitalia.be> for the new regular expression that rules getElements, a big step forward in terms of speed.
2226        */
2227
2228        getElements: function(selector){
2229                var filters = [];
2230                selector.clean().split(' ').each(function(sel, i){
2231                        var param = sel.match('^(\\w*|\\*)(?:#([\\w_-]+)|\\.([\\w_-]+))?(?:\\[["\']?(\\w+)["\']?(?:([\\*\\^\\$]?=)["\']?(\\w*)["\']?)?\\])?$');
2232                        //PARAM ARRAY: 0 = full string: 1 = tag; 2 = id; 3 = class; 4 = attribute; 5 = operator; 6 = value;
2233                        if (!param) return;
2234                        param[1] = param[1] || '*';
2235                        if (i == 0){
2236                                if (param[2]){
2237                                        var el = this.getElementById(param[2]);
2238                                        if (!el || ((param[1] != '*') && (Element.prototype.getTag.call(el) != param[1]))) return;
2239                                        filters = [el];
2240                                } else {
2241                                        filters = $A(this.getElementsByTagName(param[1]));
2242                                }
2243                        } else {
2244                                filters = Elements.prototype.filterByTagName.call(filters, param[1]);
2245                                if (param[2]) filters = Elements.prototype.filterById.call(filters, param[2]);
2246                        }
2247                        if (param[3]) filters = Elements.prototype.filterByClassName.call(filters, param[3]);
2248                        if (param[4]) filters = Elements.prototype.filterByAttribute.call(filters, param[4], param[6], param[5]);
2249                }, this);
2250                return $$(filters);
2251        },
2252
2253        /*
2254        Property: getElementById
2255                Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById.
2256
2257        Arguments:
2258                id - the id of the element to find.
2259        */
2260
2261        getElementById: function(id){
2262                var el = document.getElementById(id);
2263                if (!el) return false;
2264                for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
2265                        if (!parent) return false;
2266                }
2267                return el;
2268        },
2269
2270        /*
2271        Property: getElement
2272                Same as <Element.getElements>, but returns only the first. Alternate syntax for <$E>, where filter is the Element.
2273        */
2274
2275        getElement: function(selector){
2276                return this.getElementsBySelector(selector)[0];
2277        },
2278
2279        /*
2280        Property: getElementsBySelector
2281                Same as <Element.getElements>, but allows for comma separated selectors, as in css. Alternate syntax for <$$>, where filter is the Element.
2282
2283        */
2284
2285        getElementsBySelector: function(selector){
2286                var els = [];
2287                selector.split(',').each(function(sel){
2288                        els.extend(this.getElements(sel));
2289                }, this);
2290                return $$(els);
2291        }
2292
2293});
2294
2295document.extend = Object.extend;
2296
2297/* Section: document related functions */
2298
2299document.extend({
2300        /*
2301        Function: document.getElementsByClassName
2302                Returns all the elements that match a specific class name.
2303                Here for compatibility purposes. can also be written: document.getElements('.className'), or $$('.className')
2304        */
2305
2306        getElementsByClassName: function(className){
2307                return document.getElements('.'+className);
2308        },
2309        getElement: Element.prototype.getElement,
2310        getElements: Element.prototype.getElements,
2311        getElementsBySelector: Element.prototype.getElementsBySelector
2312
2313});
2314
2315/*
2316Class: Elements
2317        Methods for dom queries arrays, as <$$>.
2318*/
2319
2320Elements.extend({
2321
2322        //internal methods
2323
2324        filterById: function(id, tag){
2325                var found = [];
2326                this.each(function(el){
2327                        if (el.id == id) found.push(el);
2328                });
2329                return found;
2330        },
2331
2332        filterByClassName: function(className){
2333                var found = [];
2334                this.each(function(el){
2335                        if (Element.prototype.hasClass.call(el, className)) found.push(el);
2336                });
2337                return found;
2338        },
2339
2340        filterByTagName: function(tagName){
2341                var found = [];
2342                this.each(function(el){
2343                        found.extend(el.getElementsByTagName(tagName));
2344                });
2345                return found;
2346        },
2347
2348        filterByAttribute: function(name, value, operator){
2349                var found = [];
2350                this.each(function(el){
2351                        var att = el.getAttribute(name);
2352                        if (!att) return found;
2353                        if (!operator) return found.push(el);
2354
2355                        switch (operator){
2356                                case '*=': if (att.test(value)) found.push(el); break;
2357                                case '=': if (att == value) found.push(el); break;
2358                                case '^=': if (att.test('^'+value)) found.push(el); break;
2359                                case '$=': if (att.test(value+'$')) found.push(el);
2360                        }
2361                        return found;
2362                });
2363                return found;
2364        }
2365
2366});
2367
2368/*
2369Script: Hash.js
2370        Contains the class Hash.
2371
2372Author:
2373        Christophe Beyls <http://digitalia.be>
2374
2375License:
2376        MIT-style license.
2377*/
2378
2379/*
2380Class: Hash
2381        It wraps an object that it uses internally as a map. The user must use put(), get(), and remove() to add/change, retrieve and remove values, it must not access the internal object directly. With this implementation, null values are not allowed.
2382
2383Example:
2384        (start code)
2385        var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'});
2386        hash.remove('b'); // b is removed.
2387        hash.set('c', 'hello');
2388        hash.get('c'); // returns 'hello'
2389        hash.length // returns 2 (a and b)
2390        (end)
2391*/
2392
2393var Hash = new Class({
2394
2395        length: 0,
2396
2397        initialize: function(obj) {
2398                this.obj = {};
2399                for (var property in obj) {
2400                        this.obj[property] = obj[property];
2401                        this.length++;
2402                }
2403        },
2404
2405        get: function(key) {
2406                return this.obj[key];
2407        },
2408
2409        set: function(key, value) {
2410                if (value == null) return false;
2411                if (this.obj[key] == undefined) this.length++;
2412                this.obj[key] = value;
2413                return this;
2414        },
2415
2416        remove: function(key) {
2417                if (this.obj[key] == undefined) return false;
2418                var obj = {};
2419                this.length--;
2420                for (var property in this.obj){
2421                        if (property != key) obj[property] = this.obj[property];
2422                }
2423                this.obj = obj;
2424                return this;
2425        },
2426
2427        each: function(fn, bind) {
2428                for (var property in this.obj) fn.call(bind || this, property, this.obj[property]);
2429        },
2430       
2431        extend: function(obj){
2432                this.initialize(Object.extend(this.obj, obj));
2433                return this;
2434        },
2435
2436        empty: function() {
2437                return (this.length == 0);
2438        },
2439
2440        keys: function() {
2441                var keys = [];
2442                for (var property in this.obj) keys.push(property);
2443                return keys;
2444        },
2445
2446        values: function() {
2447                var values = [];
2448                for (var property in this.obj) values.push(this.obj[property]);
2449                return values;
2450        }
2451
2452});
2453
2454/*
2455Function: $H
2456        Shortcut to create an Hash from an Object.
2457*/
2458
2459function $H(obj) {
2460        return new Hash(obj);
2461};
2462
2463/*
2464Script: Color.js
2465        Contains the Color class.
2466
2467Author:
2468        Michael Jackson <http://ajaxon.com/michael>
2469
2470License:
2471        MIT-style license.
2472*/
2473
2474/*
2475Class: Color
2476        Creates a new Color Object, which is an array with some color specific methods.
2477
2478Example:
2479        (start code)
2480        var black = new Color('#000');
2481        var purple = new Color([255,0,255]);
2482        // mix black with white and purple, each time at 10% of the new color
2483        var darkpurple = black.mix('#fff', purple, 10);
2484        $('myDiv').setStyle('background-color', darkpurple);
2485        (end)
2486*/
2487
2488var Color = new Class({
2489
2490        initialize: function(color){
2491                if (color.mix && color.invert) return color;
2492                var rgb = (color.push) ? color : color.hexToRgb(true);
2493                return Object.extend(rgb, Color.prototype);
2494        },
2495       
2496        mix: function(){
2497                var colors = $A(arguments);
2498                var alpha = 50;
2499                if ($type(colors[colors.length-1]) == 'number') alpha = colors.pop();
2500                var rgb = this.copy();
2501                colors.each(function(color){
2502                        color = new Color(color);
2503                        for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
2504                });
2505                return new Color(rgb);
2506        },
2507
2508        invert: function(){
2509                var rgb = [];
2510                for (var i = 0; i < 3; i++) rgb.push(255 - this[i]);
2511                return new Color(rgb);
2512        }
2513
2514});
2515
2516function $C(color){
2517        return new Color(color);
2518};
2519
2520/*
2521Script: Window.Base.js
2522        Contains Window.onDomReady and Window.disableImageCache
2523
2524License:
2525        MIT-style license.
2526*/
2527
2528/*
2529Class: Window
2530        Cross browser methods to get the window size, onDomReady method.
2531*/
2532
2533window.extend = Object.extend;
2534
2535window.extend({
2536
2537        /*
2538        Function: window.disableImageCache
2539                Disables background image chache for internex explorer, to prevent flickering.
2540                To be called if you have effects with background images, and they flicker.
2541
2542        Example:
2543                Window.disableImageCache();
2544        */
2545
2546        disableImageCache: function(){
2547                if (this.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch (e){};
2548        },
2549
2550        addEvent: function(type, fn){
2551                if (type == 'domready'){
2552                        if (this.loaded) fn();
2553                        else if (!this.events || !this.events.domready){
2554                                var domReady = function(){
2555                                        if (this.loaded) return;
2556                                        this.loaded = true;
2557                                        if (this.timer) this.timer = $clear(this.timer);
2558                                        Element.prototype.fireEvent.call(this, 'domready');
2559                                        this.events.domready = null;
2560                                }.bind(this);
2561                                if (document.readyState && this.khtml){ //safari and konqueror
2562                                        this.timer = function(){
2563                                                if (['loaded','complete'].test(document.readyState)) domReady();
2564                                        }.periodical(50);
2565                                }
2566                                else if (document.readyState && this.ie){ //ie
2567                                        document.write("<script id=ie_ready defer src=javascript:void(0)><\/script>");
2568                                        $('ie_ready').onreadystatechange = function(){
2569                                                if (this.readyState == 'complete') domReady();
2570                                        };
2571                                } else { //others
2572                                        this.addEvent("load", domReady);
2573                                        document.addEvent("DOMContentLoaded", domReady);
2574                                }
2575                        }
2576                }
2577                Element.prototype.addEvent.call(this, type, fn);
2578                return this;
2579        },
2580
2581        /*
2582        Function: window.onDomReady
2583                Executes the passed in function when the DOM is ready (when the document tree has loaded, not waiting for images).
2584                Same as window.addEvent('domready', init);
2585
2586        Credits:
2587                (c) Dean Edwards/Matthias Miller/John Resig, remastered for mootools. Later touched up by Christophe Beyls <http://digitalia.be>.
2588
2589        Arguments:
2590                init - the function to execute when the DOM is ready
2591
2592        Example:
2593                > window.addEvent('domready', function(){alert('the dom is ready')});
2594        */
2595
2596        onDomReady: function(init){
2597                return this.addEvent('domready', init);
2598        }
2599
2600});
2601
2602/*
2603Script: Window.Size.js
2604        Window cross-browser dimensions methods.
2605
2606License:
2607        MIT-style license.
2608*/
2609
2610/*
2611Class: window
2612        Cross browser methods to get the window size, onDomReady method.
2613*/
2614
2615window.extend({
2616
2617        /*
2618        Property: getWidth
2619                Returns an integer representing the width of the browser.
2620        */
2621
2622        getWidth: function(){
2623                if (this.khtml || this.opera) return this.innerWidth;
2624                else return document.documentElement.clientWidth || document.body.clientWidth;
2625        },
2626
2627        /*
2628        Property: getHeight
2629                Returns an integer representing the height of the browser.
2630        */
2631
2632        getHeight: function(){
2633                if (this.khtml || this.opera) return this.innerHeight;
2634                return document.documentElement.clientHeight || document.body.clientHeight;
2635        },
2636
2637        /*
2638        Property: getScrollHeight
2639                Returns an integer representing the scrollHeight of the window.
2640
2641        See Also:
2642                <http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
2643        */
2644
2645        getScrollHeight: function(){
2646                return document.documentElement.scrollHeight;
2647        },
2648
2649        /*
2650        Property: getScrollWidth
2651                Returns an integer representing the scrollWidth of the window.
2652
2653        See Also:
2654                <http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
2655        */
2656
2657        getScrollWidth: function(){
2658                return document.documentElement.scrollWidth;
2659        },
2660
2661        /*
2662        Property: getScrollTop
2663                Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).
2664
2665        See Also:
2666                <http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
2667        */
2668
2669        getScrollTop: function(){
2670                return this.pageYOffset || document.documentElement.scrollTop;
2671        },
2672
2673        /*
2674        Property: getScrollLeft
2675                Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).
2676
2677        See Also:
2678                <http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
2679        */
2680
2681        getScrollLeft: function(){
2682                return this.pageXOffset || document.documentElement.scrollLeft;
2683        },
2684
2685        /*
2686        Property: getSize
2687                Same as <Element.getSize>
2688        */
2689
2690        getSize: function(){
2691                return {
2692                        'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()},
2693                        'size': {'x': this.getWidth(), 'y': this.getHeight()},
2694                        'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()}
2695                };
2696        },
2697
2698        //ignore
2699        getOffsets: function(){return {'x': 0, 'y': 0}}
2700
2701});
2702
2703/*
2704Script: Fx.Base.js
2705        Contains <Fx.Base> and two Transitions.
2706
2707Author:
2708        Valerio Proietti, <http://mad4milk.net>
2709
2710License:
2711        MIT-style license.
2712*/
2713
2714var Fx = {};
2715
2716/*
2717Class: Fx.Base
2718        Base class for the Mootools Effects (Moo.Fx) library.
2719
2720Options:
2721        onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
2722        onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
2723        transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.sineInOut>
2724        duration - the duration of the effect in ms; 500 is the default.
2725        unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%').
2726        wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true.
2727        fps - the frames per second for the transition; default is 30
2728*/
2729
2730Fx.Base = new Class({
2731
2732        getOptions: function(){
2733                return {
2734                        onStart: Class.empty,
2735                        onComplete: Class.empty,
2736                        onCancel: Class.empty,
2737                        transition: Fx.Transitions.sineInOut,
2738                        duration: 500,
2739                        unit: 'px',
2740                        wait: true,
2741                        fps: 50
2742                };
2743        },
2744
2745        initialize: function(options){
2746                this.element = this.element || null;
2747                this.setOptions(this.getOptions(), options);
2748                if (this.options.initialize) this.options.initialize.call(this);
2749        },
2750
2751        step: function(){
2752                var time = new Date().getTime();
2753                if (time < this.time + this.options.duration){
2754                        this.cTime = time - this.time;
2755                        this.setNow();
2756                        this.increase();
2757                } else {
2758                        this.stop(true);
2759                        this.now = this.to;
2760                        this.increase();
2761                        this.fireEvent('onComplete', this.element, 10);
2762                        this.callChain();
2763                }
2764        },
2765
2766        /*
2767        Property: set
2768                Immediately sets the value with no transition.
2769
2770        Arguments:
2771                to - the point to jump to
2772
2773        Example:
2774                >var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
2775        */
2776
2777        set: function(to){
2778                this.now = to;
2779                this.increase();
2780                return this;
2781        },
2782
2783        setNow: function(){
2784                this.now = this.compute(this.from, this.to);
2785        },
2786
2787        compute: function(from, to){
2788                return this.options.transition(this.cTime, from, (to - from), this.options.duration);
2789        },
2790
2791        /*
2792        Property: start
2793                Executes an effect from one position to the other.
2794
2795        Arguments:
2796                from - integer: staring value
2797                to - integer: the ending value
2798
2799        Examples:
2800                >var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque.
2801        */
2802
2803        start: function(from, to){
2804                if (!this.options.wait) this.stop();
2805                else if (this.timer) return this;
2806                this.from = from;
2807                this.to = to;
2808                this.time = new Date().getTime();
2809                this.timer = this.step.periodical(Math.round(1000/this.options.fps), this);
2810                this.fireEvent('onStart', this.element);
2811                return this;
2812        },
2813
2814        /*
2815        Property: stop
2816                Stops the transition.
2817        */
2818
2819        stop: function(end){
2820                if (!this.timer) return this;
2821                this.timer = $clear(this.timer);
2822                if (!end) this.fireEvent('onCancel', this.element);
2823                return this;
2824        },
2825
2826        //compat
2827        custom: function(from, to){return this.start(from, to)},
2828        clearTimer: function(end){return this.stop(end)}
2829
2830});
2831
2832Fx.Base.implement(new Chain);
2833Fx.Base.implement(new Events);
2834Fx.Base.implement(new Options);
2835
2836/*
2837Class: Fx.Transitions
2838        A collection of transition equations for use with the <Fx> Class.
2839
2840See Also:
2841        <Fxtransitions.js> for a whole bunch of transitions.
2842
2843Credits:
2844        Easing Equations, (c) 2003 Robert Penner (http://www.robertpenner.com/easing/), Open Source BSD License.
2845*/
2846
2847Fx.Transitions = {
2848
2849        /* Property: linear */
2850        linear: function(t, b, c, d){
2851                return c*t/d + b;
2852        },
2853
2854        /* Property: sineInOut */
2855        sineInOut: function(t, b, c, d){
2856                return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
2857        }
2858
2859};
2860
2861/*
2862Script: Fx.CSS.js
2863        Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally.
2864
2865Author:
2866        Christophe Beyls, <http://www.digitalia.be>,
2867        Valerio Proietti, <http://mad4milk.net>
2868
2869License:
2870        MIT-style license.
2871*/
2872
2873Fx.CSS = {
2874
2875        select: function(property, to){
2876                if (property.test('color', 'i')) return this.Color;
2877                if (to.test && to.test(' ')) return this.Multi;
2878                return this.Single;
2879        },
2880
2881        parse: function(el, property, fromTo){
2882                if (!fromTo.push) fromTo = [fromTo];
2883                var from = fromTo[0], to = fromTo[1];
2884                if (!to && to != 0){
2885                        to = from;
2886                        from = el.getStyle(property);
2887                }
2888                var css = this.select(property, to);
2889                return {from: css.parse(from), to: css.parse(to), css: css};
2890        }
2891
2892};
2893
2894Fx.CSS.Single = {
2895
2896        parse: function(value){
2897                return parseFloat(value);
2898        },
2899
2900        getNow: function(from, to, fx){
2901                return fx.compute(from, to);
2902        },
2903
2904        getValue: function(value, unit){
2905                return value+unit;
2906        }
2907
2908};
2909
2910Fx.CSS.Multi = {
2911
2912        parse: function(value){
2913                return value.push ? value : value.split(' ').map(function(v){
2914                        return parseFloat(v);
2915                });
2916        },
2917
2918        getNow: function(from, to, fx){
2919                var now = [];
2920                for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
2921                return now;
2922        },
2923
2924        getValue: function(value, unit){
2925                return value.join(unit+' ')+unit;
2926        }
2927
2928};
2929
2930Fx.CSS.Color = {
2931
2932        parse: function(value){
2933                return value.push ? value : value.hexToRgb(true);
2934        },
2935
2936        getNow: function(from, to, fx){
2937                var now = [];
2938                for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
2939                return now;
2940        },
2941
2942        getValue: function(value){
2943                return 'rgb('+value.join(',')+')';
2944        }
2945
2946};
2947
2948/*
2949Script: Fx.Style.js
2950        Contains <Fx.Style>
2951
2952Author:
2953        Valerio Proietti, <http://mad4milk.net>
2954
2955License:
2956        MIT-style license.
2957*/
2958
2959/*
2960Class: Fx.Style
2961        The Style effect; Extends <Fx.Base>, inherits all its properties. Used to transition any css property from one value to another. Includes colors.
2962        Colors must be in hex format.
2963
2964Arguments:
2965        el - the $(element) to apply the style transition to
2966        property - the property to transition
2967        options - the Fx.Base options (see: <Fx.Base>)
2968
2969Example:
2970        >var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
2971        >marginChange.start(10, 100);
2972*/
2973
2974Fx.Style = Fx.Base.extend({
2975
2976        initialize: function(el, property, options){
2977                this.element = $(el);
2978                this.property = property;
2979                this.parent(options);
2980        },
2981
2982        /*
2983        Property: hide
2984                Same as <Fx.Base.set>(0)
2985        */
2986
2987        hide: function(){
2988                return this.set(0);
2989        },
2990
2991        setNow: function(){
2992                this.now = this.css.getNow(this.from, this.to, this);
2993        },
2994
2995        set: function(to){
2996                this.css = Fx.CSS.select(this.property, to);
2997                return this.parent(this.css.parse(to));
2998        },
2999
3000        /*
3001        Property: start
3002                displays the transition to the value/values passed in
3003
3004        Example:
3005                (start code)
3006                var var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
3007                marginChange.start(10); //tries to read current margin top value and goes from current to 10
3008                (end)
3009        */
3010
3011        start: function(from, to){
3012                if (this.timer && this.options.wait) return this;
3013                var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
3014                this.css = parsed.css;
3015                return this.parent(parsed.from, parsed.to);
3016        },
3017
3018        increase: function(){
3019                this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit));
3020        }
3021
3022});
3023
3024/*
3025Class: Element
3026        Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3027*/
3028
3029Element.extend({
3030
3031        /*
3032        Property: effect
3033                Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>.
3034
3035        Example:
3036                >var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear});
3037                >myEffect.start(10, 100);
3038        */
3039
3040        effect: function(property, options){
3041                return new Fx.Style(this, property, options);
3042        }
3043
3044});
3045
3046/*
3047Script: Fx.Styles.js
3048        Contains <Fx.Styles>
3049
3050Author:
3051        Valerio Proietti, <http://mad4milk.net>
3052
3053License:
3054        MIT-style license.
3055*/
3056
3057/*
3058Class: Fx.Styles
3059        Allows you to animate multiple css properties at once; Extends <Fx.Base>, inherits all its properties. Includes colors.
3060        Colors must be in hex format.
3061
3062Arguments:
3063        el - the $(element) to apply the styles transition to
3064        options - the fx options (see: <Fx.Base>)
3065
3066Example:
3067        (start code)
3068        var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear});
3069
3070        //height from 10 to 100 and width from 900 to 300
3071        myEffects.start({
3072                'height': [10, 100],
3073                'width': [900, 300]
3074        });
3075
3076        //or height from current height to 100 and width from current width to 300
3077        myEffects.start({
3078                'height': 100,
3079                'width': 300
3080        });
3081        (end)
3082*/
3083
3084Fx.Styles = Fx.Base.extend({
3085
3086        initialize: function(el, options){
3087                this.element = $(el);
3088                this.parent(options);
3089        },
3090
3091        setNow: function(){
3092                for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this);
3093        },
3094
3095        set: function(to){
3096                var parsed = {};
3097                this.css = {};
3098                for (var p in to){
3099                        this.css[p] = Fx.CSS.select(p, to[p]);
3100                        parsed[p] = this.css[p].parse(to[p]);
3101                }
3102                return this.parent(parsed);
3103        },
3104
3105        /*
3106        Property: start
3107                The function you'll actually use to execute a transition.
3108
3109        Arguments:
3110                an object
3111
3112        Example:
3113                see <Fx.Styles>
3114        */
3115
3116        start: function(obj){
3117                if (this.timer && this.options.wait) return this;
3118                this.now = {};
3119                this.css = {};
3120                var from = {}, to = {};
3121                for (var p in obj){
3122                        var parsed = Fx.CSS.parse(this.element, p, obj[p]);
3123                        from[p] = parsed.from;
3124                        to[p] = parsed.to;
3125                        this.css[p] = parsed.css;
3126                }
3127                return this.parent(from, to);
3128        },
3129
3130        increase: function(){
3131                for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit));
3132        }
3133
3134});
3135
3136/*
3137Class: Element
3138        Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3139*/
3140
3141Element.extend({
3142
3143        /*
3144        Property: effects
3145                Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>.
3146
3147        Example:
3148                >var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.sineInOut});
3149                >myEffects.start({'height': [10, 100], 'width': [900, 300]});
3150        */
3151
3152        effects: function(options){
3153                return new Fx.Styles(this, options);
3154        }
3155
3156});
3157
3158/*
3159Script: Fx.Elements.js
3160        Contains <Fx.Elements>
3161
3162Author:
3163        Valerio Proietti, <http://mad4milk.net>
3164
3165License:
3166        MIT-style license.
3167*/
3168
3169/*
3170Class: Fx.Elements
3171        Fx.Elements allows you to apply any number of styles transitions to a selection of elements. Includes colors (must be in hex format).
3172
3173Arguments:
3174        elements - a collection of elements the effects will be applied to.
3175        options - same as <Fx.Base> options.
3176*/
3177
3178Fx.Elements = Fx.Base.extend({
3179
3180        initialize: function(elements, options){
3181                this.elements = $$(elements);
3182                this.parent(options);
3183        },
3184
3185        setNow: function(){
3186                for (var i in this.from){
3187                        var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {};
3188                        for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this);
3189                }
3190        },
3191
3192        set: function(to){
3193                var parsed = {};
3194                this.css = {};
3195                for (var i in to){
3196                        var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {};
3197                        for (var p in iTo){
3198                                iCss[p] = Fx.CSS.select(p, iTo[p]);
3199                                iParsed[p] = iCss[p].parse(iTo[p]);
3200                        }
3201                }
3202                return this.parent(parsed);
3203        },
3204
3205        /*
3206        Property: start
3207                Applies the passed in style transitions to each object named (see example). Each item in the collection is refered to as a numerical string ("1" for instance). The first item is "0", the second "1", etc.
3208
3209        Example:
3210                (start code)
3211                var myElementsEffects = new Fx.Elements($$('a'));
3212                myElementsEffects.start({
3213                        '0': { //let's change the first element's opacity and width
3214                                'opacity': [0,1],
3215                                'width': [100,200]
3216                        },
3217                        '1': { //and the second one's opacity
3218                                'opacity': [0.2, 0.5]
3219                        }
3220                });
3221                (end)
3222        */
3223
3224        start: function(obj){
3225                if (this.timer && this.options.wait) return this;
3226                this.now = {};
3227                this.css = {};
3228                var from = {}, to = {};
3229                for (var i in obj){
3230                        var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {};
3231                        for (var p in iProps){
3232                                var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]);
3233                                iFrom[p] = parsed.from;
3234                                iTo[p] = parsed.to;
3235                                iCss[p] = parsed.css;
3236                        }
3237                }
3238                return this.parent(from, to);
3239        },
3240
3241        increase: function(){
3242                for (var i in this.now){
3243                        var iNow = this.now[i], iCss = this.css[i];
3244                        for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit));
3245                }
3246        }
3247
3248});
3249
3250/*
3251Script: Fx.Scroll.js
3252        Contains <Fx.Scroll>
3253
3254Author:
3255        Valerio Proietti, <http://mad4milk.net>
3256
3257License:
3258        MIT-style license.
3259*/
3260
3261/*
3262Class: Fx.Scroll
3263        Scroll any element with an overflow, including the window element.
3264
3265Arguments:
3266        element - the element to scroll
3267        options - same as <Fx.Base> options.
3268*/
3269
3270Fx.Scroll = Fx.Base.extend({
3271
3272        initialize: function(element, options){
3273                this.now = [];
3274                this.element = $(element);
3275                this.addEvent('onStart', function(){
3276                        this.element.addEvent('mousewheel', this.stop.bind(this, false));
3277                }.bind(this));
3278                this.removeEvent('onComplete', function(){
3279                        this.element.removeEvent('mousewheel', this.stop.bind(this, false));
3280                }.bind(this));
3281                this.parent(options);
3282        },
3283
3284        setNow: function(){
3285                for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
3286        },
3287
3288        /*
3289        Property: scrollTo
3290                Scrolls the chosen element to the x/y coordinates.
3291
3292        Arguments:
3293                x - the x coordinate to scroll the element to
3294                y - the y coordinate to scroll the element to
3295        */
3296
3297        scrollTo: function(x, y){
3298                if (this.timer && this.options.wait) return this;
3299                var el = this.element.getSize();
3300                var values = {'x': x, 'y': y};
3301                for (var z in el.size){
3302                        var max = el.scrollSize[z] - el.size[z];
3303                        if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? Math.max(Math.min(values[z], max), 0) : max;
3304                        else values[z] = el.scroll[z];
3305                }
3306                return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]);
3307        },
3308
3309        /*
3310        Property: toTop
3311                Scrolls the chosen element to its maximum top.
3312        */
3313
3314        toTop: function(){
3315                return this.scrollTo(false, 0);
3316        },
3317
3318        /*
3319        Property: toBottom
3320                Scrolls the chosen element to its maximum bottom.
3321        */
3322
3323        toBottom: function(){
3324                return this.scrollTo(false, 'full');
3325        },
3326
3327        /*
3328        Property: toLeft
3329                Scrolls the chosen element to its maximum left.
3330        */
3331
3332        toLeft: function(){
3333                return this.scrollTo(0, false);
3334        },
3335
3336        /*
3337        Property: toRight
3338                Scrolls the chosen element to its maximum right.
3339        */
3340
3341        toRight: function(){
3342                return this.scrollTo('full', false);
3343        },
3344
3345        /*
3346        Property: toElement
3347                Scrolls the specified element to the position the passed in element is found. Only usable if the chosen element is == window.
3348
3349        Arguments:
3350                el - the $(element) to scroll the window to
3351        */
3352
3353        toElement: function(el){
3354                return this.scrollTo($(el).getLeft(), $(el).getTop());
3355        },
3356
3357        increase: function(){
3358                this.element.scrollTo(this.now[0], this.now[1]);
3359        }
3360
3361});
3362
3363/*
3364Script: Fx.Slide.js
3365        Contains <Fx.Slide>
3366
3367Author:
3368        Valerio Proietti, <http://mad4milk.net>
3369
3370License:
3371        MIT-style license.
3372*/
3373
3374/*
3375Class: Fx.Slide
3376        The slide effect; slides an element in horizontally or vertically, the contents will fold inside. Extends <Fx.Base>, inherits all its properties.
3377
3378Note:
3379        This effect works on any block element, but the element *cannot be positioned*; no margins or absolute positions. To position the element, put it inside another element (a wrapper div, for instance) and position that instead.
3380
3381Options:
3382        mode - set it to vertical or horizontal. Defaults to vertical.
3383        and all the <Fx.Base> options
3384
3385Example:
3386        (start code)
3387        var mySlider = new Fx.Slide('myElement', {duration: 500});
3388        mySlider.toggle() //toggle the slider up and down.
3389        (end)
3390*/
3391
3392Fx.Slide = Fx.Base.extend({
3393
3394        initialize: function(el, options){
3395                this.element = $(el).setStyle('margin', 0);
3396                this.wrapper = new Element('div').injectAfter(this.element).setStyle('overflow', 'hidden').adopt(this.element);
3397                this.setOptions({'mode': 'vertical'}, options);
3398                this.now = [];
3399                this.parent(this.options);
3400        },
3401
3402        setNow: function(){
3403                for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
3404        },
3405
3406        vertical: function(){
3407                this.margin = 'top';
3408                this.layout = 'height';
3409                this.offset = this.element.offsetHeight;
3410                return [this.element.getStyle('margin-top').toInt(), this.wrapper.getStyle('height').toInt()];
3411        },
3412
3413        horizontal: function(){
3414                this.margin = 'left';
3415                this.layout = 'width';
3416                this.offset = this.element.offsetWidth;
3417                return [this.element.getStyle('margin-left').toInt(), this.wrapper.getStyle('width').toInt()];
3418        },
3419
3420        /*
3421        Property: slideIn
3422                slides the elements in view horizontally or vertically, depending on the mode parameter or options.mode.
3423        */
3424
3425        slideIn: function(mode){
3426                return this.start(this[mode || this.options.mode](), [0, this.offset]);
3427        },
3428
3429        /*
3430        Property: slideOut
3431                slides the elements out of the view horizontally or vertically, depending on the mode parameter or options.mode.
3432        */
3433
3434        slideOut: function(mode){
3435                return this.start(this[mode || this.options.mode](), [-this.offset, 0]);
3436        },
3437
3438        /*
3439        Property: hide
3440                Hides the element without a transition.
3441        */
3442
3443        hide: function(mode){
3444                this[mode || this.options.mode]();
3445                return this.set([-this.offset, 0]);
3446        },
3447
3448        /*
3449        Property: show
3450                Shows the element without a transition.
3451        */
3452
3453        show: function(mode){
3454                this[mode || this.options.mode]();
3455                return this.set([0, this.offset]);
3456        },
3457
3458        /*
3459        Property: toggle
3460                Slides in or Out the element, depending on its state
3461        */
3462
3463        toggle: function(mode){
3464                if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode);
3465                else return this.slideOut(mode);
3466        },
3467
3468        increase: function(){
3469                this.element.setStyle('margin-'+this.margin, this.now[0]+this.options.unit);
3470                this.wrapper.setStyle(this.layout, this.now[1]+this.options.unit);
3471        }
3472
3473});
3474
3475/*
3476Script: Fx.Transitions.js
3477        Cool transitions, to be used with all the effects.
3478
3479Author:
3480        Robert Penner, <http://www.robertpenner.com/easing/>, modified to be used with mootools.
3481
3482License:
3483        Easing Equations v1.5, (c) 2003 Robert Penner, all rights reserved. Open Source BSD License.
3484*/
3485
3486/*
3487Class: Fx.Transitions
3488        A collection of tweaning transitions for use with the <Fx.Base> classes.
3489*/
3490
3491Fx.Transitions = {
3492
3493        /* Property: linear */
3494        linear: function(t, b, c, d){
3495                return c*t/d + b;
3496        },
3497
3498        /* Property: quadIn */
3499        quadIn: function(t, b, c, d){
3500                return c*(t/=d)*t + b;
3501        },
3502
3503        /* Property: quatOut */
3504        quadOut: function(t, b, c, d){
3505                return -c *(t/=d)*(t-2) + b;
3506        },
3507
3508        /* Property: quadInOut */
3509        quadInOut: function(t, b, c, d){
3510                if ((t/=d/2) < 1) return c/2*t*t + b;
3511                return -c/2 * ((--t)*(t-2) - 1) + b;
3512        },
3513
3514        /* Property: cubicIn */
3515        cubicIn: function(t, b, c, d){
3516                return c*(t/=d)*t*t + b;
3517        },
3518
3519        /* Property: cubicOut */
3520        cubicOut: function(t, b, c, d){
3521                return c*((t=t/d-1)*t*t + 1) + b;
3522        },
3523
3524        /* Property: cubicInOut */
3525        cubicInOut: function(t, b, c, d){
3526                if ((t/=d/2) < 1) return c/2*t*t*t + b;
3527                return c/2*((t-=2)*t*t + 2) + b;
3528        },
3529
3530        /* Property: quartIn */
3531        quartIn: function(t, b, c, d){
3532                return c*(t/=d)*t*t*t + b;
3533        },
3534
3535        /* Property: quartOut */
3536        quartOut: function(t, b, c, d){
3537                return -c * ((t=t/d-1)*t*t*t - 1) + b;
3538        },
3539
3540        /* Property: quartInOut */
3541        quartInOut: function(t, b, c, d){
3542                if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
3543                return -c/2 * ((t-=2)*t*t*t - 2) + b;
3544        },
3545
3546        /* Property: quintIn */
3547        quintIn: function(t, b, c, d){
3548                return c*(t/=d)*t*t*t*t + b;
3549        },
3550
3551        /* Property: quintOut */
3552        quintOut: function(t, b, c, d){
3553                return c*((t=t/d-1)*t*t*t*t + 1) + b;
3554        },
3555
3556        /* Property: quintInOut */
3557        quintInOut: function(t, b, c, d){
3558                if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
3559                return c/2*((t-=2)*t*t*t*t + 2) + b;
3560        },
3561
3562        /* Property: sineIn */
3563        sineIn: function(t, b, c, d){
3564                return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
3565        },
3566
3567        /* Property: sineOut */
3568        sineOut: function(t, b, c, d){
3569                return c * Math.sin(t/d * (Math.PI/2)) + b;
3570        },
3571
3572        /* Property: sineInOut */
3573        sineInOut: function(t, b, c, d){
3574                return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
3575        },
3576
3577        /* Property: expoIn */
3578        expoIn: function(t, b, c, d){
3579                return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
3580        },
3581
3582        /* Property: expoOut */
3583        expoOut: function(t, b, c, d){
3584                return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
3585        },
3586
3587        /* Property: expoInOut */
3588        expoInOut: function(t, b, c, d){
3589                if (t==0) return b;
3590                if (t==d) return b+c;
3591                if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
3592                return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
3593        },
3594
3595        /* Property: circIn */
3596        circIn: function(t, b, c, d){
3597                return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
3598        },
3599
3600        /* Property: circOut */
3601        circOut: function(t, b, c, d){
3602                return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
3603        },
3604
3605        /* Property: circInOut */
3606        circInOut: function(t, b, c, d){
3607                if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
3608                return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
3609        },
3610
3611        /* Property: elasticIn */
3612        elasticIn: function(t, b, c, d, a, p){
3613                if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
3614                if (a < Math.abs(c)){ a=c; var s=p/4; }
3615                else var s = p/(2*Math.PI) * Math.asin(c/a);
3616                return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
3617        },
3618
3619        /* Property: elasticOut */
3620        elasticOut: function(t, b, c, d, a, p){
3621                if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
3622                if (a < Math.abs(c)){ a=c; var s=p/4; }
3623                else var s = p/(2*Math.PI) * Math.asin(c/a);
3624                return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
3625        },
3626
3627        /* Property: elasticInOut */
3628        elasticInOut: function(t, b, c, d, a, p){
3629                if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (!a) a = 1;
3630                if (a < Math.abs(c)){ a=c; var s=p/4; }
3631                else var s = p/(2*Math.PI) * Math.asin(c/a);
3632                if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
3633                return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
3634        },
3635
3636        /* Property: backIn */
3637        backIn: function(t, b, c, d, s){
3638                if (!s) s = 1.70158;
3639                return c*(t/=d)*t*((s+1)*t - s) + b;
3640        },
3641
3642        /* Property: backOut */
3643        backOut: function(t, b, c, d, s){
3644                if (!s) s = 1.70158;
3645                return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
3646        },
3647
3648        /* Property: backInOut */
3649        backInOut: function(t, b, c, d, s){
3650                if (!s) s = 1.70158;
3651                if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
3652                return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
3653        },
3654
3655        /* Property: bounceIn */
3656        bounceIn: function(t, b, c, d){
3657                return c - Fx.Transitions.bounceOut (d-t, 0, c, d) + b;
3658        },
3659
3660        /* Property: bounceOut */
3661        bounceOut: function(t, b, c, d){
3662                if ((t/=d) < (1/2.75)){
3663                        return c*(7.5625*t*t) + b;
3664                } else if (t < (2/2.75)){
3665                        return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
3666                } else if (t < (2.5/2.75)){
3667                        return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
3668                } else {
3669                        return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
3670                }
3671        },
3672
3673        /* Property: bounceInOut */
3674        bounceInOut: function(t, b, c, d){
3675                if (t < d/2) return Fx.Transitions.bounceIn(t*2, 0, c, d) * .5 + b;
3676                return Fx.Transitions.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
3677        }
3678
3679};
3680
3681/*
3682Script: Drag.Base.js
3683        Contains <Drag.Base>, <Element.makeResizable>
3684
3685Author:
3686        Valerio Proietti, <http://mad4milk.net>
3687
3688License:
3689        MIT-style license.
3690*/
3691
3692var Drag = {};
3693
3694/*
3695Class: Drag.Base
3696        Modify two css properties of an element based on the position of the mouse.
3697
3698Arguments:
3699        el - the $(element) to apply the transformations to.
3700        options - optional. The options object.
3701
3702Options:
3703        handle - the $(element) to act as the handle for the draggable element. defaults to the $(element) itself.
3704        modifiers - an object. see Modifiers Below.
3705        onStart - optional, function to execute when the user starts to drag (on mousedown);
3706        onComplete - optional, function to execute when the user completes the drag.
3707        onDrag - optional, function to execute at every step of the drag
3708        limit - an object, see Limit below.
3709        snap - optional, the distance you have to drag before the element starts to respond to the drag. defaults to false
3710
3711        modifiers:
3712                x - string, the style you want to modify when the mouse moves in an horizontal direction. defaults to 'left'
3713                y - string, the style you want to modify when the mouse moves in a vertical direction. defaults to 'top'
3714
3715        limit:
3716                x - array with start and end limit relative to modifiers.x
3717                y - array with start and end limit relative to modifiers.y
3718*/
3719
3720Drag.Base = new Class({
3721
3722        getOptions: function(){
3723                return {
3724                        handle: false,
3725                        unit: 'px',
3726                        onStart: Class.empty, 
3727                        onComplete: Class.empty,
3728                        onSnap: Class.empty,
3729                        onDrag: Class.empty,
3730                        limit: false,
3731                        modifiers: {x: 'left', y: 'top'},
3732                        snap: 6
3733                };
3734        },
3735
3736        initialize: function(el, options){
3737                this.setOptions(this.getOptions(), options);
3738                this.element = $(el);
3739                this.handle = $(this.options.handle) || this.element;
3740                this.mouse = {'now': {}, 'pos': {}};
3741                this.value = {'start': {}, 'now': {}};
3742                this.bound = {'start': this.start.bindWithEvent(this)};
3743                this.handle.addEvent('mousedown', this.bound.start);
3744                if (this.options.initialize) this.options.initialize.call(this);
3745        },
3746
3747        start: function(event){
3748                this.mouse.start = event.page;
3749                var limit = this.options.limit;
3750                this.limit = {'x': [], 'y': []};
3751                for (var z in this.options.modifiers){
3752                        this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
3753                        this.mouse.pos[z] = event.page[z] - this.value.now[z];
3754                        if (limit && limit[z]){
3755                                for (var i = 0; i < 2; i++){
3756                                        if ($chk(limit[z][i])) this.limit[z][i] = limit[z][i].apply ? limit[z][i].call(this) : limit[z][i];
3757                                }
3758                        }
3759                }
3760                this.bound.drag = this.drag.bindWithEvent(this);
3761                this.bound.checkAndDrag = this.checkAndDrag.bindWithEvent(this);
3762                this.bound.stop = this.stop.bind(this);
3763                document.addEvent('mousemove', this.options.snap ? this.bound.checkAndDrag : this.bound.drag);
3764                document.addEvent('mouseup', this.bound.stop);
3765                this.fireEvent('onStart', this.element);
3766                event.stop();
3767        },
3768
3769        checkAndDrag: function(event){
3770                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)));
3771                if (distance > this.options.snap){
3772                        document.removeEvent('mousemove', this.bound.checkAndDrag);
3773                        document.addEvent('mousemove', this.bound.drag);
3774                        this.drag(event);
3775                        this.fireEvent('onSnap', this.element);
3776                }
3777                event.stop();
3778        },
3779
3780        drag: function(event){
3781                this.out = false;
3782                this.mouse.now = event.page;
3783                for (var z in this.options.modifiers){
3784                        this.value.now[z] = event.page[z] - this.mouse.pos[z];
3785                        if (this.limit[z]){
3786                                if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
3787                                        this.value.now[z] = this.limit[z][1];
3788                                        this.out = true;
3789                                } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
3790                                        this.value.now[z] = this.limit[z][0];
3791                                        this.out = true;
3792                                }
3793                        }
3794                        this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
3795                }
3796                this.fireEvent('onDrag', this.element);
3797                event.stop();
3798        },
3799       
3800        detach: function(){
3801                this.handle.removeEvent('mousedown', this.bound.start);
3802        },
3803
3804        stop: function(){
3805                document.removeEvent('mousemove', this.bound.drag);
3806                document.removeEvent('mouseup', this.bound.stop);
3807                this.fireEvent('onComplete', this.element);
3808        }
3809
3810});
3811
3812Drag.Base.implement(new Events);
3813Drag.Base.implement(new Options);
3814
3815/*
3816Class: Element
3817        Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3818*/
3819
3820Element.extend({
3821
3822        /*
3823        Property: makeResizable
3824                Makes an element resizable (by dragging) with the supplied options.
3825
3826        Arguments:
3827                options - see <Drag.Base> for acceptable options.
3828        */
3829
3830        makeResizable: function(options){
3831                return new Drag.Base(this, Object.extend(options || {}, {modifiers: {x: 'width', y: 'height'}}));
3832        }
3833
3834});
3835
3836/*
3837Script: Scroller.js
3838        Contains the <Scroller>.
3839
3840Author:
3841        Valerio Proietti, <http://mad4milk.net>
3842
3843License:
3844        MIT-style license.
3845*/
3846
3847/*
3848Class: Scroller
3849        The Scroller is a class to scroll any element with an overflow (including the window) when the mouse cursor reaches certain buondaries of that element.
3850        You must call its start method to start listening to mouse movements.
3851
3852Arguments:
3853        element - required, the element to scroll.
3854        options - optional, see options below, and <Fx.Base> options.
3855
3856Options:
3857        area - integer, the necessary boundaries to make the element scroll.
3858        velocity - integer, velocity ratio, the modifier for the window scrolling speed.
3859        onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets.
3860                Automatically passes as parameters x and y values.
3861*/
3862
3863var Scroller = new Class({
3864
3865        getOptions: function(){
3866                return {
3867                        area: 20,
3868                        velocity: 1,
3869                        onChange: function(x, y){
3870                                this.element.scrollTo(x, y);
3871                        }
3872                };
3873        },
3874
3875        initialize: function(element, options){
3876                this.setOptions(this.getOptions(), options);
3877                this.element = $(element);
3878                this.mousemover = ([window, document].test(element)) ? $(document.body) : this.element;
3879        },
3880
3881        /*
3882        Property: start
3883                The scroller starts listening to mouse movements.
3884        */
3885
3886        start: function(){
3887                this.coord = this.getCoords.bindWithEvent(this);
3888                this.mousemover.addEvent('mousemove', this.coord);
3889        },
3890
3891        /*
3892        Property: stop
3893                The scroller stops listening to mouse movements.
3894        */
3895
3896        stop: function(){
3897                this.mousemover.removeEvent('mousemove', this.coord);
3898                this.timer = $clear(this.timer);
3899        },
3900
3901        getCoords: function(event){
3902                this.page = (this.element == window) ? event.client : event.page;
3903                if (!this.timer) this.timer = this.scroll.periodical(50, this);
3904        },
3905
3906        scroll: function(){
3907                var el = this.element.getSize();
3908                var pos = this.element.getOffsets();
3909
3910                var change = {'x': 0, 'y': 0};
3911                for (var z in this.page){
3912                        if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
3913                                change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
3914                        else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
3915                                change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
3916                }
3917                if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
3918        }
3919
3920});
3921
3922Scroller.implement(new Events);
3923Scroller.implement(new Options);
3924
3925/*
3926Script: Slider.js
3927        Contains <Slider>
3928
3929Author:
3930        Valerio Proietti, <http://mad4milk.net>
3931
3932License:
3933        MIT-style license.
3934*/
3935
3936/*
3937Class: Slider
3938        Creates a slider with two elements: a knob and a container. Returns the values.
3939
3940Arguments:
3941        element - the knob container
3942        knob - the handle
3943        options - see Options below
3944
3945Options:
3946        onChange - a function to fire when the value changes.
3947        onComplete - a function to fire when you're done dragging.
3948        onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position.
3949                Passes as parameter the new position.
3950        steps - the number of steps for your slider.
3951        mode - either 'horizontal' or 'vertical'. defaults to horizontal.
3952        wheel - experimental! Also use the mouse wheel to control the slider. defaults to false.
3953*/
3954
3955var Slider = new Class({
3956
3957        getOptions: function(){
3958                return {
3959                        onChange: Class.empty,
3960                        onComplete: Class.empty,
3961                        onTick: function(pos){
3962                                this.knob.setStyle(this.p, pos+'px');
3963                        },
3964                        steps: 100,
3965                        mode: 'horizontal',
3966                        wheel: false
3967                };
3968        },
3969
3970        initialize: function(el, knob, options){
3971                this.element = $(el);
3972                this.knob = $(knob);
3973                this.setOptions(this.getOptions(), options);
3974
3975                this.previousChange = -1;
3976                this.previousEnd = -1;
3977                this.step = -1;
3978
3979                this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
3980
3981                if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this));
3982
3983                if (this.options.mode == 'horizontal'){
3984                        this.z = 'x'; this.p = 'left';
3985                        this.max = this.element.offsetWidth-this.knob.offsetWidth;
3986                        this.half = this.knob.offsetWidth/2;
3987                        this.getPos = this.element.getLeft.bind(this.element);
3988                } else if (this.options.mode == 'vertical'){
3989                        this.z = 'y'; this.p = 'top';
3990                        this.max = this.element.offsetHeight-this.knob.offsetHeight;
3991                        this.half = this.knob.offsetHeight/2;
3992                        this.getPos = this.element.getTop.bind(this.element);
3993                }
3994
3995                this.knob.setStyle('position', 'relative').setStyle(this.p, 0);
3996
3997                var modSlide = {}, limSlide = {};
3998
3999                limSlide[this.z] = [0, this.max];
4000                modSlide[this.z] = this.p;
4001
4002                this.drag = new Drag.Base(this.knob, {
4003                        limit: limSlide,
4004                        snap: 0,
4005                        modifiers: modSlide,
4006                        onStart: function(){
4007                                this.draggedKnob();
4008                        }.bind(this),
4009                        onDrag: function(){
4010                                this.draggedKnob();
4011                        }.bind(this),
4012                        onComplete: function(){
4013                                this.draggedKnob();
4014                                this.end();
4015                        }.bind(this)
4016                });
4017                if (this.options.initialize) this.options.initialize.call(this);
4018        },
4019
4020        /*
4021        Property: set
4022                The slider will get the step you pass.
4023
4024        Arguments:
4025                step - one integer
4026        */
4027
4028        set: function(step){
4029                if (step > this.options.steps) step = this.options.steps;
4030                else if (step < 0) step = 0;
4031                this.step = step;
4032                this.checkStep();
4033                this.end();
4034                this.fireEvent('onTick', this.toPosition(this.step)+'');
4035                return this;
4036        },
4037
4038        scrolledElement: function(event){
4039                if (event.wheel < 0) this.set(this.step + 1);
4040                else if (event.wheel > 0) this.set(this.step - 1);
4041                event.stop();
4042        },
4043
4044        clickedElement: function(event){
4045                var position = event.page[this.z] - this.getPos() - this.half;
4046                if (position > this.max) position = this.max;
4047                else if (position < 0) position = 0;
4048                this.step = this.toStep(position);
4049                this.checkStep();
4050                this.end();
4051                this.fireEvent('onTick', position+'');
4052        },
4053
4054        draggedKnob: function(){
4055                this.step = this.toStep(this.drag.value.now[this.z]);
4056                this.checkStep();
4057        },
4058
4059        checkStep: function(){
4060                if (this.previousChange != this.step){
4061                        this.previousChange = this.step;
4062                        this.fireEvent('onChange', this.step);
4063                }
4064        },
4065
4066        end: function(){
4067                if (this.previousEnd !== this.step){
4068                        this.previousEnd = this.step;
4069                        this.fireEvent('onComplete', this.step+'');
4070                }
4071        },
4072
4073        toStep: function(position){
4074                return Math.round(position/this.max*this.options.steps);
4075        },
4076
4077        toPosition: function(step){
4078                return (this.max)*step/this.options.steps;
4079        }
4080
4081});
4082
4083Slider.implement(new Events);
4084Slider.implement(new Options);
Note: See TracBrowser for help on using the repository browser.