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