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