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