3 Mootools - My Object Oriented javascript.
9 copyright (c) 2007 Valerio Proietti, <http://mad4milk.net>
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 inspired by 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.
21 /* Section: Core Functions */
25 Returns true if the passed in value/object is defined, that means is not null or undefined.
28 obj - object to inspect
31 function $defined(obj){
32 return (obj != undefined);
37 Returns the type of object that matches the element passed in.
40 obj - the object to inspect.
43 >var myString = 'hello';
44 >$type(myString); //returns "string"
47 'element' - if obj is a DOM element node
48 'textnode' - if obj is a DOM text node
49 'whitespace' - if obj is a DOM whitespace node
50 'arguments' - if obj is an arguments object
51 'object' - if obj is an object
52 'string' - if obj is a string
53 'number' - if obj is a number
54 'boolean' - if obj is a boolean
55 'function' - if obj is a function
56 'regexp' - if obj is a regular expression
57 'class' - if obj is a Class. (created with new Class, or the extend of another class).
58 'collection' - if obj is a native htmlelements collection, such as childNodes, getElementsByTagName .. etc.
59 false - (boolean) if the object is not defined or none of the above.
63 if (!$defined(obj)) return false;
64 if (obj.htmlElement) return 'element';
65 var type = typeof obj;
66 if (type == 'object' && obj.nodeName){
68 case 1: return 'element';
69 case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
72 if (type == 'object' || type == 'function'){
73 switch(obj.constructor){
74 case Array: return 'array';
75 case RegExp: return 'regexp';
76 case Class: return 'class';
78 if (typeof obj.length == 'number'){
79 if (obj.item) return 'collection';
80 if (obj.callee) return 'arguments';
88 merges a number of objects recursively without referencing them or their sub-objects.
91 any number of objects.
94 >var mergedObj = $merge(obj1, obj2, obj3);
95 >//obj1, obj2, and obj3 are unaltered
100 for (var i = 0; i < arguments.length; i++){
101 for (var property in arguments[i]){
102 var ap = arguments[i][property];
103 var mp = mix[property];
104 if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap);
105 else mix[property] = ap;
113 Copies all the properties from the second passed object to the first passed Object.
114 If you do myWhatever.extend = $extend the first parameter will become myWhatever, and your extend function will only need one parameter.
127 $extend(firstOb, secondOb);
128 //firstOb will become:
131 'lastName': 'Dorian',
138 The first object, extended.
141 var $extend = function(){
142 var args = arguments;
143 if (!args[1]) args = [this, args[0]];
144 for (var property in args[1]) args[0][property] = args[1][property];
150 Will add a .extend method to the objects passed as a parameter, but the property passed in will be copied to the object's prototype only if non previously existent.
151 Its handy if you dont want the .extend method of an object to overwrite existing methods.
152 Used automatically in MooTools to implement Array/String/Function/Number methods to browser that dont support them whitout manual checking.
155 a number of classes/native javascript objects
159 var $native = function(){
160 for (var i = 0, l = arguments.length; i < l; i++){
161 arguments[i].extend = function(props){
162 for (var prop in props){
163 if (!this.prototype[prop]) this.prototype[prop] = props[prop];
164 if (!this[prop]) this[prop] = $native.generic(prop);
170 $native.generic = function(prop){
171 return function(bind){
172 return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1));
176 $native(Function, Array, String, Number);
180 Returns true if the passed in value/object exists or is 0, otherwise returns false.
181 Useful to accept zeroes.
184 obj - object to inspect
188 return !!(obj || obj === 0);
193 Returns the first object if defined, otherwise returns the second.
197 picked - the default to return
202 alert($pick(msg, 'no meessage supplied'));
207 function $pick(obj, picked){
208 return $defined(obj) ? obj : picked;
213 Returns a random integer number between the two passed in values.
216 min - integer, the minimum value (inclusive).
217 max - integer, the maximum value (inclusive).
220 a random integer between min and max.
223 function $random(min, max){
224 return Math.floor(Math.random() * (max - min + 1) + min);
229 Returns the current timestamp
236 return new Date().getTime();
241 clears a timeout or an Interval.
247 timer - the setInterval or setTimeout to clear.
250 >var myTimer = myFunction.delay(5000); //wait 5 seconds and execute my function.
251 >myTimer = $clear(myTimer); //nevermind
254 <Function.delay>, <Function.periodical>
257 function $clear(timer){
259 clearInterval(timer);
265 Abstract class, to be used as singleton. Will add .extend to any object
271 the object with an .extend property, equivalent to <$extend>.
274 var Abstract = function(obj){
276 obj.extend = $extend;
282 var Window = new Abstract(window);
283 var Document = new Abstract(document);
284 document.head = document.getElementsByTagName('head')[0];
288 Some properties are attached to the window object by the browser detection.
291 browser detection is entirely object-based. We dont sniff.
294 window.ie - will be set to true if the current browser is internet explorer (any).
295 window.ie6 - will be set to true if the current browser is internet explorer 6.
296 window.ie7 - will be set to true if the current browser is internet explorer 7.
297 window.gecko - will be set to true if the current browser is Mozilla/Gecko.
298 window.webkit - will be set to true if the current browser is Safari/Konqueror.
299 window.webkit419 - will be set to true if the current browser is Safari2 / webkit till version 419.
300 window.webkit420 - will be set to true if the current browser is Safari3 (Webkit SVN Build) / webkit over version 419.
301 window.opera - is set to true by opera itself.
304 window.xpath = !!(document.evaluate);
305 if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
306 else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true;
307 else if (document.getBoxObjectFor != null) window.gecko = true;
311 window.khtml = window.webkit;
313 Object.extend = $extend;
315 /*end compatibility*/
319 if (typeof HTMLElement == 'undefined'){
320 var HTMLElement = function(){};
321 if (window.webkit) document.createElement("iframe"); //fixes safari
322 HTMLElement.prototype = (window.webkit) ? window["[[DOMElement.prototype]]"] : {};
324 HTMLElement.prototype.htmlElement = function(){};
326 //enables background image cache for internet explorer 6
328 if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){};
332 Contains the Class Function, aims to ease the creation of reusable Classes.
340 The base class object of the <http://mootools.net> framework.
341 Creates a new class, its initialize method will fire upon class instantiation.
342 Initialize wont fire on instantiation when you pass *null*.
345 properties - the collection of properties that apply to the class.
349 var Cat = new Class({
350 initialize: function(name){
354 var myCat = new Cat('Micia');
355 alert(myCat.name); //alerts 'Micia'
359 var Class = function(properties){
360 var klass = function(){
361 return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;
363 $extend(klass, this);
364 klass.prototype = properties;
365 klass.constructor = Class;
371 Returns an empty function
374 Class.empty = function(){};
380 Returns the copy of the Class extended with the passed in properties.
383 properties - the properties to add to the base class in this new Class.
387 var Animal = new Class({
388 initialize: function(age){
392 var Cat = Animal.extend({
393 initialize: function(name, age){
394 this.parent(age); //will call the previous initialize;
398 var myCat = new Cat('Micia', 20);
399 alert(myCat.name); //alerts 'Micia'
400 alert(myCat.age); //alerts 20
404 extend: function(properties){
405 var proto = new this(null);
406 for (var property in properties){
407 var pp = proto[property];
408 proto[property] = Class.Merge(pp, properties[property]);
410 return new Class(proto);
415 Implements the passed in properties to the base Class prototypes, altering the base class, unlike <Class.extend>.
418 properties - the properties to add to the base class.
422 var Animal = new Class({
423 initialize: function(age){
428 setName: function(name){
432 var myAnimal = new Animal(20);
433 myAnimal.setName('Micia');
434 alert(myAnimal.name); //alerts 'Micia'
438 implement: function(){
439 for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);
446 Class.Merge = function(previous, current){
447 if (previous && previous != current){
448 var type = $type(current);
449 if (type != $type(previous)) return current;
452 var merged = function(){
453 this.parent = arguments.callee.parent;
454 return current.apply(this, arguments);
456 merged.parent = previous;
458 case 'object': return $merge(previous, current);
465 Script: Class.Extras.js
466 Contains common implementations for custom classes. In Mootools is implemented in <Ajax>, <XHR> and <Fx.Base> and many more.
474 An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
475 Currently implemented in <Fx.Base>, <XHR> and <Ajax>. In <Fx.Base> for example, is used to execute a list of function, one after another, once the effect is completed.
476 The functions will not be fired all togheter, but one every completion, to create custom complex animations.
480 var myFx = new Fx.Style('element', 'opacity');
482 myFx.start(1,0).chain(function(){
489 //the element will appear and disappear three times
493 var Chain = new Class({
497 adds a function to the Chain instance stack.
500 fn - the function to append.
504 this.chains = this.chains || [];
505 this.chains.push(fn);
511 Executes the first function of the Chain instance stack, then removes it. The first function will then become the second.
514 callChain: function(){
515 if (this.chains && this.chains.length) this.chains.shift().delay(10, this);
520 Clears the stack of a Chain instance.
523 clearChain: function(){
531 An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
532 In <Fx.Base> Class, for example, is used to give the possibility add any number of functions to the Effects events, like onComplete, onStart, onCancel.
533 Events in a Class that implements <Events> can be either added as an option, or with addEvent. Never with .options.onEventName.
537 var myFx = new Fx.Style('element', 'opacity').addEvent('onComplete', function(){
538 alert('the effect is completed');
539 }).addEvent('onComplete', function(){
540 alert('I told you the effect is completed');
544 //upon completion it will display the 2 alerts, in order.
548 This class can be implemented into other classes to add the functionality to them.
549 Goes well with the <Options> class.
553 var Widget = new Class({
554 initialize: function(){},
556 this.fireEvent('onComplete');
559 Widget.implement(new Events);
561 var myWidget = new Widget();
562 myWidget.addEvent('onComplete', myfunction);
566 var Events = new Class({
570 adds an event to the stack of events of the Class instance.
573 type - string; the event name (e.g. 'onComplete')
574 fn - function to execute
577 addEvent: function(type, fn){
578 if (fn != Class.empty){
579 this.$events = this.$events || {};
580 this.$events[type] = this.$events[type] || [];
581 this.$events[type].include(fn);
588 fires all events of the specified type in the Class instance.
591 type - string; the event name (e.g. 'onComplete')
592 args - array or single object; arguments to pass to the function; if more than one argument, must be an array
593 delay - (integer) delay (in ms) to wait to execute the event
597 var Widget = new Class({
598 initialize: function(arg1, arg2){
600 this.fireEvent("onInitialize", [arg1, arg2], 50);
603 Widget.implement(new Events);
607 fireEvent: function(type, args, delay){
608 if (this.$events && this.$events[type]){
609 this.$events[type].each(function(fn){
610 fn.create({'bind': this, 'delay': delay, 'arguments': args})();
617 Property: removeEvent
618 removes an event from the stack of events of the Class instance.
621 type - string; the event name (e.g. 'onComplete')
622 fn - function that was added
625 removeEvent: function(type, fn){
626 if (this.$events && this.$events[type]) this.$events[type].remove(fn);
634 An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
635 Used to automate the options settings, also adding Class <Events> when the option begins with on.
639 var Widget = new Class({
647 initialize: function(options){
648 this.setOptions(options);
651 Widget.implement(new Options);
653 var myWidget = new Widget({
659 //myWidget.options = {color: #f00, size: {width: 200, height: 100}}
663 var Options = new Class({
670 defaults - object; the default set of options
671 options - object; the user entered options. can be empty too.
674 if your Class has <Events> implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event.
677 setOptions: function(){
678 this.options = $merge.apply(null, [this.options].extend(arguments));
680 for (var option in this.options){
681 if ($type(this.options[option] == 'function') && (/^on[A-Z]/).test(option)) this.addEvent(option, this.options[option]);
691 Contains Array prototypes, <$A>, <$each>
699 A collection of The Array Object prototype methods.
708 Iterates through an array; This method is only available for browsers without native *forEach* support.
709 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
711 *forEach* executes the provided function (callback) once for each element present in the array. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
714 fn - function to execute with each item in the array; passed the item and the index of that item in the array
715 bind - the object to bind "this" to (see <Function.bind>)
718 >['apple','banana','lemon'].each(function(item, index){
719 > alert(index + " = " + item); //alerts "0 = apple" etc.
720 >}, bindObj); //optional second arg for binding, not used here
723 forEach: function(fn, bind){
724 for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this);
729 This method is provided only for browsers without native *filter* support.
730 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter>
732 *filter* calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values. Array elements which do not pass the callback test are simply skipped, and are not included in the new array.
735 fn - function to execute with each item in the array; passed the item and the index of that item in the array
736 bind - the object to bind "this" to (see <Function.bind>)
739 >var biggerThanTwenty = [10,3,25,100].filter(function(item, index){
742 >//biggerThanTwenty = [25,100]
745 filter: function(fn, bind){
747 for (var i = 0, j = this.length; i < j; i++){
748 if (fn.call(bind, this[i], i, this)) results.push(this[i]);
755 This method is provided only for browsers without native *map* support.
756 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map>
758 *map* calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
761 fn - function to execute with each item in the array; passed the item and the index of that item in the array
762 bind - the object to bind "this" to (see <Function.bind>)
765 >var timesTwo = [1,2,3].map(function(item, index){
768 >//timesTwo = [2,4,6];
771 map: function(fn, bind){
773 for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this);
779 This method is provided only for browsers without native *every* support.
780 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every>
782 *every* executes the provided callback function once for each element present in the array until it finds one where callback returns a false value. If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
785 fn - function to execute with each item in the array; passed the item and the index of that item in the array
786 bind - the object to bind "this" to (see <Function.bind>)
789 >var areAllBigEnough = [10,4,25,100].every(function(item, index){
792 >//areAllBigEnough = false
795 every: function(fn, bind){
796 for (var i = 0, j = this.length; i < j; i++){
797 if (!fn.call(bind, this[i], i, this)) return false;
804 This method is provided only for browsers without native *some* support.
805 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some>
807 *some* executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, some immediately returns true. Otherwise, some returns false. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
810 fn - function to execute with each item in the array; passed the item and the index of that item in the array
811 bind - the object to bind "this" to (see <Function.bind>)
814 >var isAnyBigEnough = [10,4,25,100].some(function(item, index){
817 >//isAnyBigEnough = true
820 some: function(fn, bind){
821 for (var i = 0, j = this.length; i < j; i++){
822 if (fn.call(bind, this[i], i, this)) return true;
829 This method is provided only for browsers without native *indexOf* support.
830 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf>
832 *indexOf* compares a search element to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).
835 item - any type of object; element to locate in the array
836 from - integer; optional; the index of the array at which to begin the search (defaults to 0)
839 >['apple','lemon','banana'].indexOf('lemon'); //returns 1
840 >['apple','lemon'].indexOf('banana'); //returns -1
843 indexOf: function(item, from){
844 var len = this.length;
845 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
846 if (this[i] === item) return i;
853 Same as <Array.forEach>.
856 fn - function to execute with each item in the array; passed the item and the index of that item in the array
857 bind - optional, the object that the "this" of the function will refer to.
860 >var Animals = ['Cat', 'Dog', 'Coala'];
861 >Animals.each(function(animal){
862 > document.write(animal)
868 returns a copy of the array.
871 a new array which is a copy of the current one.
874 start - integer; optional; the index where to start the copy, default is 0. If negative, it is taken as the offset from the end of the array.
875 length - integer; optional; the number of elements to copy. By default, copies all elements from start to the end of the array.
878 >var letters = ["a","b","c"];
879 >var copy = letters.copy(); // ["a","b","c"] (new instance)
882 copy: function(start, length){
884 if (start < 0) start = this.length + start;
885 length = length || (this.length - start);
887 for (var i = 0; i < length; i++) newArray[i] = this[start++];
893 Removes all occurrences of an item from the array.
896 item - the item to remove
899 the Array with all occurrences of the item removed.
902 >["1","2","3","2"].remove("2") // ["1","3"];
905 remove: function(item){
907 var len = this.length;
909 if (this[i] === item){
921 Tests an array for the presence of an item.
924 item - the item to search for in the array.
925 from - integer; 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.
928 true - the item was found
932 >["a","b","c"].contains("a"); // true
933 >["a","b","c"].contains("d"); // false
936 contains: function(item, from){
937 return this.indexOf(item, from) != -1;
942 Creates an object with key-value pairs based on the array of keywords passed in
943 and the current content of the array.
946 keys - the array of keywords.
950 var Animals = ['Cat', 'Dog', 'Coala', 'Lizard'];
951 var Speech = ['Miao', 'Bau', 'Fruuu', 'Mute'];
952 var Speeches = Animals.associate(Speech);
953 //Speeches['Miao'] is now Cat.
954 //Speeches['Bau'] is now Dog.
959 associate: function(keys){
960 var obj = {}, length = Math.min(this.length, keys.length);
961 for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
967 Extends an array with another one.
970 array - the array to extend ours with
973 >var Animals = ['Cat', 'Dog', 'Coala'];
974 >Animals.extend(['Lizard']);
975 >//Animals is now: ['Cat', 'Dog', 'Coala', 'Lizard'];
978 extend: function(array){
979 for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
985 merges an array in another array, without duplicates. (case- and type-sensitive)
988 array - the array to merge from.
991 >['Cat','Dog'].merge(['Dog','Coala']); //returns ['Cat','Dog','Coala']
994 merge: function(array){
995 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
1001 includes the passed in element in the array, only if its not already present. (case- and type-sensitive)
1004 item - item to add to the array (if not present)
1007 >['Cat','Dog'].include('Dog'); //returns ['Cat','Dog']
1008 >['Cat','Dog'].include('Coala'); //returns ['Cat','Dog','Coala']
1011 include: function(item){
1012 if (!this.contains(item)) this.push(item);
1018 returns a random item in the Array
1021 getRandom: function(){
1022 return this[$random(0, this.length - 1)] || null;
1027 returns the last item in the Array
1030 getLast: function(){
1031 return this[this.length - 1] || null;
1038 Array.prototype.each = Array.prototype.forEach;
1039 Array.each = Array.forEach;
1041 /* Section: Utility Functions */
1045 Same as <Array.copy>, but as function.
1046 Useful to apply Array prototypes to iterable objects, as a collection of DOM elements or the arguments object.
1050 function myFunction(){
1051 $A(arguments).each(argument, function(){
1055 //the above will alert all the arguments passed to the function myFunction.
1060 return Array.copy(array);
1065 Use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, arguments of a function, or an object.
1068 iterable - an iterable element or an objct.
1069 function - function to apply to the iterable.
1070 bind - optional, the 'this' of the function will refer to this object.
1073 The function argument will be passed the following arguments.
1075 item - the current item in the iterator being procesed
1076 index - integer; the index of the item, or key in case of an object.
1080 $each(['Sun','Mon','Tue'], function(day, index){
1081 alert('name:' + day + ', index: ' + index);
1083 //alerts "name: Sun, index: 0", "name: Mon, index: 1", etc.
1085 $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
1086 alert("the " + key + " day of the week is " + value);
1088 //alerts "the first day of the week is Sunday",
1089 //"the second day of the week is Monday", etc.
1093 function $each(iterable, fn, bind){
1094 if (iterable && typeof iterable.length == 'number' && $type(iterable) != 'object'){
1095 Array.forEach(iterable, fn, bind);
1097 for (var name in iterable) fn.call(bind || iterable, iterable[name], name);
1103 Array.prototype.test = Array.prototype.contains;
1105 /*end compatibility*/
1109 Contains String prototypes.
1117 A collection of The String Object prototype methods.
1124 Tests a string with a regular expression.
1127 regex - a string or regular expression object, the regular expression you want to match the string with
1128 params - optional, if first parameter is a string, any parameters you want to pass to the regex ('g' has no effect)
1131 true if a match for the regular expression is found in the string, false if not.
1132 See <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test>
1135 >"I like cookies".test("cookie"); // returns true
1136 >"I like cookies".test("COOKIE", "i") // ignore case, returns true
1137 >"I like cookies".test("cake"); // returns false
1140 test: function(regex, params){
1141 return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
1146 parses a string to an integer.
1149 either an int or "NaN" if the string is not a number.
1152 >var value = "10px".toInt(); // value is 10
1156 return parseInt(this, 10);
1161 parses a string to an float.
1164 either a float or "NaN" if the string is not a number.
1167 >var value = "10.848".toFloat(); // value is 10.848
1170 toFloat: function(){
1171 return parseFloat(this);
1176 Converts a hiphenated string to a camelcase string.
1179 >"I-like-cookies".camelCase(); //"ILikeCookies"
1182 the camel cased string
1185 camelCase: function(){
1186 return this.replace(/-\D/g, function(match){
1187 return match.charAt(1).toUpperCase();
1193 Converts a camelCased string to a hyphen-ated string.
1196 >"ILikeCookies".hyphenate(); //"I-like-cookies"
1199 hyphenate: function(){
1200 return this.replace(/\w[A-Z]/g, function(match){
1201 return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
1206 Property: capitalize
1207 Converts the first letter in each word of a string to Uppercase.
1210 >"i like cookies".capitalize(); //"I Like Cookies"
1213 the capitalized string
1216 capitalize: function(){
1217 return this.replace(/\b[a-z]/g, function(match){
1218 return match.toUpperCase();
1224 Trims the leading and trailing spaces off a string.
1227 >" i like cookies ".trim() //"i like cookies"
1234 return this.replace(/^\s+|\s+$/g, '');
1239 trims (<String.trim>) a string AND removes all the double spaces in a string.
1245 >" i like cookies \n\n".clean() //"i like cookies"
1249 return this.replace(/\s{2,}/g, ' ').trim();
1254 Converts an RGB value to hexidecimal. The string must be in the format of "rgb(255,255,255)" or "rgba(255,255,255,1)";
1257 array - boolean value, defaults to false. Use true if you want the array ['FF','33','00'] as output instead of "#FF3300"
1260 hex string or array. returns "transparent" if the output is set as string and the fourth value of rgba in input string is 0.
1263 >"rgb(17,34,51)".rgbToHex(); //"#112233"
1264 >"rgba(17,34,51,0)".rgbToHex(); //"transparent"
1265 >"rgb(17,34,51)".rgbToHex(true); //['11','22','33']
1268 rgbToHex: function(array){
1269 var rgb = this.match(/\d{1,3}/g);
1270 return (rgb) ? rgb.rgbToHex(array) : false;
1275 Converts a hexidecimal color value to RGB. Input string must be the hex color value (with or without the hash). Also accepts triplets ('333');
1278 array - boolean value, defaults to false. Use true if you want the array [255,255,255] as output instead of "rgb(255,255,255)";
1281 rgb string or array.
1284 >"#112233".hexToRgb(); //"rgb(17,34,51)"
1285 >"#112233".hexToRgb(true); //[17,34,51]
1288 hexToRgb: function(array){
1289 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
1290 return (hex) ? hex.slice(1).hexToRgb(array) : false;
1295 checks if the passed in string is contained in the String. also accepts an optional second parameter, to check if the string is contained in a list of separated values.
1298 >'a b c'.contains('c', ' '); //true
1299 >'a bc'.contains('bc'); //true
1300 >'a bc'.contains('b', ' '); //false
1303 contains: function(string, s){
1304 return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1;
1308 Property: escapeRegExp
1309 Returns string with escaped regular expression characters
1312 >var search = 'animals.sheeps[1]'.escapeRegExp(); // search is now 'animals\.sheeps\[1\]'
1318 escapeRegExp: function(){
1319 return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
1328 see <String.rgbToHex>, but as an array method.
1331 rgbToHex: function(array){
1332 if (this.length < 3) return false;
1333 if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
1335 for (var i = 0; i < 3; i++){
1336 var bit = (this[i] - 0).toString(16);
1337 hex.push((bit.length == 1) ? '0' + bit : bit);
1339 return array ? hex : '#' + hex.join('');
1344 same as <String.hexToRgb>, but as an array method.
1347 hexToRgb: function(array){
1348 if (this.length != 3) return false;
1350 for (var i = 0; i < 3; i++){
1351 rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16));
1353 return array ? rgb : 'rgb(' + rgb.join(',') + ')';
1360 Contains Function prototypes and utility functions .
1366 - 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
1371 A collection of The Function Object prototype methods.
1378 Main function to create closures.
1384 options - An Options object.
1387 bind - The object that the "this" of the function will refer to. Default is the current function.
1388 event - If set to true, the function will act as an event listener and receive an event as first argument.
1389 If set to a class name, the function will receive a new instance of this class (with the event passed as argument's constructor) as first argument.
1391 arguments - A single argument or array of arguments that will be passed to the function when called.
1393 If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow.
1395 Default is no custom arguments, the function will receive the standard arguments when called.
1397 delay - Numeric value: if set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called.
1398 Default is no delay.
1399 periodical - Numeric value: if set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called.
1400 Default is no periodical execution.
1401 attempt - If set to true, the returned function will try to execute and return either the results or false on error. Default is false.
1404 create: function(options){
1411 'periodical': false,
1414 if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments];
1415 return function(event){
1418 event = event || window.event;
1419 args = [(options.event === true) ? event : new options.event(event)];
1420 if (options.arguments) args.extend(options.arguments);
1422 else args = options.arguments || arguments;
1423 var returns = function(){
1424 return fn.apply($pick(options.bind, fn), args);
1426 if (options.delay) return setTimeout(returns, options.delay);
1427 if (options.periodical) return setInterval(returns, options.periodical);
1428 if (options.attempt) try {return returns();} catch(err){return false;};
1435 Shortcut to create closures with arguments and bind.
1441 args - the arguments passed. must be an array if arguments > 1
1442 bind - optional, the object that the "this" of the function will refer to.
1445 >myFunction.pass([arg1, arg2], myElement);
1448 pass: function(args, bind){
1449 return this.create({'arguments': args, 'bind': bind});
1454 Tries to execute the function, returns either the result of the function or false on error.
1457 args - the arguments passed. must be an array if arguments > 1
1458 bind - optional, the object that the "this" of the function will refer to.
1461 >myFunction.attempt([arg1, arg2], myElement);
1464 attempt: function(args, bind){
1465 return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
1470 method to easily create closures with "this" altered.
1473 bind - optional, the object that the "this" of the function will refer to.
1474 args - optional, the arguments passed. must be an array if arguments > 1
1480 >function myFunction(){
1481 > this.setStyle('color', 'red');
1482 > // note that 'this' here refers to myFunction, not an element
1483 > // we'll need to bind this function to the element we want to alter
1485 >var myBoundFunction = myFunction.bind(myElement);
1486 >myBoundFunction(); // this will make the element myElement red.
1489 bind: function(bind, args){
1490 return this.create({'bind': bind, 'arguments': args});
1494 Property: bindAsEventListener
1495 cross browser method to pass event firer
1498 bind - optional, the object that the "this" of the function will refer to.
1499 args - optional, the arguments passed. must be an array if arguments > 1
1502 a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
1505 >function myFunction(event){
1506 > alert(event.clientx) //returns the coordinates of the mouse..
1508 >myElement.onclick = myFunction.bindAsEventListener(myElement);
1511 bindAsEventListener: function(bind, args){
1512 return this.create({'bind': bind, 'event': true, 'arguments': args});
1517 Delays the execution of a function by a specified duration.
1520 delay - the duration to wait in milliseconds.
1521 bind - optional, the object that the "this" of the function will refer to.
1522 args - optional, the arguments passed. must be an array if arguments > 1
1525 >myFunction.delay(50, myElement) //wait 50 milliseconds, then call myFunction and bind myElement to it
1526 >(function(){alert('one second later...')}).delay(1000); //wait a second and alert
1529 delay: function(delay, bind, args){
1530 return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
1534 Property: periodical
1535 Executes a function in the specified intervals of time
1538 interval - the duration of the intervals between executions.
1539 bind - optional, the object that the "this" of the function will refer to.
1540 args - optional, the arguments passed. must be an array if arguments > 1
1543 periodical: function(interval, bind, args){
1544 return this.create({'periodical': interval, 'bind': bind, 'arguments': args})();
1551 Contains the Number prototypes.
1559 A collection of The Number Object prototype methods.
1566 Returns this number; useful because toInt must work on both Strings and Numbers.
1570 return parseInt(this);
1575 Returns this number as a float; useful because toFloat must work on both Strings and Numbers.
1578 toFloat: function(){
1579 return parseFloat(this);
1587 min - number, minimum value
1588 max - number, maximum value
1591 the number in the given limits.
1594 >(12).limit(2, 6.5) // returns 6.5
1595 >(-4).limit(2, 6.5) // returns 2
1596 >(4.3).limit(2, 6.5) // returns 4.3
1599 limit: function(min, max){
1600 return Math.min(max, Math.max(min, this));
1605 Returns the number rounded to specified precision.
1608 precision - integer, number of digits after the decimal point. Can also be negative or zero (default).
1611 >12.45.round() // returns 12
1612 >12.45.round(1) // returns 12.5
1613 >12.45.round(-1) // returns 10
1619 round: function(precision){
1620 precision = Math.pow(10, precision || 0);
1621 return Math.round(this * precision) / precision;
1626 Executes a passed in function the specified number of times
1629 function - the function to be executed on each iteration of the loop
1635 times: function(fn){
1636 for (var i = 0; i < this; i++) fn(i);
1643 Contains useful Element prototypes, to be used with the dollar function <$>.
1649 - 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
1654 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
1657 var Element = new Class({
1660 Property: initialize
1661 Creates a new element of the type passed in.
1664 el - string; the tag name for the element you wish to create. you can also pass in an element reference, in which case it will be extended.
1665 props - object; the properties you want to add to your element.
1666 Accepts the same keys as <Element.setProperties>, but also allows events and styles
1669 the key styles will be used as setStyles, the key events will be used as addEvents. any other key is used as setProperty.
1676 'border': '1px solid black'
1679 'click': function(){
1682 'mousedown': function(){
1686 'class': 'myClassSuperClass',
1687 'href': 'http://mad4milk.net'
1693 initialize: function(el, props){
1694 if ($type(el) == 'string'){
1695 if (window.ie && props && (props.name || props.type)){
1696 var name = (props.name) ? ' name="' + props.name + '"' : '';
1697 var type = (props.type) ? ' type="' + props.type + '"' : '';
1700 el = '<' + el + name + type + '>';
1702 el = document.createElement(el);
1705 return (!props || !el) ? el : el.set(props);
1712 - Every dom function such as <$$>, or in general every function that returns a collection of nodes in mootools, returns them as an Elements class.
1713 - The purpose of the Elements class is to allow <Element> methods to work also on <Elements> array.
1714 - Elements is also an Array, so it accepts all the <Array> methods.
1715 - Every node of the Elements instance is already extended with <$>.
1718 >$$('myselector').each(function(el){
1722 some iterations here, $$('myselector') is also an array.
1724 >$$('myselector').setStyle('color', 'red');
1725 every element returned by $$('myselector') also accepts <Element> methods, in this example every element will be made red.
1728 var Elements = new Class({
1730 initialize: function(elements){
1731 return (elements) ? $extend(elements, this) : this;
1736 Elements.extend = function(props){
1737 for (var prop in props){
1738 this.prototype[prop] = props[prop];
1739 this[prop] = $native.generic(prop);
1744 Section: Utility Functions
1747 returns the element passed in with all the Element prototypes applied.
1750 el - a reference to an actual element or a string representing the id of an element
1753 >$('myElement') // gets a DOM element by id with all the Element prototypes applied.
1754 >var div = document.getElementById('myElement');
1755 >$(div) //returns an Element also with all the mootools extentions applied.
1757 You'll use this when you aren't sure if a variable is an actual element or an id, as
1758 well as just shorthand for document.getElementById().
1761 a DOM element or false (if no id was found).
1764 you need to call $ on an element only once to get all the prototypes.
1765 But its no harm to call it multiple times, as it will detect if it has been already extended.
1769 if (!el) return null;
1770 if (el.htmlElement) return Garbage.collect(el);
1771 if ([window, document].contains(el)) return el;
1772 var type = $type(el);
1773 if (type == 'string'){
1774 el = document.getElementById(el);
1775 type = (el) ? 'element' : false;
1777 if (type != 'element') return null;
1778 if (el.htmlElement) return Garbage.collect(el);
1779 if (['object', 'embed'].contains(el.tagName.toLowerCase())) return el;
1780 $extend(el, Element.prototype);
1781 el.htmlElement = function(){};
1782 return Garbage.collect(el);
1787 Selects, and extends DOM elements. Elements arrays returned with $$ will also accept all the <Element> methods.
1788 The return type of element methods run through $$ is always an array. If the return array is only made by elements,
1789 $$ will be applied automatically.
1792 HTML Collections, arrays of elements, arrays of strings as element ids, elements, strings as selectors.
1793 Any number of the above as arguments are accepted.
1796 if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names.
1799 >$$('a') //an array of all anchor tags on the page
1800 >$$('a', 'b') //an array of all anchor and bold tags on the page
1801 >$$('#myElement') //array containing only the element with id = myElement. (only with <Element.Selectors.js>)
1802 >$$('#myElement a.myClass') //an array of all anchor tags with the class "myClass"
1803 >//within the DOM element with id "myElement" (only with <Element.Selectors.js>)
1804 >$$(myelement, myelement2, 'a', ['myid', myid2, 'myid3'], document.getElementsByTagName('div')) //an array containing:
1805 >// the element referenced as myelement if existing,
1806 >// the element referenced as myelement2 if existing,
1807 >// all the elements with a as tag in the page,
1808 >// the element with id = myid if existing
1809 >// the element with id = myid2 if existing
1810 >// the element with id = myid3 if existing
1811 >// all the elements with div as tag in the page
1814 array - array of all the dom elements matched, extended with <$>. Returns as <Elements>.
1817 document.getElementsBySelector = document.getElementsByTagName;
1821 for (var i = 0, j = arguments.length; i < j; i++){
1822 var selector = arguments[i];
1823 switch($type(selector)){
1824 case 'element': elements.push(selector);
1825 case 'boolean': break;
1827 case 'string': selector = document.getElementsBySelector(selector, true);
1828 default: elements.extend(selector);
1831 return $$.unique(elements);
1834 $$.unique = function(array){
1836 for (var i = 0, l = array.length; i < l; i++){
1837 if (array[i].$included) continue;
1838 var element = $(array[i]);
1839 if (element && !element.$included){
1840 element.$included = true;
1841 elements.push(element);
1844 for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null;
1845 return new Elements(elements);
1848 Elements.Multi = function(property){
1850 var args = arguments;
1852 var elements = true;
1853 for (var i = 0, j = this.length, returns; i < j; i++){
1854 returns = this[i][property].apply(this[i], args);
1855 if ($type(returns) != 'element') elements = false;
1856 items.push(returns);
1858 return (elements) ? $$.unique(items) : items;
1862 Element.extend = function(properties){
1863 for (var property in properties){
1864 HTMLElement.prototype[property] = properties[property];
1865 Element.prototype[property] = properties[property];
1866 Element[property] = $native.generic(property);
1867 var elementsProperty = (Array.prototype[property]) ? property + 'Elements' : property;
1868 Elements.prototype[elementsProperty] = Elements.Multi(property);
1874 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
1881 you can set events, styles and properties with this shortcut. same as calling new Element.
1884 set: function(props){
1885 for (var prop in props){
1886 var val = props[prop];
1888 case 'styles': this.setStyles(val); break;
1889 case 'events': if (this.addEvents) this.addEvents(val); break;
1890 case 'properties': this.setProperties(val); break;
1891 default: this.setProperty(prop, val);
1897 inject: function(el, where){
1900 case 'before': el.parentNode.insertBefore(this, el); break;
1902 var next = el.getNext();
1903 if (!next) el.parentNode.appendChild(this);
1904 else el.parentNode.insertBefore(this, next);
1907 var first = el.firstChild;
1909 el.insertBefore(this, first);
1912 default: el.appendChild(this);
1918 Property: injectBefore
1919 Inserts the Element before the passed element.
1922 el - an element reference or the id of the element to be injected in.
1926 ><div id="myElement"></div>
1927 ><div id="mySecondElement"></div>
1929 >$('mySecondElement').injectBefore('myElement');
1931 ><div id="mySecondElement"></div>
1932 ><div id="myElement"></div>
1935 injectBefore: function(el){
1936 return this.inject(el, 'before');
1940 Property: injectAfter
1941 Same as <Element.injectBefore>, but inserts the element after.
1944 injectAfter: function(el){
1945 return this.inject(el, 'after');
1949 Property: injectInside
1950 Same as <Element.injectBefore>, but inserts the element inside.
1953 injectInside: function(el){
1954 return this.inject(el, 'bottom');
1959 Same as <Element.injectInside>, but inserts the element inside, at the top.
1962 injectTop: function(el){
1963 return this.inject(el, 'top');
1968 Inserts the passed elements inside the Element.
1971 accepts elements references, element ids as string, selectors ($$('stuff')) / array of elements, array of ids as strings and collections.
1976 $each(arguments, function(argument){
1977 elements = elements.concat(argument);
1979 $$(elements).inject(this);
1985 Removes the Element from the DOM.
1988 >$('myElement').remove() //bye bye
1992 return this.parentNode.removeChild(this);
1997 Clones the Element and returns the cloned one.
2000 contents - boolean, when true the Element is cloned with childNodes, default true
2006 >var clone = $('myElement').clone().injectAfter('myElement');
2007 >//clones the Element and append the clone after the Element.
2010 clone: function(contents){
2011 var el = $(this.cloneNode(contents !== false));
2012 if (!el.$events) return el;
2014 for (var type in this.$events) el.$events[type] = {
2015 'keys': $A(this.$events[type].keys),
2016 'values': $A(this.$events[type].values)
2018 return el.removeEvents();
2022 Property: replaceWith
2023 Replaces the Element with an element passed.
2026 el - a string representing the element to be injected in (myElementId, or div), or an element reference.
2027 If you pass div or another tag, the element will be created.
2030 the passed in element
2033 >$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place.
2036 replaceWith: function(el){
2038 this.parentNode.replaceChild(el, this);
2043 Property: appendText
2044 Appends text node to a DOM element.
2047 text - the text to append.
2050 ><div id="myElement">hey</div>
2051 >$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy"
2054 appendText: function(text){
2055 this.appendChild(document.createTextNode(text));
2061 Tests the Element to see if it has the passed in className.
2064 true - the Element has the class
2068 className - string; the class name to test.
2071 ><div id="myElement" class="testClass"></div>
2072 >$('myElement').hasClass('testClass'); //returns true
2075 hasClass: function(className){
2076 return this.className.contains(className, ' ');
2081 Adds the passed in class to the Element, if the element doesnt already have it.
2084 className - string; the class name to add
2087 ><div id="myElement" class="testClass"></div>
2088 >$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div>
2091 addClass: function(className){
2092 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
2097 Property: removeClass
2098 Works like <Element.addClass>, but removes the class from the element.
2101 removeClass: function(className){
2102 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
2107 Property: toggleClass
2108 Adds or removes the passed in class name to the element, depending on if it's present or not.
2111 className - the class to add or remove
2114 ><div id="myElement" class="myClass"></div>
2115 >$('myElement').toggleClass('myClass');
2116 ><div id="myElement" class=""></div>
2117 >$('myElement').toggleClass('myClass');
2118 ><div id="myElement" class="myClass"></div>
2121 toggleClass: function(className){
2122 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
2127 Sets a css property to the Element.
2130 property - the property to set
2131 value - the value to which to set it; for numeric values that require "px" you can pass an integer
2134 >$('myElement').setStyle('width', '300px'); //the width is now 300px
2135 >$('myElement').setStyle('width', 300); //the width is now 300px
2138 setStyle: function(property, value){
2140 case 'opacity': return this.setOpacity(parseFloat(value));
2141 case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat';
2143 property = property.camelCase();
2144 switch($type(value)){
2145 case 'number': if (!['zIndex', 'zoom'].contains(property)) value += 'px'; break;
2146 case 'array': value = 'rgb(' + value.join(',') + ')';
2148 this.style[property] = value;
2154 Applies a collection of styles to the Element.
2157 source - an object or string containing all the styles to apply. When its a string it overrides old style.
2160 >$('myElement').setStyles({
2161 > border: '1px solid #000',
2168 >$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;');
2171 setStyles: function(source){
2172 switch($type(source)){
2173 case 'object': Element.setMany(this, 'setStyle', source); break;
2174 case 'string': this.style.cssText = source;
2180 Property: setOpacity
2181 Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0.
2184 opacity - float; Accepts values from 0 to 1.
2187 >$('myElement').setOpacity(0.5) //make it 50% transparent
2190 setOpacity: function(opacity){
2192 if (this.style.visibility != "hidden") this.style.visibility = "hidden";
2194 if (this.style.visibility != "visible") this.style.visibility = "visible";
2196 if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
2197 if (window.ie) this.style.filter = (opacity == 1) ? '' : "alpha(opacity=" + opacity * 100 + ")";
2198 this.style.opacity = this.$tmp.opacity = opacity;
2204 Returns the style of the Element given the property passed in.
2207 property - the css style property you want to retrieve
2210 >$('myElement').getStyle('width'); //returns "400px"
2211 >//but you can also use
2212 >$('myElement').getStyle('width').toInt(); //returns 400
2215 the style as a string
2218 getStyle: function(property){
2219 property = property.camelCase();
2220 var result = this.style[property];
2222 if (property == 'opacity') return this.$tmp.opacity;
2224 for (var style in Element.Styles){
2225 if (property == style){
2226 Element.Styles[style].each(function(s){
2227 var style = this.getStyle(s);
2228 result.push(parseInt(style) ? style : '0px');
2230 if (property == 'border'){
2231 var every = result.every(function(bit){
2232 return (bit == result[0]);
2234 return (every) ? result[0] : false;
2236 return result.join(' ');
2239 if (property.contains('border')){
2240 if (Element.Styles.border.contains(property)){
2241 return ['Width', 'Style', 'Color'].map(function(p){
2242 return this.getStyle(property + p);
2244 } else if (Element.borderShort.contains(property)){
2245 return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){
2246 return this.getStyle('border' + p + property.replace('border', ''));
2250 if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
2251 else if (this.currentStyle) result = this.currentStyle[property];
2253 if (window.ie) result = Element.fixStyle(property, result, this);
2254 if (result && property.test(/color/i) && result.contains('rgb')){
2255 return result.split('rgb').splice(1,4).map(function(color){
2256 return color.rgbToHex();
2264 Returns an object of styles of the Element for each argument passed in.
2266 properties - strings; any number of style properties
2268 >$('myElement').getStyles('width','height','padding');
2269 >//returns an object like:
2270 >{width: "10px", height: "10px", padding: "10px 0px 10px 0px"}
2273 getStyles: function(){
2274 return Element.getMany(this, 'getStyle', arguments);
2277 walk: function(brother, start){
2278 brother += 'Sibling';
2279 var el = (start) ? this[start] : this[brother];
2280 while (el && $type(el) != 'element') el = el[brother];
2285 Property: getPrevious
2286 Returns the previousSibling of the Element, excluding text nodes.
2289 >$('myElement').getPrevious(); //get the previous DOM element from myElement
2292 the sibling element or undefined if none found.
2295 getPrevious: function(){
2296 return this.walk('previous');
2301 Works as Element.getPrevious, but tries to find the nextSibling.
2304 getNext: function(){
2305 return this.walk('next');
2310 Works as <Element.getPrevious>, but tries to find the firstChild.
2313 getFirst: function(){
2314 return this.walk('next', 'firstChild');
2319 Works as <Element.getPrevious>, but tries to find the lastChild.
2322 getLast: function(){
2323 return this.walk('previous', 'lastChild');
2328 returns the $(element.parentNode)
2331 getParent: function(){
2332 return $(this.parentNode);
2336 Property: getChildren
2337 returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>.
2340 getChildren: function(){
2341 return $$(this.childNodes);
2346 returns true if the passed in element is a child of the $(element).
2349 hasChild: function(el){
2350 return !!$A(this.getElementsByTagName('*')).contains(el);
2354 Property: getProperty
2355 Gets the an attribute of the Element.
2358 property - string; the attribute to retrieve
2361 >$('myImage').getProperty('src') // returns whatever.gif
2364 the value, or an empty string
2367 getProperty: function(property){
2368 var index = Element.Properties[property];
2369 if (index) return this[index];
2370 var flag = Element.PropertiesIFlag[property] || 0;
2371 if (!window.ie || flag) return this.getAttribute(property, flag);
2372 var node = this.attributes[property];
2373 return (node) ? node.nodeValue : null;
2377 Property: removeProperty
2378 Removes an attribute from the Element
2381 property - string; the attribute to remove
2384 removeProperty: function(property){
2385 var index = Element.Properties[property];
2386 if (index) this[index] = '';
2387 else this.removeAttribute(property);
2392 Property: getProperties
2393 same as <Element.getStyles>, but for properties
2396 getProperties: function(){
2397 return Element.getMany(this, 'getProperty', arguments);
2401 Property: setProperty
2402 Sets an attribute for the Element.
2405 property - string; the property to assign the value passed in
2406 value - the value to assign to the property passed in
2409 >$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source
2412 setProperty: function(property, value){
2413 var index = Element.Properties[property];
2414 if (index) this[index] = value;
2415 else this.setAttribute(property, value);
2420 Property: setProperties
2421 Sets numerous attributes for the Element.
2424 source - an object with key/value pairs.
2428 $('myElement').setProperties({
2429 src: 'whatever.gif',
2430 alt: 'whatever dude'
2432 <img src="whatever.gif" alt="whatever dude">
2436 setProperties: function(source){
2437 return Element.setMany(this, 'setProperty', source);
2442 Sets the innerHTML of the Element.
2445 html - string; the new innerHTML for the element.
2448 >$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML
2451 setHTML: function(){
2452 this.innerHTML = $A(arguments).join('');
2458 Sets the inner text of the Element.
2461 text - string; the new text content for the element.
2464 >$('myElement').setText('some text') //the text of myElement is now = 'some text'
2467 setText: function(text){
2468 var tag = this.getTag();
2469 if (['style', 'script'].contains(tag)){
2471 if (tag == 'style') this.styleSheet.cssText = text;
2472 else if (tag == 'script') this.setProperty('text', text);
2475 this.removeChild(this.firstChild);
2476 return this.appendText(text);
2479 this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text;
2485 Gets the inner text of the Element.
2488 getText: function(){
2489 var tag = this.getTag();
2490 if (['style', 'script'].contains(tag)){
2492 if (tag == 'style') return this.styleSheet.cssText;
2493 else if (tag == 'script') return this.getProperty('text');
2495 return this.innerHTML;
2498 return ($pick(this.innerText, this.textContent));
2503 Returns the tagName of the element in lower case.
2506 >$('myImage').getTag() // returns 'img'
2509 The tag name in lower case
2513 return this.tagName.toLowerCase();
2518 Empties an element of all its children.
2521 >$('myDiv').empty() // empties the Div and returns it
2528 Garbage.trash(this.getElementsByTagName('*'));
2529 return this.setHTML('');
2534 Element.fixStyle = function(property, result, element){
2535 if ($chk(parseInt(result))) return result;
2536 if (['height', 'width'].contains(property)){
2537 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'];
2539 values.each(function(value){
2540 size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt();
2542 return element['offset' + property.capitalize()] - size + 'px';
2543 } else if (property.test(/border(.+)Width|margin|padding/)){
2549 Element.Styles = {'border': [], 'padding': [], 'margin': []};
2550 ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
2551 for (var style in Element.Styles) Element.Styles[style].push(style + direction);
2554 Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor'];
2556 Element.getMany = function(el, method, keys){
2558 $each(keys, function(key){
2559 result[key] = el[method](key);
2564 Element.setMany = function(el, method, pairs){
2565 for (var key in pairs) el[method](key, pairs[key]);
2569 Element.Properties = new Abstract({
2570 'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan',
2571 'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength',
2572 'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value',
2573 'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected'
2575 Element.PropertiesIFlag = {
2581 addListener: function(type, fn){
2582 if (this.addEventListener) this.addEventListener(type, fn, false);
2583 else this.attachEvent('on' + type, fn);
2587 removeListener: function(type, fn){
2588 if (this.removeEventListener) this.removeEventListener(type, fn, false);
2589 else this.detachEvent('on' + type, fn);
2595 window.extend(Element.Methods.Listeners);
2596 document.extend(Element.Methods.Listeners);
2597 Element.extend(Element.Methods.Listeners);
2603 collect: function(el){
2605 Garbage.elements.push(el);
2606 el.$tmp = {'opacity': 1};
2611 trash: function(elements){
2612 for (var i = 0, j = elements.length, el; i < j; i++){
2613 if (!(el = elements[i]) || !el.$tmp) continue;
2614 if (el.$events) el.fireEvent('trash').removeEvents();
2615 for (var p in el.$tmp) el.$tmp[p] = null;
2616 for (var d in Element.prototype) el[d] = null;
2617 Garbage.elements[Garbage.elements.indexOf(el)] = null;
2618 el.htmlElement = el.$tmp = el = null;
2620 Garbage.elements.remove(null);
2624 Garbage.collect(window);
2625 Garbage.collect(document);
2626 Garbage.trash(Garbage.elements);
2631 window.addListener('beforeunload', function(){
2632 window.addListener('unload', Garbage.empty);
2633 if (window.ie) window.addListener('unload', CollectGarbage);
2637 Script: Element.Event.js
2638 Contains the Event Class, Element methods to deal with Element events, custom Events, and the Function prototype bindWithEvent.
2646 Cross browser methods to manage events.
2652 shift - true if the user pressed the shift
2653 control - true if the user pressed the control
2654 alt - true if the user pressed the alt
2655 meta - true if the user pressed the meta key
2656 wheel - the amount of third button scrolling
2657 code - the keycode of the key pressed
2658 page.x - the x position of the mouse, relative to the full window
2659 page.y - the y position of the mouse, relative to the full window
2660 client.x - the x position of the mouse, relative to the viewport
2661 client.y - the y position of the mouse, relative to the viewport
2662 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.
2663 target - the event target
2664 relatedTarget - the event related target
2668 $('myLink').onkeydown = function(event){
2669 var event = new Event(event);
2670 //event is now the Event class.
2671 alert(event.key); //returns the lowercase letter pressed
2672 alert(event.shift); //returns true if the key pressed is shift
2673 if (event.key == 's' && event.control) alert('document saved');
2678 var Event = new Class({
2680 initialize: function(event){
2681 if (event && event.$extended) return event;
2682 this.$extended = true;
2683 event = event || window.event;
2685 this.type = event.type;
2686 this.target = event.target || event.srcElement;
2687 if (this.target.nodeType == 3) this.target = this.target.parentNode;
2688 this.shift = event.shiftKey;
2689 this.control = event.ctrlKey;
2690 this.alt = event.altKey;
2691 this.meta = event.metaKey;
2692 if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){
2693 this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
2694 } else if (this.type.contains('key')){
2695 this.code = event.which || event.keyCode;
2696 for (var name in Event.keys){
2697 if (Event.keys[name] == this.code){
2702 if (this.type == 'keydown'){
2703 var fKey = this.code - 111;
2704 if (fKey > 0 && fKey < 13) this.key = 'f' + fKey;
2706 this.key = this.key || String.fromCharCode(this.code).toLowerCase();
2707 } else if (this.type.test(/(click|mouse|menu)/)){
2709 'x': event.pageX || event.clientX + document.documentElement.scrollLeft,
2710 'y': event.pageY || event.clientY + document.documentElement.scrollTop
2713 'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX,
2714 'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY
2716 this.rightClick = (event.which == 3) || (event.button == 2);
2718 case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break;
2719 case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement;
2721 this.fixRelatedTarget();
2728 cross browser method to stop an event
2732 return this.stopPropagation().preventDefault();
2736 Property: stopPropagation
2737 cross browser method to stop the propagation of an event
2740 stopPropagation: function(){
2741 if (this.event.stopPropagation) this.event.stopPropagation();
2742 else this.event.cancelBubble = true;
2747 Property: preventDefault
2748 cross browser method to prevent the default action of the event
2751 preventDefault: function(){
2752 if (this.event.preventDefault) this.event.preventDefault();
2753 else this.event.returnValue = false;
2761 relatedTarget: function(){
2762 if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode;
2765 relatedTargetGecko: function(){
2766 try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;}
2771 Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget;
2775 you can add additional Event keys codes this way:
2779 Event.keys.whatever = 80;
2780 $(myelement).addEvent(keydown, function(event){
2781 event = new Event(event);
2782 if (event.key == 'whatever') console.log(whatever key clicked).
2787 Event.keys = new Abstract({
2802 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
2805 Element.Methods.Events = {
2809 Attaches an event listener to a DOM element.
2812 type - the event to monitor ('click', 'load', etc) without the prefix 'on'.
2813 fn - the function to execute
2816 >$('myElement').addEvent('click', function(){alert('clicked!')});
2819 addEvent: function(type, fn){
2820 this.$events = this.$events || {};
2821 this.$events[type] = this.$events[type] || {'keys': [], 'values': []};
2822 if (this.$events[type].keys.contains(fn)) return this;
2823 this.$events[type].keys.push(fn);
2824 var realType = type;
2825 var custom = Element.Events[type];
2827 if (custom.add) custom.add.call(this, fn);
2828 if (custom.map) fn = custom.map;
2829 if (custom.type) realType = custom.type;
2831 if (!this.addEventListener) fn = fn.create({'bind': this, 'event': true});
2832 this.$events[type].values.push(fn);
2833 return (Element.NativeEvents.contains(realType)) ? this.addListener(realType, fn) : this;
2837 Property: removeEvent
2838 Works as Element.addEvent, but instead removes the previously added event listener.
2841 removeEvent: function(type, fn){
2842 if (!this.$events || !this.$events[type]) return this;
2843 var pos = this.$events[type].keys.indexOf(fn);
2844 if (pos == -1) return this;
2845 var key = this.$events[type].keys.splice(pos,1)[0];
2846 var value = this.$events[type].values.splice(pos,1)[0];
2847 var custom = Element.Events[type];
2849 if (custom.remove) custom.remove.call(this, fn);
2850 if (custom.type) type = custom.type;
2852 return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this;
2857 As <addEvent>, but accepts an object and add multiple events at once.
2860 addEvents: function(source){
2861 return Element.setMany(this, 'addEvent', source);
2865 Property: removeEvents
2866 removes all events of a certain type from an element. if no argument is passed in, removes all events.
2869 type - string; the event name (e.g. 'click')
2872 removeEvents: function(type){
2873 if (!this.$events) return this;
2875 for (var evType in this.$events) this.removeEvents(evType);
2876 this.$events = null;
2877 } else if (this.$events[type]){
2878 this.$events[type].keys.each(function(fn){
2879 this.removeEvent(type, fn);
2881 this.$events[type] = null;
2888 executes all events of the specified type present in the element.
2891 type - string; the event name (e.g. 'click')
2892 args - array or single object; arguments to pass to the function; if more than one argument, must be an array
2893 delay - (integer) delay (in ms) to wait to execute the event
2896 fireEvent: function(type, args, delay){
2897 if (this.$events && this.$events[type]){
2898 this.$events[type].keys.each(function(fn){
2899 fn.create({'bind': this, 'delay': delay, 'arguments': args})();
2906 Property: cloneEvents
2907 Clones all events from an element to this element.
2910 from - element, copy all events from this element
2911 type - optional, copies only events of this type
2914 cloneEvents: function(from, type){
2915 if (!from.$events) return this;
2917 for (var evType in from.$events) this.cloneEvents(from, evType);
2918 } else if (from.$events[type]){
2919 from.$events[type].keys.each(function(fn){
2920 this.addEvent(type, fn);
2928 window.extend(Element.Methods.Events);
2929 document.extend(Element.Methods.Events);
2930 Element.extend(Element.Methods.Events);
2932 /* Section: Custom Events */
2934 Element.Events = new Abstract({
2938 In addition to the standard javascript events (load, mouseover, mouseout, click, etc.) <Event.js> contains two custom events
2939 this event fires when the mouse enters the area of the dom element; will not be fired again if the mouse crosses over children of the element (unlike mouseover)
2943 >$(myElement).addEvent('mouseenter', myFunction);
2948 map: function(event){
2949 event = new Event(event);
2950 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event);
2956 this event fires when the mouse exits the area of the dom element; will not be fired again if the mouse crosses over children of the element (unlike mouseout)
2960 >$(myElement).addEvent('mouseleave', myFunction);
2965 map: function(event){
2966 event = new Event(event);
2967 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event);
2972 type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel'
2977 Element.NativeEvents = [
2978 'click', 'dblclick', 'mouseup', 'mousedown', //mouse buttons
2979 'mousewheel', 'DOMMouseScroll', //mouse wheel
2980 'mouseover', 'mouseout', 'mousemove', //mouse movement
2981 'keydown', 'keypress', 'keyup', //keys
2982 'load', 'unload', 'beforeunload', 'resize', 'move', //window
2983 'focus', 'blur', 'change', 'submit', 'reset', 'select', //forms elements
2984 'error', 'abort', 'contextmenu', 'scroll' //misc
2989 A collection of The Function Object prototype methods.
2995 Property: bindWithEvent
2996 automatically passes MooTools Event Class.
2999 bind - optional, the object that the "this" of the function will refer to.
3000 args - optional, an argument to pass to the function; if more than one argument, it must be an array of arguments.
3003 a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
3006 >function myFunction(event){
3007 > alert(event.client.x) //returns the coordinates of the mouse..
3009 >myElement.addEvent('click', myFunction.bindWithEvent(myElement));
3012 bindWithEvent: function(bind, args){
3013 return this.create({'bind': bind, 'arguments': args, 'event': Event});
3020 Script: Element.Filters.js
3021 add Filters capability to <Elements>.
3029 A collection of methods to be used with <$$> elements collections.
3035 Property: filterByTag
3036 Filters the collection by a specified tag name.
3037 Returns a new Elements collection, while the original remains untouched.
3040 filterByTag: function(tag){
3041 return new Elements(this.filter(function(el){
3042 return (Element.getTag(el) == tag);
3047 Property: filterByClass
3048 Filters the collection by a specified class name.
3049 Returns a new Elements collection, while the original remains untouched.
3052 filterByClass: function(className, nocash){
3053 var elements = this.filter(function(el){
3054 return (el.className && el.className.contains(className, ' '));
3056 return (nocash) ? elements : new Elements(elements);
3060 Property: filterById
3061 Filters the collection by a specified ID.
3062 Returns a new Elements collection, while the original remains untouched.
3065 filterById: function(id, nocash){
3066 var elements = this.filter(function(el){
3067 return (el.id == id);
3069 return (nocash) ? elements : new Elements(elements);
3073 Property: filterByAttribute
3074 Filters the collection by a specified attribute.
3075 Returns a new Elements collection, while the original remains untouched.
3078 name - the attribute name.
3079 operator - optional, the attribute operator.
3080 value - optional, the attribute value, only valid if the operator is specified.
3083 filterByAttribute: function(name, operator, value, nocash){
3084 var elements = this.filter(function(el){
3085 var current = Element.getProperty(el, name);
3086 if (!current) return false;
3087 if (!operator) return true;
3089 case '=': return (current == value);
3090 case '*=': return (current.contains(value));
3091 case '^=': return (current.substr(0, value.length) == value);
3092 case '$=': return (current.substr(current.length - value.length) == value);
3093 case '!=': return (current != value);
3094 case '~=': return current.contains(value, ' ');
3098 return (nocash) ? elements : new Elements(elements);
3104 Script: Element.Selectors.js
3105 Css Query related functions and <Element> extensions
3111 /* Section: Utility Functions */
3115 Selects a single (i.e. the first found) Element based on the selector passed in and an optional filter element.
3116 Returns as <Element>.
3119 selector - string; the css selector to match
3120 filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
3123 >$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement'
3126 a DOM element - the first element that matches the selector
3129 function $E(selector, filter){
3130 return ($(filter) || document).getElement(selector);
3135 Returns a collection of Elements that match the selector passed in limited to the scope of the optional filter.
3136 See Also: <Element.getElements> for an alternate syntax.
3137 Returns as <Elements>.
3140 an array of dom elements that match the selector within the filter
3143 selector - string; css selector to match
3144 filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
3147 >$ES("a") //gets all the anchor tags; synonymous with $$("a")
3148 >$ES('a','myElement') //get all the anchor tags within $('myElement')
3151 function $ES(selector, filter){
3152 return ($(filter) || document).getElementsBySelector(selector);
3157 'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/,
3161 getParam: function(items, context, param, i){
3162 var temp = [context.namespaceURI ? 'xhtml:' : '', param[1]];
3163 if (param[2]) temp.push('[@id="', param[2], '"]');
3164 if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]');
3166 if (param[5] && param[6]){
3168 case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break;
3169 case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break;
3170 case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break;
3171 case '=': temp.push('[@', param[4], '="', param[6], '"]'); break;
3172 case '!=': temp.push('[@', param[4], '!="', param[6], '"]');
3175 temp.push('[@', param[4], ']');
3178 items.push(temp.join(''));
3182 getItems: function(items, context, nocash){
3184 var xpath = document.evaluate('.//' + items.join('//'), context, $$.shared.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
3185 for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements.push(xpath.snapshotItem(i));
3186 return (nocash) ? elements : new Elements(elements.map($));
3193 getParam: function(items, context, param, i){
3196 var el = context.getElementById(param[2]);
3197 if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false;
3200 items = $A(context.getElementsByTagName(param[1]));
3203 items = $$.shared.getElementsByTagName(items, param[1]);
3204 if (param[2]) items = Elements.filterById(items, param[2], true);
3206 if (param[3]) items = Elements.filterByClass(items, param[3], true);
3207 if (param[4]) items = Elements.filterByAttribute(items, param[4], param[5], param[6], true);
3211 getItems: function(items, context, nocash){
3212 return (nocash) ? items : $$.unique(items);
3217 resolver: function(prefix){
3218 return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
3221 getElementsByTagName: function(context, tagName){
3223 for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName));
3229 $$.shared.method = (window.xpath) ? 'xpath' : 'normal';
3233 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3236 Element.Methods.Dom = {
3239 Property: getElements
3240 Gets all the elements within an element that match the given (single) selector.
3241 Returns as <Elements>.
3244 selector - string; the css selector to match
3247 >$('myElement').getElements('a'); // get all anchors within myElement
3248 >$('myElement').getElements('input[name=dialog]') //get all input tags with name 'dialog'
3249 >$('myElement').getElements('input[name$=log]') //get all input tags with names ending with 'log'
3252 Supports these operators in attribute selectors:
3257 - != : is not equal to
3259 Xpath is used automatically for compliant browsers.
3262 getElements: function(selector, nocash){
3264 selector = selector.trim().split(' ');
3265 for (var i = 0, j = selector.length; i < j; i++){
3266 var sel = selector[i];
3267 var param = sel.match($$.shared.regexp);
3269 param[1] = param[1] || '*';
3270 var temp = $$.shared[$$.shared.method].getParam(items, this, param, i);
3274 return $$.shared[$$.shared.method].getItems(items, this, nocash);
3278 Property: getElement
3279 Same as <Element.getElements>, but returns only the first. Alternate syntax for <$E>, where filter is the Element.
3280 Returns as <Element>.
3283 selector - string; css selector
3286 getElement: function(selector){
3287 return $(this.getElements(selector, true)[0] || false);
3291 Property: getElementsBySelector
3292 Same as <Element.getElements>, but allows for comma separated selectors, as in css. Alternate syntax for <$$>, where filter is the Element.
3293 Returns as <Elements>.
3296 selector - string; css selector
3299 getElementsBySelector: function(selector, nocash){
3301 selector = selector.split(',');
3302 for (var i = 0, j = selector.length; i < j; i++) elements = elements.concat(this.getElements(selector[i], true));
3303 return (nocash) ? elements : $$.unique(elements);
3311 Property: getElementById
3312 Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById.
3315 id - string; the id of the element to find.
3318 getElementById: function(id){
3319 var el = document.getElementById(id);
3320 if (!el) return false;
3321 for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
3322 if (!parent) return false;
3327 getElementsByClassName: function(className){
3328 return this.getElements('.' + className);
3331 /*end compatibility*/
3335 document.extend(Element.Methods.Dom);
3336 Element.extend(Element.Methods.Dom);
3339 Script: Element.Form.js
3340 Contains Element prototypes to deal with Forms and their elements.
3348 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3355 Returns the value of the Element, if its tag is textarea, select or input. getValue called on a multiple select will return an array.
3358 getValue: function(){
3359 switch(this.getTag()){
3362 $each(this.options, function(option){
3363 if (option.selected) values.push($pick(option.value, option.text));
3365 return (this.multiple) ? values : values[0];
3366 case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break;
3367 case 'textarea': return this.value;
3372 getFormElements: function(){
3373 return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea'));
3377 Property: toQueryString
3378 Reads the children inputs of the Element and generates a query string, based on their values. Used internally in <Ajax>
3382 <form id="myForm" action="submit.php">
3383 <input name="email" value="bob@bob.com">
3384 <input name="zipCode" value="90210">
3388 $('myForm').toQueryString()
3393 email=bob@bob.com&zipCode=90210
3396 toQueryString: function(){
3397 var queryString = [];
3398 this.getFormElements().each(function(el){
3400 var value = el.getValue();
3401 if (value === false || !name || el.disabled) return;
3402 var qs = function(val){
3403 queryString.push(name + '=' + encodeURIComponent(val));
3405 if ($type(value) == 'array') value.each(qs);
3408 return queryString.join('&');
3414 Script: Element.Dimensions.js
3415 Contains Element prototypes to deal with Element size and position in space.
3418 The functions in this script require n XHTML doctype.
3426 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
3433 Scrolls the element to the specified coordinated (if the element has an overflow)
3436 x - the x coordinate
3437 y - the y coordinate
3440 >$('myElement').scrollTo(0, 100)
3443 scrollTo: function(x, y){
3444 this.scrollLeft = x;
3450 Return an Object representing the size/scroll values of the element.
3454 $('myElement').getSize();
3460 'scroll': {'x': 100, 'y': 100},
3461 'size': {'x': 200, 'y': 400},
3462 'scrollSize': {'x': 300, 'y': 500}
3467 getSize: function(){
3469 'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
3470 'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
3471 'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
3476 Property: getPosition
3477 Returns the real offsets of the element.
3480 overflown - optional, an array of nested scrolling containers for scroll offset calculation, use this if your element is inside any element containing scrollbars
3483 >$('element').getPosition();
3489 getPosition: function(overflown){
3490 overflown = overflown || [];
3491 var el = this, left = 0, top = 0;
3493 left += el.offsetLeft || 0;
3494 top += el.offsetTop || 0;
3495 el = el.offsetParent;
3497 overflown.each(function(element){
3498 left -= element.scrollLeft || 0;
3499 top -= element.scrollTop || 0;
3501 return {'x': left, 'y': top};
3506 Returns the distance from the top of the window to the Element.
3509 overflown - optional, an array of nested scrolling containers, see Element::getPosition
3512 getTop: function(overflown){
3513 return this.getPosition(overflown).y;
3518 Returns the distance from the left of the window to the Element.
3521 overflown - optional, an array of nested scrolling containers, see Element::getPosition
3524 getLeft: function(overflown){
3525 return this.getPosition(overflown).x;
3529 Property: getCoordinates
3530 Returns an object with width, height, left, right, top, and bottom, representing the values of the Element
3533 overflown - optional, an array of nested scrolling containers, see Element::getPosition
3537 var myValues = $('myElement').getCoordinates();
3553 getCoordinates: function(overflown){
3554 var position = this.getPosition(overflown);
3556 'width': this.offsetWidth,
3557 'height': this.offsetHeight,
3561 obj.right = obj.left + obj.width;
3562 obj.bottom = obj.top + obj.height;
3569 Script: Window.DomReady.js
3570 Contains the custom event domready, for window.
3576 /* Section: Custom Events */
3580 executes a function when the dom tree is loaded, without waiting for images. Only works when called from window.
3583 (c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools.
3586 fn - the function to execute when the DOM is ready
3589 > window.addEvent('domready', function(){
3590 > alert('the dom is ready');
3594 Element.Events.domready = {
3601 var domReady = function(){
3602 if (window.loaded) return;
3603 window.loaded = true;
3604 window.timer = $clear(window.timer);
3605 this.fireEvent('domready');
3607 if (document.readyState && window.webkit){
3608 window.timer = function(){
3609 if (['loaded','complete'].contains(document.readyState)) domReady();
3611 } else if (document.readyState && window.ie){
3612 if (!$('ie_ready')){
3613 var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
3614 document.write('<script id="ie_ready" defer src="' + src + '"><\/script>');
3615 $('ie_ready').onreadystatechange = function(){
3616 if (this.readyState == 'complete') domReady();
3620 window.addListener("load", domReady);
3621 document.addListener("DOMContentLoaded", domReady);
3629 window.onDomReady = function(fn){
3630 return this.addEvent('domready', fn);
3633 /*end compatibility*/
3636 Script: Window.Size.js
3637 Window cross-browser dimensions methods.
3640 The Functions in this script require an XHTML doctype.
3648 Cross browser methods to get various window dimensions.
3649 Warning: All these methods require that the browser operates in strict mode, not quirks mode.
3656 Returns an integer representing the width of the browser window (without the scrollbar).
3659 getWidth: function(){
3660 if (this.webkit419) return this.innerWidth;
3661 if (this.opera) return document.body.clientWidth;
3662 return document.documentElement.clientWidth;
3667 Returns an integer representing the height of the browser window (without the scrollbar).
3670 getHeight: function(){
3671 if (this.webkit419) return this.innerHeight;
3672 if (this.opera) return document.body.clientHeight;
3673 return document.documentElement.clientHeight;
3677 Property: getScrollWidth
3678 Returns an integer representing the scrollWidth of the window.
3679 This value is equal to or bigger than <getWidth>.
3682 <http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
3685 getScrollWidth: function(){
3686 if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth);
3687 if (this.webkit) return document.body.scrollWidth;
3688 return document.documentElement.scrollWidth;
3692 Property: getScrollHeight
3693 Returns an integer representing the scrollHeight of the window.
3694 This value is equal to or bigger than <getHeight>.
3697 <http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
3700 getScrollHeight: function(){
3701 if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight);
3702 if (this.webkit) return document.body.scrollHeight;
3703 return document.documentElement.scrollHeight;
3707 Property: getScrollLeft
3708 Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).
3711 <http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
3714 getScrollLeft: function(){
3715 return this.pageXOffset || document.documentElement.scrollLeft;
3719 Property: getScrollTop
3720 Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).
3723 <http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
3726 getScrollTop: function(){
3727 return this.pageYOffset || document.documentElement.scrollTop;
3732 Same as <Element.getSize>
3735 getSize: function(){
3737 'size': {'x': this.getWidth(), 'y': this.getHeight()},
3738 'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()},
3739 'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()}
3744 getPosition: function(){return {'x': 0, 'y': 0};}
3750 Contains <Fx.Base>, the foundamentals of the MooTools Effects.
3760 Base class for the Effects.
3763 transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.Sine.easeInOut>
3764 duration - the duration of the effect in ms; 500 is the default.
3765 unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%').
3766 wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true.
3767 fps - the frames per second for the transition; default is 50
3770 onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
3771 onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
3772 onCancel - the function to execute when you manually stop the effect.
3775 Fx.Base = new Class({
3778 onStart: Class.empty,
3779 onComplete: Class.empty,
3780 onCancel: Class.empty,
3781 transition: function(p){
3782 return -(Math.cos(Math.PI * p) - 1) / 2;
3790 initialize: function(options){
3791 this.element = this.element || null;
3792 this.setOptions(options);
3793 if (this.options.initialize) this.options.initialize.call(this);
3798 if (time < this.time + this.options.duration){
3799 this.delta = this.options.transition((time - this.time) / this.options.duration);
3805 this.fireEvent('onComplete', this.element, 10);
3812 Immediately sets the value with no transition.
3815 to - the point to jump to
3818 >var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
3828 this.now = this.compute(this.from, this.to);
3831 compute: function(from, to){
3832 return (to - from) * this.delta + from;
3837 Executes an effect from one position to the other.
3840 from - integer: staring value
3841 to - integer: the ending value
3844 >var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque.
3847 start: function(from, to){
3848 if (!this.options.wait) this.stop();
3849 else if (this.timer) return this;
3852 this.change = this.to - this.from;
3853 this.time = $time();
3854 this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
3855 this.fireEvent('onStart', this.element);
3861 Stops the transition.
3864 stop: function(end){
3865 if (!this.timer) return this;
3866 this.timer = $clear(this.timer);
3867 if (!end) this.fireEvent('onCancel', this.element);
3871 custom: function(from, to){
3872 return this.start(from, to);
3875 clearTimer: function(end){
3876 return this.stop(end);
3879 /*end compatibility*/
3883 Fx.Base.implement(new Chain, new Events, new Options);
3887 Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally.
3895 select: function(property, to){
3896 if (property.test(/color/i)) return this.Color;
3897 var type = $type(to);
3898 if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi;
3902 parse: function(el, property, fromTo){
3903 if (!fromTo.push) fromTo = [fromTo];
3904 var from = fromTo[0], to = fromTo[1];
3907 from = el.getStyle(property);
3909 var css = this.select(property, to);
3910 return {'from': css.parse(from), 'to': css.parse(to), 'css': css};
3917 parse: function(value){
3918 return parseFloat(value);
3921 getNow: function(from, to, fx){
3922 return fx.compute(from, to);
3925 getValue: function(value, unit, property){
3926 if (unit == 'px' && property != 'opacity') value = Math.round(value);
3927 return value + unit;
3934 parse: function(value){
3935 return value.push ? value : value.split(' ').map(function(v){
3936 return parseFloat(v);
3940 getNow: function(from, to, fx){
3942 for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
3946 getValue: function(value, unit, property){
3947 if (unit == 'px' && property != 'opacity') value = value.map(Math.round);
3948 return value.join(unit + ' ') + unit;
3955 parse: function(value){
3956 return value.push ? value : value.hexToRgb(true);
3959 getNow: function(from, to, fx){
3961 for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
3965 getValue: function(value){
3966 return 'rgb(' + value.join(',') + ')';
3981 The Style effect, used to transition any css property from one value to another. Includes colors.
3982 Colors must be in hex format.
3983 Inherits methods, properties, options and events from <Fx.Base>.
3986 el - the $(element) to apply the style transition to
3987 property - the property to transition
3988 options - the Fx.Base options (see: <Fx.Base>)
3991 >var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
3992 >marginChange.start(10, 100);
3995 Fx.Style = Fx.Base.extend({
3997 initialize: function(el, property, options){
3998 this.element = $(el);
3999 this.property = property;
4000 this.parent(options);
4005 Same as <Fx.Base.set> (0); hides the element immediately without transition.
4013 this.now = this.css.getNow(this.from, this.to, this);
4018 Sets the element's css property (specified at instantiation) to the specified value immediately.
4022 var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4023 marginChange.set(10); //margin-top is set to 10px immediately
4028 this.css = Fx.CSS.select(this.property, to);
4029 return this.parent(this.css.parse(to));
4034 Displays the transition to the value/values passed in
4037 from - (integer; optional) the starting position for the transition
4038 to - (integer) the ending position for the transition
4041 If you provide only one argument, the transition will use the current css value for its starting value.
4045 var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
4046 marginChange.start(10); //tries to read current margin top value and goes from current to 10
4050 start: function(from, to){
4051 if (this.timer && this.options.wait) return this;
4052 var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
4053 this.css = parsed.css;
4054 return this.parent(parsed.from, parsed.to);
4057 increase: function(){
4058 this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property));
4065 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4072 Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>.
4075 property - (string) the css property to alter
4076 options - (object; optional) key/value set of options (see <Fx.Style>)
4079 >var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear});
4080 >myEffect.start(10, 100);
4082 >$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100);
4085 effect: function(property, options){
4086 return new Fx.Style(this, property, options);
4092 Script: Fx.Styles.js
4093 Contains <Fx.Styles>
4101 Allows you to animate multiple css properties at once;
4102 Colors must be in hex format.
4103 Inherits methods, properties, options and events from <Fx.Base>.
4106 el - the $(element) to apply the styles transition to
4107 options - the fx options (see: <Fx.Base>)
4111 var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear});
4113 //height from 10 to 100 and width from 900 to 300
4115 'height': [10, 100],
4119 //or height from current height to 100 and width from current width to 300
4127 Fx.Styles = Fx.Base.extend({
4129 initialize: function(el, options){
4130 this.element = $(el);
4131 this.parent(options);
4135 for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this);
4142 this.css[p] = Fx.CSS.select(p, to[p]);
4143 parsed[p] = this.css[p].parse(to[p]);
4145 return this.parent(parsed);
4150 Executes a transition for any number of css properties in tandem.
4153 obj - an object containing keys that specify css properties to alter and values that specify either the from/to values (as an array) or just the end value (an integer).
4159 start: function(obj){
4160 if (this.timer && this.options.wait) return this;
4163 var from = {}, to = {};
4165 var parsed = Fx.CSS.parse(this.element, p, obj[p]);
4166 from[p] = parsed.from;
4168 this.css[p] = parsed.css;
4170 return this.parent(from, to);
4173 increase: function(){
4174 for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit, p));
4181 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4188 Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>.
4191 >var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.Sine.easeInOut});
4192 >myEffects.start({'height': [10, 100], 'width': [900, 300]});
4195 effects: function(options){
4196 return new Fx.Styles(this, options);
4202 Script: Fx.Elements.js
4203 Contains <Fx.Elements>
4211 Fx.Elements allows you to apply any number of styles transitions to a selection of elements. Includes colors (must be in hex format).
4212 Inherits methods, properties, options and events from <Fx.Base>.
4215 elements - a collection of elements the effects will be applied to.
4216 options - same as <Fx.Base> options.
4219 Fx.Elements = Fx.Base.extend({
4221 initialize: function(elements, options){
4222 this.elements = $$(elements);
4223 this.parent(options);
4227 for (var i in this.from){
4228 var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {};
4229 for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this);
4237 var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {};
4239 iCss[p] = Fx.CSS.select(p, iTo[p]);
4240 iParsed[p] = iCss[p].parse(iTo[p]);
4243 return this.parent(parsed);
4248 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.
4252 var myElementsEffects = new Fx.Elements($$('a'));
4253 myElementsEffects.start({
4254 '0': { //let's change the first element's opacity and width
4258 '4': { //and the fifth one's opacity
4259 'opacity': [0.2, 0.5]
4265 start: function(obj){
4266 if (this.timer && this.options.wait) return this;
4269 var from = {}, to = {};
4271 var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {};
4272 for (var p in iProps){
4273 var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]);
4274 iFrom[p] = parsed.from;
4276 iCss[p] = parsed.css;
4279 return this.parent(from, to);
4282 increase: function(){
4283 for (var i in this.now){
4284 var iNow = this.now[i], iCss = this.css[i];
4285 for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit, p));
4292 Script: Fx.Scroll.js
4293 Contains <Fx.Scroll>
4301 Scroll any element with an overflow, including the window element.
4302 Inherits methods, properties, options and events from <Fx.Base>.
4305 Fx.Scroll requires an XHTML doctype.
4308 element - the element to scroll
4309 options - optional, see Options below.
4312 all the Fx.Base options and events, plus:
4313 offset - the distance for the scrollTo point/element. an Object with x/y properties.
4314 overflown - an array of nested scrolling containers, see <Element.getPosition>
4317 Fx.Scroll = Fx.Base.extend({
4321 offset: {'x': 0, 'y': 0},
4325 initialize: function(element, options){
4327 this.element = $(element);
4328 this.bound = {'stop': this.stop.bind(this, false)};
4329 this.parent(options);
4330 if (this.options.wheelStops){
4331 this.addEvent('onStart', function(){
4332 document.addEvent('mousewheel', this.bound.stop);
4334 this.addEvent('onComplete', function(){
4335 document.removeEvent('mousewheel', this.bound.stop);
4341 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4346 Scrolls the chosen element to the x/y coordinates.
4349 x - the x coordinate to scroll the element to
4350 y - the y coordinate to scroll the element to
4353 scrollTo: function(x, y){
4354 if (this.timer && this.options.wait) return this;
4355 var el = this.element.getSize();
4356 var values = {'x': x, 'y': y};
4357 for (var z in el.size){
4358 var max = el.scrollSize[z] - el.size[z];
4359 if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;
4360 else values[z] = el.scroll[z];
4361 values[z] += this.options.offset[z];
4363 return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]);
4368 Scrolls the chosen element to its maximum top.
4372 return this.scrollTo(false, 0);
4377 Scrolls the chosen element to its maximum bottom.
4380 toBottom: function(){
4381 return this.scrollTo(false, 'full');
4386 Scrolls the chosen element to its maximum left.
4390 return this.scrollTo(0, false);
4395 Scrolls the chosen element to its maximum right.
4398 toRight: function(){
4399 return this.scrollTo('full', false);
4404 Scrolls the specified element to the position the passed in element is found.
4407 el - the $(element) to scroll the window to
4410 toElement: function(el){
4411 var parent = this.element.getPosition(this.options.overflown);
4412 var target = $(el).getPosition(this.options.overflown);
4413 return this.scrollTo(target.x - parent.x, target.y - parent.y);
4416 increase: function(){
4417 this.element.scrollTo(this.now[0], this.now[1]);
4432 The slide effect; slides an element in horizontally or vertically, the contents will fold inside.
4433 Inherits methods, properties, options and events from <Fx.Base>.
4436 Fx.Slide requires an XHTML doctype.
4439 mode - set it to vertical or horizontal. Defaults to vertical.
4440 options - all the <Fx.Base> options
4444 var mySlider = new Fx.Slide('myElement', {duration: 500});
4445 mySlider.toggle() //toggle the slider up and down.
4449 Fx.Slide = Fx.Base.extend({
4455 initialize: function(el, options){
4456 this.element = $(el);
4457 this.wrapper = new Element('div', {'styles': $extend(this.element.getStyles('margin'), {'overflow': 'hidden'})}).injectAfter(this.element).adopt(this.element);
4458 this.element.setStyle('margin', 0);
4459 this.setOptions(options);
4461 this.parent(this.options);
4463 this.addEvent('onComplete', function(){
4464 this.open = (this.now[0] === 0);
4466 if (window.webkit419) this.addEvent('onComplete', function(){
4467 if (this.open) this.element.remove().inject(this.wrapper);
4472 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
4475 vertical: function(){
4476 this.margin = 'margin-top';
4477 this.layout = 'height';
4478 this.offset = this.element.offsetHeight;
4481 horizontal: function(){
4482 this.margin = 'margin-left';
4483 this.layout = 'width';
4484 this.offset = this.element.offsetWidth;
4489 Slides the elements in view horizontally or vertically.
4492 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4495 slideIn: function(mode){
4496 this[mode || this.options.mode]();
4497 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.offset]);
4502 Sides the elements out of view horizontally or vertically.
4505 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4508 slideOut: function(mode){
4509 this[mode || this.options.mode]();
4510 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]);
4515 Hides the element without a transition.
4518 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4521 hide: function(mode){
4522 this[mode || this.options.mode]();
4524 return this.set([-this.offset, 0]);
4529 Shows the element without a transition.
4532 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4535 show: function(mode){
4536 this[mode || this.options.mode]();
4538 return this.set([0, this.offset]);
4543 Slides in or Out the element, depending on its state
4546 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode.
4550 toggle: function(mode){
4551 if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode);
4552 return this.slideOut(mode);
4555 increase: function(){
4556 this.element.setStyle(this.margin, this.now[0] + this.options.unit);
4557 this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit);
4563 Script: Fx.Transitions.js
4564 Effects transitions, to be used with all the effects.
4570 Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified & optimized to be used with mootools.
4574 Class: Fx.Transitions
4575 A collection of tweening transitions for use with the <Fx.Base> classes.
4578 >//Elastic.easeOut with default values:
4579 >new Fx.Style('margin', {transition: Fx.Transitions.Elastic.easeOut});
4580 >//Elastic.easeOut with user-defined value for elasticity.
4581 > var myTransition = new Fx.Transition(Fx.Transitions.Elastic, 3);
4582 >new Fx.Style('margin', {transition: myTransition.easeOut});
4585 http://www.robertpenner.com/easing/
4588 Fx.Transition = function(transition, params){
4589 params = params || [];
4590 if ($type(params) != 'array') params = [params];
4591 return $extend(transition, {
4592 easeIn: function(pos){
4593 return transition(pos, params);
4595 easeOut: function(pos){
4596 return 1 - transition(1 - pos, params);
4598 easeInOut: function(pos){
4599 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
4604 Fx.Transitions = new Abstract({
4608 displays a linear transition.
4614 linear: function(p){
4620 Fx.Transitions.extend = function(transitions){
4621 for (var transition in transitions){
4622 Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
4624 Fx.Transitions.compat(transition);
4625 /*end compatibility*/
4631 Fx.Transitions.compat = function(transition){
4632 ['In', 'Out', 'InOut'].each(function(easeType){
4633 Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType];
4637 /*end compatibility*/
4639 Fx.Transitions.extend({
4643 displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut
4653 displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut
4663 displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut
4673 displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut
4683 Used to generate Quad, Cubic, Quart and Quint.
4690 Pow: function(p, x){
4691 return Math.pow(p, x[0] || 6);
4696 displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut
4703 return Math.pow(2, 8 * (p - 1));
4708 displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut
4715 return 1 - Math.sin(Math.acos(p));
4721 displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut
4728 return 1 - Math.sin((1 - p) * Math.PI / 2);
4733 makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut
4739 Back: function(p, x){
4741 return Math.pow(p, 2) * ((x + 1) * p - x);
4746 makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut
4752 Bounce: function(p){
4754 for (var a = 0, b = 1; 1; a += b, b /= 2){
4755 if (p >= (7 - 4 * a) / 11){
4756 value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;
4765 Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut
4771 Elastic: function(p, x){
4772 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
4777 ['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
4778 Fx.Transitions[transition] = new Fx.Transition(function(p){
4779 return Math.pow(p, [i + 2]);
4783 Fx.Transitions.compat(transition);
4784 /*end compatibility*/
4788 Script: Drag.Base.js
4789 Contains <Drag.Base>, <Element.makeResizable>
4799 Modify two css properties of an element based on the position of the mouse.
4802 Drag.Base requires an XHTML doctype.
4805 el - the $(element) to apply the transformations to.
4806 options - optional. The options object.
4809 handle - the $(element) to act as the handle for the draggable element. defaults to the $(element) itself.
4810 modifiers - an object. see Modifiers Below.
4811 limit - an object, see Limit below.
4812 grid - optional, distance in px for snap-to-grid dragging
4813 snap - optional, the distance you have to drag before the element starts to respond to the drag. defaults to false
4816 x - string, the style you want to modify when the mouse moves in an horizontal direction. defaults to 'left'
4817 y - string, the style you want to modify when the mouse moves in a vertical direction. defaults to 'top'
4820 x - array with start and end limit relative to modifiers.x
4821 y - array with start and end limit relative to modifiers.y
4824 onStart - optional, function to execute when the user starts to drag (on mousedown);
4825 onComplete - optional, function to execute when the user completes the drag.
4826 onDrag - optional, function to execute at every step of the drag
4829 Drag.Base = new Class({
4834 onStart: Class.empty,
4835 onBeforeStart: Class.empty,
4836 onComplete: Class.empty,
4837 onSnap: Class.empty,
4838 onDrag: Class.empty,
4840 modifiers: {x: 'left', y: 'top'},
4845 initialize: function(el, options){
4846 this.setOptions(options);
4847 this.element = $(el);
4848 this.handle = $(this.options.handle) || this.element;
4849 this.mouse = {'now': {}, 'pos': {}};
4850 this.value = {'start': {}, 'now': {}};
4852 'start': this.start.bindWithEvent(this),
4853 'check': this.check.bindWithEvent(this),
4854 'drag': this.drag.bindWithEvent(this),
4855 'stop': this.stop.bind(this)
4858 if (this.options.initialize) this.options.initialize.call(this);
4862 this.handle.addEvent('mousedown', this.bound.start);
4867 this.handle.removeEvent('mousedown', this.bound.start);
4871 start: function(event){
4872 this.fireEvent('onBeforeStart', this.element);
4873 this.mouse.start = event.page;
4874 var limit = this.options.limit;
4875 this.limit = {'x': [], 'y': []};
4876 for (var z in this.options.modifiers){
4877 if (!this.options.modifiers[z]) continue;
4878 this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
4879 this.mouse.pos[z] = event.page[z] - this.value.now[z];
4880 if (limit && limit[z]){
4881 for (var i = 0; i < 2; i++){
4882 if ($chk(limit[z][i])) this.limit[z][i] = ($type(limit[z][i]) == 'function') ? limit[z][i]() : limit[z][i];
4886 if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};
4887 document.addListener('mousemove', this.bound.check);
4888 document.addListener('mouseup', this.bound.stop);
4889 this.fireEvent('onStart', this.element);
4893 check: function(event){
4894 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)));
4895 if (distance > this.options.snap){
4896 document.removeListener('mousemove', this.bound.check);
4897 document.addListener('mousemove', this.bound.drag);
4899 this.fireEvent('onSnap', this.element);
4904 drag: function(event){
4906 this.mouse.now = event.page;
4907 for (var z in this.options.modifiers){
4908 if (!this.options.modifiers[z]) continue;
4909 this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
4911 if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
4912 this.value.now[z] = this.limit[z][1];
4914 } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
4915 this.value.now[z] = this.limit[z][0];
4919 if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);
4920 this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
4922 this.fireEvent('onDrag', this.element);
4927 document.removeListener('mousemove', this.bound.check);
4928 document.removeListener('mousemove', this.bound.drag);
4929 document.removeListener('mouseup', this.bound.stop);
4930 this.fireEvent('onComplete', this.element);
4935 Drag.Base.implement(new Events, new Options);
4939 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
4945 Property: makeResizable
4946 Makes an element resizable (by dragging) with the supplied options.
4949 options - see <Drag.Base> for acceptable options.
4952 makeResizable: function(options){
4953 return new Drag.Base(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));
4959 Script: Drag.Move.js
4960 Contains <Drag.Move>, <Element.makeDraggable>
4968 Extends <Drag.Base>, has additional functionality for dragging an element, support snapping and droppables.
4969 Drag.move supports either position absolute or relative. If no position is found, absolute will be set.
4970 Inherits methods, properties, options and events from <Drag.Base>.
4973 Drag.Move requires an XHTML doctype.
4976 el - the $(element) to apply the drag to.
4977 options - optional. see Options below.
4980 all the drag.Base options, plus:
4981 container - an element, will fill automatically limiting options based on the $(element) size and position. defaults to false (no limiting)
4982 droppables - an array of elements you can drop your draggable to.
4983 overflown - an array of nested scrolling containers, see Element::getPosition
4986 Drag.Move = Drag.Base.extend({
4994 initialize: function(el, options){
4995 this.setOptions(options);
4996 this.element = $(el);
4997 this.droppables = $$(this.options.droppables);
4998 this.container = $(this.options.container);
4999 this.position = {'element': this.element.getStyle('position'), 'container': false};
5000 if (this.container) this.position.container = this.container.getStyle('position');
5001 if (!['relative', 'absolute', 'fixed'].contains(this.position.element)) this.position.element = 'absolute';
5002 var top = this.element.getStyle('top').toInt();
5003 var left = this.element.getStyle('left').toInt();
5004 if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5005 top = $chk(top) ? top : this.element.getTop(this.options.overflown);
5006 left = $chk(left) ? left : this.element.getLeft(this.options.overflown);
5008 top = $chk(top) ? top : 0;
5009 left = $chk(left) ? left : 0;
5011 this.element.setStyles({'top': top, 'left': left, 'position': this.position.element});
5012 this.parent(this.element);
5015 start: function(event){
5017 if (this.container){
5018 var cont = this.container.getCoordinates();
5019 var el = this.element.getCoordinates();
5020 if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){
5021 this.options.limit = {
5022 'x': [cont.left, cont.right - el.width],
5023 'y': [cont.top, cont.bottom - el.height]
5026 this.options.limit = {
5027 'y': [0, cont.height - el.height],
5028 'x': [0, cont.width - el.width]
5035 drag: function(event){
5037 var overed = this.out ? false : this.droppables.filter(this.checkAgainst, this).getLast();
5038 if (this.overed != overed){
5039 if (this.overed) this.overed.fireEvent('leave', [this.element, this]);
5040 this.overed = overed ? overed.fireEvent('over', [this.element, this]) : null;
5045 checkAgainst: function(el){
5046 el = el.getCoordinates(this.options.overflown);
5047 var now = this.mouse.now;
5048 return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
5052 if (this.overed && !this.out) this.overed.fireEvent('drop', [this.element, this]);
5053 else this.element.fireEvent('emptydrop', this);
5062 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5068 Property: makeDraggable
5069 Makes an element draggable with the supplied options.
5072 options - see <Drag.Move> and <Drag.Base> for acceptable options.
5075 makeDraggable: function(options){
5076 return new Drag.Move(this, options);
5083 Contains the basic XMLHttpRequest Class Wrapper.
5091 Basic XMLHttpRequest Wrapper.
5094 options - an object with options names as keys. See options below.
5097 method - 'post' or 'get' - the protocol for the request; optional, defaults to 'post'.
5098 async - boolean: asynchronous option; true uses asynchronous requests. Defaults to true.
5099 encoding - the encoding, defaults to utf-8.
5100 autoCancel - cancels the already running request if another one is sent. defaults to false.
5101 headers - accepts an object, that will be set to request headers.
5104 onRequest - function to execute when the XHR request is fired.
5105 onSuccess - function to execute when the XHR request completes.
5106 onStateChange - function to execute when the state of the XMLHttpRequest changes.
5107 onFailure - function to execute when the state of the XMLHttpRequest changes.
5110 running - true if the request is running.
5111 response - object, text and xml as keys. You can access this property in the onSuccess event.
5114 >var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian');
5117 var XHR = new Class({
5122 onRequest: Class.empty,
5123 onSuccess: Class.empty,
5124 onFailure: Class.empty,
5131 setTransport: function(){
5132 this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
5136 initialize: function(options){
5137 this.setTransport().setOptions(options);
5138 this.options.isSuccess = this.options.isSuccess || this.isSuccess;
5140 if (this.options.urlEncoded && this.options.method == 'post'){
5141 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
5142 this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
5144 if (this.options.initialize) this.options.initialize.call(this);
5147 onStateChange: function(){
5148 if (this.transport.readyState != 4 || !this.running) return;
5149 this.running = false;
5151 try {status = this.transport.status;} catch(e){};
5152 if (this.options.isSuccess.call(this, status)) this.onSuccess();
5153 else this.onFailure();
5154 this.transport.onreadystatechange = Class.empty;
5157 isSuccess: function(status){
5158 return ((status >= 200) && (status < 300));
5161 onSuccess: function(){
5163 'text': this.transport.responseText,
5164 'xml': this.transport.responseXML
5166 this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
5170 onFailure: function(){
5171 this.fireEvent('onFailure', this.transport);
5176 Add/modify an header for the request. It will not override headers from the options.
5179 >var myXhr = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}});
5180 >myXhr.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT');
5183 setHeader: function(name, value){
5184 this.headers[name] = value;
5190 Opens the XHR connection and sends the data. Data has to be null or a string.
5193 >var myXhr = new XHR({method: 'post'});
5194 >myXhr.send(url, querystring);
5196 >var syncXhr = new XHR({async: false, method: 'post'});
5197 >syncXhr.send(url, null);
5201 send: function(url, data){
5202 if (this.options.autoCancel) this.cancel();
5203 else if (this.running) return this;
5204 this.running = true;
5205 if (data && this.options.method == 'get'){
5206 url = url + (url.contains('?') ? '&' : '?') + data;
5209 this.transport.open(this.options.method.toUpperCase(), url, this.options.async);
5210 this.transport.onreadystatechange = this.onStateChange.bind(this);
5211 if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');
5212 $extend(this.headers, this.options.headers);
5213 for (var type in this.headers) try {this.transport.setRequestHeader(type, this.headers[type]);} catch(e){};
5214 this.fireEvent('onRequest');
5215 this.transport.send($pick(data, null));
5221 Cancels the running request. No effect if the request is not running.
5224 >var myXhr = new XHR({method: 'get'}).send(url);
5229 if (!this.running) return this;
5230 this.running = false;
5231 this.transport.abort();
5232 this.transport.onreadystatechange = Class.empty;
5233 this.setTransport();
5234 this.fireEvent('onCancel');
5240 XHR.implement(new Chain, new Events, new Options);
5244 Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects.
5247 Loosely based on the version from prototype.js <http://prototype.conio.net>
5255 An Ajax class, For all your asynchronous needs.
5256 Inherits methods, properties, options and events from <XHR>.
5259 url - the url pointing to the server-side script.
5260 options - optional, an object containing options.
5263 data - you can write parameters here. Can be a querystring, an object or a Form element.
5264 update - $(element) to insert the response text of the XHR into, upon completion of the request.
5265 evalScripts - boolean; default is false. Execute scripts in the response text onComplete. When the response is javascript the whole response is evaluated.
5266 evalResponse - boolean; default is false. Force global evalulation of the whole response, no matter what content-type it is.
5269 onComplete - function to execute when the ajax request completes.
5272 >var myAjax = new Ajax(url, {method: 'get'}).request();
5275 var Ajax = XHR.extend({
5280 onComplete: Class.empty,
5285 initialize: function(url, options){
5286 this.addEvent('onSuccess', this.onComplete);
5287 this.setOptions(options);
5289 this.options.data = this.options.data || this.options.postBody;
5290 /*end compatibility*/
5291 if (!['post', 'get'].contains(this.options.method)){
5292 this._method = '_method=' + this.options.method;
5293 this.options.method = 'post';
5296 this.setHeader('X-Requested-With', 'XMLHttpRequest');
5297 this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
5301 onComplete: function(){
5302 if (this.options.update) $(this.options.update).empty().setHTML(this.response.text);
5303 if (this.options.evalScripts || this.options.evalResponse) this.evalScripts();
5304 this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
5309 Executes the ajax request.
5312 >var myAjax = new Ajax(url, {method: 'get'});
5317 >new Ajax(url, {method: 'get'}).request();
5320 request: function(data){
5321 data = data || this.options.data;
5322 switch($type(data)){
5323 case 'element': data = $(data).toQueryString(); break;
5324 case 'object': data = Object.toQueryString(data);
5326 if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
5327 return this.send(this.url, data);
5331 Property: evalScripts
5332 Executes scripts in the response text
5335 evalScripts: function(){
5336 var script, scripts;
5337 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) scripts = this.response.text;
5340 var regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
5341 while ((script = regexp.exec(this.response.text))) scripts.push(script[1]);
5342 scripts = scripts.join('\n');
5344 if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0);
5349 Returns the given response header or null
5352 getHeader: function(name){
5353 try {return this.transport.getResponseHeader(name);} catch(e){};
5359 /* Section: Object related Functions */
5362 Function: Object.toQueryString
5363 Generates a querystring from key/pair values in an object
5366 source - the object to generate the querystring from.
5372 >Object.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow"
5375 Object.toQueryString = function(source){
5376 var queryString = [];
5377 for (var property in source) queryString.push(encodeURIComponent(property) + '=' + encodeURIComponent(source[property]));
5378 return queryString.join('&');
5383 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
5390 Sends a form with an ajax post request
5393 options - option collection for ajax request. See <Ajax> for the options list.
5396 The Ajax Class Instance
5400 <form id="myForm" action="submit.php">
5401 <input name="email" value="bob@bob.com">
5402 <input name="zipCode" value="90210">
5410 send: function(options){
5411 return new Ajax(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request();
5418 A cookie reader/creator
5421 based on the functions by Peter-Paul Koch (http://quirksmode.org)
5426 Class for creating, getting, and removing cookies.
5429 var Cookie = new Abstract({
5440 Sets a cookie in the browser.
5443 key - the key (name) for the cookie
5444 value - the value to set, cannot contain semicolons
5445 options - an object representing the Cookie options. See Options below. Default values are stored in Cookie.options.
5448 domain - the domain the Cookie belongs to. If you want to share the cookie with pages located on a different domain, you have to set this value. Defaults to the current domain.
5449 path - the path the Cookie belongs to. If you want to share the cookie with pages located in a different path, you have to set this value, for example to "/" to share the cookie with all pages on the domain. Defaults to the current path.
5450 duration - the duration of the Cookie before it expires, in days.
5451 If set to false or 0, the cookie will be a session cookie that expires when the browser is closed. This is default.
5452 secure - Stored cookie information can be accessed only from a secure environment.
5455 An object with the options, the key and the value. You can give it as first parameter to Cookie.remove.
5458 >Cookie.set('username', 'Harald'); // session cookie (duration is false), or ...
5459 >Cookie.set('username', 'JackBauer', {duration: 1}); // save this for 1 day
5463 set: function(key, value, options){
5464 options = $merge(this.options, options);
5465 value = encodeURIComponent(value);
5466 if (options.domain) value += '; domain=' + options.domain;
5467 if (options.path) value += '; path=' + options.path;
5468 if (options.duration){
5469 var date = new Date();
5470 date.setTime(date.getTime() + options.duration * 24 * 60 * 60 * 1000);
5471 value += '; expires=' + date.toGMTString();
5473 if (options.secure) value += '; secure';
5474 document.cookie = key + '=' + value;
5475 return $extend(options, {'key': key, 'value': value});
5480 Gets the value of a cookie.
5483 key - the name of the cookie you wish to retrieve.
5486 The cookie string value, or false if not found.
5489 >Cookie.get("username") //returns JackBauer
5493 var value = document.cookie.match('(?:^|;)\\s*' + key.escapeRegExp() + '=([^;]*)');
5494 return value ? decodeURIComponent(value[1]) : false;
5499 Removes a cookie from the browser.
5502 cookie - the name of the cookie to remove or a previous cookie (for domains)
5503 options - optional. you can also pass the domain and path here. Same as options in <Cookie.set>
5506 >Cookie.remove('username') //bye-bye JackBauer, cya in 24 hours
5508 >var myCookie = Cookie.set('username', 'Aaron', {domain: 'mootools.net'}); // Cookie.set returns an object with all values need to remove the cookie
5509 >Cookie.remove(myCookie);
5512 remove: function(cookie, options){
5513 if ($type(cookie) == 'object') this.set(cookie.key, '', $merge(cookie, {duration: -1}));
5514 else this.set(cookie, '', $merge(options, {duration: -1}));
5521 Simple Json parser and Stringyfier, See: <http://www.json.org/>
5529 Simple Json parser and Stringyfier, See: <http://www.json.org/>
5536 Converts an object to a string, to be passed in server-side scripts as a parameter. Although its not normal usage for this class, this method can also be used to convert functions and arrays to strings.
5539 obj - the object to convert to string
5546 Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}'
5550 toString: function(obj){
5553 return '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
5555 return '[' + obj.map(Json.toString).join(',') + ']';
5558 for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property]));
5559 return '{' + string.join(',') + '}';
5561 if (isFinite(obj)) break;
5570 converts a json string to an javascript Object.
5573 str - the string to evaluate. if its not a string, it returns false.
5574 secure - optionally, performs syntax check on json string. Defaults to false.
5577 Json test regexp is by Douglas Crockford <http://crockford.org>.
5580 >var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}');
5581 >//myObject will become {apple: 'red', lemon: 'yellow'}
5584 evaluate: function(str, secure){
5585 return (($type(str) != 'string') || (secure && !str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/))) ? null : eval('(' + str + ')');
5591 Script: Json.Remote.js
5592 Contains <Json.Remote>.
5600 Wrapped XHR with automated sending and receiving of Javascript Objects in Json Format.
5601 Inherits methods, properties, options and events from <XHR>.
5604 url - the url you want to send your object to.
5605 options - see <XHR> options
5608 this code will send user information based on name/last name
5610 var jSonRequest = new Json.Remote("http://site.com/tellMeAge.php", {onComplete: function(person){
5611 alert(person.age); //is 25 years
5612 alert(person.height); //is 170 cm
5613 alert(person.weight); //is 120 kg
5614 }}).send({'name': 'John', 'lastName': 'Doe'});
5618 Json.Remote = XHR.extend({
5620 initialize: function(url, options){
5622 this.addEvent('onSuccess', this.onComplete);
5623 this.parent(options);
5624 this.setHeader('X-Request', 'JSON');
5627 send: function(obj){
5628 return this.parent(this.url, 'json=' + Json.toString(obj));
5631 onComplete: function(){
5632 this.fireEvent('onComplete', [Json.evaluate(this.response.text, this.options.secure)]);
5639 provides dynamic loading for images, css and javascript files.
5645 var Asset = new Abstract({
5648 Property: javascript
5649 Injects a javascript file in the page.
5652 source - the path of the javascript file
5653 properties - some additional attributes you might want to add to the script element
5656 > new Asset.javascript('/scripts/myScript.js', {id: 'myScript'});
5659 javascript: function(source, properties){
5660 properties = $merge({
5661 'onload': Class.empty
5663 var script = new Element('script', {'src': source}).addEvents({
5664 'load': properties.onload,
5665 'readystatechange': function(){
5666 if (this.readyState == 'complete') this.fireEvent('load');
5669 delete properties.onload;
5670 return script.setProperties(properties).inject(document.head);
5675 Injects a css file in the page.
5678 source - the path of the css file
5679 properties - some additional attributes you might want to add to the link element
5682 > new Asset.css('/css/myStyle.css', {id: 'myStyle', title: 'myStyle'});
5685 css: function(source, properties){
5686 return new Element('link', $merge({
5687 'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
5688 }, properties)).inject(document.head);
5693 Preloads an image and returns the img element. does not inject it to the page.
5696 source - the path of the image file
5697 properties - some additional attributes you might want to add to the img element
5700 > new Asset.image('/images/myImage.png', {id: 'myImage', title: 'myImage', onload: myFunction});
5703 the img element. you can inject it anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5706 image: function(source, properties){
5707 properties = $merge({
5708 'onload': Class.empty,
5709 'onabort': Class.empty,
5710 'onerror': Class.empty
5712 var image = new Image();
5714 var element = new Element('img', {'src': source});
5715 ['load', 'abort', 'error'].each(function(type){
5716 var event = properties['on' + type];
5717 delete properties['on' + type];
5718 element.addEvent(type, function(){
5719 this.removeEvent(type, arguments.callee);
5723 if (image.width && image.height) element.fireEvent('load', element, 1);
5724 return element.setProperties(properties);
5729 Preloads an array of images (as strings) and returns an array of img elements. does not inject them to the page.
5732 sources - array, the paths of the image files
5733 options - object, see below
5736 onComplete - a function to execute when all image files are loaded in the browser's cache
5737 onProgress - a function to execute when one image file is loaded in the browser's cache
5741 new Asset.images(['/images/myImage.png', '/images/myImage2.gif'], {
5742 onComplete: function(){
5743 alert('all images loaded!');
5749 the img elements as $$. you can inject them anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore>
5752 images: function(sources, options){
5754 onComplete: Class.empty,
5755 onProgress: Class.empty
5757 if (!sources.push) sources = [sources];
5760 sources.each(function(source){
5761 var img = new Asset.image(source, {
5762 'onload': function(){
5763 options.onProgress.call(this, counter);
5765 if (counter == sources.length) options.onComplete();
5770 return new Elements(images);
5777 Contains the class Hash.
\r
5780 MIT-style license.
\r
5785 It wraps an object that it uses internally as a map. The user must use set(), get(), and remove() to add/change, retrieve and remove values, it must not access the internal object directly. null/undefined values are allowed.
\r
5788 Each hash instance has the length property.
\r
5791 obj - an object to convert into a Hash instance.
\r
5795 var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'});
\r
5796 hash.remove('b'); // b is removed.
\r
5797 hash.set('c', 'hello');
\r
5798 hash.get('c'); // returns 'hello'
\r
5799 hash.length // returns 2 (a and c)
\r
5803 var Hash = new Class({
\r
5807 initialize: function(object){
\r
5808 this.obj = object || {};
\r
5814 Retrieves a value from the hash.
\r
5823 get: function(key){
\r
5824 return (this.hasKey(key)) ? this.obj[key] : null;
\r
5829 Check the presence of a specified key-value pair in the hash.
\r
5835 True if the Hash contains a value for the specified key, otherwise false
\r
5838 hasKey: function(key){
\r
5839 return (key in this.obj);
\r
5844 Adds a key-value pair to the hash or replaces a previous value associated with the key.
\r
5851 set: function(key, value){
\r
5852 if (!this.hasKey(key)) this.length++;
\r
5853 this.obj[key] = value;
\r
5857 setLength: function(){
\r
5859 for (var p in this.obj) this.length++;
\r
5865 Removes a key-value pair from the hash.
\r
5871 remove: function(key){
\r
5872 if (this.hasKey(key)){
\r
5873 delete this.obj[key];
\r
5881 Calls a function for each key-value pair. The first argument passed to the function will be the value, the second one will be the key, like $each.
\r
5884 fn - The function to call for each key-value pair
\r
5885 bind - Optional, the object that will be referred to as "this" in the function
\r
5888 each: function(fn, bind){
\r
5889 $each(this.obj, fn, bind);
\r
5894 Extends the current hash with an object containing key-value pairs. Values for duplicate keys will be replaced by the new ones.
\r
5897 obj - An object containing key-value pairs
\r
5900 extend: function(obj){
\r
5901 $extend(this.obj, obj);
\r
5902 return this.setLength();
\r
5907 Merges the current hash with multiple objects.
\r
5910 merge: function(){
\r
5911 this.obj = $merge.apply(null, [this.obj].extend(arguments));
\r
5912 return this.setLength();
\r
5917 Empties all hash values properties and values.
\r
5920 empty: function(){
\r
5928 Returns an array containing all the keys, in the same order as the values returned by <Hash.values>.
\r
5931 An array containing all the keys of the hash
\r
5936 for (var property in this.obj) keys.push(property);
\r
5942 Returns an array containing all the values, in the same order as the keys returned by <Hash.keys>.
\r
5945 An array containing all the values of the hash
\r
5948 values: function(){
\r
5950 for (var property in this.obj) values.push(this.obj[property]);
\r
5956 /* Section: Utility Functions */
\r
5960 Shortcut to create a Hash from an Object.
\r
5964 return new Hash(obj);
\r
5968 Script: Hash.Cookie.js
\r
5969 Stores and loads an Hash as a cookie using Json format.
\r
5973 Class: Hash.Cookie
\r
5974 Inherits all the methods from <Hash>, additional methods are save and load.
\r
5975 Hash json string has a limit of 4kb (4096byte), so be careful with your Hash size.
\r
5976 Creating a new instance automatically loads the data from the Cookie into the Hash.
\r
5977 If the Hash is emptied, the cookie is also removed.
\r
5980 name - the key (name) for the cookie
\r
5981 options - options are identical to <Cookie> and are simply passed along to it.
\r
5982 In addition, it has the autoSave option, to save the cookie at every operation. defaults to true.
\r
5986 var fruits = new Hash.Cookie('myCookieName', {duration: 3600});
\r
5988 'lemon': 'yellow',
\r
5991 fruits.set('melon', 'green');
\r
5992 fruits.get('lemon'); // yellow
\r
5994 // ... on another page ... values load automatically
\r
5996 var fruits = new Hash.Cookie('myCookieName', {duration: 365});
\r
5997 fruits.get('melon'); // green
\r
5999 fruits.erase(); // delete cookie
\r
6003 Hash.Cookie = Hash.extend({
\r
6005 initialize: function(name, options){
\r
6007 this.options = $extend({'autoSave': true}, options || {});
\r
6013 Saves the Hash to the cookie. If the hash is empty, removes the cookie.
\r
6016 Returns false when the JSON string cookie is too long (4kb), otherwise true.
\r
6020 var login = new Hash.Cookie('userstatus', {autoSave: false});
\r
6023 'username': 'John',
\r
6024 'credentials': [4, 7, 9]
\r
6026 login.set('last_message', 'User logged in!');
\r
6028 login.save(); // finally save the Hash
\r
6033 if (this.length == 0){
\r
6034 Cookie.remove(this.name, this.options);
\r
6037 var str = Json.toString(this.obj);
\r
6038 if (str.length > 4096) return false; //cookie would be truncated!
\r
6039 Cookie.set(this.name, str, this.options);
\r
6045 Loads the cookie and assigns it to the Hash.
\r
6049 this.obj = Json.evaluate(Cookie.get(this.name), true) || {};
\r
6055 Hash.Cookie.Methods = {};
\r
6056 ['extend', 'set', 'merge', 'empty', 'remove'].each(function(method){
\r
6057 Hash.Cookie.Methods[method] = function(){
\r
6058 Hash.prototype[method].apply(this, arguments);
\r
6059 if (this.options.autoSave) this.save();
\r
6063 Hash.Cookie.implement(Hash.Cookie.Methods);
6067 Contains the Color class.
6075 Creates a new Color Object, which is an array with some color specific methods.
6077 color - the hex, the RGB array or the HSB array of the color to create. For HSB colors, you need to specify the second argument.
6078 type - a string representing the type of the color to create. needs to be specified if you intend to create the color with HSB values, or an array of HEX values. Can be 'rgb', 'hsb' or 'hex'.
6082 var black = new Color('#000');
6083 var purple = new Color([255,0,255]);
6084 // mix black with white and purple, each time at 10% of the new color
6085 var darkpurple = black.mix('#fff', purple, 10);
6086 $('myDiv').setStyle('background-color', darkpurple);
6090 var Color = new Class({
6092 initialize: function(color, type){
6093 type = type || (color.push ? 'rgb' : 'hex');
6098 hsb = rgb.rgbToHsb();
6101 rgb = color.hsbToRgb();
6105 rgb = color.hexToRgb(true);
6106 hsb = rgb.rgbToHsb();
6109 rgb.hex = rgb.rgbToHex();
6110 return $extend(rgb, Color.prototype);
6115 Mixes two or more colors with the Color.
6118 color - a color to mix. you can use as arguments how many colors as you want to mix with the original one.
6119 alpha - if you use a number as the last argument, it will be threated as the amount of the color to mix.
6123 var colors = $A(arguments);
6124 var alpha = ($type(colors[colors.length - 1]) == 'number') ? colors.pop() : 50;
6125 var rgb = this.copy();
6126 colors.each(function(color){
6127 color = new Color(color);
6128 for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
6130 return new Color(rgb, 'rgb');
6139 return new Color(this.map(function(value){
6146 Modifies the hue of the Color, and returns a new one.
6149 value - the hue to set
6152 setHue: function(value){
6153 return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
6157 Property: setSaturation
6158 Changes the saturation of the Color, and returns a new one.
6161 percent - the percentage of the saturation to set
6164 setSaturation: function(percent){
6165 return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
6169 Property: setBrightness
6170 Changes the brightness of the Color, and returns a new one.
6173 percent - the percentage of the brightness to set
6176 setBrightness: function(percent){
6177 return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
6182 /* Section: Utility Functions */
6186 Shortcut to create a new color, based on red, green, blue values.
6189 r - (integer) red value (0-255)
6190 g - (integer) green value (0-255)
6191 b - (integer) blue value (0-255)
6195 function $RGB(r, g, b){
6196 return new Color([r, g, b], 'rgb');
6201 Shortcut to create a new color, based on hue, saturation, brightness values.
6204 h - (integer) hue value (0-100)
6205 s - (integer) saturation value (0-100)
6206 b - (integer) brightness value (0-100)
6209 function $HSB(h, s, b){
6210 return new Color([h, s, b], 'hsb');
6215 A collection of The Array Object prototype methods.
6222 Converts a RGB array to an HSB array.
6228 rgbToHsb: function(){
6229 var red = this[0], green = this[1], blue = this[2];
6230 var hue, saturation, brightness;
6231 var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
6232 var delta = max - min;
6233 brightness = max / 255;
6234 saturation = (max != 0) ? delta / max : 0;
6235 if (saturation == 0){
6238 var rr = (max - red) / delta;
6239 var gr = (max - green) / delta;
6240 var br = (max - blue) / delta;
6241 if (red == max) hue = br - gr;
6242 else if (green == max) hue = 2 + rr - br;
6243 else hue = 4 + gr - rr;
6247 return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
6252 Converts an HSB array to an RGB array.
6258 hsbToRgb: function(){
6259 var br = Math.round(this[2] / 100 * 255);
6261 return [br, br, br];
6263 var hue = this[0] % 360;
6265 var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
6266 var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
6267 var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
6268 switch(Math.floor(hue / 60)){
6269 case 0: return [br, t, p];
6270 case 1: return [q, br, p];
6271 case 2: return [p, br, t];
6272 case 3: return [p, q, br];
6273 case 4: return [t, p, br];
6274 case 5: return [br, p, q];
6284 Contains the <Scroller>.
6292 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.
6293 You must call its start method to start listening to mouse movements.
6296 The Scroller requires an XHTML doctype.
6299 element - required, the element to scroll.
6300 options - optional, see options below, and <Fx.Base> options.
6303 area - integer, the necessary boundaries to make the element scroll.
6304 velocity - integer, velocity ratio, the modifier for the window scrolling speed.
6307 onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets.
6308 Automatically passes as parameters x and y values.
6311 var Scroller = new Class({
6316 onChange: function(x, y){
6317 this.element.scrollTo(x, y);
6321 initialize: function(element, options){
6322 this.setOptions(options);
6323 this.element = $(element);
6324 this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element;
6329 The scroller starts listening to mouse movements.
6333 this.coord = this.getCoords.bindWithEvent(this);
6334 this.mousemover.addListener('mousemove', this.coord);
6339 The scroller stops listening to mouse movements.
6343 this.mousemover.removeListener('mousemove', this.coord);
6344 this.timer = $clear(this.timer);
6347 getCoords: function(event){
6348 this.page = (this.element == window) ? event.client : event.page;
6349 if (!this.timer) this.timer = this.scroll.periodical(50, this);
6353 var el = this.element.getSize();
6354 var pos = this.element.getPosition();
6356 var change = {'x': 0, 'y': 0};
6357 for (var z in this.page){
6358 if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
6359 change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
6360 else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
6361 change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
6363 if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
6368 Scroller.implement(new Events, new Options);
6380 Creates a slider with two elements: a knob and a container. Returns the values.
6383 The Slider requires an XHTML doctype.
6386 element - the knob container
6388 options - see Options below
6391 steps - the number of steps for your slider.
6392 mode - either 'horizontal' or 'vertical'. defaults to horizontal.
6393 offset - relative offset for knob position. default to 0.
6396 onChange - a function to fire when the value changes.
6397 onComplete - a function to fire when you're done dragging.
6398 onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position.
6399 Passes as parameter the new position.
6402 var Slider = new Class({
6405 onChange: Class.empty,
6406 onComplete: Class.empty,
6407 onTick: function(pos){
6408 this.knob.setStyle(this.p, pos);
6415 initialize: function(el, knob, options){
6416 this.element = $(el);
6417 this.knob = $(knob);
6418 this.setOptions(options);
6419 this.previousChange = -1;
6420 this.previousEnd = -1;
6422 this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
6424 switch(this.options.mode){
6428 mod = {'x': 'left', 'y': false};
6429 offset = 'offsetWidth';
6434 mod = {'x': false, 'y': 'top'};
6435 offset = 'offsetHeight';
6437 this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
6438 this.half = this.knob[offset]/2;
6439 this.getPos = this.element['get' + this.p.capitalize()].bind(this.element);
6440 this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset);
6442 lim[this.z] = [- this.options.offset, this.max - this.options.offset];
6443 this.drag = new Drag.Base(this.knob, {
6447 onStart: function(){
6453 onComplete: function(){
6458 if (this.options.initialize) this.options.initialize.call(this);
6463 The slider will get the step you pass.
6469 set: function(step){
6470 this.step = step.limit(0, this.options.steps);
6473 this.fireEvent('onTick', this.toPosition(this.step));
6477 clickedElement: function(event){
6478 var position = event.page[this.z] - this.getPos() - this.half;
6479 position = position.limit(-this.options.offset, this.max -this.options.offset);
6480 this.step = this.toStep(position);
6483 this.fireEvent('onTick', position);
6486 draggedKnob: function(){
6487 this.step = this.toStep(this.drag.value.now[this.z]);
6491 checkStep: function(){
6492 if (this.previousChange != this.step){
6493 this.previousChange = this.step;
6494 this.fireEvent('onChange', this.step);
6499 if (this.previousEnd !== this.step){
6500 this.previousEnd = this.step;
6501 this.fireEvent('onComplete', this.step + '');
6505 toStep: function(position){
6506 return Math.round((position + this.options.offset) / this.max * this.options.steps);
6509 toPosition: function(step){
6510 return this.max * step / this.options.steps;
6515 Slider.implement(new Events);
6516 Slider.implement(new Options);
6519 Script: SmoothScroll.js
6520 Contains <SmoothScroll>
6528 Auto targets all the anchors in a page and display a smooth scrolling effect upon clicking them.
6529 Inherits methods, properties, options and events from <Fx.Scroll>.
6532 SmoothScroll requires an XHTML doctype.
6535 options - the Fx.Scroll options (see: <Fx.Scroll>) plus links, a collection of elements you want your smoothscroll on. Defaults to document.links.
6538 >new SmoothScroll();
6541 var SmoothScroll = Fx.Scroll.extend({
6543 initialize: function(options){
6544 this.parent(window, options);
6545 this.links = (this.options.links) ? $$(this.options.links) : $$(document.links);
6546 var location = window.location.href.match(/^[^#]*/)[0] + '#';
6547 this.links.each(function(link){
6548 if (link.href.indexOf(location) != 0) return;
6549 var anchor = link.href.substr(location.length);
6550 if (anchor && $(anchor)) this.useLink(link, anchor);
6552 if (!window.webkit419) this.addEvent('onComplete', function(){
6553 window.location.hash = this.anchor;
6557 useLink: function(link, anchor){
6558 link.addEvent('click', function(event){
6559 this.anchor = anchor;
6560 this.toElement(anchor);
6562 }.bindWithEvent(this));
6568 Script: Sortables.js
6569 Contains <Sortables> Class.
6577 Creates an interface for <Drag.Base> and drop, resorting of a list.
6580 The Sortables require an XHTML doctype.
6583 list - required, the list that will become sortable.
6584 options - an Object, see options below.
6587 handles - a collection of elements to be used for drag handles. defaults to the elements.
6590 onStart - function executed when the item starts dragging
6591 onComplete - function executed when the item ends dragging
6594 var Sortables = new Class({
6598 onStart: Class.empty,
6599 onComplete: Class.empty,
6602 onDragStart: function(element, ghost){
6603 ghost.setStyle('opacity', 0.7);
6604 element.setStyle('opacity', 0.7);
6606 onDragComplete: function(element, ghost){
6607 element.setStyle('opacity', 1);
6609 this.trash.remove();
6613 initialize: function(list, options){
6614 this.setOptions(options);
6615 this.list = $(list);
6616 this.elements = this.list.getChildren();
6617 this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements;
6620 'moveGhost': this.moveGhost.bindWithEvent(this)
6622 for (var i = 0, l = this.handles.length; i < l; i++){
6623 this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]);
6626 if (this.options.initialize) this.options.initialize.call(this);
6627 this.bound.move = this.move.bindWithEvent(this);
6628 this.bound.end = this.end.bind(this);
6632 this.handles.each(function(handle, i){
6633 handle.addEvent('mousedown', this.bound.start[i]);
6638 this.handles.each(function(handle, i){
6639 handle.removeEvent('mousedown', this.bound.start[i]);
6643 start: function(event, el){
6645 this.coordinates = this.list.getCoordinates();
6646 if (this.options.ghost){
6647 var position = el.getPosition();
6648 this.offset = event.page.y - position.y;
6649 this.trash = new Element('div').inject(document.body);
6650 this.ghost = el.clone().inject(this.trash).setStyles({
6651 'position': 'absolute',
6653 'top': event.page.y - this.offset
6655 document.addListener('mousemove', this.bound.moveGhost);
6656 this.fireEvent('onDragStart', [el, this.ghost]);
6658 document.addListener('mousemove', this.bound.move);
6659 document.addListener('mouseup', this.bound.end);
6660 this.fireEvent('onStart', el);
6664 moveGhost: function(event){
6665 var value = event.page.y - this.offset;
6666 value = value.limit(this.coordinates.top, this.coordinates.bottom - this.ghost.offsetHeight);
6667 this.ghost.setStyle('top', value);
6671 move: function(event){
6672 var now = event.page.y;
6673 this.previous = this.previous || now;
6674 var up = ((this.previous - now) > 0);
6675 var prev = this.active.getPrevious();
6676 var next = this.active.getNext();
6677 if (prev && up && now < prev.getCoordinates().bottom) this.active.injectBefore(prev);
6678 if (next && !up && now > next.getCoordinates().top) this.active.injectAfter(next);
6679 this.previous = now;
6682 serialize: function(converter){
6683 return this.list.getChildren().map(converter || function(el){
6684 return this.elements.indexOf(el);
6689 this.previous = null;
6690 document.removeListener('mousemove', this.bound.move);
6691 document.removeListener('mouseup', this.bound.end);
6692 if (this.options.ghost){
6693 document.removeListener('mousemove', this.bound.moveGhost);
6694 this.fireEvent('onDragComplete', [this.active, this.ghost]);
6696 this.fireEvent('onComplete', this.active);
6701 Sortables.implement(new Events, new Options);
6705 Tooltips, BubbleTips, whatever they are, they will appear on mouseover
6711 The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com>
6716 Display a tip on any element with a title and/or href.
6719 Tips requires an XHTML doctype.
6722 elements - a collection of elements to apply the tooltips to on mouseover.
6723 options - an object. See options Below.
6726 maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30.
6727 showDelay - the delay the onShow method is called. (defaults to 100 ms)
6728 hideDelay - the delay the onHide method is called. (defaults to 100 ms)
6730 className - the prefix for your tooltip classNames. defaults to 'tool'.
6732 the whole tooltip will have as classname: tool-tip
6734 the title will have as classname: tool-title
6736 the text will have as classname: tool-text
6738 offsets - the distance of your tooltip from the mouse. an Object with x/y properties.
6739 fixed - if set to true, the toolTip will not follow the mouse.
6742 onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect);
6743 onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect);
6747 <img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/>
6749 var myTips = new Tips($$('.toolTipImg'), {
6750 maxTitleChars: 50 //I like my captions a little long
6756 The title of the element will always be used as the tooltip body. If you put :: on your title, the text before :: will become the tooltip title.
6759 var Tips = new Class({
6762 onShow: function(tip){
6763 tip.setStyle('visibility', 'visible');
6765 onHide: function(tip){
6766 tip.setStyle('visibility', 'hidden');
6772 offsets: {'x': 16, 'y': 16},
6776 initialize: function(elements, options){
6777 this.setOptions(options);
6778 this.toolTip = new Element('div', {
6779 'class': this.options.className + '-tip',
6781 'position': 'absolute',
6784 'visibility': 'hidden'
6786 }).inject(document.body);
6787 this.wrapper = new Element('div').inject(this.toolTip);
6788 $$(elements).each(this.build, this);
6789 if (this.options.initialize) this.options.initialize.call(this);
6792 build: function(el){
6793 el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') : (el.rel || false);
6795 var dual = el.title.split('::');
6796 if (dual.length > 1){
6797 el.$tmp.myTitle = dual[0].trim();
6798 el.$tmp.myText = dual[1].trim();
6800 el.$tmp.myText = el.title;
6802 el.removeAttribute('title');
6804 el.$tmp.myText = false;
6806 if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "…";
6807 el.addEvent('mouseenter', function(event){
6809 if (!this.options.fixed) this.locate(event);
6810 else this.position(el);
6812 if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
6813 var end = this.end.bind(this);
6814 el.addEvent('mouseleave', end);
6815 el.addEvent('trash', end);
6818 start: function(el){
6819 this.wrapper.empty();
6820 if (el.$tmp.myTitle){
6821 this.title = new Element('span').inject(new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)).setHTML(el.$tmp.myTitle);
6823 if (el.$tmp.myText){
6824 this.text = new Element('span').inject(new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)).setHTML(el.$tmp.myText);
6827 this.timer = this.show.delay(this.options.showDelay, this);
6830 end: function(event){
6832 this.timer = this.hide.delay(this.options.hideDelay, this);
6835 position: function(element){
6836 var pos = element.getPosition();
6837 this.toolTip.setStyles({
6838 'left': pos.x + this.options.offsets.x,
6839 'top': pos.y + this.options.offsets.y
6843 locate: function(event){
6844 var win = {'x': window.getWidth(), 'y': window.getHeight()};
6845 var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
6846 var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
6847 var prop = {'x': 'left', 'y': 'top'};
6848 for (var z in prop){
6849 var pos = event.page[z] + this.options.offsets[z];
6850 if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
6851 this.toolTip.setStyle(prop[z], pos);
6856 if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
6857 this.fireEvent('onShow', [this.toolTip]);
6861 this.fireEvent('onHide', [this.toolTip]);
6866 Tips.implement(new Events, new Options);
6870 For Grouping Classes or Elements Events. The Event added to the Group will fire when all of the events of the items of the group are fired.
6881 List of Class instances
6885 xhr1 = new Ajax('data.js', {evalScript: true});
6886 xhr2 = new Ajax('abstraction.js', {evalScript: true});
6887 xhr3 = new Ajax('template.js', {evalScript: true});
6889 var group = new Group(xhr1, xhr2, xhr3);
6890 group.addEvent('onComplete', function(){
6891 alert('All Scripts loaded');
6901 var Group = new Class({
6903 initialize: function(){
6904 this.instances = $A(arguments);
6911 adds an event to the stack of events of the Class instances.
6914 type - string; the event name (e.g. 'onComplete')
6915 fn - function to execute when all instances fired this event
6918 addEvent: function(type, fn){
6919 this.checker[type] = this.checker[type] || {};
6920 this.events[type] = this.events[type] || [];
6921 if (this.events[type].contains(fn)) return false;
6922 else this.events[type].push(fn);
6923 this.instances.each(function(instance, i){
6924 instance.addEvent(type, this.check.bind(this, [type, instance, i]));
6929 check: function(type, instance, i){
6930 this.checker[type][i] = true;
6931 var every = this.instances.every(function(current, j){
6932 return this.checker[type][j] || false;
6935 this.checker[type] = {};
6936 this.events[type].each(function(event){
6937 event.call(this, this.instances, instance);
6944 Script: Accordion.js
\r
6945 Contains <Accordion>
\r
6948 MIT-style license.
\r
6953 The Accordion class creates a group of elements that are toggled when their handles are clicked. When one elements toggles in, the others toggles back.
\r
6954 Inherits methods, properties, options and events from <Fx.Elements>.
\r
6957 The Accordion requires an XHTML doctype.
\r
6960 togglers - required, a collection of elements, the elements handlers that will be clickable.
\r
6961 elements - required, a collection of elements the transitions will be applied to.
\r
6962 options - optional, see options below, and <Fx.Base> options and events.
\r
6965 show - integer, the Index of the element to show at start.
\r
6966 display - integer, the Index of the element to show at start (with a transition). defaults to 0.
\r
6967 fixedHeight - integer, if you want the elements to have a fixed height. defaults to false.
\r
6968 fixedWidth - integer, if you want the elements to have a fixed width. defaults to false.
\r
6969 height - boolean, will add a height transition to the accordion if true. defaults to true.
\r
6970 opacity - boolean, will add an opacity transition to the accordion if true. defaults to true.
\r
6971 width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work!
\r
6972 alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false.
\r
6975 onActive - function to execute when an element starts to show
\r
6976 onBackground - function to execute when an element starts to hide
\r
6979 var Accordion = Fx.Elements.extend({
\r
6982 onActive: Class.empty,
\r
6983 onBackground: Class.empty,
\r
6989 fixedHeight: false,
\r
6990 fixedWidth: false,
\r
6995 initialize: function(){
\r
6996 var options, togglers, elements, container;
\r
6997 $each(arguments, function(argument, i){
\r
6998 switch($type(argument)){
\r
6999 case 'object': options = argument; break;
\r
7000 case 'element': container = $(argument); break;
\r
7002 var temp = $$(argument);
\r
7003 if (!togglers) togglers = temp;
\r
7004 else elements = temp;
\r
7007 this.togglers = togglers || [];
\r
7008 this.elements = elements || [];
\r
7009 this.container = $(container);
\r
7010 this.setOptions(options);
\r
7011 this.previous = -1;
\r
7012 if (this.options.alwaysHide) this.options.wait = true;
\r
7013 if ($chk(this.options.show)){
\r
7014 this.options.display = false;
\r
7015 this.previous = this.options.show;
\r
7017 if (this.options.start){
\r
7018 this.options.display = false;
\r
7019 this.options.show = false;
\r
7021 this.effects = {};
\r
7022 if (this.options.opacity) this.effects.opacity = 'fullOpacity';
\r
7023 if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
\r
7024 if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
\r
7025 for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
\r
7026 this.elements.each(function(el, i){
\r
7027 if (this.options.show === i){
\r
7028 this.fireEvent('onActive', [this.togglers[i], el]);
\r
7030 for (var fx in this.effects) el.setStyle(fx, 0);
\r
7033 this.parent(this.elements);
\r
7034 if ($chk(this.options.display)) this.display(this.options.display);
\r
7038 Property: addSection
\r
7039 Dynamically adds a new section into the accordion at the specified position.
\r
7042 toggler - (dom element) the element that toggles the accordion section open.
\r
7043 element - (dom element) the element that stretches open when the toggler is clicked.
\r
7044 pos - (integer) the index where these objects are to be inserted within the accordion.
\r
7047 addSection: function(toggler, element, pos){
\r
7048 toggler = $(toggler);
\r
7049 element = $(element);
\r
7050 var test = this.togglers.contains(toggler);
\r
7051 var len = this.togglers.length;
\r
7052 this.togglers.include(toggler);
\r
7053 this.elements.include(element);
\r
7054 if (len && (!test || pos)){
\r
7055 pos = $pick(pos, len - 1);
\r
7056 toggler.injectBefore(this.togglers[pos]);
\r
7057 element.injectAfter(toggler);
\r
7058 } else if (this.container && !test){
\r
7059 toggler.inject(this.container);
\r
7060 element.inject(this.container);
\r
7062 var idx = this.togglers.indexOf(toggler);
\r
7063 toggler.addEvent('click', this.display.bind(this, idx));
\r
7064 if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
\r
7065 if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
\r
7066 element.fullOpacity = 1;
\r
7067 if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
\r
7068 if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
\r
7069 element.setStyle('overflow', 'hidden');
\r
7071 for (var fx in this.effects) element.setStyle(fx, 0);
\r
7078 Shows a specific section and hides all others. Useful when triggering an accordion from outside.
\r
7081 index - integer, the index of the item to show, or the actual element to show.
\r
7084 display: function(index){
\r
7085 index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
\r
7086 if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
\r
7087 this.previous = index;
\r
7089 this.elements.each(function(el, i){
\r
7091 var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
\r
7092 this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]);
\r
7093 for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
\r
7095 return this.start(obj);
\r
7098 showThisHideOpen: function(index){return this.display(index);}
\r
7102 Fx.Accordion = Accordion;