1/* 2Script: Core.js 3 Mootools - My Object Oriented javascript. 4 5License: 6 MIT-style license. 7 8MooTools Copyright: 9 copyright (c) 2007 Valerio Proietti, <http://mad4milk.net> 10 11MooTools Credits: 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. 15*/ 16 17var MooTools = { 18 version: '1.11' 19}; 20 21/* Section: Core Functions */ 22 23/* 24Function: $defined 25 Returns true if the passed in value/object is defined, that means is not null or undefined. 26 27Arguments: 28 obj - object to inspect 29*/ 30 31function $defined(obj){ 32 return (obj != undefined); 33}; 34 35/* 36Function: $type 37 Returns the type of object that matches the element passed in. 38 39Arguments: 40 obj - the object to inspect. 41 42Example: 43 >var myString = 'hello'; 44 >$type(myString); //returns "string" 45 46Returns: 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. 60*/ 61 62function $type(obj){ 63 if (!$defined(obj)) return false; 64 if (obj.htmlElement) return 'element'; 65 var type = typeof obj; 66 if (type == 'object' && obj.nodeName){ 67 switch(obj.nodeType){ 68 case 1: return 'element'; 69 case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace'; 70 } 71 } 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'; 77 } 78 if (typeof obj.length == 'number'){ 79 if (obj.item) return 'collection'; 80 if (obj.callee) return 'arguments'; 81 } 82 } 83 return type; 84}; 85 86/* 87Function: $merge 88 merges a number of objects recursively without referencing them or their sub-objects. 89 90Arguments: 91 any number of objects. 92 93Example: 94 >var mergedObj = $merge(obj1, obj2, obj3); 95 >//obj1, obj2, and obj3 are unaltered 96*/ 97 98function $merge(){ 99 var mix = {}; 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; 106 } 107 } 108 return mix; 109}; 110 111/* 112Function: $extend 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. 115 116Example: 117 (start code) 118 var firstOb = { 119 'name': 'John', 120 'lastName': 'Doe' 121 }; 122 var secondOb = { 123 'age': '20', 124 'sex': 'male', 125 'lastName': 'Dorian' 126 }; 127 $extend(firstOb, secondOb); 128 //firstOb will become: 129 { 130 'name': 'John', 131 'lastName': 'Dorian', 132 'age': '20', 133 'sex': 'male' 134 }; 135 (end) 136 137Returns: 138 The first object, extended. 139*/ 140 141var $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]; 145 return args[0]; 146}; 147 148/* 149Function: $native 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. 153 154Arguments: 155 a number of classes/native javascript objects 156 157*/ 158 159var $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); 165 } 166 }; 167 } 168}; 169 170$native.generic = function(prop){ 171 return function(bind){ 172 return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1)); 173 }; 174}; 175 176$native(Function, Array, String, Number); 177 178/* 179Function: $chk 180 Returns true if the passed in value/object exists or is 0, otherwise returns false. 181 Useful to accept zeroes. 182 183Arguments: 184 obj - object to inspect 185*/ 186 187function $chk(obj){ 188 return !!(obj || obj === 0); 189}; 190 191/* 192Function: $pick 193 Returns the first object if defined, otherwise returns the second. 194 195Arguments: 196 obj - object to test 197 picked - the default to return 198 199Example: 200 (start code) 201 function say(msg){
202 alert($pick(msg, 'no meessage supplied')); 203 } 204 (end) 205*/ 206 207function $pick(obj, picked){ 208 return $defined(obj) ? obj : picked; 209}; 210 211/* 212Function: $random 213 Returns a random integer number between the two passed in values. 214 215Arguments: 216 min - integer, the minimum value (inclusive). 217 max - integer, the maximum value (inclusive). 218 219Returns: 220 a random integer between min and max. 221*/ 222 223function $random(min, max){ 224 return Math.floor(Math.random() * (max - min + 1) + min); 225}; 226 227/* 228Function: $time 229 Returns the current timestamp 230 231Returns: 232 a timestamp integer. 233*/ 234 235function $time(){ 236 return new Date().getTime(); 237}; 238 239/* 240Function: $clear 241 clears a timeout or an Interval. 242 243Returns: 244 null 245 246Arguments: 247 timer - the setInterval or setTimeout to clear. 248 249Example: 250 >var myTimer = myFunction.delay(5000); //wait 5 seconds and execute my function. 251 >myTimer = $clear(myTimer); //nevermind 252 253See also: 254 <Function.delay>, <Function.periodical> 255*/ 256 257function $clear(timer){ 258 clearTimeout(timer); 259 clearInterval(timer); 260 return null; 261}; 262 263/* 264Class: Abstract 265 Abstract class, to be used as singleton. Will add .extend to any object 266 267Arguments: 268 an object 269 270Returns: 271 the object with an .extend property, equivalent to <$extend>. 272*/ 273 274var Abstract = function(obj){ 275 obj = obj || {}; 276 obj.extend = $extend; 277 return obj; 278}; 279 280//window, document 281 282var Window = new Abstract(window); 283var Document = new Abstract(document); 284document.head = document.getElementsByTagName('head')[0]; 285 286/* 287Class: window 288 Some properties are attached to the window object by the browser detection. 289 290Note: 291 browser detection is entirely object-based. We dont sniff. 292 293Properties: 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. 302*/ 303 304window.xpath = !!(document.evaluate); 305if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true; 306else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true; 307else if (document.getBoxObjectFor != null) window.gecko = true; 308 309/*compatibility*/ 310 311window.khtml = window.webkit; 312 313Object.extend = $extend; 314 315/*end compatibility*/ 316 317//htmlelement 318 319if (typeof HTMLElement == 'undefined'){ 320 var HTMLElement = function(){}; 321 if (window.webkit) document.createElement("iframe"); //fixes safari 322 HTMLElement.prototype = (window.webkit) ? window["[[DOMElement.prototype]]"] : {}; 323} 324HTMLElement.prototype.htmlElement = function(){}; 325 326//enables background image cache for internet explorer 6 327 328if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){}; 329 330/* 331Script: Class.js 332 Contains the Class Function, aims to ease the creation of reusable Classes. 333 334License: 335 MIT-style license. 336*/ 337 338/* 339Class: Class 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*. 343 344Arguments: 345 properties - the collection of properties that apply to the class. 346 347Example: 348 (start code) 349 var Cat = new Class({ 350 initialize: function(name){ 351 this.name = name; 352 } 353 }); 354 var myCat = new Cat('Micia'); 355 alert(myCat.name); //alerts 'Micia' 356 (end) 357*/ 358 359var Class = function(properties){ 360 var klass = function(){ 361 return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this; 362 }; 363 $extend(klass, this); 364 klass.prototype = properties; 365 klass.constructor = Class; 366 return klass; 367}; 368 369/* 370Property: empty 371 Returns an empty function 372*/ 373 374Class.empty = function(){}; 375 376Class.prototype = { 377 378 /* 379 Property: extend 380 Returns the copy of the Class extended with the passed in properties. 381 382 Arguments: 383 properties - the properties to add to the base class in this new Class. 384 385 Example: 386 (start code) 387 var Animal = new Class({ 388 initialize: function(age){ 389 this.age = age; 390 } 391 }); 392 var Cat = Animal.extend({ 393 initialize: function(name, age){ 394 this.parent(age); //will call the previous initialize; 395 this.name = name; 396 } 397 }); 398 var myCat = new Cat('Micia', 20); 399 alert(myCat.name); //alerts 'Micia' 400 alert(myCat.age); //alerts 20 401 (end) 402 */ 403 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]); 409 } 410 return new Class(proto); 411 }, 412 413 /* 414 Property: implement 415 Implements the passed in properties to the base Class prototypes, altering the base class, unlike <Class.extend>. 416 417 Arguments: 418 properties - the properties to add to the base class. 419 420 Example: 421 (start code) 422 var Animal = new Class({ 423 initialize: function(age){ 424 this.age = age; 425 } 426 }); 427 Animal.implement({ 428 setName: function(name){ 429 this.name = name 430 } 431 }); 432 var myAnimal = new Animal(20); 433 myAnimal.setName('Micia'); 434 alert(myAnimal.name); //alerts 'Micia' 435 (end) 436 */ 437 438 implement: function(){ 439 for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]); 440 } 441 442}; 443 444//internal 445 446Class.Merge = function(previous, current){ 447 if (previous && previous != current){ 448 var type = $type(current); 449 if (type != $type(previous)) return current; 450 switch(type){ 451 case 'function': 452 var merged = function(){ 453 this.parent = arguments.callee.parent; 454 return current.apply(this, arguments); 455 }; 456 merged.parent = previous; 457 return merged; 458 case 'object': return $merge(previous, current); 459 } 460 } 461 return current; 462}; 463 464/* 465Script: Class.Extras.js 466 Contains common implementations for custom classes. In Mootools is implemented in <Ajax>, <XHR> and <Fx.Base> and many more. 467 468License: 469 MIT-style license. 470*/ 471 472/* 473Class: Chain
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. 477 478Example: 479 (start code) 480 var myFx = new Fx.Style('element', 'opacity'); 481 482 myFx.start(1,0).chain(function(){ 483 myFx.start(0,1); 484 }).chain(function(){ 485 myFx.start(1,0); 486 }).chain(function(){ 487 myFx.start(0,1); 488 }); 489 //the element will appear and disappear three times 490 (end) 491*/ 492 493var Chain = new Class({ 494 495 /* 496 Property: chain 497 adds a function to the Chain instance stack. 498 499 Arguments: 500 fn - the function to append. 501 */ 502 503 chain: function(fn){ 504 this.chains = this.chains || []; 505 this.chains.push(fn); 506 return this; 507 }, 508 509 /* 510 Property: callChain 511 Executes the first function of the Chain instance stack, then removes it. The first function will then become the second. 512 */ 513 514 callChain: function(){ 515 if (this.chains && this.chains.length) this.chains.shift().delay(10, this); 516 }, 517 518 /* 519 Property: clearChain 520 Clears the stack of a Chain instance. 521 */ 522 523 clearChain: function(){ 524 this.chains = []; 525 } 526 527}); 528 529/* 530Class: Events 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. 534 535Example: 536 (start code) 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'); 541 }); 542 543 myFx.start(0,1); 544 //upon completion it will display the 2 alerts, in order. 545 (end) 546 547Implementing: 548 This class can be implemented into other classes to add the functionality to them. 549 Goes well with the <Options> class. 550 551Example: 552 (start code) 553 var Widget = new Class({ 554 initialize: function(){}, 555 finish: function(){ 556 this.fireEvent('onComplete'); 557 } 558 }); 559 Widget.implement(new Events); 560 //later... 561 var myWidget = new Widget(); 562 myWidget.addEvent('onComplete', myfunction); 563 (end) 564*/ 565 566var Events = new Class({ 567 568 /* 569 Property: addEvent 570 adds an event to the stack of events of the Class instance. 571 572 Arguments: 573 type - string; the event name (e.g. 'onComplete') 574 fn - function to execute 575 */ 576 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); 582 } 583 return this; 584 }, 585 586 /* 587 Property: fireEvent 588 fires all events of the specified type in the Class instance. 589 590 Arguments: 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 594 595 Example: 596 (start code) 597 var Widget = new Class({ 598 initialize: function(arg1, arg2){ 599 ... 600 this.fireEvent("onInitialize", [arg1, arg2], 50); 601 } 602 }); 603 Widget.implement(new Events); 604 (end) 605 */ 606 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})(); 611 }, this); 612 } 613 return this; 614 }, 615 616 /* 617 Property: removeEvent 618 removes an event from the stack of events of the Class instance. 619 620 Arguments: 621 type - string; the event name (e.g. 'onComplete') 622 fn - function that was added 623 */ 624 625 removeEvent: function(type, fn){ 626 if (this.$events && this.$events[type]) this.$events[type].remove(fn); 627 return this; 628 } 629 630}); 631 632/* 633Class: Options 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. 636 637 Example: 638 (start code) 639 var Widget = new Class({ 640 options: { 641 color: '#fff', 642 size: { 643 width: 100 644 height: 100 645 } 646 }, 647 initialize: function(options){ 648 this.setOptions(options); 649 } 650 }); 651 Widget.implement(new Options); 652 //later... 653 var myWidget = new Widget({ 654 color: '#f00', 655 size: { 656 width: 200 657 } 658 }); 659 //myWidget.options = {color: #f00, size: {width: 200, height: 100}} 660 (end) 661*/ 662 663var Options = new Class({ 664 665 /* 666 Property: setOptions 667 sets this.options 668 669 Arguments: 670 defaults - object; the default set of options 671 options - object; the user entered options. can be empty too. 672 673 Note: 674 if your Class has <Events> implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event. 675 */ 676 677 setOptions: function(){ 678 this.options = $merge.apply(null, [this.options].extend(arguments)); 679 if (this.addEvent){ 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]); 682 } 683 } 684 return this; 685 } 686 687}); 688 689/* 690Script: Array.js 691 Contains Array prototypes, <$A>, <$each> 692 693License: 694 MIT-style license. 695*/ 696 697/* 698Class: Array 699 A collection of The Array Object prototype methods. 700*/ 701 702//custom methods 703 704Array.extend({ 705 706 /* 707 Property: forEach 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> 710 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. 712 713 Arguments: 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>) 716 717 Example: 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 721 */ 722 723 forEach: function(fn, bind){ 724 for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this); 725 }, 726 727 /* 728 Property: filter 729 This method is provided only for browsers without native *filter* supp
729ort. 730 For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter> 731 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. 733 734 Arguments: 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>) 737 738 Example: 739 >var biggerThanTwenty = [10,3,25,100].filter(function(item, index){ 740 > return item > 20; 741 >}); 742 >//biggerThanTwenty = [25,100] 743 */ 744 745 filter: function(fn, bind){ 746 var results = []; 747 for (var i = 0, j = this.length; i < j; i++){ 748 if (fn.call(bind, this[i], i, this)) results.push(this[i]); 749 } 750 return results; 751 }, 752 753 /* 754 Property: map 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> 757 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. 759 760 Arguments: 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>) 763 764 Example: 765 >var timesTwo = [1,2,3].map(function(item, index){ 766 > return item*2; 767 >}); 768 >//timesTwo = [2,4,6]; 769 */ 770 771 map: function(fn, bind){ 772 var results = []; 773 for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this); 774 return results; 775 }, 776 777 /* 778 Property: every 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> 781 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. 783 784 Arguments: 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>) 787 788 Example: 789 >var areAllBigEnough = [10,4,25,100].every(function(item, index){ 790 > return item > 20; 791 >}); 792 >//areAllBigEnough = false 793 */ 794 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; 798 } 799 return true; 800 }, 801 802 /* 803 Property: some 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> 806 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. 808 809 Arguments: 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>) 812 813 Example: 814 >var isAnyBigEnough = [10,4,25,100].some(function(item, index){ 815 > return item > 20; 816 >}); 817 >//isAnyBigEnough = true 818 */ 819 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; 823 } 824 return false;
825 }, 826 827 /* 828 Property: indexOf 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> 831 832 *indexOf* compares a search element to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator). 833 834 Arguments: 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) 837 838 Example: 839 >['apple','lemon','banana'].indexOf('lemon'); //returns 1 840 >['apple','lemon'].indexOf('banana'); //returns -1 841 */ 842 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; 847 } 848 return -1; 849 }, 850 851 /* 852 Property: each 853 Same as <Array.forEach>. 854 855 Arguments: 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. 858 859 Example: 860 >var Animals = ['Cat', 'Dog', 'Coala']; 861 >Animals.each(function(animal){ 862 > document.write(animal) 863 >}); 864 */ 865 866 /* 867 Property: copy 868 returns a copy of the array. 869 870 Returns: 871 a new array which is a copy of the current one. 872 873 Arguments: 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. 876 877 Example: 878 >var letters = ["a","b","c"]; 879 >
879var copy = letters.copy(); // ["a","b","c"] (new instance) 880 */ 881 882 copy: function(start, length){ 883 start = start || 0; 884 if (start < 0) start = this.length + start; 885 length = length || (this.length - start); 886 var newArray = []; 887 for (var i = 0; i < length; i++) newArray[i] = this[start++]; 888 return newArray; 889 }, 890 891 /* 892 Property: remove 893 Removes all occurrences of an item from the array. 894 895 Arguments: 896 item - the item to remove 897 898 Returns: 899 the Array with all occurrences of the item removed. 900 901 Example: 902 >["1","2","3","2"].remove("2") // ["1","3"]; 903 */ 904 905 remove: function(item){ 906 var i = 0; 907 var len = this.length; 908 while (i < len){ 909 if (this[i] === item){ 910 this.splice(i, 1); 911 len--; 912 } else { 913 i++; 914 } 915 } 916 return this; 917 }, 918 919 /* 920 Property: contains 921 Tests an array for the presence of an item. 922 923 Arguments: 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. 926 927 Returns: 928 true - the item was found 929 false - it wasn't 930 931 Example: 932 >["a","b","c"].contains("a"); // true 933 >["a","b","c"].contains("d"); // false 934 */ 935 936 contains: function(item, from){ 937 return this.indexOf(item, from) != -1; 938 }, 939 940 /* 941 Property: associate 942 Creates an object with key-value pairs based on the array of keywords passed in 943 and the current content of the array. 944 945 Arguments: 946 keys - the array of keywords. 947 948 Example: 949 (start code) 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. 955 //... 956 (end) 957 */ 958 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]; 962 return obj; 963 }, 964 965 /* 966 Property: extend 967 Extends an array with another one. 968 969 Arguments: 970 array - the array to extend ours with 971 972 Example: 973 >var Animals = ['Cat', 'Dog', 'Coala']; 974 >Animals.extend(['Lizard']); 975 >//Animals is now: ['Cat', 'Dog', 'Coala', 'Lizard']; 976 */ 977 978 extend: function(array){ 979 for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); 980 return this; 981 }, 982 983 /* 984 Property: merge 985 merges an array in another array, without duplicates. (case- and type-sensitive) 986 987 Arguments: 988 array - the array to merge from. 989 990 Example: 991 >['Cat','Dog'].merge(['Dog','Coala']); //returns ['Cat','Dog','Coala'] 992 */ 993 994 merge: function(array){ 995 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 996 return this; 997 }, 998 999 /* 1000 Property: include 1001 includes the passed in element in the array, only if its not already present. (case- and type-sensitive) 1002 1003 Arguments: 1004 item - item to add to the array (if not present) 1005 1006 Example: 1007 >['Cat','Dog'].include('Dog'); //returns ['Cat','Dog'] 1008 >['Cat','Dog'].include('Coala'); //returns ['Cat','Dog','Coala'] 1009 */ 1010 1011 include: function(item){ 1012 if (!this.contains(item)) this.push(item); 1013 return this; 1014 }, 1015 1016 /* 1017 Property: getRandom 1018 returns a random item in the Array 1019 */ 1020 1021 getRandom: function(){ 1022 return this[$random(0, this.length - 1)] || null; 1023 }, 1024 1025 /* 1026 Property: getLast 1027 returns the last item in the Array 1028 */ 1029 1030 getLast: function(){ 1031 return this[this.length - 1] || null; 1032 } 1033 1034}); 1035 1036//copies 1037 1038Array.prototype.each = Array.prototype.forEach; 1039Array.each = Array.forEach; 1040 1041/* Section: Utility Functions */ 1042 1043/* 1044Function: $A() 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. 1047 1048Example: 1049 (start code) 1050 function myFunction(){ 1051 $A(arguments).each(argument, function(){ 1052 alert(argument); 1053 }); 1054 }; 1055 //the above will alert all the arguments passed to the function myFunction. 1056 (end) 1057*/ 1058 1059function $A(array){ 1060 return Array.copy(array); 1061}; 1062 1063/* 1064Function: $each 1065 Use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, arguments of a function, or an object. 1066 1067Arguments: 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. 1071 1072Function argument: 1073 The function argument will be passed the following arguments. 1074 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. 1077 1078Examples: 1079 (start code) 1080 $each(['Sun','Mon','Tue'], function(day, index){ 1081 alert('name:' + day + ', index: ' + index); 1082 }); 1083 //alerts "name: Sun, index: 0", "name: Mon, index: 1", etc. 1084 //over an object 1085 $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){ 1086 alert("the " + key + " day of the week is " + value); 1087 }); 1088 //alerts "the first day of the week is Sunday", 1089 //"the second day of the week is Monday", etc. 1090 (end) 1091*/ 1092 1093function $each(iterable, fn, bind){ 1094 if (iterable && typeof iterable.length == 'number' && $type(iterable) != 'object'){ 1095 Array.forEach(iterable, fn, bind); 1096 } else { 1097 for (var name in iterable) fn.call(bind || iterable, iterable[name], name); 1098 } 1099}; 1100 1101/*compatibility*/ 1102 1103Array.prototype.test = Array.prototype.contains; 1104 1105/*end compatibility*/ 1106 1107/* 1108Script: String.js 1109 Contains String prototypes. 1110 1111License: 1112 MIT-style license. 1113*/ 1114 1115/* 1116Class: String 1117 A collection of The String Object prototype methods. 1118*/ 1119 1120String.extend({ 1121 1122 /* 1123 Property: test 1124 Tests a string with a regular expression. 1125 1126 Arguments: 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) 1129 1130 Returns: 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> 1133 1134 Example: 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 1138 */ 1139 1140 test: function(regex, params){ 1141 return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this); 1142 }, 1143 1144 /* 1145 Property: toInt 1146 parses a string to an integer. 1147 1148 Returns: 1149 either an int or "NaN" if the string is not a number. 1150 1151 Example: 1152 >var value = "10px".toInt(); // value is 10 1153 */ 1154 1155 toInt: function(){ 1156 return parseInt(this, 10); 1157 }, 1158 1159 /* 1160 Property: toFloat 1161 parses a string to an float. 1162 1163 Returns: 1164 either a float or "NaN" if the string is not a number. 1165 1166 Example: 1167 >var value = "10.848".toFloat(); // value is 10.848 1168 */ 1169 1170 toFloat: function(){ 1171 return parseFloat(this); 1172 }, 1173 1174 /* 1175 Property: camelCase 1176 Converts a hiphenated string to a camelcase string. 1177 1178 Example: 1179 >
1179"I-like-cookies".camelCase(); //"ILikeCookies" 1180 1181 Returns: 1182 the camel cased string 1183 */ 1184 1185 camelCase: function(){ 1186 return this.replace(/-\D/g, function(match){ 1187 return match.charAt(1).toUpperCase(); 1188 }); 1189 }, 1190 1191 /* 1192 Property: hyphenate 1193 Converts a camelCased string to a hyphen-ated string. 1194 1195 Example: 1196 >"ILikeCookies".hyphenate(); //"I-like-cookies" 1197 */ 1198 1199 hyphenate: function(){ 1200 return this.replace(/\w[A-Z]/g, function(match){ 1201 return (match.charAt(0) + '-' + match.charAt(1).toLowerCase()); 1202 }); 1203 }, 1204 1205 /* 1206 Property: capitalize 1207 Converts the first letter in each word of a string to Uppercase. 1208 1209 Example: 1210 >"i like cookies".capitalize(); //"I Like Cookies" 1211 1212 Returns: 1213 the capitalized string 1214 */ 1215 1216 capitalize: function(){ 1217 return this.replace(/\b[a-z]/g, function(match){ 1218 return match.toUpperCase(); 1219 }); 1220 }, 1221 1222 /* 1223 Property: trim 1224 Trims the leading and trailing spaces off a string. 1225 1226 Example: 1227 >" i like cookies ".trim() //"i like cookies" 1228 1229 Returns: 1230 the trimmed string 1231 */ 1232 1233 trim: function(){ 1234 return this.replace(/^\s+|\s+$/g, ''); 1235 }, 1236 1237 /* 1238 Property: clean 1239 trims (<String.trim>) a string AND removes all the double spaces in a string. 1240 1241 Returns: 1242 the cleaned string 1243 1244 Example: 1245 >" i like cookies \n\n".clean() //"i like cookies" 1246 */ 1247 1248 clean: function(){ 1249 return this.replace(/\s{2,}/g, ' ').trim(); 1250 }, 1251 1252 /* 1253 Property: rgbToHex 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)"; 1255 1256 Arguments: 1257 array - boolean value, defaults to false. Use true if you want the array ['FF','33','00'] as output instead of "#FF3300" 1258 1259 Returns: 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. 1261 1262 Example: 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'] 1266 */ 1267 1268 rgbToHex: function(array){ 1269 var rgb = this.match(/\d{1,3}/g); 1270 return (rgb) ? rgb.rgbToHex(array) : false; 1271 }, 1272 1273 /* 1274 Property: hexToRgb 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'); 1276 1277 Arguments: 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)"; 1279 1280 Returns: 1281 rgb string or array. 1282 1283 Example: 1284 >"#112233".hexToRgb(); //"rgb(17,34,51)" 1285 >"#112233".hexToRgb(true); //[17,34,51] 1286 */ 1287 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; 1291 }, 1292 1293 /* 1294 Property: contains 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. 1296 1297 Example: 1298 >'a b c'.contains('c', ' '); //true 1299 >'a bc'.contains('bc'); //true 1300 >'a bc'.contains('b', ' '); //false 1301 */ 1302 1303 contains: function(string, s){ 1304 return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1; 1305 }, 1306 1307 /* 1308 Property: escapeRegExp 1309 Returns string with escaped regular expression characters 1310 1311 Example: 1312 >var search = 'animals.sheeps[1]'.escapeRegExp(); // search is now 'animals\.sheeps\[1\]' 1313 1314 Returns: 1315 Escaped string 1316 */ 1317 1318 escapeRegExp: function(){ 1319 return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); 1320 } 1321 1322}); 1323 1324Array.extend({ 1325 1326 /* 1327 Property: rgbToHex 1328 see <String.rgbToHex>, but as an array method. 1329 */ 1330 1331 rgbToHex: function(array){ 1332 if (this.length < 3) return false; 1333 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 1334 var hex = []; 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); 1338 } 1339 return array ? hex : '#' + hex.join(''); 1340 }, 1341 1342 /* 1343 Property: hexToRgb 1344 same as <String.hexToRgb>, but as an array method. 1345 */ 1346 1347 hexToRgb: function(array){ 1348 if (this.length != 3) return false; 1349 var rgb = []; 1350 for (var i = 0; i < 3; i++){ 1351 rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16)); 1352 } 1353 return array ? rgb : 'rgb(' + rgb.join(',') + ')'; 1354 } 1355 1356}); 1357 1358/* 1359Script: Function.js 1360 Contains Function prototypes and utility functions . 1361 1362License: 1363 MIT-style license. 1364 1365Credits: 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 1367*/ 1368 1369/* 1370Class: Function 1371 A collection of The Function Object prototype methods. 1372*/ 1373 1374Function.extend({ 1375 1376 /* 1377 Property: create 1378 Main function to create closures. 1379 1380 Returns: 1381 a function. 1382 1383 Arguments: 1384 options - An Options object. 1385 1386 Options: 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. 1390 Default is false. 1391 arguments - A single argument or array of arguments that will be passed to the function when called. 1392 1393 If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow. 1394 1395 Default is no custom arguments, the function will receive the standard arguments when called. 1396 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. 1402 */ 1403 1404 create: function(options){ 1405 var fn = this; 1406 options = $merge({ 1407 'bind': fn, 1408 'event': false, 1409 'arguments': null, 1410 'delay': false, 1411 'periodical': false, 1412 'attempt': false 1413 }, options); 1414 if ($chk(options.arguments) && $type(options.arguments) != 'array') o
1414ptions.arguments = [options.arguments]; 1415 return function(event){ 1416 var args; 1417 if (options.event){ 1418 event = event || window.event; 1419 args = [(options.event === true) ? event : new options.event(event)]; 1420 if (options.arguments) args.extend(options.arguments); 1421 } 1422 else args = options.arguments || arguments; 1423 var returns = function(){ 1424 return fn.apply($pick(options.bind, fn), args); 1425 }; 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;}; 1429 return returns(); 1430 }; 1431 }, 1432 1433 /* 1434 Property: pass 1435 Shortcut to create closures with arguments and bind. 1436 1437 Returns: 1438 a function. 1439 1440 Arguments: 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. 1443 1444 Example: 1445 >myFunction.pass([arg1, arg2], myElement); 1446 */ 1447 1448 pass: function(args, bind){ 1449 return this.create({'arguments': args, 'bind': bind}); 1450 }, 1451 1452 /* 1453 Property: attempt 1454 Tries to execute the function, returns either the result of the function or false on error. 1455 1456 Arguments: 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. 1459 1460 Example: 1461 >myFunction.attempt([arg1, arg2], myElement); 1462 */ 1463 1464 attempt: function(args, bind){ 1465 return this.create({'arguments': args, 'bind': bind, 'attempt': true})(); 1466 }, 1467 1468 /* 1469 Property: bind 1470 method to easily create closures with "this" altered. 1471 1472 Arguments: 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 1475 1476 Returns: 1477 a function. 1478 1479 Example: 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 1484 >}; 1485 >var myBoundFunction = myFunction.bind(myElement); 1486 >myBoundFunction(); // this will make the element myElement red. 1487 */ 1488 1489 bind: function(bind, args){ 1490 return this.create({'bind': bind, 'arguments': args}); 1491 }, 1492 1493 /* 1494 Property: bindAsEventListener 1495 cross browser method to pass event firer 1496 1497 Arguments: 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 1500 1501 Returns: 1502 a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser. 1503 1504 Example: 1505 >function myFunction(event){ 1506 > alert(event.clientx) //returns the coordinates of the mouse.. 1507 >}; 1508 >myElement.onclick = myFunction.bindAsEventListener(myElement); 1509 */ 1510 1511 bindAsEventListener: function(bind, args){ 1512 return this.create({'bind': bind, 'event': true, 'arguments': args}); 1513 }, 1514 1515 /* 1516 Property: delay 1517 Delays the execution of a function by a specified duration. 1518 1519 Arguments: 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 1523 1524 Example: 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 1527 */ 1528 1529 delay: function(delay, bind, args){ 1530 return this.create({'delay': delay, 'bind': bind, 'arguments': args})(); 1531 }, 1532 1533 /* 1534 Property: periodical 1535 Executes a function in the specified intervals of time 1536 1537 Arguments: 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 1541 */ 1542 1543 periodical: function(interval, bind, args){ 1544 return this.create({'periodical': interval, 'bind': bind, 'arguments': args})(); 1545 } 1546 1547}); 1548 1549/* 1550Script: Number.js 1551 Contains the Number prototypes. 1552 1553License: 1554 MIT-style license. 1555*/ 1556 1557/* 1558Class: Number 1559 A collection of The Number Object prototype methods. 1560*/ 1561 1562Number.extend({ 1563 1564 /* 1565 Property: toInt 1566 Returns this number; useful because toInt must work on both Strings and Numbers. 1567 */ 1568 1569 toInt: function(){ 1570 return parseInt(this); 1571 }, 1572 1573 /* 1574 Property: toFloat 1575 Returns this number as a float; useful because toFloat must work on both Strings and Numbers. 1576 */ 1577 1578 toFloat: function(){ 1579 return parseFloat(this); 1580 }, 1581 1582 /* 1583 Property: limit 1584 Limits the number. 1585 1586 Arguments: 1587 min - number, minimum value 1588 max - number, maximum value 1589 1590 Returns: 1591 the number in the given limits. 1592 1593 Example: 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 1597 */ 1598 1599 limit: function(min, max){ 1600 return Math.min(max, Math.max(min, this)); 1601 }, 1602 1603 /* 1604 Property: round 1605 Returns the number rounded to specified precision. 1606 1607 Arguments: 1608 precision - integer, number of digits after the decimal point. Can also be negative or zero (default). 1609 1610 Example: 1611 >12.45.round() // returns 12 1612 >12.45.round(1) // returns 12.5 1613 >12.45.round(-1) // returns 10 1614 1615 Returns: 1616 The rounded number. 1617 */ 1618 1619 round: function(precision){ 1620 precision = Math.pow(10, precision || 0); 1621 return Math.round(this * precision) / precision; 1622 }, 1623 1624 /* 1625 Property: times 1626 Executes a passed in function the specified number of times 1627 1628 Arguments: 1629 function - the function to be executed on each iteration of the loop 1630 1631 Example: 1632 >(4).times(alert); 1633 */ 1634 1635 times: function(fn){ 1636 for (var i = 0; i < this; i++) fn(i); 1637 } 1638 1639}); 1640 1641/* 1642Script: Element.js 1643 Contains useful Element prototypes, to be used with the dollar function <$>. 1644 1645License: 1646 MIT-style license. 1647 1648Credits: 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 1650*/ 1651 1652/* 1653Class: Element 1654 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 1655*/ 1656 1657var Element = new Class({ 1658 1659 /* 1660 Property: initialize 1661 Creates a new element of the type passed in. 1662 1663 Arguments: 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 1667 1668 Props: 1669 the key styles will be used as setStyles, the key events will be used as addEvents. any other key is used as setProperty. 1670
1671 Example: 1672 (start code) 1673 new Element('a', { 1674 'styles': { 1675 'display': 'block', 1676 'border': '1px solid black' 1677 }, 1678 'events': { 1679 'click': function(){ 1680 //aaa 1681 }, 1682 'mousedown': function(){ 1683 //aaa 1684 } 1685 }, 1686 'class': 'myClassSuperClass', 1687 'href': 'http://mad4milk.net' 1688 }); 1689 1690 (end) 1691 */ 1692 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 + '"' : ''; 1698 delete props.name; 1699 delete props.type; 1700 el = '<' + el + name + type + '>'; 1701 } 1702 el = document.createElement(el); 1703 } 1704 el = $(el); 1705 return (!props || !el) ? el : el.set(props); 1706 } 1707 1708}); 1709 1710/* 1711Class: Elements 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 <$>. 1716 1717Example: 1718 >$$('myselector').each(function(el){ 1719 > //... 1720 >}); 1721 1722 some iterations here, $$('myselector') is also an array. 1723 1724 >$$('myselector').setStyle('color', 'red'); 1725 every element returned by $$('myselector') also accepts <Element> methods, in this example every element will be made red. 1726*/ 1727 1728var Elements = new Class({ 1729 1730 initialize: function(elements){ 1731 return (elements) ? $extend(elements, this) : this; 1732 } 1733 1734}); 1735 1736Elements.extend = function(props){ 1737 for (var prop in props){ 1738 this.prototype[prop] = props[prop]; 1739 this[prop] = $native.generic(prop); 1740 } 1741}; 1742 1743/* 1744Section: Utility Functions 1745 1746Function: $ 1747 returns the element passed in with all the Element prototypes applied. 1748 1749Arguments: 1750 el - a reference to an actual element or a string representing the id of an element 1751 1752Example: 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. 1756 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(). 1759 1760Returns: 1761 a DOM element or false (if no id was found). 1762 1763Note: 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. 1766*/ 1767 1768function $(el){ 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;
1776 } 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); 1783}; 1784 1785/* 1786Function: $$ 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. 1790 1791Arguments: 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. 1794 1795Note: 1796 if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names. 1797 1798Example: 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 1812 1813Returns: 1814 array - array of all the dom elements matched, extended with <$>. Returns as <Elements>. 1815*/ 1816 1817document.getElementsBySelector = document.getElementsByTagName; 1818 1819function $$(){ 1820 var elements = []; 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; 1826 case false: break; 1827 case 'string': selector = document.getElementsBySelector(selector, true); 1828 default: elements.extend(selector); 1829 } 1830 } 1831 return $$.unique(elements); 1832}; 1833 1834$$.unique = function(array){ 1835 var elements = []; 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); 1842 } 1843 } 1844 for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null; 1845 return new Elements(elements); 1846}; 1847 1848Elements.Multi = function(property){ 1849 return function(){ 1850 var args = arguments; 1851 var items = []; 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); 1857 }; 1858 return (elements) ? $$.unique(items) : items; 1859 }; 1860}; 1861 1862Element.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); 1869 } 1870}; 1871 1872/* 1873Class: Element 1874 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 1875*/ 1876 1877Element.extend({ 1878 1879 /* 1880 Property: set 1881 you can set events, styles and properties with this shortcut. same as calling new Element. 1882 */ 1883 1884 set: function(props){ 1885 for (var prop in props){ 1886 var val = props[prop]; 1887 switch(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); 1892 } 1893 } 1894 return this; 1895 }, 1896 1897 inject: function(el, where){ 1898 el = $(el); 1899 switch(where){ 1900 case 'before': el.parentNode.insertBefore(this, el); break; 1901 case 'after': 1902 var next = el.getNext(); 1903 if (!next) el.parentNode.appendChild(this); 1904 else el.parentNode.insertBefore(this, next); 1905 break; 1906 case 'top': 1907 var first = el.firstChild; 1908 if (first){ 1909 el.insertBefore(this, first); 1910 break; 1911 }
1912 default: el.appendChild(this); 1913 } 1914 return this; 1915 }, 1916 1917 /* 1918 Property: injectBefore 1919 Inserts the Element before the passed element. 1920 1921 Arguments: 1922 el - an element reference or the id of the element to be injected in. 1923 1924 Example: 1925 >html: 1926 ><div id="myElement"></div> 1927 ><div id="mySecondElement"></div> 1928 >js: 1929 >$('mySecondElement').injectBefore('myElement'); 1930 >resulting html: 1931 ><div id="mySecondElement"></div> 1932 ><div id="myElement"></div> 1933 */ 1934 1935 injectBefore: function(el){ 1936 return this.inject(el, 'before'); 1937 }, 1938 1939 /* 1940 Property: injectAfter 1941 Same as <Element.injectBefore>, but inserts the element after. 1942 */ 1943 1944 injectAfter: function(el){ 1945 return this.inject(el, 'after'); 1946 }, 1947 1948 /* 1949 Property: injectInside 1950 Same as <Element.injectBefore>, but inserts the element inside. 1951 */ 1952 1953 injectInside: function(el){ 1954 return this.inject(el, 'bottom'); 1955 }, 1956 1957 /* 1958 Property: injectTop 1959 Same as <Element.injectInside>, but inserts the element inside, at the top. 1960 */ 1961 1962 injectTop: function(el){ 1963 return this.inject(el, 'top'); 1964 }, 1965 1966 /* 1967 Property: adopt 1968 Inserts the passed elements inside the Element. 1969 1970 Arguments: 1971 accepts elements references, element ids as string, selectors ($$('stuff')) / array of elements, array of ids as strings and collections. 1972 */ 1973 1974 adopt: function(){ 1975 var elements = []; 1976 $each(arguments, function(argument){ 1977 elements = elements.concat(argument); 1978 }); 1979 $$(elements).inject(this); 1980 return this; 1981 }, 1982 1983 /* 1984 Property: remove 1985 Removes the Element from the DOM. 1986 1987 Example: 1988 >$('myElement').remove() //bye bye 1989 */ 1990 1991 remove: function(){ 1992 return this.parentNode.removeChild(this); 1993 }, 1994 1995 /* 1996 Property: clone 1997 Clones the Element and returns the cloned one. 1998 1999 Arguments: 2000 contents - boolean, when true the Element is cloned with childNodes, default true 2001 2002 Returns: 2003 the cloned element 2004 2005 Example: 2006 >var clone = $('myElement').clone().injectAfter('myElement'); 2007 >//clones the Element and append the clone after the Element. 2008 */ 2009 2010 clone: function(contents){ 2011 var el = $(this.cloneNode(contents !== false)); 2012 if (!el.$events) return el; 2013 el.$events = {}; 2014 for (var type in this.$events) el.$events[type] = { 2015 'keys': $A(this.$events[type].keys), 2016 'values': $A(this.$events[type].values) 2017 }; 2018 return el.removeEvents(); 2019 }, 2020 2021 /* 2022 Property: replaceWith 2023 Replaces the Element with an element passed. 2024 2025 Arguments: 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. 2028 2029 Returns: 2030 the passed in element 2031 2032 Example: 2033 >$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place. 2034 */ 2035 2036 replaceWith: function(el){ 2037 el = $(el); 2038 this.parentNode.replaceChild(el, this); 2039 return el; 2040 }, 2041 2042 /* 2043 Property: appendText 2044 Appends text node to a DOM element. 2045 2046 Arguments: 2047 text - the text to append. 2048 2049 Example: 2050 ><div id="myElement">hey</div> 2051 >$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy" 2052 */ 2053 2054 appendText: function(text){ 2055 this.appendChild(document.createTextNode(text)); 2056 return this; 2057 }, 2058 2059 /* 2060 Property: hasClass 2061 Tests the Element to see if it has the passed in className. 2062 2063 Returns: 2064 true - the Element has the class 2065 false - it doesn't 2066 2067 Arguments: 2068 className - string; the class name to test. 2069 2070 Example: 2071 ><div id="myElement" class="testClass"></div> 2072 >$('myElement').hasClass('testClass'); //returns true 2073 */ 2074 2075 hasClass: function(className){ 2076 return this.className.contains(className, ' '); 2077 }, 2078 2079 /* 2080 Property: addClass 2081 Adds the passed in class to the Element, if the element doesnt already have it. 2082 2083 Arguments: 2084 className - string; the class name to add 2085 2086 Example: 2087 ><div id="myElement" class="testClass"></div> 2088 >$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div> 2089 */ 2090 2091 addClass: function(className){ 2092 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 2093 return this; 2094 }, 2095 2096 /* 2097 Property: removeClass 2098 Works like <Element.addClass>, but removes the class from the element. 2099 */ 2100 2101 removeClass: function(className){ 2102 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean(); 2103 return this; 2104 }, 2105 2106 /* 2107 Property: toggleClass 2108 Adds or removes the passed in class name to the element, depending on if it's present or not. 2109 2110 Arguments: 2111 className - the class to add or remove 2112 2113 Example: 2114 >
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> 2119 */ 2120 2121 toggleClass: function(className){ 2122 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); 2123 }, 2124 2125 /* 2126 Property: setStyle 2127 Sets a css property to the Element. 2128 2129 Arguments: 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 2132 2133 Example: 2134 >$('myElement').setStyle('width', '300px'); //the width is now 300px 2135 >$('myElement').setStyle('width', 300); //the width is now 300px 2136 */ 2137 2138 setStyle: function(property, value){ 2139 switch(property){ 2140 case 'opacity': return this.setOpacity(parseFloat(value)); 2141 case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat'; 2142 } 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(',') + ')'; 2147 } 2148 this.style[property] = value; 2149 return this; 2150 }, 2151 2152 /* 2153 Property: setStyles 2154 Applies a collection of styles to the Element. 2155 2156 Arguments: 2157 source - an object or string containing all the styles to apply. When its a string it overrides old style. 2158 2159 Examples: 2160 >$('myElement').setStyles({ 2161 > border: '1px solid #000', 2162 > width: 300, 2163 > height: 400 2164 >}); 2165 2166 OR 2167 2168 >$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;'); 2169 */ 2170 2171 setStyles: function(source){ 2172 switch($type(source)){ 2173 case 'object': Element.setMany(this, 'setStyle', source); break; 2174 case 'string': this.style.cssText = source; 2175 } 2176 return this; 2177 }, 2178 2179 /* 2180 Property: setOpacity 2181 Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0. 2182 2183 Arguments: 2184 opacity - float; Accepts values from 0 to 1. 2185 2186 Example: 2187 >$('myElement').setOpacity(0.5) //make it 50% transparent 2188 */ 2189 2190 setOpacity: function(opacity){ 2191 if (opacity == 0){ 2192 if (this.style.visibility != "hidden") this.style.visibility = "hidden"; 2193 } else { 2194 if (this.style.visibility != "visible") this.style.visibility = "visible"; 2195 } 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; 2199 return this; 2200 }, 2201 2202 /* 2203 Property: getStyle 2204 Returns the style of the Element given the property passed in. 2205 2206 Arguments: 2207 property - the css style property you want to retrieve 2208 2209 Example: 2210 >$('myElement').getStyle('width'); //returns "400px" 2211 >//but you can also use 2212 >$('myElement').getStyle('width').toInt(); //returns 400 2213 2214 Returns: 2215 the style as a string 2216 */ 2217 2218 getStyle: function(property){ 2219 property = property.camelCase(); 2220 var result = this.style[property]; 2221 if (!$chk(result)){ 2222 if (property == 'opacity') return this.$tmp.opacity; 2223 result = []; 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'); 2229 }, this); 2230 if (property == 'border'){ 2231 var every = result.every(function(bit){ 2232 return (bit == result[0]); 2233 }); 2234 return (every) ? result[0] : false; 2235 } 2236 return result.join(' '); 2237 } 2238 } 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); 2243 }, this).join(' '); 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', '')); 2247 }, this).join(' '); 2248 } 2249 } 2250 if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate()); 2251 else if (this.currentStyle) result = this.currentStyle[property]; 2252 } 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(); 2257 }).join(' '); 2258 } 2259 return result; 2260 }, 2261 2262 /* 2263 Property: getStyles 2264 Returns an object of styles of the Element for each argument passed in. 2265 Arguments: 2266 properties - strings; any number of style properties
2267 Example: 2268 >$('myElement').getStyles('width','height','padding'); 2269 >//returns an object like: 2270 >{width: "10px", height: "10px", padding: "10px 0px 10px 0px"} 2271 */ 2272 2273 getStyles: function(){ 2274 return Element.getMany(this, 'getStyle', arguments); 2275 }, 2276 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]; 2281 return $(el); 2282 }, 2283 2284 /* 2285 Property: getPrevious 2286 Returns the previousSibling of the Element, excluding text nodes. 2287 2288 Example: 2289 >$('myElement').getPrevious(); //get the previous DOM element from myElement 2290 2291 Returns: 2292 the sibling element or undefined if none found. 2293 */ 2294 2295 getPrevious: function(){ 2296 return this.walk('previous'); 2297 }, 2298 2299 /* 2300 Property: getNext 2301 Works as Element.getPrevious, but tries to find the nextSibling. 2302 */ 2303 2304 getNext: function(){ 2305 return this.walk('next'); 2306 }, 2307 2308 /* 2309 Property: getFirst 2310 Works as <Element.getPrevious>, but tries to find the firstChild. 2311 */ 2312 2313 getFirst: function(){ 2314 return this.walk('next', 'firstChild'); 2315 }, 2316 2317 /* 2318 Property: getLast 2319 Works as <Element.getPrevious>, but tries to find the lastChild. 2320 */ 2321 2322 getLast: function(){ 2323 return this.walk('previous', 'lastChild'); 2324 }, 2325 2326 /* 2327 Property: getParent 2328 returns the $(element.parentNode) 2329 */ 2330 2331 getParent: function(){ 2332 return $(this.parentNode); 2333 }, 2334 2335 /* 2336 Property: getChildren 2337 returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>. 2338 */ 2339 2340 getChildren: function(){ 2341 return $$(this.childNodes); 2342 }, 2343 2344 /* 2345 Property: hasChild 2346 returns true if the passed in element is a child of the $(element). 2347 */ 2348 2349 hasChild: function(el){ 2350 return !!$A(this.getElementsByTagName('*')).contains(el); 2351 }, 2352 2353 /* 2354 Property: getProperty 2355 Gets the an attribute of the Element. 2356 2357 Arguments: 2358 property - string; the attribute to retrieve 2359 2360 Example: 2361 >$('myImage').getProperty('src') // returns whatever.gif 2362 2363 Returns: 2364 the value, or an empty string 2365 */ 2366 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; 2374 }, 2375 2376 /* 2377 Property: removeProperty 2378 Removes an attribute from the Element 2379 2380 Arguments: 2381 property - string; the attribute to remove 2382 */ 2383 2384 removeProperty: function(property){ 2385 var index = Element.Properties[property]; 2386 if (index) this[index] = ''; 2387 else this.removeAttribute(property); 2388 return this; 2389 }, 2390 2391 /* 2392 Property: getProperties 2393 same as <Element.getStyles>, but for properties 2394 */ 2395 2396 getProperties: function(){ 2397 return Element.getMany(this, 'getProperty', arguments); 2398 }, 2399 2400 /* 2401 Property: setProperty 2402 Sets an attribute for the Element. 2403 2404 Arguments: 2405 property - string; the property to assign the value passed in 2406 value - the value to assign to the property passed in 2407 2408 Example: 2409 >$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source 2410 */ 2411 2412 setProperty: function(property, value){ 2413 var index = Element.Properties[property]; 2414 if (index) this[index] = value; 2415 else this.setAttribute(property, value); 2416 return this; 2417 }, 2418 2419 /* 2420 Property: setProperties 2421 Sets numerous attributes for the Element. 2422 2423 Arguments: 2424 source - an object with key/value pairs. 2425 2426 Example: 2427 (start code) 2428 $('myElement').setProperties({ 2429 src: 'whatever.gif', 2430 alt: 'whatever dude' 2431 }); 2432 <img src="whatever.gif" alt="whatever dude"> 2433 (end) 2434 */ 2435 2436 setProperties: function(source){ 2437 return Element.setMany(this, 'setProperty', source); 2438 }, 2439 2440 /* 2441 Property: setHTML 2442 Sets the innerHTML of the Element. 2443 2444 Arguments: 2445 html - string; the new innerHTML for the element. 2446 2447 Example: 2448 >$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML 2449 */ 2450 2451 setHTML: function(){ 2452 this.innerHTML = $A(arguments).join(''); 2453 return this; 2454 }, 2455 2456 /* 2457 Property: setText 2458 Sets the inner text of the Element. 2459 2460 Arguments: 2461 text - string; the new text content for the element. 2462 2463 Example: 2464 >$('myElement').setText('some text') //the text of myElement is now = 'some text' 2465 */ 2466 2467 setText: function(text){ 2468 var tag = this.getTag(); 2469 if (['style', 'script'].contains(tag)){ 2470 if (window.ie){ 2471 if (tag == 'style') this.styleSheet.cssText = text; 2472 else if (tag == 'script') this.setProperty('text', text); 2473 return this; 2474 } else { 2475 this.removeChild(this.firstChild); 2476 return this.appendText(text); 2477 } 2478 } 2479 this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text; 2480 return this; 2481 }, 2482 2483 /* 2484 Property: getText 2485 Gets the inner text of the Element. 2486 */ 2487 2488 getText: function(){ 2489 var tag = this.getTag(); 2490 if (['style', 'script'].contains(tag)){ 2491 if (window.ie){ 2492 if (tag == 'style') return this.styleSheet.cssText; 2493 else if (tag == 'script') return this.getProperty('text'); 2494 } else { 2495 return this.innerHTML; 2496 } 2497 } 2498 return ($pick(this.innerText, this.textContent)); 2499 }, 2500 2501 /* 2502 Property: getTag 2503 Returns the tagName of the element in lower case. 2504 2505 Example: 2506 >$('myImage').getTag() // returns 'img' 2507 2508 Returns: 2509 The tag name in lower case 2510 */ 2511 2512 getTag: function(){ 2513 return this.tagName.toLowerCase(); 2514 }, 2515 2516 /* 2517 Property: empty 2518 Empties an element of all its children. 2519 2520 Example: 2521 >$('myDiv').empty() // empties the Div and returns it 2522 2523 Returns: 2524 The element. 2525 */ 2526 2527 empty: function(){ 2528 Garbage.trash(this.getElementsByTagName('*')); 2529 return this.setHTML(''); 2530 } 2531 2532}); 2533 2534Element.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']; 2538 var size = 0; 2539 values.each(function(value){ 2540 size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt(); 2541 }); 2542 return element['offset' + property.capitalize()] - size + 'px'; 2543 } else if (property.test(/border(.+)Width|margin|padding/)){ 2544 return '0px'; 2545 } 2546 return result; 2547}; 2548 2549Element.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); 2552}); 2553 2554Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor']; 2555 2556Element.getMany = function(el, method, keys){ 2557 var result = {}; 2558 $each(keys, function(key){ 2559 result[key] = el[method](key); 2560 }); 2561 return result; 2562}; 2563 2564Element.setMany = function(el, method, pairs){ 2565 for (var key in pairs) el[method](key, pairs[key]); 2566 return el; 2567}; 2568 2569Element.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' 2574}); 2575Element.PropertiesIFlag = { 2576 'href': 2, 'src': 2 2577}; 2578 2579Element.Methods = { 2580 Listeners: {
2581 addListener: function(type, fn){ 2582 if (this.addEventListener) this.addEventListener(type, fn, false); 2583 else this.attachEvent('on' + type, fn); 2584 return this; 2585 }, 2586 2587 removeListener: function(type, fn){ 2588 if (this.removeEventListener) this.removeEventListener(type, fn, false); 2589 else this.detachEvent('on' + type, fn); 2590 return this; 2591 } 2592 } 2593}; 2594 2595window.extend(Element.Methods.Listeners); 2596document.extend(Element.Methods.Listeners); 2597Element.extend(Element.Methods.Listeners); 2598 2599var Garbage = { 2600 2601 elements: [], 2602 2603 collect: function(el){ 2604 if (!el.$tmp){ 2605 Garbage.elements.push(el); 2606 el.$tmp = {'opacity': 1}; 2607 } 2608 return el; 2609 }, 2610 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; 2619 } 2620 Garbage.elements.remove(null); 2621 }, 2622 2623 empty: function(){ 2624 Garbage.collect(window); 2625 Garbage.collect(document); 2626 Garbage.trash(Garbage.elements); 2627 } 2628 2629}; 2630 2631window.addListener('beforeunload', function(){ 2632 window.addListener('unload', Garbage.empty); 2633 if (window.ie) window.addListener('unload', CollectGarbage); 2634}); 2635 2636/* 2637Script: Element.Event.js 2638 Contains the Event Class, Element methods to deal with Element events, custom Events, and the Function prototype bindWithEvent. 2639 2640License: 2641 MIT-style license. 2642*/ 2643 2644/* 2645Class: Event 2646 Cross browser methods to manage events. 2647 2648Arguments: 2649 event - the event 2650 2651Properties: 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 2665 2666Example: 2667 (start code) 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'); 2674 }; 2675 (end) 2676*/ 2677 2678var Event = new Class({ 2679 2680 initialize: function(event){ 2681 if (event && event.$extended) return event; 2682 this.$extended = true; 2683 event = event || window.event; 2684 this.event = 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){ 2698 this.key = name; 2699 break; 2700 } 2701 } 2702 if (this.type == 'keydown'){ 2703 var fKey = this.code - 111; 2704 if (fKey > 0 && fKey < 13) this.key = 'f' + fKey; 2705 } 2706 this.key = this.key || String.fromCharCode(this.code).toLowerCase(); 2707 } else if (this.type.test(/(click|mouse|menu)/)){ 2708 this.page = { 2709 'x': event.pageX || event.clientX + document.documentElement.scrollLeft, 2710 'y': event.pageY || event.clientY + document.documentElement.scrollTop 2711 }; 2712 this.client = { 2713 'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX, 2714 'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY 2715 }; 2716 this.rightClick = (event.which == 3) || (event.button == 2); 2717 switch(this.type){ 2718 case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break; 2719 case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement; 2720 } 2721 this.fixRelatedTarget(); 2722 } 2723 return this; 2724 }, 2725 2726 /* 2727 Property: stop 2728 cross browser method to stop an event 2729 */ 2730 2731 stop: function(){ 2732 return this.stopPropagation().preventDefault(); 2733 }, 2734 2735 /* 2736 Property: stopPropagation 2737 cross browser method to stop the propagation of an event 2738 */ 2739 2740 stopPropagation: function(){ 2741 if (this.event.stopPropagation) this.event.stopPropagation(); 2742 else this.event.cancelBubble = true; 2743 return this; 2744 }, 2745 2746 /* 2747 Property: preventDefault 2748 cross browser method to prevent the default action of the event 2749 */ 2750 2751 preventDefault: function(){ 2752 if (this.event.preventDefault) this.event.preventDefault(); 2753 else this.event.returnValue = false;
2754 return this; 2755 } 2756 2757}); 2758 2759Event.fix = { 2760 2761 relatedTarget: function(){ 2762 if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode; 2763 }, 2764 2765 relatedTargetGecko: function(){ 2766 try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;} 2767 } 2768 2769}; 2770 2771Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget; 2772 2773/* 2774Property: keys 2775 you can add additional Event keys codes this way: 2776 2777Example: 2778 (start code) 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). 2783 }); 2784 (end) 2785*/ 2786 2787Event.keys = new Abstract({ 2788 'enter': 13, 2789 'up': 38, 2790 'down': 40, 2791 'left': 37, 2792 'right': 39, 2793 'esc': 27, 2794 'space': 32, 2795 'backspace': 8, 2796 'tab': 9, 2797 'delete': 46 2798}); 2799 2800/* 2801Class: Element 2802 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 2803*/ 2804 2805Element.Methods.Events = { 2806 2807 /* 2808 Property: addEvent 2809 Attaches an event listener to a DOM element. 2810 2811 Arguments: 2812 type - the event to monitor ('click', 'load', etc) without the prefix 'on'. 2813 fn - the function to execute 2814 2815 Example: 2816 >$('myElement').addEvent('click', function(){alert('clicked!')}); 2817 */ 2818 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]; 2826 if (custom){ 2827 if (custom.add) custom.add.call(this, fn); 2828 if (custom.map) fn = custom.map; 2829 if (custom.type) realType = custom.type; 2830 } 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; 2834 }, 2835 2836 /* 2837 Property: removeEvent 2838 Works as Element.addEvent, but instead removes the previously added event listener. 2839 */ 2840 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]; 2848 if (custom){ 2849 if (custom.remove) custom.remove.call(this, fn); 2850 if (custom.type) type = custom.type; 2851 } 2852 return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this; 2853 }, 2854 2855 /* 2856 Property: addEvents 2857 As <addEvent>, but accepts an object and add multiple events at once. 2858 */ 2859 2860 addEvents: function(source){ 2861 return Element.setMany(this, 'addEvent', source); 2862 }, 2863 2864 /* 2865 Property: removeEvents 2866 removes all events of a certain type from an element. if no argument is passed in, removes all events. 2867 2868 Arguments: 2869 type - string; the event name (e.g. 'click') 2870 */ 2871 2872 removeEvents: function(type){ 2873 if (!this.$events) return this; 2874 if (!type){ 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); 2880 }, this); 2881 this.$events[type] = null; 2882 } 2883 return this; 2884 }, 2885 2886 /* 2887 Property: fireEvent 2888 executes all events of the specified type present in the element. 2889 2890 Arguments: 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 2894 */ 2895 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})(); 2900 }, this); 2901 } 2902 return this; 2903 }, 2904 2905 /* 2906 Property: cloneEvents 2907 Clones all events from an element to this element. 2908 2909 Arguments: 2910 from - element, copy all events from this element 2911 type - optional, copies only events of this type 2912 */ 2913 2914 cloneEvents: function(from, type){ 2915 if (!from.$events) return this; 2916 if (!type){ 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); 2921 }, this); 2922 } 2923 return this; 2924 } 2925 2926}; 2927 2928window.extend(Element.Methods.Events); 2929document.extend(Element.Methods.Events); 2930Element.extend(Element.Methods.Events); 2931 2932/* Section: Custom Events */ 2933 2934Element.Events = new Abstract({ 2935 2936 /* 2937 Event: mouseenter 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) 2940 2941 2942 Example: 2943 >$(myElement).addEvent('mouseenter', myFunction); 2944 */ 2945 2946 'mouseenter': { 2947 type: 'mouseover', 2948 map: function(event){ 2949 event = new Event(event); 2950 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event); 2951 } 2952 }, 2953 2954 /* 2955 Event: mouseleave 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) 2957 2958 2959 Example: 2960 >$(myElement).addEvent('mouseleave', myFunction); 2961 */ 2962 2963 'mouseleave': { 2964 type: 'mouseout', 2965 map: function(event){ 2966 event = new Event(event); 2967 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event); 2968 } 2969 }, 2970 2971 'mousewheel': { 2972 type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel' 2973 } 2974 2975}); 2976 2977Element.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 2985]; 2986 2987/* 2988Class: Function 2989 A collection of The Function Object prototype methods. 2990*/ 2991 2992Function.extend({ 2993 2994 /* 2995 Property: bindWithEvent 2996 automatically passes MooTools Event Class. 2997 2998 Arguments: 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. 3001 3002 Returns: 3003 a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser. 3004 3005 Example: 3006 >function myFunction(event){ 3007 > alert(event.client.x) //returns the coordinates of the mouse.. 3008 >}; 3009 >myElement.addEvent('click', myFunction.bindWithEvent(myElement)); 3010 */ 3011 3012 bindWithEvent: function(bind, args){ 3013 return this.create({'bind': bind, 'arguments': args, 'event': Event}); 3014 } 3015 3016}); 3017 3018 3019/* 3020Script: Element.Filters.js 3021 add Filters capability to <Elements>. 3022 3023License: 3024 MIT-style license. 3025*/ 3026 3027/* 3028Class: Elements 3029 A collection of methods to be used with <$$> elements collections. 3030*/ 3031 3032Elements.extend({ 3033 3034 /* 3035 Property: filterByTag 3036 Filters the collection by a specified tag name. 3037 Returns a new Elements collection, while the original remains untouched. 3038 */ 3039 3040 filterByTag: function(tag){ 3041 return new Elements(this.filter(function(el){ 3042 return (Element.getTag(el) == tag); 3043 })); 3044 }, 3045 3046 /* 3047 Property: filterByClass 3048 Filters the collection by a specified class name. 3049 Returns a new Elements collection, while the original remains untouched. 3050 */ 3051 3052 filterByClass: function(className, nocash){ 3053 var elements = this.filter(function(el){ 3054 return (el.className && el.className.contains(className, ' ')); 3055 }); 3056 return (nocash) ? elements : new Elements(elements); 3057 }, 3058 3059 /* 3060 Property: filterById 3061 Filters the collection by a specified ID. 3062 Returns a new Elements collection, while the original remains untouched. 3063 */ 3064 3065 filterById: function(id, nocash){ 3066 var elements = this.filter(function(el){ 3067 return (el.id == id); 3068 }); 3069 return (nocash) ? elements : new Elements(elements); 3070 }, 3071 3072 /* 3073 Property: filterByAttribute 3074 Filters the collection by a specified attribute. 3075 Returns a new Elements collection, while the original remains untouched. 3076 3077 Arguments: 3078 name - the attribute name. 3079 operator - optional, the attribute operator. 3080 value - optional, the attribute value, only valid if the operator is specified. 3081 */ 3082 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; 3088 switch(operator){ 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, ' '); 3095 } 3096 return false; 3097 }); 3098 return (nocash) ? elements : new Elements(elements); 3099 } 3100 3101}); 3102 3103/* 3104Script: Element.Selectors.js 3105 Css Query related functions and <Element> extensions 3106 3107License: 3108 MIT-style license. 3109*/ 3110 3111/* Section: Utility Functions */ 3112 3113/* 3114Function: $E 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>. 3117 3118Arguments: 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. 3121 3122Example: 3123 >$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement' 3124 3125Returns: 3126 a DOM element - the first element that matches the selector 3127*/ 3128 3129function $E(selector, filter){ 3130 return ($(filter) || document).getElement(selector); 3131}; 3132 3133/* 3134Function: $ES 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>. 3138 3139Returns: 3140 an array of dom elements that match the selector within the filter 3141 3142Arguments: 3143 selector - string; css selector to match 3144 filter - optional; a DOM element to limit the scope of the selector match; defaults to document. 3145 3146Examples: 3147 >$ES("a") //gets all the anchor tags; synonymous with $$("a") 3148 >$ES('a','myElement') //get all the anchor tags within $('myElement') 3149*/ 3150 3151function $ES(selector, filter){ 3152 return ($(filter) || document).getElementsBySelector(selector); 3153}; 3154 3155$$.shared = { 3156 3157 'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/, 3158 3159 'xpath': { 3160 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], ' ")]'); 3165 if (param[4]){ 3166 if (param[5] && param[6]){ 3167 switch(param[5]){ 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], '"]'); 3173 } 3174 } else { 3175 temp.push('[@', param[4], ']'); 3176 } 3177 } 3178 items.push(temp.join('')); 3179 return items; 3180 }, 3181 3182 getItems: function(items, context, nocash){ 3183 var elements = []; 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($)); 3187 } 3188 3189 }, 3190 3191 'normal': { 3192 3193 getParam: function(items, context, param, i){ 3194 if (i == 0){ 3195 if (param[2]){ 3196 var el = context.getElementById(param[2]); 3197 if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false; 3198 items = [el]; 3199 } else { 3200 items = $A(context.getElementsByTagName(param[1])); 3201 } 3202 } else { 3203 items = $$.shared.getElementsByTagName(items, param[1]); 3204 if (param[2]) items = Elements.filterById(items, param[2], true); 3205 } 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); 3208 return items; 3209 }, 3210 3211 getItems: function(items, context, nocash){ 3212 return (nocash) ? items : $$.unique(items); 3213 } 3214 3215 }, 3216 3217 resolver: function(prefix){ 3218 return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
3219 }, 3220 3221 getElementsByTagName: function(context, tagName){ 3222 var found = []; 3223 for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName)); 3224 return found; 3225 } 3226 3227}; 3228 3229$$.shared.method = (window.xpath) ? 'xpath' : 'normal'; 3230 3231/* 3232Class: Element 3233 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3234*/ 3235 3236Element.Methods.Dom = { 3237 3238 /* 3239 Property: getElements 3240 Gets all the elements within an element that match the given (single) selector. 3241 Returns as <Elements>. 3242 3243 Arguments: 3244 selector - string; the css selector to match 3245 3246 Examples: 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' 3250 3251 Notes: 3252 Supports these operators in attribute selectors: 3253 3254 - = : is equal to 3255 - ^= : starts-with 3256 - $= : ends-with 3257 - != : is not equal to 3258 3259 Xpath is used automatically for compliant browsers. 3260 */ 3261 3262 getElements: function(selector, nocash){ 3263 var items = []; 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); 3268 if (!param) break; 3269 param[1] = param[1] || '*'; 3270 var temp = $$.shared[$$.shared.method].getParam(items, this, param, i); 3271 if (!temp) break; 3272 items = temp; 3273 } 3274 return $$.shared[$$.shared.method].getItems(items, this, nocash); 3275 }, 3276 3277 /* 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>. 3281 3282 Arguments: 3283 selector - string; css selector 3284 */ 3285 3286 getElement: function(selector){ 3287 return $(this.getElements(selector, true)[0] || false); 3288 }, 3289 3290 /* 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>. 3294 3295 Arguments: 3296 selector - string; css selector 3297 */ 3298 3299 getElementsBySelector: function(selector, nocash){ 3300 var elements = []; 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); 3304 } 3305 3306}; 3307 3308Element.extend({ 3309 3310 /* 3311 Property: getElementById 3312 Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById. 3313 3314 Arguments: 3315 id - string; the id of the element to find. 3316 */ 3317 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; 3323 } 3324 return el; 3325 }/*compatibility*/, 3326 3327 getElementsByClassName: function(className){ 3328 return this.getElements('.' + className); 3329 } 3330 3331 /*end compatibility*/ 3332 3333}); 3334 3335document.extend(Element.Methods.Dom); 3336Element.extend(Element.Methods.Dom); 3337 3338/* 3339Script: Element.Form.js 3340 Contains Element prototypes to deal with Forms and their elements. 3341 3342License: 3343 MIT-style license. 3344*/ 3345 3346/* 3347Class: Element 3348 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3349*/ 3350 3351Element.extend({ 3352 3353 /* 3354 Property: getValue 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. 3356 */ 3357 3358 getValue: function(){ 3359 switch(this.getTag()){ 3360 case 'select': 3361 var values = []; 3362 $each(this.options, function(option){ 3363 if (option.selected) values.push($pick(option.value, option.text)); 3364 }); 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; 3368 } 3369 return false; 3370 }, 3371 3372 getFormElements: function(){ 3373 return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea')); 3374 }, 3375 3376 /* 3377 Property: toQueryString 3378 Reads the children inputs of the Element and generates a query string, based on their values. Used internally in <Ajax> 3379 3380 Example: 3381 (start code) 3382 <form id="myForm" action="submit.php"> 3383 <input name="email" value="[email protected]"> 3384 <input name="zipCode" value="90210"> 3385 </form> 3386 3387 <script> 3388 $('myForm').toQueryString() 3389 </script> 3390 (end) 3391 3392 Returns: 3393 [email protected]&zipCode=90210 3394 */ 3395 3396 toQueryString: function(){ 3397 var queryString = []; 3398 this.getFormElements().each(function(el){ 3399 var name = el.name; 3400 var value = el.getValue(); 3401 if (value === false || !name || el.disabled) return; 3402 var qs = function(val){ 3403 queryString.push(name + '=' + encodeURIComponent(val)); 3404 }; 3405 if ($type(value) == 'array') value.each(qs); 3406 else qs(value); 3407 }); 3408 return queryString.join('&'); 3409 } 3410 3411}); 3412 3413/* 3414Script: Element.Dimensions.js 3415 Contains Element prototypes to deal with Element size and position in space. 3416 3417Note: 3418 The functions in this script require n XHTML doctype. 3419 3420License: 3421 MIT-style license. 3422*/ 3423 3424/* 3425Class: Element 3426 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3427*/ 3428 3429Element.extend({ 3430 3431 /* 3432 Property: scrollTo 3433 Scrolls the element to the specified coordinated (if the element has an overflow) 3434 3435 Arguments: 3436 x - the x coordinate 3437 y - the y coordinate 3438 3439 Example: 3440 >$('myElement').scrollTo(0, 100) 3441 */ 3442 3443 scrollTo: function(x, y){ 3444 this.scrollLeft = x; 3445 this.scrollTop = y; 3446 }, 3447 3448 /* 3449 Property: getSize 3450 Return an Object representing the size/scroll values of the element. 3451 3452 Example: 3453 (start code) 3454 $('myElement').getSize(); 3455 (end) 3456 3457 Returns: 3458 (start code) 3459 { 3460 'scroll': {'x': 100, 'y': 100}, 3461 'size': {'x': 200, 'y': 400}, 3462 'scrollSize': {'x': 300, 'y': 500} 3463 } 3464 (end) 3465 */ 3466 3467 getSize: function(){ 3468 return { 3469 'scroll': {'x': this.scrollLeft, 'y': this.scrollTop}, 3470 'size': {'x': this.offsetWidth, 'y': this.offsetHeight}, 3471 'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight} 3472 }; 3473 }, 3474 3475 /* 3476 Property: getPosition 3477 Returns the real offsets of the element. 3478 3479 Arguments: 3480 overflown - optional, an array of nested scrolling containers for scroll offset calculation, use this if your element is inside any element containing scrollbars 3481 3482 Example: 3483 >$('element').getPosition(); 3484 3485 Returns: 3486 >{x: 100, y:500}; 3487 */ 3488 3489 getPosition: function(overflown){
3490 overflown = overflown || []; 3491 var el = this, left = 0, top = 0; 3492 do { 3493 left += el.offsetLeft || 0; 3494 top += el.offsetTop || 0; 3495 el = el.offsetParent; 3496 } while (el); 3497 overflown.each(function(element){ 3498 left -= element.scrollLeft || 0; 3499 top -= element.scrollTop || 0; 3500 }); 3501 return {'x': left, 'y': top}; 3502 }, 3503 3504 /* 3505 Property: getTop 3506 Returns the distance from the top of the window to the Element. 3507 3508 Arguments: 3509 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3510 */ 3511 3512 getTop: function(overflown){ 3513 return this.getPosition(overflown).y; 3514 }, 3515 3516 /* 3517 Property: getLeft 3518 Returns the distance from the left of the window to the Element. 3519 3520 Arguments: 3521 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3522 */ 3523 3524 getLeft: function(overflown){ 3525 return this.getPosition(overflown).x; 3526 }, 3527 3528 /* 3529 Property: getCoordinates 3530 Returns an object with width, height, left, right, top, and bottom, representing the values of the Element 3531 3532 Arguments: 3533 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3534 3535 Example: 3536 (start code) 3537 var myValues = $('myElement').getCoordinates(); 3538 (end) 3539 3540 Returns: 3541 (start code) 3542 { 3543 width: 200, 3544 height: 300, 3545 left: 100, 3546 top: 50, 3547 right: 300, 3548 bottom: 350 3549 } 3550 (end) 3551 */ 3552 3553 getCoordinates: function(overflown){ 3554 var position = this.getPosition(overflown); 3555 var obj = { 3556 'width': this.offsetWidth, 3557 'height': this.offsetHeight, 3558 'left': position.x, 3559 'top': position.y 3560 }; 3561 obj.right = obj.left + obj.width; 3562 obj.bottom = obj.top + obj.height; 3563 return obj; 3564 } 3565 3566}); 3567 3568/* 3569Script: Window.DomReady.js 3570 Contains the custom event domready, for window. 3571 3572License: 3573 MIT-style license. 3574*/ 3575 3576/* Section: Custom Events */ 3577 3578/* 3579Event: domready 3580 executes a function when the dom tree is loaded, without waiting for images. Only works when called from window. 3581 3582Credits: 3583 (c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools. 3584 3585Arguments: 3586 fn - the function to execute when the DOM is ready 3587 3588Example: 3589 > window.addEvent('domready', function(){ 3590 > alert('the dom is ready'); 3591 > }); 3592*/ 3593 3594Element.Events.domready = { 3595 3596 add: function(fn){ 3597 if (window.loaded){ 3598 fn.call(this); 3599 return; 3600 } 3601 var domReady = function(){ 3602 if (window.loaded) return; 3603 window.loaded = true; 3604 window.timer = $clear(window.timer); 3605 this.fireEvent('domready'); 3606 }.bind(this); 3607 if (document.readyState && window.webkit){ 3608 window.timer = function(){ 3609 if (['loaded','complete'].contains(document.readyState)) domReady(); 3610 }.periodical(50); 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(); 3617 }; 3618 } 3619 } else { 3620 window.addListener("load", domReady); 3621 document.addListener("DOMContentLoaded", domReady); 3622 } 3623 } 3624 3625}; 3626 3627/*compatibility*/ 3628 3629window.onDomReady = function(fn){ 3630 return this.addEvent('domready', fn); 3631}; 3632 3633/*end compatibility*/ 3634 3635/* 3636Script: Window.Size.js 3637 Window cross-browser dimensions methods. 3638 3639Note: 3640 The Functions in this script require an XHTML doctype. 3641 3642License: 3643 MIT-style license. 3644*/ 3645 3646/* 3647Class: window 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. 3650*/ 3651 3652window.extend({ 3653 3654 /* 3655 Property: getWidth 3656 Returns an integer representing the width of the browser window (without the scrollbar). 3657 */ 3658 3659 getWidth: function(){ 3660 if (this.webkit419) return this.innerWidth; 3661 if (this.opera) return document.body.clientWidth; 3662 return document.documentElement.clientWidth; 3663 }, 3664 3665 /* 3666 Property: getHeight 3667 Returns an integer representing the height of the browser window (without the scrollbar). 3668 */ 3669 3670 getHeight: function(){ 3671 if (this.webkit419) return this.innerHeight; 3672 if (this.opera) return document.body.clientHeight; 3673 return document.documentElement.clientHeight; 3674 }, 3675 3676 /* 3677 Property: getScrollWidth 3678 Returns an integer representing the scrollWidth of the window. 3679 This value is equal to or bigger than <getWidth>. 3680 3681 See Also: 3682 <http://developer.mozilla.org/en/docs/DOM:element.scrollWidth> 3683 */ 3684 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; 3689 }, 3690 3691 /* 3692 Property: getScrollHeight 3693 Returns an integer representing the scrollHeight of the window. 3694 This value is equal to or bigger than <getHeight>. 3695 3696 See Also: 3697 <http://developer.mozilla.org/en/docs/DOM:element.scrollHeight> 3698 */ 3699 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; 3704 }, 3705 3706 /* 3707 Property: getScrollLeft 3708 Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left). 3709 3710 See Also: 3711 <http://developer.mozilla.org/en/docs/DOM:element.scrollLeft> 3712 */ 3713 3714 getScrollLeft: function(){ 3715 return this.pageXOffset || document.documentElement.scrollLeft; 3716 }, 3717 3718 /* 3719 Property: getScrollTop 3720 Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top). 3721 3722 See Also: 3723 <http://developer.mozilla.org/en/docs/DOM:element.scrollTop> 3724 */ 3725 3726 getScrollTop: function(){ 3727 return this.pageYOffset || document.documentElement.scrollTop; 3728 }, 3729 3730 /* 3731 Property: getSize 3732 Same as <Element.getSize> 3733 */ 3734 3735 getSize: function(){ 3736 return { 3737 'size': {'x': this.getWidth(), 'y': this.getHeight()}, 3738 'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()}, 3739 'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()} 3740 }; 3741 }, 3742 3743 //ignore 3744 getPosition: function(){return {'x': 0, 'y': 0};} 3745 3746}); 3747 3748/* 3749Script: Fx.Base.js 3750 Contains <Fx.Base>, the foundamentals of the MooTools Effects. 3751 3752License: 3753 MIT-style license. 3754*/ 3755 3756var Fx = {}; 3757 3758/* 3759Class: Fx.Base 3760 Base class for the Effects. 3761 3762Options: 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 3768 3769Events: 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. 3773*/ 3774 3775Fx.Base = new Class({ 3776 3777 options: { 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; 3783 }, 3784 duration: 500, 3785 unit: 'px', 3786 wait: true, 3787 fps: 50 3788 }, 3789 3790 initialize: function(options){ 3791 this.element = this.element || null; 3792 this.setOptions(options); 3793 if (this.options.initialize) this.options.initialize.call(this); 3794 }, 3795 3796 step: function(){ 3797 var time = $time(); 3798 if (time < this.time + this.options.duration){ 3799 this.delta = this.options.transition((time - this.time) / this.options.duration); 3800 this.setNow(); 3801 this.increase(); 3802 } else { 3803 this.stop(true); 3804 this.set(this.to); 3805 this.fireEvent('onComplete', this.element, 10); 3806 this.callChain(); 3807 } 3808 }, 3809 3810 /* 3811 Property: set 3812 Immediately sets the value with no transition. 3813 3814 Arguments: 3815 to - the point to jump to 3816 3817 Example: 3818 >var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent 3819 */ 3820 3821 set: function(to){ 3822 this.now = to; 3823 this.increase(); 3824 return this; 3825 }, 3826 3827 setNow: function(){ 3828 this.now = this.compute(this.from, this.to); 3829 }, 3830 3831 compute: function(from, to){ 3832 return (to - from) * this.delta + from; 3833 }, 3834 3835 /* 3836 Property: start 3837 Executes an effect from one position to the other. 3838 3839 Arguments: 3840 from - integer: staring value 3841 to - integer: the ending value 3842 3843 Examples: 3844 >var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque. 3845 */ 3846 3847 start: function(from, to){ 3848 if (!this.options.wait) this.stop(); 3849 else if (this.timer) return this; 3850 this.from = from; 3851 this.to = to; 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); 3856 return this; 3857 }, 3858 3859 /* 3860 Property: stop 3861 Stops the transition. 3862 */ 3863
3864 stop: function(end){ 3865 if (!this.timer) return this; 3866 this.timer = $clear(this.timer); 3867 if (!end) this.fireEvent('onCancel', this.element); 3868 return this; 3869 }/*compatibility*/, 3870 3871 custom: function(from, to){ 3872 return this.start(from, to); 3873 }, 3874 3875 clearTimer: function(end){ 3876 return this.stop(end); 3877 } 3878 3879 /*end compatibility*/ 3880 3881}); 3882 3883Fx.Base.implement(new Chain, new Events, new Options); 3884 3885/* 3886Script: Fx.CSS.js 3887 Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally. 3888 3889License: 3890 MIT-style license. 3891*/ 3892 3893Fx.CSS = { 3894 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; 3899 return this.Single; 3900 }, 3901 3902 parse: function(el, property, fromTo){ 3903 if (!fromTo.push) fromTo = [fromTo]; 3904 var from = fromTo[0], to = fromTo[1]; 3905 if (!$chk(to)){ 3906 to = from; 3907 from = el.getStyle(property); 3908 } 3909 var css = this.select(property, to); 3910 return {'from': css.parse(from), 'to': css.parse(to), 'css': css}; 3911 } 3912 3913}; 3914 3915Fx.CSS.Single = { 3916 3917 parse: function(value){ 3918 return parseFloat(value); 3919 }, 3920 3921 getNow: function(from, to, fx){ 3922 return fx.compute(from, to); 3923 }, 3924 3925 getValue: function(value, unit, property){ 3926 if (unit == 'px' && property != 'opacity') value = Math.round(value); 3927 return value + unit; 3928 } 3929 3930}; 3931 3932Fx.CSS.Multi = { 3933 3934 parse: function(value){ 3935 return value.push ? value : value.split(' ').map(function(v){ 3936 return parseFloat(v); 3937 }); 3938 }, 3939 3940 getNow: function(from, to, fx){ 3941 var now = []; 3942 for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]); 3943 return now; 3944 }, 3945 3946 getValue: function(value, unit, property){ 3947 if (unit == 'px' && property != 'opacity') value = value.map(Math.round); 3948 return value.join(unit + ' ') + unit; 3949 } 3950 3951}; 3952 3953Fx.CSS.Color = { 3954 3955 parse: function(value){ 3956 return value.push ? value : value.hexToRgb(true); 3957 }, 3958 3959 getNow: function(from, to, fx){ 3960 var now = []; 3961 for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i])); 3962 return now; 3963 }, 3964 3965 getValue: function(value){ 3966 return 'rgb(' + value.join(',') + ')'; 3967 } 3968 3969}; 3970 3971/* 3972Script: Fx.Style.js 3973 Contains <Fx.Style> 3974 3975License: 3976 MIT-style license. 3977*/ 3978 3979/* 3980Class: Fx.Style 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>. 3984 3985Arguments: 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>) 3989 3990Example: 3991 >var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500}); 3992 >marginChange.start(10, 100); 3993*/ 3994 3995Fx.Style = Fx.Base.extend({ 3996 3997 initialize: function(el, property, options){ 3998 this.element = $(el); 3999 this.property = property; 4000 this.parent(options); 4001 }, 4002 4003 /* 4004 Property: hide 4005 Same as <Fx.Base.set> (0); hides the element immediately without transition. 4006 */ 4007 4008 hide: function(){ 4009 return this.set(0); 4010 }, 4011 4012 setNow: function(){ 4013 this.now = this.css.getNow(this.from, this.to, this); 4014 }, 4015 4016 /* 4017 Property: set 4018 Sets the element's css property (specified at instantiation) to the specified value immediately. 4019 4020 Example: 4021 (start code) 4022 var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500}); 4023 marginChange.set(10); //margin-top is set to 10px immediately 4024 (end) 4025 */ 4026 4027 set: function(to){ 4028 this.css = Fx.CSS.select(this.property, to); 4029 return this.parent(this.css.parse(to)); 4030 }, 4031 4032 /* 4033 Property: start 4034 Displays the transition to the value/values passed in 4035 4036 Arguments: 4037 from - (integer; optional) the starting position for the transition 4038 to - (integer) the ending position for the transition 4039 4040 Note: 4041 If you provide only one argument, the transition will use the current css value for its starting value. 4042 4043 Example: 4044 (start code) 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 4047 (end) 4048 */ 4049 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); 4055 }, 4056 4057 increase: function(){ 4058 this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property)); 4059 } 4060 4061}); 4062 4063/* 4064Class: Element 4065 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4066*/ 4067 4068Element.extend({ 4069 4070 /* 4071 Property: effect 4072 Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>. 4073 4074 Arguments: 4075 property - (string) the css property to alter 4076 options - (object; optional) key/value set of options (see <Fx.Style>) 4077 4078 Example: 4079 >var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}); 4080 >myEffect.start(10, 100); 4081 >//OR 4082 >$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100); 4083 */ 4084 4085 effect: function(property, options){ 4086 return new Fx.Style(this, property, options); 4087 } 4088 4089}); 4090 4091/* 4092Script: Fx.Styles.js 4093 Contains <Fx.Styles> 4094 4095License: 4096 MIT-style license. 4097*/ 4098 4099/* 4100Class: 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>. 4104 4105Arguments: 4106 el - the $(element) to apply the styles transition to 4107 options - the fx options (see: <Fx.Base>) 4108 4109Example: 4110 (start code) 4111 var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear}); 4112 4113 //height from 10 to 100 and width from 900 to 300 4114 myEffects.start({ 4115 'height': [10, 100], 4116 'width': [900, 300] 4117 }); 4118 4119 //or height from current height to 100 and width from current width to 300 4120 myEffects.start({ 4121 'height': 100, 4122 'width': 300 4123 }); 4124 (end) 4125*/ 4126 4127Fx.Styles = Fx.Base.extend({ 4128 4129 initialize: function(el, options){ 4130 this.element = $(el); 4131 this.parent(options); 4132 }, 4133 4134 setNow: function(){ 4135 for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this); 4136 }, 4137 4138 set: function(to){ 4139 var parsed = {}; 4140 this.css = {}; 4141 for (var p in to){ 4142 this.css[p] = Fx.CSS.select(p, to[p]); 4143 parsed[p] = this.css[p].parse(to[p]); 4144 } 4145 return this.parent(parsed); 4146 }, 4147 4148 /* 4149 Property: start 4150 Executes a transition for any number of css properties in tandem. 4151 4152 Arguments:
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). 4154 4155 Example: 4156 see <Fx.Styles> 4157 */ 4158 4159 start: function(obj){ 4160 if (this.timer && this.options.wait) return this; 4161 this.now = {}; 4162 this.css = {}; 4163 var from = {}, to = {}; 4164 for (var p in obj){ 4165 var parsed = Fx.CSS.parse(this.element, p, obj[p]); 4166 from[p] = parsed.from; 4167 to[p] = parsed.to; 4168 this.css[p] = parsed.css; 4169 } 4170 return this.parent(from, to); 4171 }, 4172 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)); 4175 } 4176 4177}); 4178 4179/* 4180Class: Element 4181 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4182*/ 4183 4184Element.extend({ 4185 4186 /* 4187 Property: effects 4188 Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>. 4189 4190 Example: 4191 >var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.Sine.easeInOut}); 4192 >myEffects.start({'height': [10, 100], 'width': [900, 300]}); 4193 */ 4194 4195 effects: function(options){ 4196 return new Fx.Styles(this, options); 4197 } 4198 4199}); 4200 4201/* 4202Script: Fx.Elements.js 4203 Contains <Fx.Elements> 4204 4205License: 4206 MIT-style license. 4207*/ 4208 4209/* 4210Class: 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>. 4213 4214Arguments: 4215 elements - a collection of elements the effects will be applied to. 4216 options - same as <Fx.Base> options. 4217*/ 4218 4219Fx.Elements = Fx.Base.extend({ 4220 4221 initialize: function(elements, options){ 4222 this.elements = $$(elements); 4223 this.parent(options); 4224 }, 4225 4226 setNow: function(){ 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); 4230 } 4231 }, 4232 4233 set: function(to){ 4234 var parsed = {}; 4235 this.css = {}; 4236 for (var i in to){ 4237 var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {}; 4238 for (var p in iTo){ 4239 iCss[p] = Fx.CSS.select(p, iTo[p]); 4240 iParsed[p] = iCss[p].parse(iTo[p]); 4241 } 4242 } 4243 return this.parent(parsed); 4244 }, 4245 4246 /* 4247 Property: start 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. 4249 4250 Example: 4251 (start code) 4252 var myElementsEffects = new Fx.Elements($$('a')); 4253 myElementsEffects.start({ 4254 '0': { //let's change the first element's opacity and width 4255 'opacity': [0,1], 4256 'width': [100,200] 4257 }, 4258 '4': { //and the fifth one's opacity 4259 'opacity': [0.2, 0.5] 4260 } 4261 }); 4262 (end) 4263 */ 4264 4265 start: function(obj){ 4266 if (this.timer && this.options.wait) return this; 4267 this.now = {}; 4268 this.css = {}; 4269 var from = {}, to = {}; 4270 for (var i in obj){ 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; 4275 iTo[p] = parsed.to; 4276 iCss[p] = parsed.css; 4277 } 4278 } 4279 return this.parent(from, to); 4280 }, 4281 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)); 4286 } 4287 } 4288 4289}); 4290 4291/* 4292Script: Fx.Scroll.js 4293 Contains <Fx.Scroll> 4294 4295License: 4296 MIT-style license. 4297*/ 4298 4299/* 4300Class: Fx.Scroll 4301 Scroll any element with an overflow, including the window element. 4302 Inherits methods, properties, options and events from <Fx.Base>. 4303 4304Note: 4305 Fx.Scroll requires an XHTML doctype. 4306 4307Arguments: 4308 element - the element to scroll 4309 options - optional, see Options below. 4310 4311Options: 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> 4315*/ 4316 4317Fx.Scroll = Fx.Base.extend({ 4318 4319 options: { 4320 overflown: [], 4321 offset: {'x': 0, 'y': 0}, 4322 wheelStops: true 4323 }, 4324 4325 initialize: function(element, options){ 4326 this.now = []; 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); 4333 }.bind(this)); 4334 this.addEvent('onComplete', function(){ 4335 document.removeEvent('mousewheel', this.bound.stop); 4336 }.bind(this)); 4337 } 4338 }, 4339 4340 setNow: function(){ 4341 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 4342 }, 4343 4344 /* 4345 Property: scrollTo 4346 Scrolls the chosen element to the x/y coordinates. 4347 4348 Arguments: 4349 x - the x coordinate to scroll the element to 4350 y - the y coordinate to scroll the element to 4351 */ 4352 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]; 4362 } 4363 return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]); 4364 }, 4365 4366 /* 4367 Property: toTop 4368 Scrolls the chosen element to its maximum top. 4369 */ 4370 4371 toTop: function(){ 4372 return this.scrollTo(false, 0); 4373 }, 4374 4375 /* 4376 Property: toBottom 4377 Scrolls the chosen element to its maximum bottom. 4378 */ 4379 4380 toBottom: function(){ 4381 return this.scrollTo(false, 'full'); 4382 }, 4383 4384 /* 4385 Property: toLeft 4386 Scrolls the chosen element to its maximum left. 4387 */ 4388 4389 toLeft: function(){ 4390 return this.scrollTo(0, false); 4391 }, 4392 4393 /* 4394 Property: toRight 4395 Scrolls the chosen element to its maximum right. 4396 */ 4397 4398 toRight: function(){ 4399 return this.scrollTo('full', false); 4400 }, 4401 4402 /* 4403 Property: toElement 4404 Scrolls the specified element to the position the passed in element is found. 4405 4406 Arguments: 4407 el - the $(element) to scroll the window to 4408 */ 4409 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); 4414 }, 4415 4416 increase: function(){ 4417 this.element.scrollTo(this.now[0], this.now[1]); 4418 } 4419 4420}); 4421 4422/* 4423Script: Fx.Slide.js 4424 Contains <Fx.Slide> 4425 4426License: 4427 MIT-style license. 4428*/ 4429 4430/* 4431Class: Fx.Slide 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>. 4434 4435Note: 4436 Fx.Slide requires an XHTML doctype. 4437 4438Options: 4439 mode - set it to vertical or horizontal. Defaults to vertical. 4440 options - all the <Fx.Base> options 4441 4442Example: 4443 (start code) 4444 var mySlider = new Fx.Slide('myElement', {duration: 500});
4445 mySlider.toggle() //toggle the slider up and down. 4446 (end) 4447*/ 4448 4449Fx.Slide = Fx.Base.extend({ 4450 4451 options: { 4452 mode: 'vertical' 4453 }, 4454 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); 4460 this.now = []; 4461 this.parent(this.options); 4462 this.open = true; 4463 this.addEvent('onComplete', function(){ 4464 this.open = (this.now[0] === 0); 4465 }); 4466 if (window.webkit419) this.addEvent('onComplete', function(){ 4467 if (this.open) this.element.remove().inject(this.wrapper); 4468 }); 4469 }, 4470 4471 setNow: function(){ 4472 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 4473 }, 4474 4475 vertical: function(){ 4476 this.margin = 'margin-top'; 4477 this.layout = 'height'; 4478 this.offset = this.element.offsetHeight; 4479 }, 4480 4481 horizontal: function(){ 4482 this.margin = 'margin-left'; 4483 this.layout = 'width'; 4484 this.offset = this.element.offsetWidth; 4485 }, 4486 4487 /* 4488 Property: slideIn 4489 Slides the elements in view horizontally or vertically. 4490 4491 Arguments: 4492 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4493 */ 4494 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]); 4498 }, 4499 4500 /* 4501 Property: slideOut 4502 Sides the elements out of view horizontally or vertically. 4503 4504 Arguments: 4505 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4506 */ 4507 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]); 4511 }, 4512 4513 /* 4514 Property: hide 4515 Hides the element without a transition. 4516 4517 Arguments: 4518 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4519 */ 4520 4521 hide: function(mode){ 4522 this[mode || this.options.mode](); 4523 this.open = false; 4524 return this.set([-this.offset, 0]); 4525 }, 4526 4527 /* 4528 Property: show 4529 Shows the element without a transition. 4530 4531 Arguments: 4532 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4533 */ 4534 4535 show: function(mode){ 4536 this[mode || this.options.mode](); 4537 this.open = true; 4538 return this.set([0, this.offset]); 4539 }, 4540 4541 /* 4542 Property: toggle 4543 Slides in or Out the element, depending on its state 4544 4545 Arguments: 4546 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4547 4548 */ 4549 4550 toggle: function(mode){ 4551 if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode); 4552 return this.slideOut(mode); 4553 }, 4554 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); 4558 } 4559 4560}); 4561 4562/* 4563Script: Fx.Transitions.js 4564 Effects transitions, to be used with all the effects. 4565 4566License: 4567 MIT-style license. 4568 4569Credits: 4570 Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified & optimized to be used with mootools. 4571*/ 4572 4573/* 4574Class: Fx.Transitions 4575 A collection of tweening transitions for use with the <Fx.Base> classes. 4576 4577Example: 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}); 4583 4584See also: 4585 http://www.robertpenner.com/easing/ 4586*/ 4587 4588Fx.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); 4594 }, 4595 easeOut: function(pos){ 4596 return 1 - transition(1 - pos, params); 4597 }, 4598 easeInOut: function(pos){ 4599 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2; 4600 } 4601 }); 4602}; 4603 4604Fx.Transitions = new Abstract({ 4605 4606 /* 4607 Property: linear 4608 displays a linear transition. 4609 4610 Graph: 4611 (see Linear.png) 4612 */ 4613 4614 linear: function(p){ 4615 return p; 4616 } 4617 4618}); 4619 4620Fx.Transitions.extend = function(transitions){ 4621 for (var transition in transitions){ 4622 Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 4623 /*compatibility*/ 4624 Fx.Transitions.compat(transition); 4625 /*end compatibility*/ 4626 } 4627}; 4628 4629/*compatibility*/ 4630 4631Fx.Transitions.compat = function(transition){ 4632 ['In', 'Out', 'InOut'].each(function(easeType){ 4633 Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType]; 4634 }); 4635}; 4636 4637/*end compatibility*/ 4638 4639Fx.Transitions.extend({ 4640 4641 /* 4642 Property: Quad 4643 displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut 4644 4645 Graph: 4646 (see Quad.png) 4647 */ 4648 4649 //auto generated 4650 4651 /* 4652 Property: Cubic 4653 displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut 4654 4655 Graph: 4656 (see Cubic.png) 4657 */ 4658 4659 //auto generated 4660 4661 /* 4662 Property: Quart 4663 displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut 4664 4665 Graph: 4666 (see Quart.png) 4667 */ 4668 4669 //auto generated 4670 4671 /* 4672 Property: Quint 4673 displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut 4674 4675 Graph: 4676 (see Quint.png) 4677 */ 4678 4679 //auto generated 4680 4681 /* 4682 Property: Pow
4683 Used to generate Quad, Cubic, Quart and Quint. 4684 By default is p^6. 4685 4686 Graph: 4687 (see Pow.png) 4688 */ 4689 4690 Pow: function(p, x){ 4691 return Math.pow(p, x[0] || 6); 4692 }, 4693 4694 /* 4695 Property: Expo 4696 displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut 4697 4698 Graph: 4699 (see Expo.png) 4700 */ 4701 4702 Expo: function(p){ 4703 return Math.pow(2, 8 * (p - 1)); 4704 }, 4705 4706 /* 4707 Property: Circ 4708 displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut 4709 4710 Graph: 4711 (see Circ.png) 4712 */ 4713 4714 Circ: function(p){ 4715 return 1 - Math.sin(Math.acos(p)); 4716 }, 4717 4718 4719 /* 4720 Property: Sine 4721 displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut 4722 4723 Graph: 4724 (see Sine.png) 4725 */ 4726 4727 Sine: function(p){ 4728 return 1 - Math.sin((1 - p) * Math.PI / 2); 4729 }, 4730 4731 /* 4732 Property: Back 4733 makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut 4734 4735 Graph: 4736 (see Back.png) 4737 */ 4738 4739 Back: function(p, x){ 4740 x = x[0] || 1.618; 4741 return Math.pow(p, 2) * ((x + 1) * p - x); 4742 }, 4743 4744 /* 4745 Property: Bounce 4746 makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut 4747 4748 Graph: 4749 (see Bounce.png) 4750 */ 4751 4752 Bounce: function(p){ 4753 var value; 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; 4757 break; 4758 } 4759 } 4760 return value; 4761 }, 4762 4763 /* 4764 Property: Elastic 4765 Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut 4766 4767 Graph: 4768 (see Elastic.png) 4769 */ 4770 4771 Elastic: function(p, x){ 4772 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3); 4773 } 4774 4775}); 4776 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]); 4780 }); 4781 4782 /*compatibility*/ 4783 Fx.Transitions.compat(transition); 4784 /*end compatibility*/ 4785}); 4786 4787/* 4788Script: Drag.Base.js 4789 Contains <Drag.Base>, <Element.makeResizable> 4790 4791License: 4792 MIT-style license. 4793*/ 4794 4795var Drag = {}; 4796 4797/* 4798Class: Drag.Base 4799 Modify two css properties of an element based on the position of the mouse. 4800 4801Note: 4802 Drag.Base requires an XHTML doctype. 4803 4804Arguments: 4805 el - the $(element) to apply the transformations to. 4806 options - optional. The options object. 4807 4808Options: 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 4814 4815 modifiers: 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' 4818 4819 limit: 4820 x - array with start and end limit relative to modifiers.x 4821 y - array with start and end limit relative to modifiers.y 4822 4823Events: 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 4827*/ 4828 4829Drag.Base = new Class({ 4830 4831 options: { 4832 handle: false, 4833 unit: 'px', 4834 onStart: Class.empty, 4835 onBeforeStart: Class.empty, 4836 onComplete: Class.empty, 4837 onSnap: Class.empty, 4838 onDrag: Class.empty, 4839 limit: false, 4840 modifiers: {x: 'left', y: 'top'}, 4841 grid: false, 4842 snap: 6 4843 }, 4844 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': {}}; 4851 this.bound = { 4852 'start': this.start.bindWithEvent(this), 4853 'check': this.check.bindWithEvent(this), 4854 'drag': this.drag.bindWithEvent(this), 4855 'stop': this.stop.bind(this) 4856 }; 4857 this.attach(); 4858 if (this.options.initialize) this.options.initialize.call(this); 4859 }, 4860 4861 attach: function(){ 4862 this.handle.addEvent('mousedown', this.bound.start); 4863 return this; 4864 }, 4865 4866 detach: function(){ 4867 this.handle.removeEvent('mousedown', this.bound.start); 4868 return this; 4869 }, 4870 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]; 4883 } 4884 } 4885 } 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); 4890 event.stop(); 4891 }, 4892 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); 4898 this.drag(event); 4899 this.fireEvent('onSnap', this.element); 4900 } 4901 event.stop(); 4902 }, 4903 4904 drag: function(event){ 4905 this.out = false;
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]; 4910 if (this.limit[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]; 4913 this.out = true; 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]; 4916 this.out = true; 4917 } 4918 } 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); 4921 } 4922 this.fireEvent('onDrag', this.element); 4923 event.stop(); 4924 }, 4925 4926 stop: function(){ 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); 4931 } 4932 4933}); 4934 4935Drag.Base.implement(new Events, new Options); 4936 4937/* 4938Class: Element 4939 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4940*/ 4941 4942Element.extend({ 4943 4944 /* 4945 Property: makeResizable 4946 Makes an element resizable (by dragging) with the supplied options. 4947 4948 Arguments: 4949 options - see <Drag.Base> for acceptable options. 4950 */ 4951 4952 makeResizable: function(options){ 4953 return new Drag.Base(this, $merge({modifiers: {x: 'width', y: 'height'}}, options)); 4954 } 4955 4956}); 4957 4958/* 4959Script: Drag.Move.js 4960 Contains <Drag.Move>, <Element.makeDraggable> 4961 4962License: 4963 MIT-style license. 4964*/ 4965 4966/* 4967Class: Drag.Move 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>. 4971 4972Note: 4973 Drag.Move requires an XHTML doctype. 4974 4975Arguments: 4976 el - the $(element) to apply the drag to. 4977 options - optional. see Options below. 4978 4979Options: 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 4984*/ 4985 4986Drag.Move = Drag.Base.extend({ 4987 4988 options: { 4989 droppables: [], 4990 container: false, 4991 overflown: [] 4992 }, 4993 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); 5007 } else { 5008 top = $chk(top) ? top : 0; 5009 left = $chk(left) ? left : 0; 5010 } 5011 this.element.setStyles({'top': top, 'left': left, 'position': this.position.element}); 5012 this.parent(this.element); 5013 }, 5014 5015 start: function(event){ 5016 this.overed = null; 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] 5024 }; 5025 } else { 5026 this.options.limit = { 5027 'y': [0, cont.height - el.height], 5028 'x': [0, cont.width - el.width] 5029 }; 5030 } 5031 } 5032 this.parent(event); 5033 }, 5034 5035 drag: function(event){ 5036 this.parent(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; 5041 } 5042 return this; 5043 }, 5044 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); 5049 }, 5050 5051 stop: function(){ 5052 if (this.overed && !this.out) this.overed.fireEvent('drop', [this.element, this]); 5053 else this.element.fireEvent('emptydrop', this); 5054 this.parent(); 5055 return this; 5056 } 5057 5058}); 5059 5060/* 5061Class: Element 5062 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 5063*/ 5064 5065Element.extend({ 5066 5067 /* 5068 Property: makeDraggable 5069 Makes an element draggable with the supplied options. 5070 5071 Arguments: 5072 options - see <Drag.Move> and <Drag.Base> for acceptable options. 5073 */ 5074 5075 makeDraggable: function(options){ 5076 return new Drag.Move(this, options); 5077 } 5078 5079}); 5080 5081/* 5082Script: XHR.js 5083 Contains the basic XMLHttpRequest Class Wrapper. 5084 5085License: 5086 MIT-style license. 5087*/ 5088 5089/* 5090Class: XHR 5091 Basic XMLHttpRequest Wrapper. 5092 5093Arguments: 5094 options - an object with options names as keys. See options below. 5095 5096Options: 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. 5102 5103Events: 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. 5108 5109Properties: 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. 5112 5113Example: 5114 >var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian'); 5115*/ 5116 5117var XHR = new Class({ 5118 5119 options: { 5120 method: 'post', 5121 async: true, 5122 onRequest: Class.empty, 5123 onSuccess: Class.empty, 5124 onFailure: Class.empty, 5125 urlEncoded: true, 5126 encoding: 'utf-8', 5127 autoCancel: false, 5128 headers: {} 5129 }, 5130 5131 setTransport: function(){ 5132 this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false); 5133 return this; 5134 }, 5135 5136 initialize: function(options){ 5137 this.setTransport().setOptions(options); 5138 this.options.isSuccess = this.options.isSuccess || this.isSuccess; 5139 this.headers = {}; 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); 5143 } 5144 if (this.options.initialize) this.options.initialize.call(this); 5145 }, 5146 5147 onStateChange: function(){ 5148 if (this.transport.readyState != 4 || !this.running) return; 5149 this.running = false;
5150 var status = 0; 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; 5155 }, 5156 5157 isSuccess: function(status){ 5158 return ((status >= 200) && (status < 300)); 5159 }, 5160 5161 onSuccess: function(){ 5162 this.response = { 5163 'text': this.transport.responseText, 5164 'xml': this.transport.responseXML 5165 }; 5166 this.fireEvent('onSuccess', [this.response.text, this.response.xml]); 5167 this.callChain(); 5168 }, 5169 5170 onFailure: function(){ 5171 this.fireEvent('onFailure', this.transport); 5172 }, 5173 5174 /* 5175 Property: setHeader 5176 Add/modify an header for the request. It will not override headers from the options. 5177 5178 Example: 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'); 5181 */ 5182 5183 setHeader: function(name, value){ 5184 this.headers[name] = value; 5185 return this; 5186 }, 5187 5188 /* 5189 Property: send 5190 Opens the XHR connection and sends the data. Data has to be null or a string. 5191 5192 Example: 5193 >var myXhr = new XHR({method: 'post'}); 5194 >myXhr.send(url, querystring); 5195 > 5196 >var syncXhr = new XHR({async: false, method: 'post'}); 5197 >syncXhr.send(url, null); 5198 > 5199 */ 5200 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; 5207 data = null; 5208 } 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)); 5216 return this; 5217 }, 5218 5219 /* 5220 Property: cancel 5221 Cancels the running request. No effect if the request is not running. 5222 5223 Example: 5224 >var myXhr = new XHR({method: 'get'}).send(url); 5225 >myXhr.cancel(); 5226 */ 5227 5228 cancel: function(){ 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'); 5235 return this; 5236 } 5237 5238}); 5239 5240XHR.implement(new Chain, new Events, new Options); 5241 5242/* 5243Script: Ajax.js 5244 Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects. 5245 5246Credits: 5247 Loosely based on the version from prototype.js <http://prototype.conio.net> 5248 5249License: 5250 MIT-style license. 5251*/ 5252 5253/* 5254Class: Ajax 5255 An Ajax class, For all your asynchronous needs. 5256 Inherits methods, properties, options and events from <XHR>. 5257 5258Arguments: 5259 url - the url pointing to the server-side script. 5260 options - optional, an object containing options. 5261 5262Options: 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. 5267 5268Events: 5269 onComplete - function to execute when the ajax request completes. 5270 5271Example: 5272 >var myAjax = new Ajax(url, {method: 'get'}).request(); 5273*/ 5274 5275var Ajax = XHR.extend({ 5276 5277 options: { 5278 data: null, 5279 update: null, 5280 onComplete: Class.empty, 5281 evalScripts: false, 5282 evalResponse: false 5283 }, 5284 5285 initialize: function(url, options){ 5286 this.addEvent('onSuccess', this.onComplete); 5287 this.setOptions(options); 5288 /*compatibility*/ 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'; 5294 } 5295 this.parent(); 5296 this.setHeader('X-Requested-With', 'XMLHttpRequest'); 5297 this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*'); 5298 this.url = url; 5299 }, 5300 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); 5305 }, 5306 5307 /* 5308 Property: request
5309 Executes the ajax request. 5310 5311 Example: 5312 >var myAjax = new Ajax(url, {method: 'get'}); 5313 >myAjax.request(); 5314 5315 OR 5316 5317 >new Ajax(url, {method: 'get'}).request(); 5318 */ 5319 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); 5325 } 5326 if (this._method) data = (data) ? [this._method, data].join('&') : this._method; 5327 return this.send(this.url, data); 5328 }, 5329 5330 /* 5331 Property: evalScripts 5332 Executes scripts in the response text 5333 */ 5334 5335 evalScripts: function(){ 5336 var script, scripts; 5337 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) scripts = this.response.text; 5338 else { 5339 scripts = []; 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'); 5343 } 5344 if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0); 5345 }, 5346 5347 /* 5348 Property: getHeader 5349 Returns the given response header or null 5350 */ 5351 5352 getHeader: function(name){ 5353 try {return this.transport.getResponseHeader(name);} catch(e){}; 5354 return null; 5355 } 5356 5357}); 5358 5359/* Section: Object related Functions */ 5360 5361/* 5362Function: Object.toQueryString 5363 Generates a querystring from key/pair values in an object 5364 5365Arguments: 5366 source - the object to generate the querystring from. 5367 5368Returns: 5369 the query string. 5370 5371Example: 5372 >Object.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow" 5373*/ 5374 5375Object.toQueryString = function(source){ 5376 var queryString = []; 5377 for (var property in source) queryString.push(encodeURIComponent(property) + '=' + encodeURIComponent(source[property])); 5378 return queryString.join('&'); 5379}; 5380 5381/* 5382Class: Element 5383 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 5384*/ 5385 5386Element.extend({ 5387 5388 /* 5389 Property: send 5390 Sends a form with an ajax post request 5391 5392 Arguments: 5393 options - option collection for ajax request. See <Ajax> for the options list. 5394 5395 Returns: 5396 The Ajax Class Instance 5397 5398 Example: 5399 (start code) 5400 <form id="myForm" action="submit.php"> 5401 <input name="email" value="[email protected]"> 5402 <input name="zipCode" value="90210"> 5403 </form> 5404 <script> 5405 $('myForm').send() 5406 </script> 5407 (end) 5408 */ 5409 5410 send: function(options){ 5411 return new Ajax(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request(); 5412 } 5413 5414}); 5415 5416/* 5417Script: Cookie.js 5418 A cookie reader/creator 5419 5420Credits: 5421 based on the functions by Peter-Paul Koch (http://quirksmode.org) 5422*/ 5423 5424/* 5425Class: Cookie 5426 Class for creating, getting, and removing cookies. 5427*/ 5428 5429var Cookie = new Abstract({ 5430 5431 options: { 5432 domain: false, 5433 path: false, 5434 duration: false, 5435 secure: false 5436 }, 5437 5438 /* 5439 Property: set 5440 Sets a cookie in the browser. 5441 5442 Arguments: 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. 5446 5447 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. 5453 5454 Returns: 5455 An object with the options, the key and the value. You can give it as first parameter to Cookie.remove. 5456 5457 Example: 5458 >Cookie.set('username', 'Harald'); // session cookie (duration is false), or ... 5459 >Cookie.set('username', 'JackBauer', {duration: 1}); // save this for 1 day 5460 5461 */ 5462 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(); 5472 } 5473 if (options.secure) value += '; secure'; 5474 document.cookie = key + '=' + value; 5475 return $extend(options, {'key': key, 'value': value}); 5476 }, 5477 5478 /* 5479 Property: get 5480 Gets the value of a cookie. 5481 5482 Arguments: 5483 key - the name of the cookie you wish to retrieve. 5484 5485 Returns: 5486 The cookie string value, or false if not found. 5487
5488 Example: 5489 >Cookie.get("username") //returns JackBauer 5490 */ 5491 5492 get: function(key){ 5493 var value = document.cookie.match('(?:^|;)\\s*' + key.escapeRegExp() + '=([^;]*)'); 5494 return value ? decodeURIComponent(value[1]) : false; 5495 }, 5496 5497 /* 5498 Property: remove 5499 Removes a cookie from the browser. 5500 5501 Arguments: 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> 5504 5505 Examples: 5506 >Cookie.remove('username') //bye-bye JackBauer, cya in 24 hours 5507 > 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); 5510 */ 5511 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})); 5515 } 5516 5517}); 5518 5519/* 5520Script: Json.js 5521 Simple Json parser and Stringyfier, See: <http://www.json.org/> 5522 5523License: 5524 MIT-style license. 5525*/ 5526 5527/* 5528Class: Json 5529 Simple Json parser and Stringyfier, See: <http://www.json.org/> 5530*/ 5531 5532var Json = { 5533 5534 /* 5535 Property: toString 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. 5537 5538 Arguments: 5539 obj - the object to convert to string 5540 5541 Returns: 5542 A json string 5543 5544 Example: 5545 (start code) 5546 Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}' 5547 (end) 5548 */ 5549 5550 toString: function(obj){ 5551 switch($type(obj)){ 5552 case 'string': 5553 return '"' + obj.replace(/(["\\])/g, '\\$1') + '"'; 5554 case 'array': 5555 return '[' + obj.map(Json.toString).join(',') + ']'; 5556 case 'object': 5557 var string = []; 5558 for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property])); 5559 return '{' + string.join(',') + '}'; 5560 case 'number': 5561 if (isFinite(obj)) break; 5562 case false: 5563 return 'null'; 5564 } 5565 return String(obj); 5566 }, 5567 5568 /* 5569 Property: evaluate 5570 converts a json string to an javascript Object. 5571 5572 Arguments: 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. 5575 5576 Credits: 5577 Json test regexp is by Douglas Crockford <http://crockford.org>. 5578 5579 Example: 5580 >var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}'); 5581 >//myObject will become {apple: 'red', lemon: 'yellow'} 5582 */ 5583 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 + ')'); 5586 } 5587 5588}; 5589 5590/* 5591Script: Json.Remote.js 5592 Contains <Json.Remote>. 5593 5594License: 5595 MIT-style license. 5596*/ 5597 5598/* 5599Class: 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>. 5602 5603Arguments: 5604 url - the url you want to send your object to. 5605 options - see <XHR> options 5606 5607Example: 5608 this code will send user information based on name/last name 5609 (start code) 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'}); 5615 (end) 5616*/ 5617 5618Json.Remote = XHR.extend({ 5619 5620 initialize: function(url, options){ 5621 this.url = url; 5622 this.addEvent('onSuccess', this.onComplete); 5623 this.parent(options); 5624 this.setHeader('X-Request', 'JSON'); 5625 }, 5626 5627 send: function(obj){ 5628 return this.parent(this.url, 'json=' + Json.toString(obj)); 5629 }, 5630 5631 onComplete: function(){ 5632 this.fireEvent('onComplete', [Json.evaluate(this.response.text, this.options.secure)]); 5633 } 5634 5635}); 5636 5637/* 5638Script: Assets.js 5639 provides dynamic loading for images, css and javascript files. 5640 5641License: 5642 MIT-style license. 5643*/ 5644 5645var Asset = new Abstract({ 5646 5647 /* 5648 Property: javascript 5649 Injects a javascript file in the page. 5650 5651 Arguments: 5652 source - the path of the javascript file 5653 properties - some additional attributes you might want to add to the script element 5654 5655 Example: 5656 >
5656 new Asset.javascript('/scripts/myScript.js', {id: 'myScript'}); 5657 */ 5658 5659 javascript: function(source, properties){ 5660 properties = $merge({ 5661 'onload': Class.empty 5662 }, properties); 5663 var script = new Element('script', {'src': source}).addEvents({ 5664 'load': properties.onload, 5665 'readystatechange': function(){ 5666 if (this.readyState == 'complete') this.fireEvent('load'); 5667 } 5668 }); 5669 delete properties.onload; 5670 return script.setProperties(properties).inject(document.head); 5671 }, 5672 5673 /* 5674 Property: css 5675 Injects a css file in the page. 5676 5677 Arguments: 5678 source - the path of the css file 5679 properties - some additional attributes you might want to add to the link element 5680 5681 Example: 5682 > new Asset.css('/css/myStyle.css', {id: 'myStyle', title: 'myStyle'}); 5683 */ 5684 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); 5689 }, 5690 5691 /* 5692 Property: image 5693 Preloads an image and returns the img element. does not inject it to the page. 5694 5695 Arguments: 5696 source - the path of the image file 5697 properties - some additional attributes you might want to add to the img element 5698 5699 Example: 5700 > new Asset.image('/images/myImage.png', {id: 'myImage', title: 'myImage', onload: myFunction}); 5701 5702 Returns: 5703 the img element. you can inject it anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore> 5704 */ 5705 5706 image: function(source, properties){ 5707 properties = $merge({ 5708 'onload': Class.empty, 5709 'onabort': Class.empty, 5710 'onerror': Class.empty 5711 }, properties); 5712 var image = new Image(); 5713 image.src = source; 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); 5720 event.call(this); 5721 }); 5722 }); 5723 if (image.width && image.height) element.fireEvent('load', element, 1); 5724 return element.setProperties(properties); 5725 }, 5726 5727 /* 5728 Property: images 5729 Preloads an array of images (as strings) and returns an array of img elements. does not inject them to the page. 5730 5731 Arguments: 5732 sources - array, the paths of the image files 5733 options - object, see below 5734 5735 Options: 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 5738 5739 Example: 5740 (start code) 5741 new Asset.images(['/images/myImage.png', '/images/myImage2.gif'], { 5742 onComplete: function(){ 5743 alert('all images loaded!'); 5744 } 5745 }); 5746 (end) 5747 5748 Returns: 5749 the img elements as $$. you can inject them anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore> 5750 */ 5751 5752 images: function(sources, options){ 5753 options = $merge({ 5754 onComplete: Class.empty, 5755 onProgress: Class.empty 5756 }, options); 5757 if (!sources.push) sources = [sources]; 5758 var images = []; 5759 var counter = 0; 5760 sources.each(function(source){ 5761 var img = new Asset.image(source, { 5762 'onload': function(){ 5763 options.onProgress.call(this, counter); 5764 counter++; 5765 if (counter == sources.length) options.onComplete(); 5766 } 5767 }); 5768 images.push(img); 5769 }); 5770 return new Elements(images); 5771 } 5772 5773}); 5774 5775/* 5776Script: Scroller.js 5777 Contains the <Scroller>. 5778 5779License: 5780 MIT-style license. 5781*/ 5782 5783/* 5784Class: Scroller 5785 The Scroller is a class to scroll any element with an overflow (including the window) when the mouse
5785cursor reaches certain buondaries of that element. 5786 You must call its start method to start listening to mouse movements. 5787 5788Note: 5789 The Scroller requires an XHTML doctype. 5790 5791Arguments: 5792 element - required, the element to scroll. 5793 options - optional, see options below, and <Fx.Base> options. 5794 5795Options: 5796 area - integer, the necessary boundaries to make the element scroll. 5797 velocity - integer, velocity ratio, the modifier for the window scrolling speed. 5798 5799Events: 5800 onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets. 5801 Automatically passes as parameters x and y values. 5802*/ 5803 5804var Scroller = new Class({ 5805 5806 options: { 5807 area: 20, 5808 velocity: 1, 5809 onChange: function(x, y){ 5810 this.element.scrollTo(x, y); 5811 } 5812 }, 5813 5814 initialize: function(element, options){ 5815 this.setOptions(options); 5816 this.element = $(element); 5817 this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element; 5818 }, 5819 5820 /* 5821 Property: start 5822 The scroller starts listening to mouse movements. 5823 */ 5824 5825 start: function(){ 5826 this.coord = this.getCoords.bindWithEvent(this); 5827 this.mousemover.addListener('mousemove', this.coord); 5828 }, 5829 5830 /* 5831 Property: stop 5832 The scroller stops listening to mouse movements. 5833 */ 5834 5835 stop: function(){ 5836 this.mousemover.removeListener('mousemove', this.coord); 5837 this.timer = $clear(this.timer); 5838 }, 5839 5840 getCoords: function(event){ 5841 this.page = (this.element == window) ? event.client : event.page; 5842 if (!this.timer) this.timer = this.scroll.periodical(50, this); 5843 }, 5844 5845 scroll: function(){ 5846 var el = this.element.getSize(); 5847 var pos = this.element.getPosition(); 5848 5849 var change = {'x': 0, 'y': 0}; 5850 for (var z in this.page){ 5851 if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0) 5852 change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity; 5853 else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z]) 5854 change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity; 5855 } 5856 if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]); 5857 } 5858 5859}); 5860 5861Scroller.implement(new Events, new Options); 5862 5863/* 5864Script: Slider.js 5865 Contains <Slider> 5866 5867License: 5868 MIT-style license. 5869*/ 5870 5871/* 5872Class: Slider 5873 Creates a slider with two elements: a knob and a container. Returns the values. 5874 5875Note: 5876 The Slider requires an XHTML doctype. 5877 5878Arguments: 5879 element - the knob container 5880 knob - the handle 5881 options - see Options below 5882 5883Options: 5884 steps - the number of steps for your slider. 5885 mode - either 'horizontal' or 'vertical'. defaults to horizontal. 5886 offset - relative offset for knob position. default to 0. 5887 5888Events: 5889 onChange - a function to fire when the value changes. 5890 onComplete - a function to fire when you're done dragging. 5891 onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position. 5892 Passes as parameter the new position. 5893*/ 5894 5895var Slider = new Class({ 5896 5897 options: { 5898 onChange: Class.empty, 5899 onComplete: Class.empty, 5900 onTick: function(pos){ 5901 this.knob.setStyle(this.p, pos); 5902 }, 5903 mode: 'horizontal', 5904 steps: 100, 5905 offset: 0 5906 }, 5907 5908 initialize: function(el, knob, options){ 5909 this.element = $(el); 5910 this.knob = $(knob); 5911 this.setOptions(options); 5912 this.previousChange = -1; 5913 this.previousEnd = -1; 5914 this.step = -1; 5915 this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this)); 5916 var mod, offset; 5917 switch(this.options.mode){ 5918 case 'horizontal': 5919 this.z = 'x'; 5920 this.p = 'left'; 5921 mod = {'x': 'left', 'y': false}; 5922 offset = 'offsetWidth'; 5923 break; 5924 case 'vertical': 5925 this.z = 'y'; 5926 this.p = 'top'; 5927 mod = {'x': false, 'y': 'top'}; 5928 offset = 'offsetHeight'; 5929 } 5930 this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2); 5931 this.half = this.knob[offset]/2; 5932 this.getPos = this.element['get' + this.p.capitalize()].bind(this.element); 5933 this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset); 5934 var lim = {}; 5935 lim[this.z] = [- this.options.offset, this.max - this.options.offset]; 5936 this.drag = new Drag.Base(this.knob, { 5937 limit: lim, 5938 modifiers: mod, 5939 snap: 0, 5940 onStart: function(){ 5941 this.draggedKnob(); 5942 }.bind(this), 5943 onDrag: function(){ 5944 this.draggedKnob(); 5945 }.bind(this), 5946 onComplete: function(){ 5947 this.draggedKnob(); 5948 this.end(); 5949 }.bind(this) 5950 }); 5951 if (this.options.initialize) this.options.initialize.call(this); 5952 }, 5953 5954 /* 5955 Property: set 5956 The slider will get the step you pass. 5957 5958 Arguments: 5959 step - one integer 5960 */ 5961 5962 set: function(step){ 5963 this.step = step.limit(0, this.options.steps); 5964 this.checkStep(); 5965 this.end(); 5966 this.fireEvent('onTick', this.toPosition(this.step)); 5967 return this; 5968 }, 5969 5970 clickedElement: function(event){ 5971 var position = event.page[this.z] - this.getPos() - this.half; 5972 position = position.limit(-this.options.offset, this.max -this.options.offset); 5973 this.step = this.toStep(position); 5974 this.checkStep(); 5975 this.end(); 5976 this.fireEvent('onTick', position); 5977 }, 5978 5979 draggedKnob: function(){ 5980 this.step = this.toStep(this.drag.value.now[this.z]); 5981 this.checkStep(); 5982 }, 5983 5984 checkStep: function(){ 5985 if (this.previousChange != this.step){ 5986 this.previousChange = this.step; 5987 this.fireEvent('onChange', this.step); 5988 } 5989 }, 5990 5991 end: function(){ 5992 if (this.previousEnd !== this.step){ 5993 this.previousEnd = this.step; 5994 this.fireEvent('onComplete', this.step + ''); 5995 } 5996 }, 5997 5998 toStep: function(position){ 5999 return Math.round((position + this.options.offset) / this.max * this.options.steps); 6000 }, 6001 6002 toPosition: function(step){ 6003 return this.max * step / this.options.steps; 6004 } 6005 6006}); 6007 6008Slider.implement(new Events); 6009Slider.implement(new Options); 6010 6011/* 6012Script: SmoothScroll.js 6013 Contains <SmoothScroll> 6014 6015License: 6016 MIT-style license. 6017*/ 6018 6019/* 6020Class: SmoothScroll
6021 Auto targets all the anchors in a page and display a smooth scrolling effect upon clicking them. 6022 Inherits methods, properties, options and events from <Fx.Scroll>. 6023 6024Note: 6025 SmoothScroll requires an XHTML doctype. 6026 6027Arguments: 6028 options - the Fx.Scroll options (see: <Fx.Scroll>) plus links, a collection of elements you want your smoothscroll on. Defaults to document.links. 6029 6030Example: 6031 >new SmoothScroll(); 6032*/ 6033 6034var SmoothScroll = Fx.Scroll.extend({ 6035 6036 initialize: function(options){ 6037 this.parent(window, options); 6038 this.links = (this.options.links) ? $$(this.options.links) : $$(document.links); 6039 var location = window.location.href.match(/^[^#]*/)[0] + '#'; 6040 this.links.each(function(link){ 6041 if (link.href.indexOf(location) != 0) return; 6042 var anchor = link.href.substr(location.length); 6043 if (anchor && $(anchor)) this.useLink(link, anchor); 6044 }, this); 6045 if (!window.webkit419) this.addEvent('onComplete', function(){ 6046 window.location.hash = this.anchor; 6047 }); 6048 }, 6049 6050 useLink: function(link, anchor){ 6051 link.addEvent('click', function(event){ 6052 this.anchor = anchor; 6053 this.toElement(anchor); 6054 event.stop(); 6055 }.bindWithEvent(this)); 6056 } 6057 6058}); 6059 6060/* 6061Script: Sortables.js 6062 Contains <Sortables> Class. 6063 6064License: 6065 MIT-style license. 6066*/ 6067 6068/* 6069Class: Sortables 6070 Creates an interface for <Drag.Base> and drop, resorting of a list. 6071 6072Note: 6073 The Sortables require an XHTML doctype. 6074 6075Arguments: 6076 list - required, the list that will become sortable. 6077 options - an Object, see options below. 6078 6079Options: 6080 handles - a collection of elements to be used for drag handles. defaults to the elements. 6081 6082Events: 6083 onStart - function executed when the item starts dragging 6084 onComplete - function executed when the item ends dragging 6085*/ 6086 6087var Sortables = new Class({ 6088 6089 options: { 6090 handles: false, 6091 onStart: Class.empty, 6092 onComplete: Class.empty, 6093 ghost: true, 6094 snap: 3, 6095 onDragStart: function(element, ghost){ 6096 ghost.setStyle('opacity', 0.7); 6097 element.setStyle('opacity', 0.7); 6098 }, 6099 onDragComplete: function(element, ghost){ 6100 element.setStyle('opacity', 1); 6101 ghost.remove(); 6102 this.trash.remove(); 6103 } 6104 }, 6105 6106 initialize: function(list, options){ 6107 this.setOptions(options); 6108 this.list = $(list); 6109 this.elements = this.list.getChildren(); 6110 this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements; 6111 this.bound = { 6112 'start': [], 6113 'moveGhost': this.moveGhost.bindWithEvent(this) 6114 }; 6115 for (var i = 0, l = this.handles.length; i < l; i++){ 6116 this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]); 6117 } 6118 this.attach(); 6119 if (this.options.initialize) this.options.initialize.call(this); 6120 this.bound.move = this.move.bindWithEvent(this); 6121 this.bound.end = this.end.bind(this); 6122 }, 6123 6124 attach: function(){ 6125 this.handles.each(function(handle, i){ 6126 handle.addEvent('mousedown', this.bound.start[i]); 6127 }, this); 6128 }, 6129 6130 detach: function(){ 6131 this.handles.each(function(handle, i){ 6132 handle.removeEvent('mousedown', this.bound.start[i]); 6133 }, this); 6134 }, 6135 6136 start: function(event, el){ 6137 this.active = el; 6138 this.coordinates = this.list.getCoordinates(); 6139 if (this.options.ghost){ 6140 var position = el.getPosition(); 6141 this.offset = event.page.y - position.y; 6142 this.trash = new Element('div').inject(document.body); 6143 this.ghost = el.clone().inject(this.trash).setStyles({ 6144 'position': 'absolute', 6145 'left': position.x, 6146 'top': event.page.y - this.offset 6147 }); 6148 document.addListener('mousemove', this.bound.moveGhost); 6149 this.fireEvent('onDragStart', [el, this.ghost]); 6150 } 6151 document.addListener('mousemove', this.bound.move); 6152 document.addListener('mouseup', this.bound.end); 6153 this.fireEvent('onStart', el); 6154 event.stop(); 6155 }, 6156 6157 moveGhost: function(event){ 6158 var value = event.page.y - this.offset; 6159 value = value.limit(this.coordinates.top, this.coordinates.bottom - this.ghost.offsetHeight); 6160 this.ghost.setStyle('top', value); 6161 event.stop(); 6162 }, 6163 6164 move: function(event){ 6165 var now = event.page.y; 6166 this.previous = this.previous || now; 6167 var up = ((this.previous - now) > 0); 6168 var prev = this.active.getPrevious(); 6169 var next = this.active.getNext(); 6170 if (prev && up && now < prev.getCoordinates().bottom) this.active.injectBefore(prev); 6171 if (next && !up && now > next.getCoordinates().top) this.active.injectAfter(next); 6172 this.previous = now; 6173 }, 6174 6175 serialize: function(converter){ 6176 return this.list.getChildren().map(converter || function(el){ 6177 return this.elements.indexOf(el); 6178 }, this); 6179 }, 6180 6181 end: function(){ 6182 this.previous = null; 6183 document.removeListener('mousemove', this.bound.move); 6184 document.removeListener('mouseup', this.bound.end); 6185 if (this.options.ghost){ 6186 document.removeListener('mousemove', this.bound.moveGhost); 6187 this.fireEvent('onDragComplete', [this.active, this.ghost]); 6188 } 6189 this.fireEvent('onComplete', this.active); 6190 } 6191 6192}); 6193 6194Sortables.implement(new Events, new Options); 6195 6196/* 6197Script: Tips.js 6198 Tooltips, BubbleTips, whatever they are, they will appear on mouseover 6199 6200License: 6201 MIT-style license. 6202 6203Credits: 6204 The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com> 6205*/ 6206 6207/* 6208Class: Tips 6209 Display a tip on any element with a title and/or href. 6210 6211Note: 6212 Tips requires an XHTML doctype. 6213 6214Arguments: 6215 elements - a collection of elements to apply the tooltips to on mouseover. 6216 options - an object. See options Below. 6217 6218Options: 6219 maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30. 6220 showDelay - the delay the onShow method is called. (defaults to 100 ms) 6221 hideDelay - the delay the onHide method is called. (defaults to 100 ms) 6222 6223 className - the prefix for your tooltip classNames. defaults to 'tool'. 6224 6225 the whole tooltip will have as classname: tool-tip 6226 6227 the title will have as classname: tool-title 6228 6229 the text will have as classname: tool-text 6230 6231 offsets - the distance of your tooltip from the mouse. an Object with x/y properties. 6232 fixed - if set to true, the toolTip will not follow the mouse. 6233 6234Events: 6235 onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect); 6236 onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect); 6237 6238Example: 6239 (start code) 6240 <img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/> 6241 <script> 6242 var myTips = new Tips($$('.toolTipImg'), { 6243 maxTitleChars: 50 //I like my captions a little long 6244 }); 6245 </script> 6246 (end) 6247 6248Note: 6249 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. 6250*/ 6251 6252var Tips = new Class({ 6253 6254 options: { 6255 onShow: function(tip){ 6256 tip.setStyle('visibility', 'visible'); 6257 }, 6258 onHide: function(tip){ 6259 tip.setStyle('visibility', 'hidden'); 6260 }, 6261 maxTitleChars: 30, 6262 showDelay: 100, 6263 hideDelay: 100, 6264 className: 'tool', 6265 offsets: {'x': 16, 'y': 16}, 6266 fixed: false 6267 }, 6268 6269 initialize: function(elements, options){ 6270 this.setOptions(options); 6271 this.toolTip = new Element('div', { 6272 'class': this.options.className + '-tip', 6273 'styles': { 6274 'position': 'absolute', 6275 'top': '0', 6276 'left': '0', 6277 'visibility': 'hidden' 6278 } 6279 }).inject(document.body); 6280 this.wrapper = new Element('div').inject(this.toolTip); 6281 $$(elements).each(this.build, this); 6282 if (this.options.initialize) this.options.initialize.call(this); 6283 }, 6284 6285 build: function(el){ 6286 el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '')
6286: (el.rel || false); 6287 if (el.title){ 6288 var dual = el.title.split('::'); 6289 if (dual.length > 1){ 6290 el.$tmp.myTitle = dual[0].trim(); 6291 el.$tmp.myText = dual[1].trim(); 6292 } else { 6293 el.$tmp.myText = el.title; 6294 } 6295 el.removeAttribute('title'); 6296 } else { 6297 el.$tmp.myText = false; 6298 } 6299 if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "…"; 6300 el.addEvent('mouseenter', function(event){ 6301 this.start(el); 6302 if (!this.options.fixed) this.locate(event); 6303 else this.position(el); 6304 }.bind(this)); 6305 if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this)); 6306 var end = this.end.bind(this); 6307 el.addEvent('mouseleave', end); 6308 el.addEvent('trash', end); 6309 }, 6310 6311 start: function(el){ 6312 this.wrapper.empty(); 6313 if (el.$tmp.myTitle){ 6314 this.title = new Element('span').inject(new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)).setHTML(el.$tmp.myTitle); 6315 } 6316 if (el.$tmp.myText){ 6317 this.text = new Element('span').inject(new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)).setHTML(el.$tmp.myText); 6318 } 6319 $clear(this.timer); 6320 this.timer = this.show.delay(this.options.showDelay, this); 6321 }, 6322 6323 end: function(event){ 6324 $clear(this.timer); 6325 this.timer = this.hide.delay(this.options.hideDelay, this); 6326 }, 6327 6328 position: function(element){ 6329 var pos = element.getPosition(); 6330 this.toolTip.setStyles({ 6331 'left': pos.x + this.options.offsets.x, 6332 'top': pos.y + this.options.offsets.y 6333 }); 6334 }, 6335 6336 locate: function(event){ 6337 var win = {'x': window.getWidth(), 'y': window.getHeight()}; 6338 var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()}; 6339 var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight}; 6340 var prop = {'x': 'left', 'y': 'top'}; 6341 for (var z in prop){ 6342 var pos = event.page[z] + this.options.offsets[z]; 6343 if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z]; 6344 this.toolTip.setStyle(prop[z], pos); 6345 }; 6346 }, 6347 6348 show: function(){ 6349 if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this); 6350 this.fireEvent('onShow', [this.toolTip]); 6351 }, 6352 6353 hide: function(){ 6354 this.fireEvent('onHide', [this.toolTip]); 6355 } 6356 6357}); 6358 6359Tips.implement(new Events, new Options); 6360 6361/* 6362Script: Group.js 6363 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. 6364 6365License: 6366 MIT-style license. 6367*/ 6368 6369/* 6370Class: Group 6371 An "Utility" Class. 6372 6373Arguments: 6374 List of Class instances 6375 6376Example: 6377 (start code) 6378 xhr1 = new Ajax('data.js', {evalScript: true}); 6379 xhr2 = new Ajax('abstraction.js', {evalScript: true}); 6380 xhr3 = new Ajax('template.js', {evalScript: true}); 6381 6382 var group = new Group(xhr1, xhr2, xhr3); 6383 group.addEvent('onComplete', function(){ 6384 alert('All Scripts loaded'); 6385 }); 6386 6387 xhr1.request(); 6388 xhr2.request(); 6389 xhr3.request(); 6390 (end) 6391 6392*/ 6393 6394var Group = new Class({ 6395 6396 initialize: function(){ 6397 this.instances = $A(arguments); 6398 this.events = {}; 6399 this.checker = {}; 6400 }, 6401 6402 /* 6403 Property: addEvent 6404 adds an event to the stack of events of the Class instances. 6405 6406 Arguments: 6407 type - string; the event name (e.g. 'onComplete') 6408 fn - function to execute when all instances fired this event 6409 */ 6410 6411 addEvent: function(type, fn){ 6412 this.checker[type] = this.checker[type] || {}; 6413 this.events[type] = this.events[type] || []; 6414 if (this.events[type].contains(fn)) return false; 6415 else this.events[type].push(fn); 6416 this.instances.each(function(instance, i){ 6417 instance.addEvent(type, this.check.bind(this, [type, instance, i])); 6418 }, this); 6419 return this; 6420 }, 6421 6422 check: function(type, instance, i){ 6423 this.checker[type][i] = true; 6424 var every = this.instances.every(function(current, j){ 6425 return this.checker[type][j] || false; 6426 }, this); 6427 if (!every) return; 6428 this.checker[type] = {}; 6429 this.events[type].each(function(event){ 6430 event.call(this, this.instances, instance); 6431 }, this); 6432 } 6433 6434}); 6435 6436/* 6437Script: Accordion.js 6438 Contains <Accordion> 6439 6440License: 6441 MIT-style license. 6442*/ 6443 6444/* 6445Class: Accordion 6446 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. 6447 Inherits methods, properties, options and events from <Fx.Elements>. 6448 6449Note: 6450 The Accordion requires an XHTML doctype. 6451 6452Arguments: 6453 togglers - required, a collection of elements, the elements handlers that will be clickable. 6454 elements - required, a collection of elements the transitions will be applied to. 6455 options - optional, see options below, and <Fx.Base> options and events. 6456 6457Options: 6458 show - integer, the Index of the element to show at start. 6459 display - integer, the Index of the element to show at start (with a transition). defaults to 0. 6460 fixedHeight - integer, if you want the elements to have a fixed height. defaults to false. 6461 fixedWidth - integer, if you want the elements to have a fixed width. defaults to false. 6462 height - boolean, will add a height transition to the accordion if true. defaults to true. 6463 opacity - boolean, will add an opacity transition to the accordion if true. defaults to true. 6464 width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work! 6465 alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false. 6466 6467Events: 6468 onActive - function to execute when an element starts to show
6469 onBackground - function to execute when an element starts to hide 6470*/ 6471 6472var Accordion = Fx.Elements.extend({ 6473 6474 options: { 6475 onActive: Class.empty, 6476 onBackground: Class.empty, 6477 display: 0, 6478 show: false, 6479 height: true, 6480 width: false, 6481 opacity: true, 6482 fixedHeight: false, 6483 fixedWidth: false, 6484 wait: false, 6485 alwaysHide: false 6486 }, 6487 6488 initialize: function(){ 6489 var options, togglers, elements, container; 6490 $each(arguments, function(argument, i){ 6491 switch($type(argument)){ 6492 case 'object': options = argument; break; 6493 case 'element': container = $(argument); break; 6494 default: 6495 var temp = $$(argument); 6496 if (!togglers) togglers = temp; 6497 else elements = temp; 6498 } 6499 }); 6500 this.togglers = togglers || []; 6501 this.elements = elements || []; 6502 this.container = $(container); 6503 this.setOptions(options); 6504 this.previous = -1; 6505 if (this.options.alwaysHide) this.options.wait = true; 6506 if ($chk(this.options.show)){ 6507 this.options.display = false; 6508 this.previous = this.options.show; 6509 } 6510 if (this.options.start){ 6511 this.options.display = false; 6512 this.options.show = false; 6513 } 6514 this.effects = {}; 6515 if (this.options.opacity) this.effects.opacity = 'fullOpacity'; 6516 if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth'; 6517 if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight'; 6518 for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]); 6519 this.elements.each(function(el, i){ 6520 if (this.options.show === i){ 6521 this.fireEvent('onActive', [this.togglers[i], el]); 6522 } else { 6523 for (var fx in this.effects) el.setStyle(fx, 0); 6524 } 6525 }, this); 6526 this.parent(this.elements); 6527 if ($chk(this.options.display)) this.display(this.options.display); 6528 }, 6529 6530 /* 6531 Property: addSection 6532 Dynamically adds a new section into the accordion at the specified position. 6533 6534 Arguments: 6535 toggler - (dom element) the element that toggles the accordion section open. 6536 element - (dom element) the element that stretches open when the toggler is clicked. 6537 pos - (integer) the index where these objects are to be inserted within the accordion. 6538 */ 6539 6540 addSection: function(toggler, element, pos){ 6541 toggler = $(toggler); 6542 element = $(element); 6543 var test = this.togglers.contains(toggler); 6544 var len = this.togglers.length; 6545 this.togglers.include(toggler); 6546 this.elements.include(element); 6547 if (len && (!test || pos)){ 6548 pos = $pick(pos, len - 1); 6549 toggler.injectBefore(this.togglers[pos]); 6550 element.injectAfter(toggler); 6551 } else if (this.container && !test){ 6552 toggler.inject(this.container); 6553 element.inject(this.container); 6554 } 6555 var idx = this.togglers.indexOf(toggler); 6556 toggler.addEvent('click', this.display.bind(this, idx)); 6557 if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'}); 6558 if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'}); 6559 element.fullOpacity = 1; 6560 if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth; 6561 if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight; 6562 element.setStyle('overflow', 'hidden'); 6563 if (!test){ 6564 for (var fx in this.effects) element.setStyle(fx, 0); 6565 } 6566 return this; 6567 }, 6568 6569 /* 6570 Property: display 6571 Shows a specific section and hides all others. Useful when triggering an accordion from outside. 6572 6573 Arguments: 6574 index - integer, the index of the item to show, or the actual element to show. 6575 */ 6576 6577 display: function(index){ 6578 index = ($type(index) == 'element') ? this.elements.indexOf(index) : index; 6579 if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this; 6580 this.previous = index; 6581 var obj = {}; 6582 this.elements.each(function(el, i){ 6583 obj[i] = {}; 6584 var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0)); 6585 this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]); 6586 for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]]; 6587 }, this); 6588 return this.start(obj); 6589 }, 6590 6591 showThisHideOpen: function(index){return this.display(index);} 6592 6593}); 6594 6595Fx.Accordion = Accordion;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.