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.12' 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.mozInnerScreenX != 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 1770 if (!el) { return null }; 1771 1772 if (el.htmlElement) { return Garbage.collect(el) }; 1773 if ([window, document].contains(el) && el.htlmElement){ return el }; 1774 var type = $type(el); 1775 if (type == 'string'){ 1776 el = document.getElementById(el); 1777 type = (el) ? 'element' : false;
1778 } 1779 if (type != 'element') return null; 1780 if (el.htmlElement) return Garbage.collect(el); 1781 if (['object', 'embed'].contains(el.tagName.toLowerCase())&& el.htmlElement){ return el; } 1782 $extend(el, Element.prototype); 1783 el.htmlElement = function(){}; 1784 return Garbage.collect(el); 1785}; 1786 1787/* 1788Function: $$ 1789 Selects, and extends DOM elements. Elements arrays returned with $$ will also accept all the <Element> methods. 1790 The return type of element methods run through $$ is always an array. If the return array is only made by elements, 1791 $$ will be applied automatically. 1792 1793Arguments: 1794 HTML Collections, arrays of elements, arrays of strings as element ids, elements, strings as selectors. 1795 Any number of the above as arguments are accepted. 1796 1797Note: 1798 if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names. 1799 1800Example: 1801 >$$('a') //an array of all anchor tags on the page 1802 >$$('a', 'b') //an array of all anchor and bold tags on the page 1803 >$$('#myElement') //array containing only the element with id = myElement. (only with <Element.Selectors.js>) 1804 >$$('#myElement a.myClass') //an array of all anchor tags with the class "myClass" 1805 >//within the DOM element with id "myElement" (only with <Element.Selectors.js>) 1806 >$$(myelement, myelement2, 'a', ['myid', myid2, 'myid3'], document.getElementsByTagName('div')) //an array containing: 1807 >// the element referenced as myelement if existing, 1808 >// the element referenced as myelement2 if existing, 1809 >// all the elements with a as tag in the page, 1810 >// the element with id = myid if existing 1811 >// the element with id = myid2 if existing 1812 >// the element with id = myid3 if existing 1813 >// all the elements with div as tag in the page 1814 1815Returns: 1816 array - array of all the dom elements matched, extended with <$>. Returns as <Elements>. 1817*/ 1818 1819document.getElementsBySelector = document.getElementsByTagName; 1820 1821function $$(){ 1822 var elements = []; 1823 for (var i = 0, j = arguments.length; i < j; i++){ 1824 var selector = arguments[i]; 1825 switch($type(selector)){ 1826 case 'element': elements.push(selector); 1827 case 'boolean': break; 1828 case false: break; 1829 case 'string': selector = document.getElementsBySelector(selector, true); 1830 default: elements.extend(selector); 1831 } 1832 } 1833 return $$.unique(elements); 1834}; 1835 1836$$.unique = function(array){ 1837 var elements = []; 1838 for (var i = 0, l = array.length; i < l; i++){ 1839 if (array[i].$included) continue; 1840 var element = $(array[i]); 1841 if (element && !element.$included){ 1842 element.$included = true; 1843 elements.push(element); 1844 } 1845 } 1846 for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null; 1847 return new Elements(elements); 1848}; 1849 1850Elements.Multi = function(property){ 1851 return function(){ 1852 var args = arguments; 1853 var items = []; 1854 var elements = true; 1855 for (var i = 0, j = this.length, returns; i < j; i++){ 1856 returns = this[i][property].apply(this[i], args); 1857 if ($type(returns) != 'element') elements = false; 1858 items.push(returns); 1859 }; 1860 return (elements) ? $$.unique(items) : items; 1861 }; 1862}; 1863 1864Element.extend = function(properties){ 1865 for (var property in properties){ 1866 HTMLElement.prototype[property] = properties[property]; 1867 Element.prototype[property] = properties[property]; 1868 Element[property] = $native.generic(property); 1869 var elementsProperty = (Array.prototype[property]) ? property + 'Elements' : property; 1870 Elements.prototype[elementsProperty] = Elements.Multi(property); 1871 } 1872}; 1873 1874/* 1875Class: Element 1876 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 1877*/ 1878 1879Element.extend({ 1880 1881 /* 1882 Property: set 1883 you can set events, styles and properties with this shortcut. same as calling new Element. 1884 */ 1885 1886 set: function(props){ 1887 for (var prop in props){ 1888 var val = props[prop]; 1889 switch(prop){ 1890 case 'styles': this.setStyles(val); break; 1891 case 'events': if (this.addEvents) this.addEvents(val); break; 1892 case 'properties': this.setProperties(val); break; 1893 default: this.setProperty(prop, val); 1894 } 1895 } 1896 return this; 1897 }, 1898 1899 inject: function(el, where){ 1900 el = $(el); 1901 switch(where){ 1902 case 'before': el.parentNode.insertBefore(this, el); break; 1903 case 'after': 1904 var next = el.getNext(); 1905 if (!next) el.parentNode.appendChild(this); 1906 else el.parentNode.insertBefore(this, next); 1907 break; 1908 case 'top': 1909 var first = el.firstChild; 1910 if (first){ 1911 el.insertBefore(this, first); 1912 break; 1913 }
1914 default: el.appendChild(this); 1915 } 1916 return this; 1917 }, 1918 1919 /* 1920 Property: injectBefore 1921 Inserts the Element before the passed element. 1922 1923 Arguments: 1924 el - an element reference or the id of the element to be injected in. 1925 1926 Example: 1927 >html: 1928 ><div id="myElement"></div> 1929 ><div id="mySecondElement"></div> 1930 >js: 1931 >$('mySecondElement').injectBefore('myElement'); 1932 >resulting html: 1933 ><div id="mySecondElement"></div> 1934 ><div id="myElement"></div> 1935 */ 1936 1937 injectBefore: function(el){ 1938 return this.inject(el, 'before'); 1939 }, 1940 1941 /* 1942 Property: injectAfter 1943 Same as <Element.injectBefore>, but inserts the element after. 1944 */ 1945 1946 injectAfter: function(el){ 1947 return this.inject(el, 'after'); 1948 }, 1949 1950 /* 1951 Property: injectInside 1952 Same as <Element.injectBefore>, but inserts the element inside. 1953 */ 1954 1955 injectInside: function(el){ 1956 return this.inject(el, 'bottom'); 1957 }, 1958 1959 /* 1960 Property: injectTop 1961 Same as <Element.injectInside>, but inserts the element inside, at the top. 1962 */ 1963 1964 injectTop: function(el){ 1965 return this.inject(el, 'top'); 1966 }, 1967 1968 /* 1969 Property: adopt 1970 Inserts the passed elements inside the Element. 1971 1972 Arguments: 1973 accepts elements references, element ids as string, selectors ($$('stuff')) / array of elements, array of ids as strings and collections. 1974 */ 1975 1976 adopt: function(){ 1977 var elements = []; 1978 $each(arguments, function(argument){ 1979 elements = elements.concat(argument); 1980 }); 1981 $$(elements).inject(this); 1982 return this; 1983 }, 1984 1985 /* 1986 Property: remove 1987 Removes the Element from the DOM. 1988 1989 Example: 1990 >$('myElement').remove() //bye bye 1991 */ 1992 1993 remove: function(){ 1994 return this.parentNode.removeChild(this); 1995 }, 1996 1997 /* 1998 Property: clone 1999 Clones the Element and returns the cloned one. 2000 2001 Arguments: 2002 contents - boolean, when true the Element is cloned with childNodes, default true 2003 2004 Returns: 2005 the cloned element 2006 2007 Example: 2008 >var clone = $('myElement').clone().injectAfter('myElement'); 2009 >//clones the Element and append the clone after the Element. 2010 */ 2011 2012 clone: function(contents){ 2013 var el = $(this.cloneNode(contents !== false)); 2014 if (!el.$events) return el; 2015 el.$events = {}; 2016 for (var type in this.$events) el.$events[type] = { 2017 'keys': $A(this.$events[type].keys), 2018 'values': $A(this.$events[type].values) 2019 }; 2020 return el.removeEvents(); 2021 }, 2022 2023 /* 2024 Property: replaceWith 2025 Replaces the Element with an element passed. 2026 2027 Arguments: 2028 el - a string representing the element to be injected in (myElementId, or div), or an element reference. 2029 If you pass div or another tag, the element will be created. 2030 2031 Returns: 2032 the passed in element 2033 2034 Example: 2035 >$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place. 2036 */ 2037 2038 replaceWith: function(el){ 2039 el = $(el); 2040 this.parentNode.replaceChild(el, this); 2041 return el; 2042 }, 2043 2044 /* 2045 Property: appendText 2046 Appends text node to a DOM element. 2047 2048 Arguments: 2049 text - the text to append. 2050 2051 Example: 2052 ><div id="myElement">hey</div> 2053 >$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy" 2054 */ 2055 2056 appendText: function(text){ 2057 this.appendChild(document.createTextNode(text)); 2058 return this; 2059 }, 2060 2061 /* 2062 Property: hasClass 2063 Tests the Element to see if it has the passed in className. 2064 2065 Returns: 2066 true - the Element has the class 2067 false - it doesn't 2068 2069 Arguments: 2070 className - string; the class name to test. 2071 2072 Example: 2073 ><div id="myElement" class="testClass"></div> 2074 >$('myElement').hasClass('testClass'); //returns true 2075 */ 2076 2077 hasClass: function(className){ 2078 return this.className.contains(className, ' '); 2079 }, 2080 2081 /* 2082 Property: addClass 2083 Adds the passed in class to the Element, if the element doesnt already have it. 2084 2085 Arguments: 2086 className - string; the class name to add 2087 2088 Example: 2089 ><div id="myElement" class="testClass"></div> 2090 >$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div> 2091 */ 2092 2093 addClass: function(className){ 2094 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 2095 return this; 2096 }, 2097 2098 /* 2099 Property: removeClass 2100 Works like <Element.addClass>, but removes the class from the element. 2101 */ 2102 2103 removeClass: function(className){ 2104 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean(); 2105 return this; 2106 }, 2107 2108 /* 2109 Property: toggleClass 2110 Adds or removes the passed in class name to the element, depending on if it's present or not. 2111 2112 Arguments: 2113 className - the class to add or remove 2114 2115 Example: 2116 >
2116<div id="myElement" class="myClass"></div> 2117 >$('myElement').toggleClass('myClass'); 2118 ><div id="myElement" class=""></div> 2119 >$('myElement').toggleClass('myClass'); 2120 ><div id="myElement" class="myClass"></div> 2121 */ 2122 2123 toggleClass: function(className){ 2124 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); 2125 }, 2126 2127 /* 2128 Property: setStyle 2129 Sets a css property to the Element. 2130 2131 Arguments: 2132 property - the property to set 2133 value - the value to which to set it; for numeric values that require "px" you can pass an integer 2134 2135 Example: 2136 >$('myElement').setStyle('width', '300px'); //the width is now 300px 2137 >$('myElement').setStyle('width', 300); //the width is now 300px 2138 */ 2139 2140 setStyle: function(property, value){ 2141 switch(property){ 2142 case 'opacity': return this.setOpacity(parseFloat(value)); 2143 case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat'; 2144 } 2145 property = property.camelCase(); 2146 switch($type(value)){ 2147 case 'number': if (!['zIndex', 'zoom'].contains(property)) value += 'px'; break; 2148 case 'array': value = 'rgb(' + value.join(',') + ')'; 2149 } 2150 this.style[property] = value; 2151 return this; 2152 }, 2153 2154 /* 2155 Property: setStyles 2156 Applies a collection of styles to the Element. 2157 2158 Arguments: 2159 source - an object or string containing all the styles to apply. When its a string it overrides old style. 2160 2161 Examples: 2162 >$('myElement').setStyles({ 2163 > border: '1px solid #000', 2164 > width: 300, 2165 > height: 400 2166 >}); 2167 2168 OR 2169 2170 >$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;'); 2171 */ 2172 2173 setStyles: function(source){ 2174 switch($type(source)){ 2175 case 'object': Element.setMany(this, 'setStyle', source); break; 2176 case 'string': this.style.cssText = source; 2177 } 2178 return this; 2179 }, 2180 2181 /* 2182 Property: setOpacity 2183 Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0. 2184 2185 Arguments: 2186 opacity - float; Accepts values from 0 to 1. 2187 2188 Example: 2189 >$('myElement').setOpacity(0.5) //make it 50% transparent 2190 */ 2191 2192 setOpacity: function(opacity){ 2193 if (opacity == 0){ 2194 if (this.style.visibility != "hidden") this.style.visibility = "hidden"; 2195 } else { 2196 if (this.style.visibility != "visible") this.style.visibility = "visible"; 2197 } 2198 if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1; 2199 if (window.ie) this.style.filter = (opacity == 1) ? '' : "alpha(opacity=" + opacity * 100 + ")"; 2200 this.style.opacity = this.$tmp.opacity = opacity; 2201 return this; 2202 }, 2203 2204 /* 2205 Property: getStyle 2206 Returns the style of the Element given the property passed in. 2207 2208 Arguments: 2209 property - the css style property you want to retrieve 2210 2211 Example: 2212 >$('myElement').getStyle('width'); //returns "400px" 2213 >//but you can also use 2214 >$('myElement').getStyle('width').toInt(); //returns 400 2215 2216 Returns: 2217 the style as a string 2218 */ 2219 2220 getStyle: function(property){ 2221 property = property.camelCase(); 2222 var result = this.style[property]; 2223 if (!$chk(result)){ 2224 if (property == 'opacity') return this.$tmp.opacity; 2225 result = []; 2226 for (var style in Element.Styles){ 2227 if (property == style){ 2228 Element.Styles[style].each(function(s){ 2229 var style = this.getStyle(s); 2230 result.push(parseInt(style) ? style : '0px'); 2231 }, this); 2232 if (property == 'border'){ 2233 var every = result.every(function(bit){ 2234 return (bit == result[0]); 2235 }); 2236 return (every) ? result[0] : false; 2237 } 2238 return result.join(' '); 2239 } 2240 } 2241 if (property.contains('border')){ 2242 if (Element.Styles.border.contains(property)){ 2243 return ['Width', 'Style', 'Color'].map(function(p){ 2244 return this.getStyle(property + p); 2245 }, this).join(' '); 2246 } else if (Element.borderShort.contains(property)){ 2247 return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){ 2248 return this.getStyle('border' + p + property.replace('border', '')); 2249 }, this).join(' '); 2250 } 2251 } 2252 if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate()); 2253 else if (this.currentStyle) result = this.currentStyle[property]; 2254 } 2255 if (window.ie) result = Element.fixStyle(property, result, this); 2256 if (result && property.test(/color/i) && result.contains('rgb')){ 2257 return result.split('rgb').splice(1,4).map(function(color){ 2258 return color.rgbToHex(); 2259 }).join(' '); 2260 } 2261 return result; 2262 }, 2263 2264 /* 2265 Property: getStyles 2266 Returns an object of styles of the Element for each argument passed in. 2267 Arguments: 2268 properties - strings; any number of style properties
2269 Example: 2270 >$('myElement').getStyles('width','height','padding'); 2271 >//returns an object like: 2272 >{width: "10px", height: "10px", padding: "10px 0px 10px 0px"} 2273 */ 2274 2275 getStyles: function(){ 2276 return Element.getMany(this, 'getStyle', arguments); 2277 }, 2278 2279 walk: function(brother, start){ 2280 brother += 'Sibling'; 2281 var el = (start) ? this[start] : this[brother]; 2282 while (el && $type(el) != 'element') el = el[brother]; 2283 return $(el); 2284 }, 2285 2286 /* 2287 Property: getPrevious 2288 Returns the previousSibling of the Element, excluding text nodes. 2289 2290 Example: 2291 >$('myElement').getPrevious(); //get the previous DOM element from myElement 2292 2293 Returns: 2294 the sibling element or undefined if none found. 2295 */ 2296 2297 getPrevious: function(){ 2298 return this.walk('previous'); 2299 }, 2300 2301 /* 2302 Property: getNext 2303 Works as Element.getPrevious, but tries to find the nextSibling. 2304 */ 2305 2306 getNext: function(){ 2307 return this.walk('next'); 2308 }, 2309 2310 /* 2311 Property: getFirst 2312 Works as <Element.getPrevious>, but tries to find the firstChild. 2313 */ 2314 2315 getFirst: function(){ 2316 return this.walk('next', 'firstChild'); 2317 }, 2318 2319 /* 2320 Property: getLast 2321 Works as <Element.getPrevious>, but tries to find the lastChild. 2322 */ 2323 2324 getLast: function(){ 2325 return this.walk('previous', 'lastChild'); 2326 }, 2327 2328 /* 2329 Property: getParent 2330 returns the $(element.parentNode) 2331 */ 2332 2333 getParent: function(){ 2334 return $(this.parentNode); 2335 }, 2336 2337 /* 2338 Property: getChildren 2339 returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>. 2340 */ 2341 2342 getChildren: function(){ 2343 return $$(this.childNodes); 2344 }, 2345 2346 /* 2347 Property: hasChild 2348 returns true if the passed in element is a child of the $(element). 2349 */ 2350 2351 hasChild: function(el){ 2352 return !!$A(this.getElementsByTagName('*')).contains(el); 2353 }, 2354 2355 /* 2356 Property: getProperty 2357 Gets the an attribute of the Element. 2358 2359 Arguments: 2360 property - string; the attribute to retrieve 2361 2362 Example: 2363 >$('myImage').getProperty('src') // returns whatever.gif 2364 2365 Returns: 2366 the value, or an empty string 2367 */ 2368 2369 getProperty: function(property){ 2370 var index = Element.Properties[property]; 2371 if (index) return this[index]; 2372 var flag = Element.PropertiesIFlag[property] || 0; 2373 if (!window.ie || flag) return this.getAttribute(property, flag); 2374 var node = this.attributes[property]; 2375 return (node) ? node.nodeValue : null; 2376 }, 2377 2378 /* 2379 Property: removeProperty 2380 Removes an attribute from the Element 2381 2382 Arguments: 2383 property - string; the attribute to remove 2384 */ 2385 2386 removeProperty: function(property){ 2387 var index = Element.Properties[property]; 2388 if (index) this[index] = ''; 2389 else this.removeAttribute(property); 2390 return this; 2391 }, 2392 2393 /* 2394 Property: getProperties 2395 same as <Element.getStyles>, but for properties 2396 */ 2397 2398 getProperties: function(){ 2399 return Element.getMany(this, 'getProperty', arguments); 2400 }, 2401 2402 /* 2403 Property: setProperty 2404 Sets an attribute for the Element. 2405 2406 Arguments: 2407 property - string; the property to assign the value passed in 2408 value - the value to assign to the property passed in 2409 2410 Example: 2411 >$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source 2412 */ 2413 2414 setProperty: function(property, value){ 2415 var index = Element.Properties[property]; 2416 if (index) this[index] = value; 2417 else this.setAttribute(property, value); 2418 return this; 2419 }, 2420 2421 /* 2422 Property: setProperties 2423 Sets numerous attributes for the Element. 2424 2425 Arguments: 2426 source - an object with key/value pairs. 2427 2428 Example: 2429 (start code) 2430 $('myElement').setProperties({ 2431 src: 'whatever.gif', 2432 alt: 'whatever dude' 2433 }); 2434 <img src="whatever.gif" alt="whatever dude"> 2435 (end) 2436 */ 2437 2438 setProperties: function(source){ 2439 return Element.setMany(this, 'setProperty', source); 2440 }, 2441 2442 /* 2443 Property: setHTML 2444 Sets the innerHTML of the Element. 2445 2446 Arguments: 2447 html - string; the new innerHTML for the element. 2448 2449 Example: 2450 >$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML 2451 */ 2452 2453 setHTML: function(){ 2454 this.innerHTML = $A(arguments).join(''); 2455 return this; 2456 }, 2457 2458 /* 2459 Property: setText 2460 Sets the inner text of the Element. 2461 2462 Arguments: 2463 text - string; the new text content for the element. 2464 2465 Example: 2466 >$('myElement').setText('some text') //the text of myElement is now = 'some text' 2467 */ 2468 2469 setText: function(text){ 2470 var tag = this.getTag(); 2471 if (['style', 'script'].contains(tag)){ 2472 if (window.ie){ 2473 if (tag == 'style') this.styleSheet.cssText = text; 2474 else if (tag == 'script') this.setProperty('text', text); 2475 return this; 2476 } else { 2477 this.removeChild(this.firstChild); 2478 return this.appendText(text); 2479 } 2480 } 2481 this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text; 2482 return this; 2483 }, 2484 2485 /* 2486 Property: getText 2487 Gets the inner text of the Element. 2488 */ 2489 2490 getText: function(){ 2491 var tag = this.getTag(); 2492 if (['style', 'script'].contains(tag)){ 2493 if (window.ie){ 2494 if (tag == 'style') return this.styleSheet.cssText; 2495 else if (tag == 'script') return this.getProperty('text'); 2496 } else { 2497 return this.innerHTML; 2498 } 2499 } 2500 return ($pick(this.innerText, this.textContent)); 2501 }, 2502 2503 /* 2504 Property: getTag 2505 Returns the tagName of the element in lower case. 2506 2507 Example: 2508 >$('myImage').getTag() // returns 'img' 2509 2510 Returns: 2511 The tag name in lower case 2512 */ 2513 2514 getTag: function(){ 2515 return this.tagName.toLowerCase(); 2516 }, 2517 2518 /* 2519 Property: empty 2520 Empties an element of all its children. 2521 2522 Example: 2523 >$('myDiv').empty() // empties the Div and returns it 2524 2525 Returns: 2526 The element. 2527 */ 2528 2529 empty: function(){ 2530 Garbage.trash(this.getElementsByTagName('*')); 2531 return this.setHTML(''); 2532 } 2533 2534}); 2535 2536Element.fixStyle = function(property, result, element){ 2537 if ($chk(parseInt(result))) return result; 2538 if (['height', 'width'].contains(property)){ 2539 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom']; 2540 var size = 0; 2541 values.each(function(value){ 2542 size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt(); 2543 }); 2544 return element['offset' + property.capitalize()] - size + 'px'; 2545 } else if (property.test(/border(.+)Width|margin|padding/)){ 2546 return '0px'; 2547 } 2548 return result; 2549}; 2550 2551Element.Styles = {'border': [], 'padding': [], 'margin': []}; 2552['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ 2553 for (var style in Element.Styles) Element.Styles[style].push(style + direction); 2554}); 2555 2556Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor']; 2557 2558Element.getMany = function(el, method, keys){ 2559 var result = {}; 2560 $each(keys, function(key){ 2561 result[key] = el[method](key); 2562 }); 2563 return result; 2564}; 2565 2566Element.setMany = function(el, method, pairs){ 2567 for (var key in pairs) el[method](key, pairs[key]); 2568 return el; 2569}; 2570 2571Element.Properties = new Abstract({ 2572 'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan', 2573 'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength', 2574 'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value', 2575 'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected' 2576}); 2577Element.PropertiesIFlag = { 2578 'href': 2, 'src': 2 2579}; 2580 2581Element.Methods = { 2582 Listeners: {
2583 addListener: function(type, fn){ 2584 if (this.addEventListener) this.addEventListener(type, fn, false); 2585 else this.attachEvent('on' + type, fn); 2586 return this; 2587 }, 2588 2589 removeListener: function(type, fn){ 2590 if (this.removeEventListener) this.removeEventListener(type, fn, false); 2591 else this.detachEvent('on' + type, fn); 2592 return this; 2593 } 2594 } 2595}; 2596 2597window.extend(Element.Methods.Listeners); 2598document.extend(Element.Methods.Listeners); 2599Element.extend(Element.Methods.Listeners); 2600 2601var Garbage = { 2602 2603 elements: [], 2604 2605 collect: function(el){ 2606 if (!el.$tmp){ 2607 Garbage.elements.push(el); 2608 el.$tmp = {'opacity': 1}; 2609 } 2610 return el; 2611 }, 2612 2613 trash: function(elements){ 2614 for (var i = 0, j = elements.length, el; i < j; i++){ 2615 if (!(el = elements[i]) || !el.$tmp) continue; 2616 if (el.$events) el.fireEvent('trash').removeEvents(); 2617 for (var p in el.$tmp) el.$tmp[p] = null; 2618 for (var d in Element.prototype) el[d] = null; 2619 Garbage.elements[Garbage.elements.indexOf(el)] = null; 2620 el.htmlElement = el.$tmp = el = null; 2621 } 2622 Garbage.elements.remove(null); 2623 }, 2624 2625 empty: function(){ 2626 Garbage.collect(window); 2627 Garbage.collect(document); 2628 Garbage.trash(Garbage.elements); 2629 } 2630 2631}; 2632 2633window.addListener('beforeunload', function(){ 2634 window.addListener('unload', Garbage.empty); 2635 if (window.ie) window.addListener('unload', CollectGarbage); 2636}); 2637 2638/* 2639Script: Element.Event.js 2640 Contains the Event Class, Element methods to deal with Element events, custom Events, and the Function prototype bindWithEvent. 2641 2642License: 2643 MIT-style license. 2644*/ 2645 2646/* 2647Class: Event 2648 Cross browser methods to manage events. 2649 2650Arguments: 2651 event - the event 2652 2653Properties: 2654 shift - true if the user pressed the shift 2655 control - true if the user pressed the control 2656 alt - true if the user pressed the alt 2657 meta - true if the user pressed the meta key 2658 wheel - the amount of third button scrolling 2659 code - the keycode of the key pressed 2660 page.x - the x position of the mouse, relative to the full window 2661 page.y - the y position of the mouse, relative to the full window 2662 client.x - the x position of the mouse, relative to the viewport 2663 client.y - the y position of the mouse, relative to the viewport 2664 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. 2665 target - the event target 2666 relatedTarget - the event related target 2667 2668Example: 2669 (start code) 2670 $('myLink').onkeydown = function(event){ 2671 var event = new Event(event); 2672 //event is now the Event class. 2673 alert(event.key); //returns the lowercase letter pressed 2674 alert(event.shift); //returns true if the key pressed is shift 2675 if (event.key == 's' && event.control) alert('document saved'); 2676 }; 2677 (end) 2678*/ 2679 2680var Event = new Class({ 2681 2682 initialize: function(event){ 2683 if (event && event.$extended) return event; 2684 this.$extended = true; 2685 event = event || window.event; 2686 this.event = event; 2687 this.type = event.type; 2688 this.target = event.target || event.srcElement; 2689 if (this.target.nodeType == 3) this.target = this.target.parentNode; 2690 this.shift = event.shiftKey; 2691 this.control = event.ctrlKey; 2692 this.alt = event.altKey; 2693 this.meta = event.metaKey; 2694 if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){ 2695 this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; 2696 } else if (this.type.contains('key')){ 2697 this.code = event.which || event.keyCode; 2698 for (var name in Event.keys){ 2699 if (Event.keys[name] == this.code){ 2700 this.key = name; 2701 break; 2702 } 2703 } 2704 if (this.type == 'keydown'){ 2705 var fKey = this.code - 111; 2706 if (fKey > 0 && fKey < 13) this.key = 'f' + fKey; 2707 } 2708 this.key = this.key || String.fromCharCode(this.code).toLowerCase(); 2709 } else if (this.type.test(/(click|mouse|menu)/)){ 2710 this.page = { 2711 'x': event.pageX || event.clientX + document.documentElement.scrollLeft, 2712 'y': event.pageY || event.clientY + document.documentElement.scrollTop 2713 }; 2714 this.client = { 2715 'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX, 2716 'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY 2717 }; 2718 this.rightClick = (event.which == 3) || (event.button == 2); 2719 switch(this.type){ 2720 case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break; 2721 case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement; 2722 } 2723 this.fixRelatedTarget(); 2724 } 2725 return this; 2726 }, 2727 2728 /* 2729 Property: stop 2730 cross browser method to stop an event 2731 */ 2732 2733 stop: function(){ 2734 return this.stopPropagation().preventDefault(); 2735 }, 2736 2737 /* 2738 Property: stopPropagation 2739 cross browser method to stop the propagation of an event 2740 */ 2741 2742 stopPropagation: function(){ 2743 if (this.event.stopPropagation) this.event.stopPropagation(); 2744 else this.event.cancelBubble = true; 2745 return this; 2746 }, 2747 2748 /* 2749 Property: preventDefault 2750 cross browser method to prevent the default action of the event 2751 */ 2752 2753 preventDefault: function(){ 2754 if (this.event.preventDefault) this.event.preventDefault(); 2755 else this.event.returnValue = false;
2756 return this; 2757 } 2758 2759}); 2760 2761Event.fix = { 2762 2763 relatedTarget: function(){ 2764 if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode; 2765 }, 2766 2767 relatedTargetGecko: function(){ 2768 try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;} 2769 } 2770 2771}; 2772 2773Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget; 2774 2775/* 2776Property: keys 2777 you can add additional Event keys codes this way: 2778 2779Example: 2780 (start code) 2781 Event.keys.whatever = 80; 2782 $(myelement).addEvent(keydown, function(event){ 2783 event = new Event(event); 2784 if (event.key == 'whatever') console.log(whatever key clicked). 2785 }); 2786 (end) 2787*/ 2788 2789Event.keys = new Abstract({ 2790 'enter': 13, 2791 'up': 38, 2792 'down': 40, 2793 'left': 37, 2794 'right': 39, 2795 'esc': 27, 2796 'space': 32, 2797 'backspace': 8, 2798 'tab': 9, 2799 'delete': 46 2800}); 2801 2802/* 2803Class: Element 2804 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 2805*/ 2806 2807Element.Methods.Events = { 2808 2809 /* 2810 Property: addEvent 2811 Attaches an event listener to a DOM element. 2812 2813 Arguments: 2814 type - the event to monitor ('click', 'load', etc) without the prefix 'on'. 2815 fn - the function to execute 2816 2817 Example: 2818 >$('myElement').addEvent('click', function(){alert('clicked!')}); 2819 */ 2820 2821 addEvent: function(type, fn){ 2822 this.$events = this.$events || {}; 2823 this.$events[type] = this.$events[type] || {'keys': [], 'values': []}; 2824 if (this.$events[type].keys.contains(fn)) return this; 2825 this.$events[type].keys.push(fn); 2826 var realType = type; 2827 var custom = Element.Events[type]; 2828 if (custom){ 2829 if (custom.add) custom.add.call(this, fn); 2830 if (custom.map) fn = custom.map; 2831 if (custom.type) realType = custom.type; 2832 } 2833 if (!this.addEventListener) fn = fn.create({'bind': this, 'event': true}); 2834 this.$events[type].values.push(fn); 2835 return (Element.NativeEvents.contains(realType)) ? this.addListener(realType, fn) : this; 2836 }, 2837 2838 /* 2839 Property: removeEvent 2840 Works as Element.addEvent, but instead removes the previously added event listener. 2841 */ 2842 2843 removeEvent: function(type, fn){ 2844 if (!this.$events || !this.$events[type]) return this; 2845 var pos = this.$events[type].keys.indexOf(fn); 2846 if (pos == -1) return this; 2847 var key = this.$events[type].keys.splice(pos,1)[0]; 2848 var value = this.$events[type].values.splice(pos,1)[0]; 2849 var custom = Element.Events[type]; 2850 if (custom){ 2851 if (custom.remove) custom.remove.call(this, fn); 2852 if (custom.type) type = custom.type; 2853 } 2854 return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this; 2855 }, 2856 2857 /* 2858 Property: addEvents 2859 As <addEvent>, but accepts an object and add multiple events at once. 2860 */ 2861 2862 addEvents: function(source){ 2863 return Element.setMany(this, 'addEvent', source); 2864 }, 2865 2866 /* 2867 Property: removeEvents 2868 removes all events of a certain type from an element. if no argument is passed in, removes all events. 2869 2870 Arguments: 2871 type - string; the event name (e.g. 'click') 2872 */ 2873 2874 removeEvents: function(type){ 2875 if (!this.$events) return this; 2876 if (!type){ 2877 for (var evType in this.$events) this.removeEvents(evType); 2878 this.$events = null; 2879 } else if (this.$events[type]){ 2880 this.$events[type].keys.each(function(fn){ 2881 this.removeEvent(type, fn); 2882 }, this); 2883 this.$events[type] = null; 2884 } 2885 return this; 2886 }, 2887 2888 /* 2889 Property: fireEvent 2890 executes all events of the specified type present in the element. 2891 2892 Arguments: 2893 type - string; the event name (e.g. 'click') 2894 args - array or single object; arguments to pass to the function; if more than one argument, must be an array 2895 delay - (integer) delay (in ms) to wait to execute the event 2896 */ 2897 2898 fireEvent: function(type, args, delay){ 2899 if (this.$events && this.$events[type]){ 2900 this.$events[type].keys.each(function(fn){ 2901 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 2902 }, this); 2903 } 2904 return this; 2905 }, 2906 2907 /* 2908 Property: cloneEvents 2909 Clones all events from an element to this element. 2910 2911 Arguments: 2912 from - element, copy all events from this element 2913 type - optional, copies only events of this type 2914 */ 2915 2916 cloneEvents: function(from, type){ 2917 if (!from.$events) return this; 2918 if (!type){ 2919 for (var evType in from.$events) this.cloneEvents(from, evType); 2920 } else if (from.$events[type]){ 2921 from.$events[type].keys.each(function(fn){
2922 this.addEvent(type, fn); 2923 }, this); 2924 } 2925 return this; 2926 } 2927 2928}; 2929 2930window.extend(Element.Methods.Events); 2931document.extend(Element.Methods.Events); 2932Element.extend(Element.Methods.Events); 2933 2934/* Section: Custom Events */ 2935 2936Element.Events = new Abstract({ 2937 2938 /* 2939 Event: mouseenter 2940 In addition to the standard javascript events (load, mouseover, mouseout, click, etc.) <Event.js> contains two custom events 2941 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) 2942 2943 2944 Example: 2945 >$(myElement).addEvent('mouseenter', myFunction); 2946 */ 2947 2948 'mouseenter': { 2949 type: 'mouseover', 2950 map: function(event){ 2951 event = new Event(event); 2952 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event); 2953 } 2954 }, 2955 2956 /* 2957 Event: mouseleave 2958 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) 2959 2960 2961 Example: 2962 >$(myElement).addEvent('mouseleave', myFunction); 2963 */ 2964 2965 'mouseleave': { 2966 type: 'mouseout', 2967 map: function(event){ 2968 event = new Event(event); 2969 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event); 2970 } 2971 }, 2972 2973 'mousewheel': { 2974 type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel' 2975 } 2976 2977}); 2978 2979Element.NativeEvents = [ 2980 'click', 'dblclick', 'mouseup', 'mousedown', //mouse buttons 2981 'mousewheel', 'DOMMouseScroll', //mouse wheel 2982 'mouseover', 'mouseout', 'mousemove', //mouse movement 2983 'keydown', 'keypress', 'keyup', //keys 2984 'load', 'unload', 'beforeunload', 'resize', 'move', //window 2985 'focus', 'blur', 'change', 'submit', 'reset', 'select', //forms elements 2986 'error', 'abort', 'contextmenu', 'scroll' //misc 2987]; 2988 2989/* 2990Class: Function 2991 A collection of The Function Object prototype methods. 2992*/ 2993 2994Function.extend({ 2995 2996 /* 2997 Property: bindWithEvent 2998 automatically passes MooTools Event Class. 2999 3000 Arguments: 3001 bind - optional, the object that the "this" of the function will refer to. 3002 args - optional, an argument to pass to the function; if more than one argument, it must be an array of arguments. 3003 3004 Returns: 3005 a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser. 3006 3007 Example: 3008 >function myFunction(event){ 3009 > alert(event.client.x) //returns the coordinates of the mouse.. 3010 >}; 3011 >myElement.addEvent('click', myFunction.bindWithEvent(myElement)); 3012 */ 3013 3014 bindWithEvent: function(bind, args){ 3015 return this.create({'bind': bind, 'arguments': args, 'event': Event}); 3016 } 3017 3018}); 3019 3020 3021/* 3022Script: Element.Filters.js 3023 add Filters capability to <Elements>. 3024 3025License: 3026 MIT-style license. 3027*/ 3028 3029/* 3030Class: Elements 3031 A collection of methods to be used with <$$> elements collections. 3032*/ 3033 3034Elements.extend({ 3035 3036 /* 3037 Property: filterByTag 3038 Filters the collection by a specified tag name. 3039 Returns a new Elements collection, while the original remains untouched. 3040 */ 3041 3042 filterByTag: function(tag){ 3043 return new Elements(this.filter(function(el){ 3044 return (Element.getTag(el) == tag); 3045 })); 3046 }, 3047 3048 /* 3049 Property: filterByClass 3050 Filters the collection by a specified class name. 3051 Returns a new Elements collection, while the original remains untouched. 3052 */ 3053 3054 filterByClass: function(className, nocash){ 3055 var elements = this.filter(function(el){ 3056 return (el.className && el.className.contains(className, ' ')); 3057 }); 3058 return (nocash) ? elements : new Elements(elements); 3059 }, 3060 3061 /* 3062 Property: filterById 3063 Filters the collection by a specified ID. 3064 Returns a new Elements collection, while the original remains untouched. 3065 */ 3066 3067 filterById: function(id, nocash){ 3068 var elements = this.filter(function(el){ 3069 return (el.id == id); 3070 }); 3071 return (nocash) ? elements : new Elements(elements); 3072 }, 3073 3074 /* 3075 Property: filterByAttribute 3076 Filters the collection by a specified attribute. 3077 Returns a new Elements collection, while the original remains untouched. 3078 3079 Arguments: 3080 name - the attribute name. 3081 operator - optional, the attribute operator. 3082 value - optional, the attribute value, only valid if the operator is specified. 3083 */ 3084 3085 filterByAttribute: function(name, operator, value, nocash){ 3086 var elements = this.filter(function(el){ 3087 var current = Element.getProperty(el, name); 3088 if (!current) return false;
3089 if (!operator) return true; 3090 switch(operator){ 3091 case '=': return (current == value); 3092 case '*=': return (current.contains(value)); 3093 case '^=': return (current.substr(0, value.length) == value); 3094 case '$=': return (current.substr(current.length - value.length) == value); 3095 case '!=': return (current != value); 3096 case '~=': return current.contains(value, ' '); 3097 } 3098 return false; 3099 }); 3100 return (nocash) ? elements : new Elements(elements); 3101 } 3102 3103}); 3104 3105/* 3106Script: Element.Selectors.js 3107 Css Query related functions and <Element> extensions 3108 3109License: 3110 MIT-style license. 3111*/ 3112 3113/* Section: Utility Functions */ 3114 3115/* 3116Function: $E 3117 Selects a single (i.e. the first found) Element based on the selector passed in and an optional filter element. 3118 Returns as <Element>. 3119 3120Arguments: 3121 selector - string; the css selector to match 3122 filter - optional; a DOM element to limit the scope of the selector match; defaults to document. 3123 3124Example: 3125 >$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement' 3126 3127Returns: 3128 a DOM element - the first element that matches the selector 3129*/ 3130 3131function $E(selector, filter){ 3132 return ($(filter) || document).getElement(selector); 3133}; 3134 3135/* 3136Function: $ES 3137 Returns a collection of Elements that match the selector passed in limited to the scope of the optional filter. 3138 See Also: <Element.getElements> for an alternate syntax. 3139 Returns as <Elements>. 3140 3141Returns: 3142 an array of dom elements that match the selector within the filter 3143 3144Arguments: 3145 selector - string; css selector to match 3146 filter - optional; a DOM element to limit the scope of the selector match; defaults to document. 3147 3148Examples: 3149 >$ES("a") //gets all the anchor tags; synonymous with $$("a") 3150 >$ES('a','myElement') //get all the anchor tags within $('myElement') 3151*/ 3152 3153function $ES(selector, filter){ 3154 return ($(filter) || document).getElementsBySelector(selector); 3155}; 3156 3157$$.shared = { 3158 3159 'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/, 3160 3161 'xpath': { 3162 3163 getParam: function(items, context, param, i){ 3164 var temp = [context.namespaceURI ? 'xhtml:' : '', param[1]]; 3165 if (param[2]) temp.push('[@id="', param[2], '"]'); 3166 if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]'); 3167 if (param[4]){ 3168 if (param[5] && param[6]){ 3169 switch(param[5]){ 3170 case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break; 3171 case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break; 3172 case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break; 3173 case '=': temp.push('[@', param[4], '="', param[6], '"]'); break; 3174 case '!=': temp.push('[@', param[4], '!="', param[6], '"]'); 3175 } 3176 } else { 3177 temp.push('[@', param[4], ']'); 3178 } 3179 } 3180 items.push(temp.join('')); 3181 return items; 3182 }, 3183 3184 getItems: function(items, context, nocash){ 3185 var elements = []; 3186 var xpath = document.evaluate('.//' + items.join('//'), context, $$.shared.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 3187 for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements.push(xpath.snapshotItem(i)); 3188 return (nocash) ? elements : new Elements(elements.map($)); 3189 } 3190 3191 }, 3192 3193 'normal': { 3194 3195 getParam: function(items, context, param, i){ 3196 if (i == 0){ 3197 if (param[2]){ 3198 var el = context.getElementById(param[2]); 3199 if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false; 3200 items = [el]; 3201 } else { 3202 items = $A(context.getElementsByTagName(param[1])); 3203 } 3204 } else { 3205 items = $$.shared.getElementsByTagName(items, param[1]); 3206 if (param[2]) items = Elements.filterById(items, param[2], true); 3207 } 3208 if (param[3]) items = Elements.filterByClass(items, param[3], true); 3209 if (param[4]) items = Elements.filterByAttribute(items, param[4], param[5], param[6], true); 3210 return items; 3211 }, 3212 3213 getItems: function(items, context, nocash){ 3214 return (nocash) ? items : $$.unique(items); 3215 } 3216 3217 }, 3218 3219 resolver: function(prefix){ 3220 return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
3221 }, 3222 3223 getElementsByTagName: function(context, tagName){ 3224 var found = []; 3225 for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName)); 3226 return found; 3227 } 3228 3229}; 3230 3231$$.shared.method = (window.xpath) ? 'xpath' : 'normal'; 3232 3233/* 3234Class: Element 3235 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3236*/ 3237 3238Element.Methods.Dom = { 3239 3240 /* 3241 Property: getElements 3242 Gets all the elements within an element that match the given (single) selector. 3243 Returns as <Elements>. 3244 3245 Arguments: 3246 selector - string; the css selector to match 3247 3248 Examples: 3249 >$('myElement').getElements('a'); // get all anchors within myElement 3250 >$('myElement').getElements('input[name=dialog]') //get all input tags with name 'dialog' 3251 >$('myElement').getElements('input[name$=log]') //get all input tags with names ending with 'log' 3252 3253 Notes: 3254 Supports these operators in attribute selectors: 3255 3256 - = : is equal to 3257 - ^= : starts-with 3258 - $= : ends-with 3259 - != : is not equal to 3260 3261 Xpath is used automatically for compliant browsers. 3262 */ 3263 3264 getElements: function(selector, nocash){ 3265 var items = []; 3266 selector = selector.trim().split(' '); 3267 for (var i = 0, j = selector.length; i < j; i++){ 3268 var sel = selector[i]; 3269 var param = sel.match($$.shared.regexp); 3270 if (!param) break; 3271 param[1] = param[1] || '*'; 3272 var temp = $$.shared[$$.shared.method].getParam(items, this, param, i); 3273 if (!temp) break; 3274 items = temp; 3275 } 3276 return $$.shared[$$.shared.method].getItems(items, this, nocash); 3277 }, 3278 3279 /* 3280 Property: getElement 3281 Same as <Element.getElements>, but returns only the first. Alternate syntax for <$E>, where filter is the Element. 3282 Returns as <Element>. 3283 3284 Arguments: 3285 selector - string; css selector 3286 */ 3287 3288 getElement: function(selector){ 3289 return $(this.getElements(selector, true)[0] || false); 3290 }, 3291 3292 /* 3293 Property: getElementsBySelector 3294 Same as <Element.getElements>, but allows for comma separated selectors, as in css. Alternate syntax for <$$>, where filter is the Element. 3295 Returns as <Elements>. 3296 3297 Arguments: 3298 selector - string; css selector 3299 */ 3300 3301 getElementsBySelector: function(selector, nocash){ 3302 var elements = []; 3303 selector = selector.split(','); 3304 for (var i = 0, j = selector.length; i < j; i++) elements = elements.concat(this.getElements(selector[i], true)); 3305 return (nocash) ? elements : $$.unique(elements); 3306 } 3307 3308}; 3309 3310Element.extend({ 3311 3312 /* 3313 Property: getElementById 3314 Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById. 3315 3316 Arguments: 3317 id - string; the id of the element to find. 3318 */ 3319 3320 getElementById: function(id){ 3321 var el = document.getElementById(id); 3322 if (!el) return false; 3323 for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ 3324 if (!parent) return false; 3325 } 3326 return el; 3327 }/*compatibility*/, 3328 3329 getElementsByClassName: function(className){ 3330 return this.getElements('.' + className); 3331 } 3332 3333 /*end compatibility*/ 3334 3335}); 3336 3337document.extend(Element.Methods.Dom); 3338Element.extend(Element.Methods.Dom); 3339 3340/* 3341Script: Element.Form.js 3342 Contains Element prototypes to deal with Forms and their elements. 3343 3344License: 3345 MIT-style license. 3346*/ 3347 3348/* 3349Class: Element 3350 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3351*/ 3352 3353Element.extend({ 3354 3355 /* 3356 Property: getValue 3357 Returns the value of the Element, if its tag is textarea, select or input. getValue called on a multiple select will return an array. 3358 */ 3359 3360 getValue: function(){ 3361 switch(this.getTag()){ 3362 case 'select': 3363 var values = []; 3364 $each(this.options, function(option){ 3365 if (option.selected) values.push($pick(option.value, option.text)); 3366 }); 3367 return (this.multiple) ? values : values[0]; 3368 case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break; 3369 case 'textarea': return this.value; 3370 } 3371 return false; 3372 }, 3373 3374 getFormElements: function(){ 3375 return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea')); 3376 }, 3377 3378 /* 3379 Property: toQueryString 3380 Reads the children inputs of the Element and generates a query string, based on their values. Used internally in <Ajax> 3381 3382 Example: 3383 (start code) 3384 <form id="myForm" action="submit.php"> 3385 <input name="email" value="[email protected]"> 3386 <input name="zipCode" value="90210"> 3387 </form> 3388 3389 <script> 3390 $('myForm').toQueryString() 3391 </script> 3392 (end) 3393 3394 Returns: 3395 [email protected]&zipCode=90210 3396 */ 3397 3398 toQueryString: function(){ 3399 var queryString = []; 3400 this.getFormElements().each(function(el){ 3401 var name = el.name; 3402 var value = el.getValue(); 3403 if (value === false || !name || el.disabled) return; 3404 var qs = function(val){ 3405 queryString.push(name + '=' + encodeURIComponent(val)); 3406 }; 3407 if ($type(value) == 'array') value.each(qs); 3408 else qs(value); 3409 }); 3410 return queryString.join('&'); 3411 } 3412 3413}); 3414 3415/* 3416Script: Element.Dimensions.js 3417 Contains Element prototypes to deal with Element size and position in space. 3418 3419Note: 3420 The functions in this script require n XHTML doctype. 3421 3422License: 3423 MIT-style license. 3424*/ 3425 3426/* 3427Class: Element 3428 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 3429*/ 3430 3431Element.extend({ 3432 3433 /* 3434 Property: scrollTo 3435 Scrolls the element to the specified coordinated (if the element has an overflow) 3436 3437 Arguments: 3438 x - the x coordinate 3439 y - the y coordinate 3440 3441 Example: 3442 >$('myElement').scrollTo(0, 100) 3443 */ 3444 3445 scrollTo: function(x, y){ 3446 this.scrollLeft = x; 3447 this.scrollTop = y; 3448 }, 3449 3450 /* 3451 Property: getSize 3452 Return an Object representing the size/scroll values of the element. 3453 3454 Example: 3455 (start code) 3456 $('myElement').getSize(); 3457 (end) 3458 3459 Returns: 3460 (start code) 3461 { 3462 'scroll': {'x': 100, 'y': 100}, 3463 'size': {'x': 200, 'y': 400}, 3464 'scrollSize': {'x': 300, 'y': 500} 3465 } 3466 (end) 3467 */ 3468 3469 getSize: function(){ 3470 return { 3471 'scroll': {'x': this.scrollLeft, 'y': this.scrollTop}, 3472 'size': {'x': this.offsetWidth, 'y': this.offsetHeight}, 3473 'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight} 3474 }; 3475 }, 3476 3477 /* 3478 Property: getPosition 3479 Returns the real offsets of the element. 3480 3481 Arguments: 3482 overflown - optional, an array of nested scrolling containers for scroll offset calculation, use this if your element is inside any element containing scrollbars 3483 3484 Example: 3485 >$('element').getPosition(); 3486 3487 Returns: 3488 >{x: 100, y:500}; 3489 */ 3490 3491 getPosition: function(overflown){
3492 overflown = overflown || []; 3493 var el = this, left = 0, top = 0; 3494 do { 3495 left += el.offsetLeft || 0; 3496 top += el.offsetTop || 0; 3497 el = el.offsetParent; 3498 } while (el); 3499 overflown.each(function(element){ 3500 left -= element.scrollLeft || 0; 3501 top -= element.scrollTop || 0; 3502 }); 3503 return {'x': left, 'y': top}; 3504 }, 3505 3506 /* 3507 Property: getTop 3508 Returns the distance from the top of the window to the Element. 3509 3510 Arguments: 3511 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3512 */ 3513 3514 getTop: function(overflown){ 3515 return this.getPosition(overflown).y; 3516 }, 3517 3518 /* 3519 Property: getLeft 3520 Returns the distance from the left of the window to the Element. 3521 3522 Arguments: 3523 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3524 */ 3525 3526 getLeft: function(overflown){ 3527 return this.getPosition(overflown).x; 3528 }, 3529 3530 /* 3531 Property: getCoordinates 3532 Returns an object with width, height, left, right, top, and bottom, representing the values of the Element 3533 3534 Arguments: 3535 overflown - optional, an array of nested scrolling containers, see Element::getPosition 3536 3537 Example: 3538 (start code) 3539 var myValues = $('myElement').getCoordinates(); 3540 (end) 3541 3542 Returns: 3543 (start code) 3544 { 3545 width: 200, 3546 height: 300, 3547 left: 100, 3548 top: 50, 3549 right: 300, 3550 bottom: 350 3551 } 3552 (end) 3553 */ 3554 3555 getCoordinates: function(overflown){ 3556 var position = this.getPosition(overflown); 3557 var obj = { 3558 'width': this.offsetWidth, 3559 'height': this.offsetHeight, 3560 'left': position.x, 3561 'top': position.y 3562 }; 3563 obj.right = obj.left + obj.width; 3564 obj.bottom = obj.top + obj.height; 3565 return obj; 3566 } 3567 3568}); 3569 3570/* 3571Script: Window.DomReady.js 3572 Contains the custom event domready, for window. 3573 3574License: 3575 MIT-style license. 3576*/ 3577 3578/* Section: Custom Events */ 3579 3580/* 3581Event: domready 3582 executes a function when the dom tree is loaded, without waiting for images. Only works when called from window. 3583 3584Credits: 3585 (c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools. 3586 3587Arguments: 3588 fn - the function to execute when the DOM is ready 3589 3590Example: 3591 > window.addEvent('domready', function(){ 3592 > alert('the dom is ready'); 3593 > }); 3594*/ 3595 3596Element.Events.domready = { 3597 3598 add: function(fn){ 3599 if (window.loaded){ 3600 fn.call(this); 3601 return; 3602 } 3603 var domReady = function(){ 3604 if (window.loaded) return; 3605 window.loaded = true; 3606 window.timer = $clear(window.timer); 3607 this.fireEvent('domready'); 3608 }.bind(this); 3609 if (document.readyState && window.webkit){ 3610 window.timer = function(){ 3611 if (['loaded','complete'].contains(document.readyState)) domReady(); 3612 }.periodical(50); 3613 } else if (document.readyState && window.ie){ 3614 if (!$('ie_ready')){ 3615 var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
3616 document.write('<script id="ie_ready" defer src="' + src + '"><\/script>'); 3617 $('ie_ready').onreadystatechange = function(){ 3618 if (this.readyState == 'complete') domReady(); 3619 }; 3620 } 3621 } else { 3622 window.addListener("load", domReady); 3623 document.addListener("DOMContentLoaded", domReady); 3624 } 3625 } 3626 3627}; 3628 3629/*compatibility*/ 3630 3631window.onDomReady = function(fn){ 3632 return this.addEvent('domready', fn); 3633}; 3634 3635/*end compatibility*/ 3636 3637/* 3638Script: Window.Size.js 3639 Window cross-browser dimensions methods. 3640 3641Note: 3642 The Functions in this script require an XHTML doctype. 3643 3644License: 3645 MIT-style license. 3646*/ 3647 3648/* 3649Class: window 3650 Cross browser methods to get various window dimensions. 3651 Warning: All these methods require that the browser operates in strict mode, not quirks mode. 3652*/ 3653 3654window.extend({ 3655 3656 /* 3657 Property: getWidth 3658 Returns an integer representing the width of the browser window (without the scrollbar). 3659 */ 3660 3661 getWidth: function(){ 3662 if (this.webkit419) return this.innerWidth; 3663 if (this.opera) return document.body.clientWidth; 3664 return document.documentElement.clientWidth; 3665 }, 3666 3667 /* 3668 Property: getHeight 3669 Returns an integer representing the height of the browser window (without the scrollbar). 3670 */ 3671 3672 getHeight: function(){ 3673 if (this.webkit419) return this.innerHeight; 3674 if (this.opera) return document.body.clientHeight; 3675 return document.documentElement.clientHeight; 3676 }, 3677 3678 /* 3679 Property: getScrollWidth 3680 Returns an integer representing the scrollWidth of the window. 3681 This value is equal to or bigger than <getWidth>. 3682 3683 See Also: 3684 <http://developer.mozilla.org/en/docs/DOM:element.scrollWidth> 3685 */ 3686 3687 getScrollWidth: function(){ 3688 if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth); 3689 if (this.webkit) return document.body.scrollWidth; 3690 return document.documentElement.scrollWidth; 3691 }, 3692 3693 /* 3694 Property: getScrollHeight 3695 Returns an integer representing the scrollHeight of the window. 3696 This value is equal to or bigger than <getHeight>. 3697 3698 See Also: 3699 <http://developer.mozilla.org/en/docs/DOM:element.scrollHeight> 3700 */ 3701 3702 getScrollHeight: function(){ 3703 if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight); 3704 if (this.webkit) return document.body.scrollHeight; 3705 return document.documentElement.scrollHeight; 3706 }, 3707 3708 /* 3709 Property: getScrollLeft 3710 Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left). 3711 3712 See Also: 3713 <http://developer.mozilla.org/en/docs/DOM:element.scrollLeft> 3714 */ 3715 3716 getScrollLeft: function(){ 3717 return this.pageXOffset || document.documentElement.scrollLeft; 3718 }, 3719 3720 /* 3721 Property: getScrollTop 3722 Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top). 3723 3724 See Also: 3725 <http://developer.mozilla.org/en/docs/DOM:element.scrollTop> 3726 */ 3727 3728 getScrollTop: function(){ 3729 return this.pageYOffset || document.documentElement.scrollTop; 3730 }, 3731 3732 /* 3733 Property: getSize 3734 Same as <Element.getSize> 3735 */ 3736 3737 getSize: function(){ 3738 return { 3739 'size': {'x': this.getWidth(), 'y': this.getHeight()}, 3740 'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()}, 3741 'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()} 3742 }; 3743 }, 3744 3745 //ignore 3746 getPosition: function(){return {'x': 0, 'y': 0};} 3747 3748}); 3749 3750/* 3751Script: Fx.Base.js 3752 Contains <Fx.Base>, the foundamentals of the MooTools Effects. 3753 3754License: 3755 MIT-style license. 3756*/ 3757 3758var Fx = {}; 3759 3760/* 3761Class: Fx.Base 3762 Base class for the Effects. 3763 3764Options: 3765 transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.Sine.easeInOut> 3766 duration - the duration of the effect in ms; 500 is the default. 3767 unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%'). 3768 wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true. 3769 fps - the frames per second for the transition; default is 50 3770 3771Events: 3772 onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default. 3773 onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default. 3774 onCancel - the function to execute when you manually stop the effect. 3775*/ 3776 3777Fx.Base = new Class({ 3778 3779 options: { 3780 onStart: Class.empty, 3781 onComplete: Class.empty, 3782 onCancel: Class.empty, 3783 transition: function(p){ 3784 return -(Math.cos(Math.PI * p) - 1) / 2; 3785 }, 3786 duration: 500, 3787 unit: 'px', 3788 wait: true, 3789 fps: 50 3790 }, 3791 3792 initialize: function(options){ 3793 this.element = this.element || null; 3794 this.setOptions(options); 3795 if (this.options.initialize) this.options.initialize.call(this); 3796 }, 3797 3798 step: function(){ 3799 var time = $time(); 3800 if (time < this.time + this.options.duration){ 3801 this.delta = this.options.transition((time - this.time) / this.options.duration); 3802 this.setNow(); 3803 this.increase(); 3804 } else { 3805 this.stop(true); 3806 this.set(this.to); 3807 this.fireEvent('onComplete', this.element, 10); 3808 this.callChain(); 3809 } 3810 }, 3811 3812 /* 3813 Property: set 3814 Immediately sets the value with no transition. 3815 3816 Arguments: 3817 to - the point to jump to 3818 3819 Example: 3820 >var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent 3821 */ 3822 3823 set: function(to){ 3824 this.now = to; 3825 this.increase(); 3826 return this; 3827 }, 3828 3829 setNow: function(){ 3830 this.now = this.compute(this.from, this.to); 3831 }, 3832 3833 compute: function(from, to){ 3834 return (to - from) * this.delta + from; 3835 }, 3836 3837 /* 3838 Property: start 3839 Executes an effect from one position to the other. 3840 3841 Arguments: 3842 from - integer: staring value 3843 to - integer: the ending value 3844 3845 Examples: 3846 >var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque. 3847 */ 3848 3849 start: function(from, to){ 3850 if (!this.options.wait) this.stop(); 3851 else if (this.timer) return this; 3852 this.from = from; 3853 this.to = to; 3854 this.change = this.to - this.from; 3855 this.time = $time(); 3856 this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); 3857 this.fireEvent('onStart', this.element); 3858 return this; 3859 }, 3860 3861 /* 3862 Property: stop 3863 Stops the transition. 3864 */ 3865
3866 stop: function(end){ 3867 if (!this.timer) return this; 3868 this.timer = $clear(this.timer); 3869 if (!end) this.fireEvent('onCancel', this.element); 3870 return this; 3871 }/*compatibility*/, 3872 3873 custom: function(from, to){ 3874 return this.start(from, to); 3875 }, 3876 3877 clearTimer: function(end){ 3878 return this.stop(end); 3879 } 3880 3881 /*end compatibility*/ 3882 3883}); 3884 3885Fx.Base.implement(new Chain, new Events, new Options); 3886 3887/* 3888Script: Fx.CSS.js 3889 Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally. 3890 3891License: 3892 MIT-style license. 3893*/ 3894 3895Fx.CSS = { 3896 3897 select: function(property, to){ 3898 if (property.test(/color/i)) return this.Color; 3899 var type = $type(to); 3900 if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi; 3901 return this.Single; 3902 }, 3903 3904 parse: function(el, property, fromTo){ 3905 if (!fromTo.push) fromTo = [fromTo]; 3906 var from = fromTo[0], to = fromTo[1]; 3907 if (!$chk(to)){ 3908 to = from; 3909 from = el.getStyle(property); 3910 } 3911 var css = this.select(property, to); 3912 return {'from': css.parse(from), 'to': css.parse(to), 'css': css}; 3913 } 3914 3915}; 3916 3917Fx.CSS.Single = { 3918 3919 parse: function(value){ 3920 return parseFloat(value); 3921 }, 3922 3923 getNow: function(from, to, fx){ 3924 return fx.compute(from, to); 3925 }, 3926 3927 getValue: function(value, unit, property){ 3928 if (unit == 'px' && property != 'opacity') value = Math.round(value); 3929 return value + unit; 3930 } 3931 3932}; 3933 3934Fx.CSS.Multi = { 3935 3936 parse: function(value){ 3937 return value.push ? value : value.split(' ').map(function(v){ 3938 return parseFloat(v); 3939 }); 3940 }, 3941 3942 getNow: function(from, to, fx){ 3943 var now = []; 3944 for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]); 3945 return now; 3946 }, 3947 3948 getValue: function(value, unit, property){ 3949 if (unit == 'px' && property != 'opacity') value = value.map(Math.round); 3950 return value.join(unit + ' ') + unit; 3951 } 3952 3953}; 3954 3955Fx.CSS.Color = { 3956 3957 parse: function(value){ 3958 return value.push ? value : value.hexToRgb(true); 3959 }, 3960 3961 getNow: function(from, to, fx){ 3962 var now = []; 3963 for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i])); 3964 return now; 3965 }, 3966 3967 getValue: function(value){ 3968 return 'rgb(' + value.join(',') + ')'; 3969 } 3970 3971}; 3972 3973/* 3974Script: Fx.Style.js 3975 Contains <Fx.Style> 3976 3977License: 3978 MIT-style license. 3979*/ 3980 3981/* 3982Class: Fx.Style 3983 The Style effect, used to transition any css property from one value to another. Includes colors. 3984 Colors must be in hex format. 3985 Inherits methods, properties, options and events from <Fx.Base>. 3986 3987Arguments: 3988 el - the $(element) to apply the style transition to 3989 property - the property to transition 3990 options - the Fx.Base options (see: <Fx.Base>) 3991 3992Example: 3993 >var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500}); 3994 >marginChange.start(10, 100); 3995*/ 3996 3997Fx.Style = Fx.Base.extend({ 3998 3999 initialize: function(el, property, options){ 4000 this.element = $(el); 4001 this.property = property; 4002 this.parent(options); 4003 }, 4004 4005 /* 4006 Property: hide 4007 Same as <Fx.Base.set> (0); hides the element immediately without transition. 4008 */ 4009 4010 hide: function(){ 4011 return this.set(0); 4012 }, 4013 4014 setNow: function(){ 4015 this.now = this.css.getNow(this.from, this.to, this); 4016 }, 4017 4018 /* 4019 Property: set 4020 Sets the element's css property (specified at instantiation) to the specified value immediately. 4021 4022 Example: 4023 (start code) 4024 var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500}); 4025 marginChange.set(10); //margin-top is set to 10px immediately 4026 (end) 4027 */ 4028 4029 set: function(to){ 4030 this.css = Fx.CSS.select(this.property, to); 4031 return this.parent(this.css.parse(to)); 4032 }, 4033 4034 /* 4035 Property: start 4036 Displays the transition to the value/values passed in 4037 4038 Arguments: 4039 from - (integer; optional) the starting position for the transition 4040 to - (integer) the ending position for the transition 4041 4042 Note: 4043 If you provide only one argument, the transition will use the current css value for its starting value. 4044 4045 Example: 4046 (start code) 4047 var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500}); 4048 marginChange.start(10); //tries to read current margin top value and goes from current to 10 4049 (end) 4050 */ 4051 4052 start: function(from, to){ 4053 if (this.timer && this.options.wait) return this; 4054 var parsed = Fx.CSS.parse(this.element, this.property, [from, to]); 4055 this.css = parsed.css; 4056 return this.parent(parsed.from, parsed.to); 4057 }, 4058 4059 increase: function(){ 4060 this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property)); 4061 } 4062 4063}); 4064 4065/* 4066Class: Element 4067 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4068*/ 4069 4070Element.extend({ 4071 4072 /* 4073 Property: effect 4074 Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>. 4075 4076 Arguments: 4077 property - (string) the css property to alter 4078 options - (object; optional) key/value set of options (see <Fx.Style>) 4079 4080 Example: 4081 >var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}); 4082 >myEffect.start(10, 100); 4083 >//OR 4084 >$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100); 4085 */ 4086 4087 effect: function(property, options){ 4088 return new Fx.Style(this, property, options); 4089 } 4090 4091}); 4092 4093/* 4094Script: Fx.Styles.js 4095 Contains <Fx.Styles> 4096 4097License: 4098 MIT-style license. 4099*/ 4100 4101/* 4102Class: Fx.Styles 4103 Allows you to animate multiple css properties at once; 4104 Colors must be in hex format. 4105 Inherits methods, properties, options and events from <Fx.Base>. 4106 4107Arguments: 4108 el - the $(element) to apply the styles transition to 4109 options - the fx options (see: <Fx.Base>) 4110 4111Example: 4112 (start code) 4113 var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.linear}); 4114 4115 //height from 10 to 100 and width from 900 to 300 4116 myEffects.start({ 4117 'height': [10, 100], 4118 'width': [900, 300] 4119 }); 4120 4121 //or height from current height to 100 and width from current width to 300 4122 myEffects.start({ 4123 'height': 100, 4124 'width': 300 4125 }); 4126 (end) 4127*/ 4128 4129Fx.Styles = Fx.Base.extend({ 4130 4131 initialize: function(el, options){ 4132 this.element = $(el); 4133 this.parent(options); 4134 }, 4135 4136 setNow: function(){ 4137 for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this); 4138 }, 4139 4140 set: function(to){ 4141 var parsed = {}; 4142 this.css = {}; 4143 for (var p in to){ 4144 this.css[p] = Fx.CSS.select(p, to[p]); 4145 parsed[p] = this.css[p].parse(to[p]); 4146 } 4147 return this.parent(parsed); 4148 }, 4149 4150 /* 4151 Property: start 4152 Executes a transition for any number of css properties in tandem. 4153 4154 Arguments:
4155 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). 4156 4157 Example: 4158 see <Fx.Styles> 4159 */ 4160 4161 start: function(obj){ 4162 if (this.timer && this.options.wait) return this; 4163 this.now = {}; 4164 this.css = {}; 4165 var from = {}, to = {}; 4166 for (var p in obj){ 4167 var parsed = Fx.CSS.parse(this.element, p, obj[p]); 4168 from[p] = parsed.from; 4169 to[p] = parsed.to; 4170 this.css[p] = parsed.css; 4171 } 4172 return this.parent(from, to); 4173 }, 4174 4175 increase: function(){ 4176 for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit, p)); 4177 } 4178 4179}); 4180 4181/* 4182Class: Element 4183 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4184*/ 4185 4186Element.extend({ 4187 4188 /* 4189 Property: effects 4190 Applies an <Fx.Styles> to the Element; This a shortcut for <Fx.Styles>. 4191 4192 Example: 4193 >var myEffects = $(myElement).effects({duration: 1000, transition: Fx.Transitions.Sine.easeInOut}); 4194 >myEffects.start({'height': [10, 100], 'width': [900, 300]}); 4195 */ 4196 4197 effects: function(options){ 4198 return new Fx.Styles(this, options); 4199 } 4200 4201}); 4202 4203/* 4204Script: Fx.Elements.js 4205 Contains <Fx.Elements> 4206 4207License: 4208 MIT-style license. 4209*/ 4210 4211/* 4212Class: Fx.Elements 4213 Fx.Elements allows you to apply any number of styles transitions to a selection of elements. Includes colors (must be in hex format). 4214 Inherits methods, properties, options and events from <Fx.Base>. 4215 4216Arguments: 4217 elements - a collection of elements the effects will be applied to. 4218 options - same as <Fx.Base> options. 4219*/ 4220 4221Fx.Elements = Fx.Base.extend({ 4222 4223 initialize: function(elements, options){ 4224 this.elements = $$(elements); 4225 this.parent(options); 4226 }, 4227 4228 setNow: function(){ 4229 for (var i in this.from){ 4230 var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {}; 4231 for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this); 4232 } 4233 }, 4234 4235 set: function(to){ 4236 var parsed = {}; 4237 this.css = {}; 4238 for (var i in to){ 4239 var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {}; 4240 for (var p in iTo){ 4241 iCss[p] = Fx.CSS.select(p, iTo[p]); 4242 iParsed[p] = iCss[p].parse(iTo[p]); 4243 } 4244 } 4245 return this.parent(parsed); 4246 }, 4247 4248 /* 4249 Property: start 4250 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. 4251 4252 Example: 4253 (start code) 4254 var myElementsEffects = new Fx.Elements($$('a')); 4255 myElementsEffects.start({ 4256 '0': { //let's change the first element's opacity and width 4257 'opacity': [0,1], 4258 'width': [100,200] 4259 }, 4260 '4': { //and the fifth one's opacity 4261 'opacity': [0.2, 0.5] 4262 } 4263 }); 4264 (end) 4265 */ 4266 4267 start: function(obj){ 4268 if (this.timer && this.options.wait) return this; 4269 this.now = {}; 4270 this.css = {}; 4271 var from = {}, to = {}; 4272 for (var i in obj){ 4273 var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {}; 4274 for (var p in iProps){ 4275 var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]); 4276 iFrom[p] = parsed.from; 4277 iTo[p] = parsed.to; 4278 iCss[p] = parsed.css; 4279 } 4280 } 4281 return this.parent(from, to); 4282 }, 4283 4284 increase: function(){ 4285 for (var i in this.now){ 4286 var iNow = this.now[i], iCss = this.css[i]; 4287 for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit, p)); 4288 } 4289 } 4290 4291}); 4292 4293/* 4294Script: Fx.Scroll.js 4295 Contains <Fx.Scroll> 4296 4297License: 4298 MIT-style license. 4299*/ 4300 4301/* 4302Class: Fx.Scroll 4303 Scroll any element with an overflow, including the window element. 4304 Inherits methods, properties, options and events from <Fx.Base>. 4305 4306Note: 4307 Fx.Scroll requires an XHTML doctype. 4308 4309Arguments: 4310 element - the element to scroll 4311 options - optional, see Options below. 4312 4313Options: 4314 all the Fx.Base options and events, plus: 4315 offset - the distance for the scrollTo point/element. an Object with x/y properties. 4316 overflown - an array of nested scrolling containers, see <Element.getPosition> 4317*/ 4318 4319Fx.Scroll = Fx.Base.extend({ 4320 4321 options: { 4322 overflown: [], 4323 offset: {'x': 0, 'y': 0}, 4324 wheelStops: true 4325 }, 4326 4327 initialize: function(element, options){ 4328 this.now = []; 4329 this.element = $(element); 4330 this.bound = {'stop': this.stop.bind(this, false)}; 4331 this.parent(options); 4332 if (this.options.wheelStops){ 4333 this.addEvent('onStart', function(){ 4334 document.addEvent('mousewheel', this.bound.stop); 4335 }.bind(this)); 4336 this.addEvent('onComplete', function(){ 4337 document.removeEvent('mousewheel', this.bound.stop); 4338 }.bind(this)); 4339 } 4340 }, 4341 4342 setNow: function(){ 4343 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 4344 }, 4345 4346 /* 4347 Property: scrollTo 4348 Scrolls the chosen element to the x/y coordinates. 4349 4350 Arguments: 4351 x - the x coordinate to scroll the element to 4352 y - the y coordinate to scroll the element to 4353 */ 4354 4355 scrollTo: function(x, y){ 4356 if (this.timer && this.options.wait) return this; 4357 var el = this.element.getSize(); 4358 var values = {'x': x, 'y': y}; 4359 for (var z in el.size){ 4360 var max = el.scrollSize[z] - el.size[z]; 4361 if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max; 4362 else values[z] = el.scroll[z]; 4363 values[z] += this.options.offset[z]; 4364 } 4365 return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]); 4366 }, 4367 4368 /* 4369 Property: toTop 4370 Scrolls the chosen element to its maximum top. 4371 */ 4372 4373 toTop: function(){ 4374 return this.scrollTo(false, 0); 4375 }, 4376 4377 /* 4378 Property: toBottom 4379 Scrolls the chosen element to its maximum bottom. 4380 */ 4381 4382 toBottom: function(){ 4383 return this.scrollTo(false, 'full'); 4384 }, 4385 4386 /* 4387 Property: toLeft 4388 Scrolls the chosen element to its maximum left. 4389 */ 4390 4391 toLeft: function(){ 4392 return this.scrollTo(0, false); 4393 }, 4394 4395 /* 4396 Property: toRight 4397 Scrolls the chosen element to its maximum right. 4398 */ 4399 4400 toRight: function(){ 4401 return this.scrollTo('full', false); 4402 }, 4403 4404 /* 4405 Property: toElement 4406 Scrolls the specified element to the position the passed in element is found. 4407 4408 Arguments: 4409 el - the $(element) to scroll the window to 4410 */ 4411 4412 toElement: function(el){ 4413 var parent = this.element.getPosition(this.options.overflown); 4414 var target = $(el).getPosition(this.options.overflown); 4415 return this.scrollTo(target.x - parent.x, target.y - parent.y); 4416 }, 4417 4418 increase: function(){ 4419 this.element.scrollTo(this.now[0], this.now[1]); 4420 } 4421 4422}); 4423 4424/* 4425Script: Fx.Slide.js 4426 Contains <Fx.Slide> 4427 4428License: 4429 MIT-style license. 4430*/ 4431 4432/* 4433Class: Fx.Slide 4434 The slide effect; slides an element in horizontally or vertically, the contents will fold inside. 4435 Inherits methods, properties, options and events from <Fx.Base>. 4436 4437Note: 4438 Fx.Slide requires an XHTML doctype. 4439 4440Options: 4441 mode - set it to vertical or horizontal. Defaults to vertical. 4442 options - all the <Fx.Base> options 4443 4444Example: 4445 (start code) 4446 var mySlider = new Fx.Slide('myElement', {duration: 500});
4447 mySlider.toggle() //toggle the slider up and down. 4448 (end) 4449*/ 4450 4451Fx.Slide = Fx.Base.extend({ 4452 4453 options: { 4454 mode: 'vertical' 4455 }, 4456 4457 initialize: function(el, options){ 4458 4459 this.element = $(el); 4460 4461 this.wrapper = new Element('div', {'styles': $extend({margin: "0px 0px 0px 0px"}, {'overflow': 'hidden'})}).injectAfter(this.element).adopt(this.element); 4462 this.element.setStyle('margin', 0); 4463 this.setOptions(options); 4464 this.now = []; 4465 this.parent(this.options); 4466 this.open = true; 4467 this.addEvent('onComplete', function(){ 4468 this.open = (this.now[0] === 0); 4469 }); 4470 if (window.webkit419) this.addEvent('onComplete', function(){ 4471 if (this.open) this.element.remove().inject(this.wrapper); 4472 }); 4473 }, 4474 4475 setNow: function(){ 4476 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 4477 }, 4478 4479 vertical: function(){ 4480 this.margin = 'margin-top'; 4481 this.layout = 'height'; 4482 this.offset = this.element.offsetHeight; 4483 }, 4484 4485 horizontal: function(){ 4486 this.margin = 'margin-left'; 4487 this.layout = 'width'; 4488 this.offset = this.element.offsetWidth; 4489 }, 4490 4491 /* 4492 Property: slideIn 4493 Slides the elements in view horizontally or vertically. 4494 4495 Arguments: 4496 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4497 */ 4498 4499 slideIn: function(mode){ 4500 this[mode || this.options.mode](); 4501 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.offset]); 4502 }, 4503 4504 /* 4505 Property: slideOut 4506 Sides the elements out of view horizontally or vertically. 4507 4508 Arguments: 4509 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4510 */ 4511 4512 slideOut: function(mode){ 4513 this[mode || this.options.mode](); 4514 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]); 4515 }, 4516 4517 /* 4518 Property: hide 4519 Hides the element without a transition. 4520 4521 Arguments: 4522 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4523 */ 4524 4525 hide: function(mode){ 4526 this[mode || this.options.mode](); 4527 this.open = false; 4528 return this.set([-this.offset, 0]); 4529 }, 4530 4531 /* 4532 Property: show 4533 Shows the element without a transition. 4534 4535 Arguments: 4536 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4537 */ 4538 4539 show: function(mode){ 4540 this[mode || this.options.mode](); 4541 this.open = true; 4542 return this.set([0, this.offset]); 4543 }, 4544 4545 /* 4546 Property: toggle 4547 Slides in or Out the element, depending on its state 4548 4549 Arguments: 4550 mode - (optional, string) 'horizontal' or 'vertical'; defaults to options.mode. 4551 4552 */ 4553 4554 toggle: function(mode){ 4555 if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode); 4556 return this.slideOut(mode); 4557 }, 4558 4559 increase: function(){ 4560 this.element.setStyle(this.margin, this.now[0] + this.options.unit); 4561 this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit); 4562 } 4563 4564}); 4565 4566/* 4567Script: Fx.Transitions.js 4568 Effects transitions, to be used with all the effects. 4569 4570License: 4571 MIT-style license. 4572 4573Credits: 4574 Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified & optimized to be used with mootools. 4575*/ 4576 4577/* 4578Class: Fx.Transitions 4579 A collection of tweening transitions for use with the <Fx.Base> classes. 4580 4581Example: 4582 >//Elastic.easeOut with default values: 4583 >new Fx.Style('margin', {transition: Fx.Transitions.Elastic.easeOut}); 4584 >//Elastic.easeOut with user-defined value for elasticity. 4585 > var myTransition = new Fx.Transition(Fx.Transitions.Elastic, 3); 4586 >new Fx.Style('margin', {transition: myTransition.easeOut}); 4587 4588See also: 4589 http://www.robertpenner.com/easing/ 4590*/ 4591 4592Fx.Transition = function(transition, params){ 4593 params = params || []; 4594 if ($type(params) != 'array') params = [params]; 4595 return $extend(transition, { 4596 easeIn: function(pos){ 4597 return transition(pos, params); 4598 }, 4599 easeOut: function(pos){ 4600 return 1 - transition(1 - pos, params); 4601 }, 4602 easeInOut: function(pos){ 4603 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2; 4604 } 4605 }); 4606}; 4607 4608Fx.Transitions = new Abstract({ 4609 4610 /* 4611 Property: linear 4612 displays a linear transition. 4613 4614 Graph: 4615 (see Linear.png) 4616 */ 4617 4618 linear: function(p){ 4619 return p; 4620 } 4621 4622}); 4623 4624Fx.Transitions.extend = function(transitions){ 4625 for (var transition in transitions){ 4626 Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 4627 /*compatibility*/ 4628 Fx.Transitions.compat(transition); 4629 /*end compatibility*/ 4630 } 4631}; 4632 4633/*compatibility*/ 4634 4635Fx.Transitions.compat = function(transition){ 4636 ['In', 'Out', 'InOut'].each(function(easeType){ 4637 Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType]; 4638 }); 4639}; 4640 4641/*end compatibility*/ 4642 4643Fx.Transitions.extend({ 4644 4645 /* 4646 Property: Quad 4647 displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut 4648 4649 Graph: 4650 (see Quad.png) 4651 */ 4652 4653 //auto generated 4654 4655 /* 4656 Property: Cubic 4657 displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut 4658 4659 Graph: 4660 (see Cubic.png) 4661 */ 4662 4663 //auto generated 4664 4665 /* 4666 Property: Quart 4667 displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut 4668 4669 Graph: 4670 (see Quart.png) 4671 */ 4672 4673 //auto generated 4674 4675 /* 4676 Property: Quint 4677 displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut 4678 4679 Graph: 4680 (see Quint.png) 4681 */ 4682 4683 //auto generated 4684 4685 /* 4686 Property: Pow
4687 Used to generate Quad, Cubic, Quart and Quint. 4688 By default is p^6. 4689 4690 Graph: 4691 (see Pow.png) 4692 */ 4693 4694 Pow: function(p, x){ 4695 return Math.pow(p, x[0] || 6); 4696 }, 4697 4698 /* 4699 Property: Expo 4700 displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut 4701 4702 Graph: 4703 (see Expo.png) 4704 */ 4705 4706 Expo: function(p){ 4707 return Math.pow(2, 8 * (p - 1)); 4708 }, 4709 4710 /* 4711 Property: Circ 4712 displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut 4713 4714 Graph: 4715 (see Circ.png) 4716 */ 4717 4718 Circ: function(p){ 4719 return 1 - Math.sin(Math.acos(p)); 4720 }, 4721 4722 4723 /* 4724 Property: Sine 4725 displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut 4726 4727 Graph: 4728 (see Sine.png) 4729 */ 4730 4731 Sine: function(p){ 4732 return 1 - Math.sin((1 - p) * Math.PI / 2); 4733 }, 4734 4735 /* 4736 Property: Back 4737 makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut 4738 4739 Graph: 4740 (see Back.png) 4741 */ 4742 4743 Back: function(p, x){ 4744 x = x[0] || 1.618; 4745 return Math.pow(p, 2) * ((x + 1) * p - x); 4746 }, 4747 4748 /* 4749 Property: Bounce 4750 makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut 4751 4752 Graph: 4753 (see Bounce.png) 4754 */ 4755 4756 Bounce: function(p){ 4757 var value; 4758 for (var a = 0, b = 1; 1; a += b, b /= 2){ 4759 if (p >= (7 - 4 * a) / 11){ 4760 value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b; 4761 break; 4762 } 4763 } 4764 return value; 4765 }, 4766 4767 /* 4768 Property: Elastic 4769 Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut 4770 4771 Graph: 4772 (see Elastic.png) 4773 */ 4774 4775 Elastic: function(p, x){ 4776 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3); 4777 } 4778 4779}); 4780 4781['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ 4782 Fx.Transitions[transition] = new Fx.Transition(function(p){ 4783 return Math.pow(p, [i + 2]); 4784 }); 4785 4786 /*compatibility*/ 4787 Fx.Transitions.compat(transition); 4788 /*end compatibility*/ 4789}); 4790 4791/* 4792Script: Drag.Base.js 4793 Contains <Drag.Base>, <Element.makeResizable> 4794 4795License: 4796 MIT-style license. 4797*/ 4798 4799var Drag = {}; 4800 4801/* 4802Class: Drag.Base 4803 Modify two css properties of an element based on the position of the mouse. 4804 4805Note: 4806 Drag.Base requires an XHTML doctype. 4807 4808Arguments: 4809 el - the $(element) to apply the transformations to. 4810 options - optional. The options object. 4811 4812Options: 4813 handle - the $(element) to act as the handle for the draggable element. defaults to the $(element) itself. 4814 modifiers - an object. see Modifiers Below. 4815 limit - an object, see Limit below. 4816 grid - optional, distance in px for snap-to-grid dragging 4817 snap - optional, the distance you have to drag before the element starts to respond to the drag. defaults to false 4818 4819 modifiers: 4820 x - string, the style you want to modify when the mouse moves in an horizontal direction. defaults to 'left' 4821 y - string, the style you want to modify when the mouse moves in a vertical direction. defaults to 'top' 4822 4823 limit: 4824 x - array with start and end limit relative to modifiers.x 4825 y - array with start and end limit relative to modifiers.y 4826 4827Events: 4828 onStart - optional, function to execute when the user starts to drag (on mousedown); 4829 onComplete - optional, function to execute when the user completes the drag. 4830 onDrag - optional, function to execute at every step of the drag 4831*/ 4832 4833Drag.Base = new Class({ 4834 4835 options: { 4836 handle: false, 4837 unit: 'px', 4838 onStart: Class.empty, 4839 onBeforeStart: Class.empty, 4840 onComplete: Class.empty, 4841 onSnap: Class.empty, 4842 onDrag: Class.empty, 4843 limit: false, 4844 modifiers: {x: 'left', y: 'top'}, 4845 grid: false, 4846 snap: 6 4847 }, 4848 4849 initialize: function(el, options){ 4850 this.setOptions(options); 4851 this.element = $(el); 4852 this.handle = $(this.options.handle) || this.element; 4853 this.mouse = {'now': {}, 'pos': {}}; 4854 this.value = {'start': {}, 'now': {}}; 4855 this.bound = { 4856 'start': this.start.bindWithEvent(this), 4857 'check': this.check.bindWithEvent(this), 4858 'drag': this.drag.bindWithEvent(this), 4859 'stop': this.stop.bind(this) 4860 }; 4861 this.attach(); 4862 if (this.options.initialize) this.options.initialize.call(this); 4863 }, 4864 4865 attach: function(){ 4866 this.handle.addEvent('mousedown', this.bound.start); 4867 return this; 4868 }, 4869 4870 detach: function(){ 4871 this.handle.removeEvent('mousedown', this.bound.start); 4872 return this; 4873 }, 4874 4875 start: function(event){ 4876 this.fireEvent('onBeforeStart', this.element); 4877 this.mouse.start = event.page; 4878 var limit = this.options.limit; 4879 this.limit = {'x': [], 'y': []}; 4880 for (var z in this.options.modifiers){ 4881 if (!this.options.modifiers[z]) continue; 4882 this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt(); 4883 this.mouse.pos[z] = event.page[z] - this.value.now[z]; 4884 if (limit && limit[z]){ 4885 for (var i = 0; i < 2; i++){ 4886 if ($chk(limit[z][i])) this.limit[z][i] = ($type(limit[z][i]) == 'function') ? limit[z][i]() : limit[z][i]; 4887 } 4888 } 4889 } 4890 if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid}; 4891 document.addListener('mousemove', this.bound.check); 4892 document.addListener('mouseup', this.bound.stop); 4893 this.fireEvent('onStart', this.element); 4894 event.stop(); 4895 }, 4896 4897 check: function(event){ 4898 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))); 4899 if (distance > this.options.snap){ 4900 document.removeListener('mousemove', this.bound.check); 4901 document.addListener('mousemove', this.bound.drag); 4902 this.drag(event); 4903 this.fireEvent('onSnap', this.element); 4904 } 4905 event.stop(); 4906 }, 4907 4908 drag: function(event){ 4909 this.out = false;
4910 this.mouse.now = event.page; 4911 for (var z in this.options.modifiers){ 4912 if (!this.options.modifiers[z]) continue; 4913 this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; 4914 if (this.limit[z]){ 4915 if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){ 4916 this.value.now[z] = this.limit[z][1]; 4917 this.out = true; 4918 } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){ 4919 this.value.now[z] = this.limit[z][0]; 4920 this.out = true; 4921 } 4922 } 4923 if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]); 4924 this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit); 4925 } 4926 this.fireEvent('onDrag', this.element); 4927 event.stop(); 4928 }, 4929 4930 stop: function(){ 4931 document.removeListener('mousemove', this.bound.check); 4932 document.removeListener('mousemove', this.bound.drag); 4933 document.removeListener('mouseup', this.bound.stop); 4934 this.fireEvent('onComplete', this.element); 4935 } 4936 4937}); 4938 4939Drag.Base.implement(new Events, new Options); 4940 4941/* 4942Class: Element 4943 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 4944*/ 4945 4946Element.extend({ 4947 4948 /* 4949 Property: makeResizable 4950 Makes an element resizable (by dragging) with the supplied options. 4951 4952 Arguments: 4953 options - see <Drag.Base> for acceptable options. 4954 */ 4955 4956 makeResizable: function(options){ 4957 return new Drag.Base(this, $merge({modifiers: {x: 'width', y: 'height'}}, options)); 4958 } 4959 4960}); 4961 4962/* 4963Script: Drag.Move.js 4964 Contains <Drag.Move>, <Element.makeDraggable> 4965 4966License: 4967 MIT-style license. 4968*/ 4969 4970/* 4971Class: Drag.Move 4972 Extends <Drag.Base>, has additional functionality for dragging an element, support snapping and droppables. 4973 Drag.move supports either position absolute or relative. If no position is found, absolute will be set. 4974 Inherits methods, properties, options and events from <Drag.Base>. 4975 4976Note: 4977 Drag.Move requires an XHTML doctype. 4978 4979Arguments: 4980 el - the $(element) to apply the drag to. 4981 options - optional. see Options below. 4982 4983Options: 4984 all the drag.Base options, plus: 4985 container - an element, will fill automatically limiting options based on the $(element) size and position. defaults to false (no limiting) 4986 droppables - an array of elements you can drop your draggable to. 4987 overflown - an array of nested scrolling containers, see Element::getPosition 4988*/ 4989 4990Drag.Move = Drag.Base.extend({ 4991 4992 options: { 4993 droppables: [], 4994 container: false, 4995 overflown: [] 4996 }, 4997 4998 initialize: function(el, options){ 4999 this.setOptions(options); 5000 this.element = $(el); 5001 this.droppables = $$(this.options.droppables); 5002 this.container = $(this.options.container); 5003 this.position = {'element': this.element.getStyle('position'), 'container': false}; 5004 if (this.container) this.position.container = this.container.getStyle('position'); 5005 if (!['relative', 'absolute', 'fixed'].contains(this.position.element)) this.position.element = 'absolute'; 5006 var top = this.element.getStyle('top').toInt(); 5007 var left = this.element.getStyle('left').toInt(); 5008 if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){ 5009 top = $chk(top) ? top : this.element.getTop(this.options.overflown); 5010 left = $chk(left) ? left : this.element.getLeft(this.options.overflown); 5011 } else { 5012 top = $chk(top) ? top : 0; 5013 left = $chk(left) ? left : 0; 5014 } 5015 this.element.setStyles({'top': top, 'left': left, 'position': this.position.element}); 5016 this.parent(this.element); 5017 }, 5018 5019 start: function(event){ 5020 this.overed = null; 5021 if (this.container){ 5022 var cont = this.container.getCoordinates(); 5023 var el = this.element.getCoordinates(); 5024 if (this.position.element == 'absolute' && !['relative', 'absolute', 'fixed'].contains(this.position.container)){ 5025 this.options.limit = { 5026 'x': [cont.left, cont.right - el.width], 5027 'y': [cont.top, cont.bottom - el.height] 5028 }; 5029 } else { 5030 this.options.limit = { 5031 'y': [0, cont.height - el.height], 5032 'x': [0, cont.width - el.width] 5033 }; 5034 } 5035 } 5036 this.parent(event); 5037 }, 5038 5039 drag: function(event){ 5040 this.parent(event); 5041 var overed = this.out ? false : this.droppables.filter(this.checkAgainst, this).getLast(); 5042 if (this.overed != overed){ 5043 if (this.overed) this.overed.fireEvent('leave', [this.element, this]); 5044 this.overed = overed ? overed.fireEvent('over', [this.element, this]) : null; 5045 } 5046 return this; 5047 }, 5048 5049 checkAgainst: function(el){ 5050 el = el.getCoordinates(this.options.overflown); 5051 var now = this.mouse.now; 5052 return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); 5053 }, 5054 5055 stop: function(){ 5056 if (this.overed && !this.out) this.overed.fireEvent('drop', [this.element, this]); 5057 else this.element.fireEvent('emptydrop', this); 5058 this.parent(); 5059 return this; 5060 } 5061 5062}); 5063 5064/* 5065Class: Element 5066 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 5067*/ 5068 5069Element.extend({ 5070 5071 /* 5072 Property: makeDraggable 5073 Makes an element draggable with the supplied options. 5074 5075 Arguments: 5076 options - see <Drag.Move> and <Drag.Base> for acceptable options. 5077 */ 5078 5079 makeDraggable: function(options){ 5080 return new Drag.Move(this, options); 5081 } 5082 5083}); 5084 5085/* 5086Script: XHR.js 5087 Contains the basic XMLHttpRequest Class Wrapper. 5088 5089License: 5090 MIT-style license. 5091*/ 5092 5093/* 5094Class: XHR 5095 Basic XMLHttpRequest Wrapper. 5096 5097Arguments: 5098 options - an object with options names as keys. See options below. 5099 5100Options: 5101 method - 'post' or 'get' - the protocol for the request; optional, defaults to 'post'. 5102 async - boolean: asynchronous option; true uses asynchronous requests. Defaults to true. 5103 encoding - the encoding, defaults to utf-8. 5104 autoCancel - cancels the already running request if another one is sent. defaults to false. 5105 headers - accepts an object, that will be set to request headers. 5106 5107Events: 5108 onRequest - function to execute when the XHR request is fired. 5109 onSuccess - function to execute when the XHR request completes. 5110 onStateChange - function to execute when the state of the XMLHttpRequest changes. 5111 onFailure - function to execute when the state of the XMLHttpRequest changes. 5112 5113Properties: 5114 running - true if the request is running. 5115 response - object, text and xml as keys. You can access this property in the onSuccess event. 5116 5117Example: 5118 >var myXHR = new XHR({method: 'get'}).send('http://site.com/requestHandler.php', 'name=john&lastname=dorian'); 5119*/ 5120 5121var XHR = new Class({ 5122 5123 options: { 5124 method: 'post', 5125 async: true, 5126 onRequest: Class.empty, 5127 onSuccess: Class.empty, 5128 onFailure: Class.empty, 5129 urlEncoded: true, 5130 encoding: 'utf-8', 5131 autoCancel: false, 5132 headers: {} 5133 }, 5134 5135 setTransport: function(){ 5136 this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false); 5137 return this; 5138 }, 5139 5140 initialize: function(options){ 5141 this.setTransport().setOptions(options); 5142 this.options.isSuccess = this.options.isSuccess || this.isSuccess; 5143 this.headers = {}; 5144 if (this.options.urlEncoded && this.options.method == 'post'){ 5145 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; 5146 this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding); 5147 } 5148 if (this.options.initialize) this.options.initialize.call(this); 5149 }, 5150 5151 onStateChange: function(){ 5152 if (this.transport.readyState != 4 || !this.running) return; 5153 this.running = false;
5154 var status = 0; 5155 try {status = this.transport.status;} catch(e){}; 5156 if (this.options.isSuccess.call(this, status)) this.onSuccess(); 5157 else this.onFailure(); 5158 this.transport.onreadystatechange = Class.empty; 5159 }, 5160 5161 isSuccess: function(status){ 5162 return ((status >= 200) && (status < 300)); 5163 }, 5164 5165 onSuccess: function(){ 5166 this.response = { 5167 'text': this.transport.responseText, 5168 'xml': this.transport.responseXML 5169 }; 5170 this.fireEvent('onSuccess', [this.response.text, this.response.xml]); 5171 this.callChain(); 5172 }, 5173 5174 onFailure: function(){ 5175 this.fireEvent('onFailure', this.transport); 5176 }, 5177 5178 /* 5179 Property: setHeader 5180 Add/modify an header for the request. It will not override headers from the options. 5181 5182 Example: 5183 >var myXhr = new XHR(url, {method: 'get', headers: {'X-Request': 'JSON'}}); 5184 >myXhr.setHeader('Last-Modified','Sat, 1 Jan 2005 05:00:00 GMT'); 5185 */ 5186 5187 setHeader: function(name, value){ 5188 this.headers[name] = value; 5189 return this; 5190 }, 5191 5192 /* 5193 Property: send 5194 Opens the XHR connection and sends the data. Data has to be null or a string. 5195 5196 Example: 5197 >var myXhr = new XHR({method: 'post'}); 5198 >myXhr.send(url, querystring); 5199 > 5200 >var syncXhr = new XHR({async: false, method: 'post'}); 5201 >syncXhr.send(url, null); 5202 > 5203 */ 5204 5205 send: function(url, data){ 5206 if (this.options.autoCancel) this.cancel(); 5207 else if (this.running) return this; 5208 this.running = true; 5209 if (data && this.options.method == 'get'){ 5210 url = url + (url.contains('?') ? '&' : '?') + data; 5211 data = null; 5212 } 5213 this.transport.open(this.options.method.toUpperCase(), url, this.options.async); 5214 this.transport.onreadystatechange = this.onStateChange.bind(this); 5215 if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close'); 5216 $extend(this.headers, this.options.headers); 5217 for (var type in this.headers) try {this.transport.setRequestHeader(type, this.headers[type]);} catch(e){}; 5218 this.fireEvent('onRequest'); 5219 this.transport.send($pick(data, null)); 5220 return this; 5221 }, 5222 5223 /* 5224 Property: cancel 5225 Cancels the running request. No effect if the request is not running. 5226 5227 Example: 5228 >var myXhr = new XHR({method: 'get'}).send(url); 5229 >myXhr.cancel(); 5230 */ 5231 5232 cancel: function(){ 5233 if (!this.running) return this; 5234 this.running = false; 5235 this.transport.abort(); 5236 this.transport.onreadystatechange = Class.empty; 5237 this.setTransport(); 5238 this.fireEvent('onCancel'); 5239 return this; 5240 } 5241 5242}); 5243 5244XHR.implement(new Chain, new Events, new Options); 5245 5246/* 5247Script: Ajax.js 5248 Contains the <Ajax> class. Also contains methods to generate querystings from forms and Objects. 5249 5250Credits: 5251 Loosely based on the version from prototype.js <http://prototype.conio.net> 5252 5253License: 5254 MIT-style license. 5255*/ 5256 5257/* 5258Class: Ajax 5259 An Ajax class, For all your asynchronous needs. 5260 Inherits methods, properties, options and events from <XHR>. 5261 5262Arguments: 5263 url - the url pointing to the server-side script. 5264 options - optional, an object containing options. 5265 5266Options: 5267 data - you can write parameters here. Can be a querystring, an object or a Form element. 5268 update - $(element) to insert the response text of the XHR into, upon completion of the request. 5269 evalScripts - boolean; default is false. Execute scripts in the response text onComplete. When the response is javascript the whole response is evaluated. 5270 evalResponse - boolean; default is false. Force global evalulation of the whole response, no matter what content-type it is. 5271 5272Events: 5273 onComplete - function to execute when the ajax request completes. 5274 5275Example: 5276 >var myAjax = new Ajax(url, {method: 'get'}).request(); 5277*/ 5278 5279var Ajax = XHR.extend({ 5280 5281 options: { 5282 data: null, 5283 update: null, 5284 onComplete: Class.empty, 5285 evalScripts: false, 5286 evalResponse: false 5287 }, 5288 5289 initialize: function(url, options){ 5290 this.addEvent('onSuccess', this.onComplete); 5291 this.setOptions(options); 5292 /*compatibility*/ 5293 this.options.data = this.options.data || this.options.postBody; 5294 /*end compatibility*/ 5295 if (!['post', 'get'].contains(this.options.method)){ 5296 this._method = '_method=' + this.options.method; 5297 this.options.method = 'post'; 5298 } 5299 this.parent(); 5300 this.setHeader('X-Requested-With', 'XMLHttpRequest'); 5301 this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*'); 5302 this.url = url; 5303 }, 5304 5305 onComplete: function(){ 5306 if (this.options.update) $(this.options.update).empty().setHTML(this.response.text); 5307 if (this.options.evalScripts || this.options.evalResponse) this.evalScripts(); 5308 this.fireEvent('onComplete', [this.response.text, this.response.xml], 20); 5309 }, 5310 5311 /* 5312 Property: request
5313 Executes the ajax request. 5314 5315 Example: 5316 >var myAjax = new Ajax(url, {method: 'get'}); 5317 >myAjax.request(); 5318 5319 OR 5320 5321 >new Ajax(url, {method: 'get'}).request(); 5322 */ 5323 5324 request: function(data){ 5325 data = data || this.options.data; 5326 switch($type(data)){ 5327 case 'element': data = $(data).toQueryString(); break; 5328 case 'object': data = Object.toQueryString(data); 5329 } 5330 if (this._method) data = (data) ? [this._method, data].join('&') : this._method; 5331 return this.send(this.url, data); 5332 }, 5333 5334 /* 5335 Property: evalScripts 5336 Executes scripts in the response text 5337 */ 5338 5339 evalScripts: function(){ 5340 var script, scripts; 5341 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) scripts = this.response.text; 5342 else { 5343 scripts = []; 5344 var regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi; 5345 while ((script = regexp.exec(this.response.text))) scripts.push(script[1]); 5346 scripts = scripts.join('\n'); 5347 } 5348 if (scripts) (window.execScript) ? window.execScript(scripts) : window.setTimeout(scripts, 0); 5349 }, 5350 5351 /* 5352 Property: getHeader 5353 Returns the given response header or null 5354 */ 5355 5356 getHeader: function(name){ 5357 try {return this.transport.getResponseHeader(name);} catch(e){}; 5358 return null; 5359 } 5360 5361}); 5362 5363/* Section: Object related Functions */ 5364 5365/* 5366Function: Object.toQueryString 5367 Generates a querystring from key/pair values in an object 5368 5369Arguments: 5370 source - the object to generate the querystring from. 5371 5372Returns: 5373 the query string. 5374 5375Example: 5376 >Object.toQueryString({apple: "red", lemon: "yellow"}); //returns "apple=red&lemon=yellow" 5377*/ 5378 5379Object.toQueryString = function(source){ 5380 var queryString = []; 5381 for (var property in source) queryString.push(encodeURIComponent(property) + '=' + encodeURIComponent(source[property])); 5382 return queryString.join('&'); 5383}; 5384 5385/* 5386Class: Element 5387 Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>. 5388*/ 5389 5390Element.extend({ 5391 5392 /* 5393 Property: send 5394 Sends a form with an ajax post request 5395 5396 Arguments: 5397 options - option collection for ajax request. See <Ajax> for the options list. 5398 5399 Returns: 5400 The Ajax Class Instance 5401 5402 Example: 5403 (start code) 5404 <form id="myForm" action="submit.php"> 5405 <input name="email" value="[email protected]"> 5406 <input name="zipCode" value="90210"> 5407 </form> 5408 <script> 5409 $('myForm').send() 5410 </script> 5411 (end) 5412 */ 5413 5414 send: function(options){ 5415 return new Ajax(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request(); 5416 } 5417 5418}); 5419 5420/* 5421Script: Cookie.js 5422 A cookie reader/creator 5423 5424Credits: 5425 based on the functions by Peter-Paul Koch (http://quirksmode.org) 5426*/ 5427 5428/* 5429Class: Cookie 5430 Class for creating, getting, and removing cookies. 5431*/ 5432 5433var Cookie = new Abstract({ 5434 5435 options: { 5436 domain: false, 5437 path: false, 5438 duration: false, 5439 secure: false 5440 }, 5441 5442 /* 5443 Property: set 5444 Sets a cookie in the browser. 5445 5446 Arguments: 5447 key - the key (name) for the cookie 5448 value - the value to set, cannot contain semicolons 5449 options - an object representing the Cookie options. See Options below. Default values are stored in Cookie.options. 5450 5451 Options: 5452 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. 5453 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. 5454 duration - the duration of the Cookie before it expires, in days. 5455 If set to false or 0, the cookie will be a session cookie that expires when the browser is closed. This is default. 5456 secure - Stored cookie information can be accessed only from a secure environment. 5457 5458 Returns: 5459 An object with the options, the key and the value. You can give it as first parameter to Cookie.remove. 5460 5461 Example: 5462 >Cookie.set('username', 'Harald'); // session cookie (duration is false), or ... 5463 >Cookie.set('username', 'JackBauer', {duration: 1}); // save this for 1 day 5464 5465 */ 5466 5467 set: function(key, value, options){ 5468 options = $merge(this.options, options); 5469 value = encodeURIComponent(value); 5470 if (options.domain) value += '; domain=' + options.domain; 5471 if (options.path) value += '; path=' + options.path; 5472 if (options.duration){ 5473 var date = new Date(); 5474 date.setTime(date.getTime() + options.duration * 24 * 60 * 60 * 1000); 5475 value += '; expires=' + date.toGMTString(); 5476 } 5477 if (options.secure) value += '; secure'; 5478 document.cookie = key + '=' + value; 5479 return $extend(options, {'key': key, 'value': value}); 5480 }, 5481 5482 /* 5483 Property: get 5484 Gets the value of a cookie. 5485 5486 Arguments: 5487 key - the name of the cookie you wish to retrieve. 5488 5489 Returns: 5490 The cookie string value, or false if not found. 5491
5492 Example: 5493 >Cookie.get("username") //returns JackBauer 5494 */ 5495 5496 get: function(key){ 5497 var value = document.cookie.match('(?:^|;)\\s*' + key.escapeRegExp() + '=([^;]*)'); 5498 return value ? decodeURIComponent(value[1]) : false; 5499 }, 5500 5501 /* 5502 Property: remove 5503 Removes a cookie from the browser. 5504 5505 Arguments: 5506 cookie - the name of the cookie to remove or a previous cookie (for domains) 5507 options - optional. you can also pass the domain and path here. Same as options in <Cookie.set> 5508 5509 Examples: 5510 >Cookie.remove('username') //bye-bye JackBauer, cya in 24 hours 5511 > 5512 >var myCookie = Cookie.set('username', 'Aaron', {domain: 'mootools.net'}); // Cookie.set returns an object with all values need to remove the cookie 5513 >Cookie.remove(myCookie); 5514 */ 5515 5516 remove: function(cookie, options){ 5517 if ($type(cookie) == 'object') this.set(cookie.key, '', $merge(cookie, {duration: -1})); 5518 else this.set(cookie, '', $merge(options, {duration: -1})); 5519 } 5520 5521}); 5522 5523/* 5524Script: Json.js 5525 Simple Json parser and Stringyfier, See: <http://www.json.org/> 5526 5527License: 5528 MIT-style license. 5529*/ 5530 5531/* 5532Class: Json 5533 Simple Json parser and Stringyfier, See: <http://www.json.org/> 5534*/ 5535 5536var Json = { 5537 5538 /* 5539 Property: toString 5540 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. 5541 5542 Arguments: 5543 obj - the object to convert to string 5544 5545 Returns: 5546 A json string 5547 5548 Example: 5549 (start code) 5550 Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}' 5551 (end) 5552 */ 5553 5554 toString: function(obj){ 5555 switch($type(obj)){ 5556 case 'string': 5557 return '"' + obj.replace(/(["\\])/g, '\\$1') + '"'; 5558 case 'array': 5559 return '[' + obj.map(Json.toString).join(',') + ']'; 5560 case 'object': 5561 var string = []; 5562 for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property])); 5563 return '{' + string.join(',') + '}'; 5564 case 'number': 5565 if (isFinite(obj)) break; 5566 case false: 5567 return 'null'; 5568 } 5569 return String(obj); 5570 }, 5571 5572 /* 5573 Property: evaluate 5574 converts a json string to an javascript Object. 5575 5576 Arguments: 5577 str - the string to evaluate. if its not a string, it returns false. 5578 secure - optionally, performs syntax check on json string. Defaults to false. 5579 5580 Credits: 5581 Json test regexp is by Douglas Crockford <http://crockford.org>. 5582 5583 Example: 5584 >var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}'); 5585 >//myObject will become {apple: 'red', lemon: 'yellow'} 5586 */ 5587 5588 evaluate: function(str, secure){ 5589 return (($type(str) != 'string') || (secure && !str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/))) ? null : eval('(' + str + ')'); 5590 } 5591 5592}; 5593 5594/* 5595Script: Json.Remote.js 5596 Contains <Json.Remote>. 5597 5598License: 5599 MIT-style license. 5600*/ 5601 5602/* 5603Class: Json.Remote 5604 Wrapped XHR with automated sending and receiving of Javascript Objects in Json Format. 5605 Inherits methods, properties, options and events from <XHR>. 5606 5607Arguments: 5608 url - the url you want to send your object to. 5609 options - see <XHR> options 5610 5611Example: 5612 this code will send user information based on name/last name 5613 (start code) 5614 var jSonRequest = new Json.Remote("http://site.com/tellMeAge.php", {onComplete: function(person){ 5615 alert(person.age); //is 25 years 5616 alert(person.height); //is 170 cm 5617 alert(person.weight); //is 120 kg 5618 }}).send({'name': 'John', 'lastName': 'Doe'}); 5619 (end) 5620*/ 5621 5622Json.Remote = XHR.extend({ 5623 5624 initialize: function(url, options){ 5625 this.url = url; 5626 this.addEvent('onSuccess', this.onComplete); 5627 this.parent(options); 5628 this.setHeader('X-Request', 'JSON'); 5629 }, 5630 5631 send: function(obj){ 5632 return this.parent(this.url, 'json=' + Json.toString(obj)); 5633 }, 5634 5635 onComplete: function(){ 5636 this.fireEvent('onComplete', [Json.evaluate(this.response.text, this.options.secure)]); 5637 } 5638 5639}); 5640 5641/* 5642Script: Assets.js 5643 provides dynamic loading for images, css and javascript files. 5644 5645License: 5646 MIT-style license. 5647*/ 5648 5649var Asset = new Abstract({ 5650 5651 /* 5652 Property: javascript 5653 Injects a javascript file in the page. 5654 5655 Arguments: 5656 source - the path of the javascript file 5657 properties - some additional attributes you might want to add to the script element 5658 5659 Example: 5660 >
5660 new Asset.javascript('/scripts/myScript.js', {id: 'myScript'}); 5661 */ 5662 5663 javascript: function(source, properties){ 5664 properties = $merge({ 5665 'onload': Class.empty 5666 }, properties); 5667 var script = new Element('script', {'src': source}).addEvents({ 5668 'load': properties.onload, 5669 'readystatechange': function(){ 5670 if (this.readyState == 'complete') this.fireEvent('load'); 5671 } 5672 }); 5673 delete properties.onload; 5674 return script.setProperties(properties).inject(document.head); 5675 }, 5676 5677 /* 5678 Property: css 5679 Injects a css file in the page. 5680 5681 Arguments: 5682 source - the path of the css file 5683 properties - some additional attributes you might want to add to the link element 5684 5685 Example: 5686 > new Asset.css('/css/myStyle.css', {id: 'myStyle', title: 'myStyle'}); 5687 */ 5688 5689 css: function(source, properties){ 5690 return new Element('link', $merge({ 5691 'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source 5692 }, properties)).inject(document.head); 5693 }, 5694 5695 /* 5696 Property: image 5697 Preloads an image and returns the img element. does not inject it to the page. 5698 5699 Arguments: 5700 source - the path of the image file 5701 properties - some additional attributes you might want to add to the img element 5702 5703 Example: 5704 > new Asset.image('/images/myImage.png', {id: 'myImage', title: 'myImage', onload: myFunction}); 5705 5706 Returns: 5707 the img element. you can inject it anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore> 5708 */ 5709 5710 image: function(source, properties){ 5711 properties = $merge({ 5712 'onload': Class.empty, 5713 'onabort': Class.empty, 5714 'onerror': Class.empty 5715 }, properties); 5716 var image = new Image(); 5717 image.src = source; 5718 var element = new Element('img', {'src': source}); 5719 ['load', 'abort', 'error'].each(function(type){ 5720 var event = properties['on' + type]; 5721 delete properties['on' + type]; 5722 element.addEvent(type, function(){ 5723 this.removeEvent(type, arguments.callee); 5724 event.call(this); 5725 }); 5726 }); 5727 if (image.width && image.height) element.fireEvent('load', element, 1); 5728 return element.setProperties(properties); 5729 }, 5730 5731 /* 5732 Property: images 5733 Preloads an array of images (as strings) and returns an array of img elements. does not inject them to the page. 5734 5735 Arguments: 5736 sources - array, the paths of the image files 5737 options - object, see below 5738 5739 Options: 5740 onComplete - a function to execute when all image files are loaded in the browser's cache 5741 onProgress - a function to execute when one image file is loaded in the browser's cache 5742 5743 Example: 5744 (start code) 5745 new Asset.images(['/images/myImage.png', '/images/myImage2.gif'], { 5746 onComplete: function(){ 5747 alert('all images loaded!'); 5748 } 5749 }); 5750 (end) 5751 5752 Returns: 5753 the img elements as $$. you can inject them anywhere you want with <Element.injectInside>/<Element.injectAfter>/<Element.injectBefore> 5754 */ 5755 5756 images: function(sources, options){ 5757 options = $merge({ 5758 onComplete: Class.empty, 5759 onProgress: Class.empty 5760 }, options); 5761 if (!sources.push) sources = [sources]; 5762 var images = []; 5763 var counter = 0; 5764 sources.each(function(source){ 5765 var img = new Asset.image(source, { 5766 'onload': function(){ 5767 options.onProgress.call(this, counter); 5768 counter++; 5769 if (counter == sources.length) options.onComplete(); 5770 } 5771 }); 5772 images.push(img); 5773 }); 5774 return new Elements(images); 5775 } 5776 5777}); 5778 5779/* 5780Script: Hash.js 5781 Contains the class Hash. 5782 5783License: 5784 MIT-style license. 5785*/ 5786 5787/* 5788Class: Hash 5789 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. 5790 5791Note: 5792 Each hash instance has the length property. 5793 5794Arguments: 5795 obj - an object to convert into a Hash instance. 5796 5797Example: 5798 (start code) 5799 var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'}); 5800 hash.remove('b'); // b is removed. 5801 hash.set('c', 'hello'); 5802 hash.get('c'); // returns 'hello' 5803 hash.length // returns 2 (a and c) 5804 (end) 5805*/ 5806 5807var Hash = new Class({ 5808 5809 length: 0, 5810 5811 initialize: function(object){ 5812 this.obj = object || {}; 5813 this.setLength(); 5814 }, 5815 5816 /* 5817 Property: get 5818 Retrieves a value from the hash. 5819 5820 Arguments: 5821 key - The key 5822 5823 Returns: 5824 The value 5825 */ 5826 5827 get: function(key){ 5828 return (this.hasKey(key)) ? this.obj[key] : null; 5829 }, 5830 5831 /* 5832 Property: hasKey 5833 Check the presence of a specified key-value pair in the hash. 5834 5835 Arguments: 5836 key - The key 5837 5838 Returns: 5839 True if the Hash contains a value for the specified key, otherwise false 5840 */ 5841 5842 hasKey: function(key){ 5843 return (key in this.obj); 5844 }, 5845 5846 /* 5847 Property: set 5848 Adds a key-value pair to the hash or replaces a previous value associated with the key. 5849 5850 Arguments: 5851 key - The key 5852 value - The value 5853 */ 5854 5855 set: function(key, value){ 5856 if (!this.hasKey(key)) this.length++; 5857 this.obj[key] = value; 5858 return this; 5859 }, 5860 5861 setLength: function(){ 5862 this.length = 0; 5863 for (var p in this.obj) this.length++; 5864 return this; 5865 }, 5866 5867 /* 5868 Property: remove 5869 Removes a key-value pair from the hash. 5870 5871 Arguments: 5872 key - The key 5873 */ 5874 5875 remove: function(key){ 5876 if (this.hasKey(key)){ 5877 delete this.obj[key]; 5878 this.length--; 5879 } 5880 return this; 5881 }, 5882 5883 /* 5884 Property: each 5885 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. 5886 5887 Arguments: 5888 fn - The function to call for each key-value pair 5889 bind - Optional, the object that will be referred to as "this" in the function 5890 */ 5891 5892 each: function(fn, bind){ 5893 $each(this.obj, fn, bind); 5894 }, 5895 5896 /* 5897 Property: extend
5898 Extends the current hash with an object containing key-value pairs. Values for duplicate keys will be replaced by the new ones. 5899 5900 Arguments: 5901 obj - An object containing key-value pairs 5902 */ 5903 5904 extend: function(obj){ 5905 $extend(this.obj, obj); 5906 return this.setLength(); 5907 }, 5908 5909 /* 5910 Property: merge 5911 Merges the current hash with multiple objects. 5912 */ 5913 5914 merge: function(){ 5915 this.obj = $merge.apply(null, [this.obj].extend(arguments)); 5916 return this.setLength(); 5917 }, 5918 5919 /* 5920 Property: empty 5921 Empties all hash values properties and values. 5922 */ 5923 5924 empty: function(){ 5925 this.obj = {}; 5926 this.length = 0; 5927 return this; 5928 }, 5929 5930 /* 5931 Property: keys 5932 Returns an array containing all the keys, in the same order as the values returned by <Hash.values>. 5933 5934 Returns: 5935 An array containing all the keys of the hash 5936 */ 5937 5938 keys: function(){ 5939 var keys = []; 5940 for (var property in this.obj) keys.push(property); 5941 return keys; 5942 }, 5943 5944 /* 5945 Property: values 5946 Returns an array containing all the values, in the same order as the keys returned by <Hash.keys>. 5947 5948 Returns: 5949 An array containing all the values of the hash 5950 */ 5951 5952 values: function(){ 5953 var values = []; 5954 for (var property in this.obj) values.push(this.obj[property]); 5955 return values; 5956 } 5957 5958}); 5959 5960/* Section: Utility Functions */ 5961 5962/* 5963Function: $H 5964 Shortcut to create a Hash from an Object. 5965*/ 5966 5967function $H(obj){ 5968 return new Hash(obj); 5969}; 5970 5971/* 5972Script: Hash.Cookie.js 5973 Stores and loads an Hash as a cookie using Json format. 5974*/ 5975 5976/* 5977Class: Hash.Cookie 5978 Inherits all the methods from <Hash>, additional methods are save and load. 5979 Hash json string has a limit of 4kb (4096byte), so be careful with your Hash size. 5980 Creating a new instance automatically loads the data from the Cookie into the Hash. 5981 If the Hash is emptied, the cookie is also removed. 5982 5983Arguments: 5984 name - the key (name) for the cookie 5985 options - options are identical to <Cookie> and are simply passed along to it. 5986 In addition, it has the autoSave option, to save the cookie at every operation. defaults to true. 5987 5988Example: 5989 (start code) 5990 var fruits = new Hash.Cookie('myCookieName', {duration: 3600}); 5991 fruits.extend({ 5992 'lemon': 'yellow', 5993 'apple': 'red' 5994 }); 5995 fruits.set('melon', 'green'); 5996 fruits.get('lemon'); // yellow 5997 5998 // ... on another page ... values load automatically 5999 6000 var fruits = new Hash.Cookie('myCookieName', {duration: 365}); 6001 fruits.get('melon'); // green 6002 6003 fruits.erase(); // delete cookie 6004 (end) 6005*/ 6006 6007Hash.Cookie = Hash.extend({ 6008 6009 initialize: function(name, options){ 6010 this.name = name; 6011 this.options = $extend({'autoSave': true}, options || {}); 6012 this.load(); 6013 }, 6014 6015 /* 6016 Property: save 6017 Saves the Hash to the cookie. If the hash is empty, removes the cookie. 6018 6019 Returns: 6020 Returns false when the JSON string cookie is too long (4kb), otherwise true. 6021 6022 Example: 6023 (start code) 6024 var login = new Hash.Cookie('userstatus', {autoSave: false}); 6025 6026 login.extend({ 6027 'username': 'John', 6028 'credentials': [4, 7, 9] 6029 }); 6030 login.set('last_message', 'User logged in!'); 6031 6032 login.save(); // finally save the Hash 6033 (end) 6034 */ 6035 6036 save: function(){ 6037 if (this.length == 0){ 6038 Cookie.remove(this.name, this.options); 6039 return true; 6040 } 6041 var str = Json.toString(this.obj); 6042 if (str.length > 4096) return false; //cookie would be truncated! 6043 Cookie.set(this.name, str, this.options); 6044 return true; 6045 }, 6046 6047 /* 6048 Property: load 6049 Loads the cookie and assigns it to the Hash. 6050 */ 6051 6052 load: function(){ 6053 this.obj = Json.evaluate(Cookie.get(this.name), true) || {}; 6054 this.setLength(); 6055 } 6056 6057}); 6058 6059Hash.Cookie.Methods = {}; 6060['extend', 'set', 'merge', 'empty', 'remove'].each(function(method){ 6061 Hash.Cookie.Methods[method] = function(){ 6062 Hash.prototype[method].apply(this, arguments); 6063 if (this.options.autoSave) this.save(); 6064 return this; 6065 }; 6066}); 6067Hash.Cookie.implement(Hash.Cookie.Methods); 6068 6069/* 6070Script: Color.js 6071 Contains the Color class. 6072 6073License: 6074 MIT-style license. 6075*/ 6076 6077/* 6078Class: Color 6079 Creates a new Color Object, which is an array with some color specific methods. 6080Arguments: 6081 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. 6082 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'. 6083 6084Example: 6085 (start code) 6086 var black = new Color('#000'); 6087 var purple = new Color([255,0,255]); 6088 // mix black with white and purple, each time at 10% of the new color 6089 var darkpurple = black.mix('#fff', purple, 10); 6090 $('myDiv').setStyle('background-color', darkpurple); 6091 (end) 6092*/ 6093 6094var Color = new Class({ 6095 6096 initialize: function(color, type){ 6097 type = type || (color.push ? 'rgb' : 'hex'); 6098 var rgb, hsb; 6099 switch(type){ 6100 case 'rgb': 6101 rgb = color; 6102 hsb = rgb.rgbToHsb(); 6103 break; 6104 case 'hsb': 6105 rgb = color.hsbToRgb(); 6106 hsb = color; 6107 break; 6108 default: 6109 rgb = color.hexToRgb(true); 6110 hsb = rgb.rgbToHsb(); 6111 } 6112 rgb.hsb = hsb; 6113 rgb.hex = rgb.rgbToHex(); 6114 return $extend(rgb, Color.prototype); 6115 }, 6116 6117 /* 6118 Property: mix 6119 Mixes two or more colors with the Color. 6120 6121 Arguments: 6122 color - a color to mix. you can use as arguments how many colors as you want to mix with the original one. 6123 alpha - if you use a number as the last argument, it will be threated as the amount of the color to mix. 6124 */ 6125 6126 mix: function(){ 6127 var colors = $A(arguments); 6128 var alpha = ($type(colors[colors.length - 1]) == 'number') ? colors.pop() : 50; 6129 var rgb = this.copy(); 6130 colors.each(function(color){ 6131 color = new Color(color); 6132 for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); 6133 }); 6134 return new Color(rgb, 'rgb'); 6135 }, 6136 6137 /* 6138 Property: invert
6139 Inverts the Color. 6140 */ 6141 6142 invert: function(){ 6143 return new Color(this.map(function(value){ 6144 return 255 - value; 6145 })); 6146 }, 6147 6148 /* 6149 Property: setHue 6150 Modifies the hue of the Color, and returns a new one. 6151 6152 Arguments: 6153 value - the hue to set 6154 */ 6155 6156 setHue: function(value){ 6157 return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); 6158 }, 6159 6160 /* 6161 Property: setSaturation 6162 Changes the saturation of the Color, and returns a new one. 6163 6164 Arguments: 6165 percent - the percentage of the saturation to set 6166 */ 6167 6168 setSaturation: function(percent){ 6169 return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); 6170 }, 6171 6172 /* 6173 Property: setBrightness 6174 Changes the brightness of the Color, and returns a new one. 6175 6176 Arguments: 6177 percent - the percentage of the brightness to set 6178 */ 6179 6180 setBrightness: function(percent){ 6181 return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); 6182 } 6183 6184}); 6185 6186/* Section: Utility Functions */ 6187 6188/* 6189Function: $RGB 6190 Shortcut to create a new color, based on red, green, blue values. 6191 6192Arguments: 6193 r - (integer) red value (0-255) 6194 g - (integer) green value (0-255) 6195 b - (integer) blue value (0-255) 6196 6197*/ 6198 6199function $RGB(r, g, b){ 6200 return new Color([r, g, b], 'rgb'); 6201}; 6202 6203/* 6204Function: $HSB 6205 Shortcut to create a new color, based on hue, saturation, brightness values. 6206 6207Arguments: 6208 h - (integer) hue value (0-100) 6209 s - (integer) saturation value (0-100) 6210 b - (integer) brightness value (0-100) 6211*/ 6212 6213function $HSB(h, s, b){ 6214 return new Color([h, s, b], 'hsb'); 6215}; 6216 6217/* 6218Class: Array 6219 A collection of The Array Object prototype methods. 6220*/ 6221 6222Array.extend({ 6223 6224 /* 6225 Property: rgbToHsb 6226 Converts a RGB array to an HSB array. 6227 6228 Returns: 6229 the HSB array. 6230 */ 6231 6232 rgbToHsb: function(){ 6233 var red = this[0], green = this[1], blue = this[2]; 6234 var hue, saturation, brightness; 6235 var max = Math.max(red, green, blue), min = Math.min(red, green, blue); 6236 var delta = max - min; 6237 brightness = max / 255; 6238 saturation = (max != 0) ? delta / max : 0; 6239 if (saturation == 0){ 6240 hue = 0; 6241 } else { 6242 var rr = (max - red) / delta; 6243 var gr = (max - green) / delta; 6244 var br = (max - blue) / delta; 6245 if (red == max) hue = br - gr; 6246 else if (green == max) hue = 2 + rr - br; 6247 else hue = 4 + gr - rr; 6248 hue /= 6; 6249 if (hue < 0) hue++; 6250 } 6251 return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; 6252 }, 6253 6254 /* 6255 Property: hsbToRgb 6256 Converts an HSB array to an RGB array. 6257 6258 Returns: 6259 the RGB array. 6260 */ 6261 6262 hsbToRgb: function(){ 6263 var br = Math.round(this[2] / 100 * 255); 6264 if (this[1] == 0){ 6265 return [br, br, br]; 6266 } else { 6267 var hue = this[0] % 360; 6268 var f = hue % 60; 6269 var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); 6270 var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); 6271 var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); 6272 switch(Math.floor(hue / 60)){ 6273 case 0: return [br, t, p]; 6274 case 1: return [q, br, p]; 6275 case 2: return [p, br, t]; 6276 case 3: return [p, q, br]; 6277 case 4: return [t, p, br]; 6278 case 5: return [br, p, q]; 6279 } 6280 } 6281 return false; 6282 } 6283 6284}); 6285 6286/* 6287Script: Scroller.js 6288 Contains the <Scroller>. 6289 6290License: 6291 MIT-style license. 6292*/ 6293 6294/* 6295Class: Scroller 6296 The Scroller is a class to scroll any element with an overflow (including the window) when the mouse
6296cursor reaches certain buondaries of that element. 6297 You must call its start method to start listening to mouse movements. 6298 6299Note: 6300 The Scroller requires an XHTML doctype. 6301 6302Arguments: 6303 element - required, the element to scroll. 6304 options - optional, see options below, and <Fx.Base> options. 6305 6306Options: 6307 area - integer, the necessary boundaries to make the element scroll. 6308 velocity - integer, velocity ratio, the modifier for the window scrolling speed. 6309 6310Events: 6311 onChange - optionally, when the mouse reaches some boundaries, you can choose to alter some other values, instead of the scrolling offsets. 6312 Automatically passes as parameters x and y values. 6313*/ 6314 6315var Scroller = new Class({ 6316 6317 options: { 6318 area: 20, 6319 velocity: 1, 6320 onChange: function(x, y){ 6321 this.element.scrollTo(x, y); 6322 } 6323 }, 6324 6325 initialize: function(element, options){ 6326 this.setOptions(options); 6327 this.element = $(element); 6328 this.mousemover = ([window, document].contains(element)) ? $(document.body) : this.element; 6329 }, 6330 6331 /* 6332 Property: start 6333 The scroller starts listening to mouse movements. 6334 */ 6335 6336 start: function(){ 6337 this.coord = this.getCoords.bindWithEvent(this); 6338 this.mousemover.addListener('mousemove', this.coord); 6339 }, 6340 6341 /* 6342 Property: stop 6343 The scroller stops listening to mouse movements. 6344 */ 6345 6346 stop: function(){ 6347 this.mousemover.removeListener('mousemove', this.coord); 6348 this.timer = $clear(this.timer); 6349 }, 6350 6351 getCoords: function(event){ 6352 this.page = (this.element == window) ? event.client : event.page; 6353 if (!this.timer) this.timer = this.scroll.periodical(50, this); 6354 }, 6355 6356 scroll: function(){ 6357 var el = this.element.getSize(); 6358 var pos = this.element.getPosition(); 6359 6360 var change = {'x': 0, 'y': 0}; 6361 for (var z in this.page){ 6362 if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0) 6363 change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity; 6364 else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z]) 6365 change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity; 6366 } 6367 if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]); 6368 } 6369 6370}); 6371 6372Scroller.implement(new Events, new Options); 6373 6374/* 6375Script: Slider.js 6376 Contains <Slider> 6377 6378License: 6379 MIT-style license. 6380*/ 6381 6382/* 6383Class: Slider 6384 Creates a slider with two elements: a knob and a container. Returns the values. 6385 6386Note: 6387 The Slider requires an XHTML doctype. 6388 6389Arguments: 6390 element - the knob container 6391 knob - the handle 6392 options - see Options below 6393 6394Options: 6395 steps - the number of steps for your slider. 6396 mode - either 'horizontal' or 'vertical'. defaults to horizontal. 6397 offset - relative offset for knob position. default to 0. 6398 6399Events: 6400 onChange - a function to fire when the value changes. 6401 onComplete - a function to fire when you're done dragging. 6402 onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position. 6403 Passes as parameter the new position. 6404*/ 6405 6406var Slider = new Class({ 6407 6408 options: { 6409 onChange: Class.empty, 6410 onComplete: Class.empty, 6411 onTick: function(pos){ 6412 this.knob.setStyle(this.p, pos); 6413 }, 6414 mode: 'horizontal', 6415 steps: 100, 6416 offset: 0 6417 }, 6418 6419 initialize: function(el, knob, options){ 6420 this.element = $(el); 6421 this.knob = $(knob); 6422 this.setOptions(options); 6423 this.previousChange = -1; 6424 this.previousEnd = -1; 6425 this.step = -1; 6426 this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this)); 6427 var mod, offset; 6428 switch(this.options.mode){ 6429 case 'horizontal': 6430 this.z = 'x'; 6431 this.p = 'left'; 6432 mod = {'x': 'left', 'y': false}; 6433 offset = 'offsetWidth'; 6434 break; 6435 case 'vertical': 6436 this.z = 'y'; 6437 this.p = 'top'; 6438 mod = {'x': false, 'y': 'top'}; 6439 offset = 'offsetHeight'; 6440 } 6441 this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2); 6442 this.half = this.knob[offset]/2; 6443 this.getPos = this.element['get' + this.p.capitalize()].bind(this.element); 6444 this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset); 6445 var lim = {}; 6446 lim[this.z] = [- this.options.offset, this.max - this.options.offset]; 6447 this.drag = new Drag.Base(this.knob, { 6448 limit: lim, 6449 modifiers: mod, 6450 snap: 0, 6451 onStart: function(){ 6452 this.draggedKnob(); 6453 }.bind(this), 6454 onDrag: function(){ 6455 this.draggedKnob(); 6456 }.bind(this), 6457 onComplete: function(){ 6458 this.draggedKnob(); 6459 this.end(); 6460 }.bind(this) 6461 }); 6462 if (this.options.initialize) this.options.initialize.call(this); 6463 }, 6464 6465 /* 6466 Property: set 6467 The slider will get the step you pass. 6468 6469 Arguments: 6470 step - one integer 6471 */ 6472 6473 set: function(step){ 6474 this.step = step.limit(0, this.options.steps); 6475 this.checkStep(); 6476 this.end(); 6477 this.fireEvent('onTick', this.toPosition(this.step)); 6478 return this; 6479 }, 6480 6481 clickedElement: function(event){ 6482 var position = event.page[this.z] - this.getPos() - this.half; 6483 position = position.limit(-this.options.offset, this.max -this.options.offset); 6484 this.step = this.toStep(position); 6485 this.checkStep(); 6486 this.end(); 6487 this.fireEvent('onTick', position); 6488 }, 6489 6490 draggedKnob: function(){ 6491 this.step = this.toStep(this.drag.value.now[this.z]); 6492 this.checkStep(); 6493 }, 6494 6495 checkStep: function(){ 6496 if (this.previousChange != this.step){ 6497 this.previousChange = this.step; 6498 this.fireEvent('onChange', this.step); 6499 } 6500 }, 6501 6502 end: function(){ 6503 if (this.previousEnd !== this.step){ 6504 this.previousEnd = this.step; 6505 this.fireEvent('onComplete', this.step + ''); 6506 } 6507 }, 6508 6509 toStep: function(position){ 6510 return Math.round((position + this.options.offset) / this.max * this.options.steps); 6511 }, 6512 6513 toPosition: function(step){ 6514 return this.max * step / this.options.steps; 6515 } 6516 6517}); 6518 6519Slider.implement(new Events); 6520Slider.implement(new Options); 6521 6522/* 6523Script: SmoothScroll.js 6524 Contains <SmoothScroll> 6525 6526License: 6527 MIT-style license. 6528*/ 6529 6530/* 6531Class: SmoothScroll
6532 Auto targets all the anchors in a page and display a smooth scrolling effect upon clicking them. 6533 Inherits methods, properties, options and events from <Fx.Scroll>. 6534 6535Note: 6536 SmoothScroll requires an XHTML doctype. 6537 6538Arguments: 6539 options - the Fx.Scroll options (see: <Fx.Scroll>) plus links, a collection of elements you want your smoothscroll on. Defaults to document.links. 6540 6541Example: 6542 >new SmoothScroll(); 6543*/ 6544 6545var SmoothScroll = Fx.Scroll.extend({ 6546 6547 initialize: function(options){ 6548 this.parent(window, options); 6549 this.links = (this.options.links) ? $$(this.options.links) : $$(document.links); 6550 var location = window.location.href.match(/^[^#]*/)[0] + '#'; 6551 this.links.each(function(link){ 6552 if (link.href.indexOf(location) != 0) return; 6553 var anchor = link.href.substr(location.length); 6554 if (anchor && $(anchor)) this.useLink(link, anchor); 6555 }, this); 6556 if (!window.webkit419) this.addEvent('onComplete', function(){ 6557 window.location.hash = this.anchor; 6558 }); 6559 }, 6560 6561 useLink: function(link, anchor){ 6562 link.addEvent('click', function(event){ 6563 this.anchor = anchor; 6564 this.toElement(anchor); 6565 event.stop(); 6566 }.bindWithEvent(this)); 6567 } 6568 6569}); 6570 6571/* 6572Script: Sortables.js 6573 Contains <Sortables> Class. 6574 6575License: 6576 MIT-style license. 6577*/ 6578 6579/* 6580Class: Sortables 6581 Creates an interface for <Drag.Base> and drop, resorting of a list. 6582 6583Note: 6584 The Sortables require an XHTML doctype. 6585 6586Arguments: 6587 list - required, the list that will become sortable. 6588 options - an Object, see options below. 6589 6590Options: 6591 handles - a collection of elements to be used for drag handles. defaults to the elements. 6592 6593Events: 6594 onStart - function executed when the item starts dragging 6595 onComplete - function executed when the item ends dragging 6596*/ 6597 6598var Sortables = new Class({ 6599 6600 options: { 6601 handles: false, 6602 onStart: Class.empty, 6603 onComplete: Class.empty, 6604 ghost: true, 6605 snap: 3, 6606 onDragStart: function(element, ghost){ 6607 ghost.setStyle('opacity', 0.7); 6608 element.setStyle('opacity', 0.7); 6609 }, 6610 onDragComplete: function(element, ghost){ 6611 element.setStyle('opacity', 1); 6612 ghost.remove(); 6613 this.trash.remove(); 6614 } 6615 }, 6616 6617 initialize: function(list, options){ 6618 this.setOptions(options); 6619 this.list = $(list); 6620 this.elements = this.list.getChildren(); 6621 this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements; 6622 this.bound = { 6623 'start': [], 6624 'moveGhost': this.moveGhost.bindWithEvent(this) 6625 }; 6626 for (var i = 0, l = this.handles.length; i < l; i++){ 6627 this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]); 6628 } 6629 this.attach(); 6630 if (this.options.initialize) this.options.initialize.call(this); 6631 this.bound.move = this.move.bindWithEvent(this); 6632 this.bound.end = this.end.bind(this); 6633 }, 6634 6635 attach: function(){ 6636 this.handles.each(function(handle, i){ 6637 handle.addEvent('mousedown', this.bound.start[i]); 6638 }, this); 6639 }, 6640 6641 detach: function(){ 6642 this.handles.each(function(handle, i){ 6643 handle.removeEvent('mousedown', this.bound.start[i]); 6644 }, this); 6645 }, 6646 6647 start: function(event, el){ 6648 this.active = el; 6649 this.coordinates = this.list.getCoordinates(); 6650 if (this.options.ghost){ 6651 var position = el.getPosition(); 6652 this.offset = event.page.y - position.y; 6653 this.trash = new Element('div').inject(document.body); 6654 this.ghost = el.clone().inject(this.trash).setStyles({ 6655 'position': 'absolute', 6656 'left': position.x, 6657 'top': event.page.y - this.offset 6658 }); 6659 document.addListener('mousemove', this.bound.moveGhost); 6660 this.fireEvent('onDragStart', [el, this.ghost]); 6661 } 6662 document.addListener('mousemove', this.bound.move); 6663 document.addListener('mouseup', this.bound.end); 6664 this.fireEvent('onStart', el); 6665 event.stop(); 6666 }, 6667 6668 moveGhost: function(event){ 6669 var value = event.page.y - this.offset; 6670 value = value.limit(this.coordinates.top, this.coordinates.bottom - this.ghost.offsetHeight); 6671 this.ghost.setStyle('top', value); 6672 event.stop(); 6673 }, 6674 6675 move: function(event){ 6676 var now = event.page.y; 6677 this.previous = this.previous || now; 6678 var up = ((this.previous - now) > 0); 6679 var prev = this.active.getPrevious(); 6680 var next = this.active.getNext(); 6681 if (prev && up && now < prev.getCoordinates().bottom) this.active.injectBefore(prev); 6682 if (next && !up && now > next.getCoordinates().top) this.active.injectAfter(next); 6683 this.previous = now; 6684 }, 6685 6686 serialize: function(converter){ 6687 return this.list.getChildren().map(converter || function(el){ 6688 return this.elements.indexOf(el); 6689 }, this); 6690 }, 6691 6692 end: function(){ 6693 this.previous = null; 6694 document.removeListener('mousemove', this.bound.move); 6695 document.removeListener('mouseup', this.bound.end); 6696 if (this.options.ghost){ 6697 document.removeListener('mousemove', this.bound.moveGhost); 6698 this.fireEvent('onDragComplete', [this.active, this.ghost]); 6699 } 6700 this.fireEvent('onComplete', this.active); 6701 } 6702 6703}); 6704 6705Sortables.implement(new Events, new Options); 6706 6707/* 6708Script: Tips.js 6709 Tooltips, BubbleTips, whatever they are, they will appear on mouseover 6710 6711License: 6712 MIT-style license. 6713 6714Credits: 6715 The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com> 6716*/ 6717 6718/* 6719Class: Tips 6720 Display a tip on any element with a title and/or href. 6721 6722Note: 6723 Tips requires an XHTML doctype. 6724 6725Arguments: 6726 elements - a collection of elements to apply the tooltips to on mouseover. 6727 options - an object. See options Below. 6728 6729Options: 6730 maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30. 6731 showDelay - the delay the onShow method is called. (defaults to 100 ms) 6732 hideDelay - the delay the onHide method is called. (defaults to 100 ms) 6733 6734 className - the prefix for your tooltip classNames. defaults to 'tool'. 6735 6736 the whole tooltip will have as classname: tool-tip 6737 6738 the title will have as classname: tool-title 6739 6740 the text will have as classname: tool-text 6741 6742 offsets - the distance of your tooltip from the mouse. an Object with x/y properties. 6743 fixed - if set to true, the toolTip will not follow the mouse. 6744 6745Events: 6746 onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect); 6747 onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect); 6748 6749Example: 6750 (start code) 6751 <img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/> 6752 <script> 6753 var myTips = new Tips($$('.toolTipImg'), { 6754 maxTitleChars: 50 //I like my captions a little long 6755 }); 6756 </script> 6757 (end) 6758 6759Note: 6760 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. 6761*/ 6762 6763var Tips = new Class({ 6764 6765 options: { 6766 onShow: function(tip){ 6767 tip.setStyle('visibility', 'visible'); 6768 }, 6769 onHide: function(tip){ 6770 tip.setStyle('visibility', 'hidden'); 6771 }, 6772 maxTitleChars: 30, 6773 showDelay: 100, 6774 hideDelay: 100, 6775 className: 'tool', 6776 offsets: {'x': 16, 'y': 16}, 6777 fixed: false 6778 }, 6779 6780 initialize: function(elements, options){ 6781 this.setOptions(options); 6782 this.toolTip = new Element('div', { 6783 'class': this.options.className + '-tip', 6784 'styles': { 6785 'position': 'absolute', 6786 'top': '0', 6787 'left': '0', 6788 'visibility': 'hidden' 6789 } 6790 }).inject(document.body); 6791 this.wrapper = new Element('div').inject(this.toolTip); 6792 $$(elements).each(this.build, this); 6793 if (this.options.initialize) this.options.initialize.call(this); 6794 }, 6795 6796 build: function(el){ 6797 el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '')
6797: (el.rel || false); 6798 if (el.title){ 6799 var dual = el.title.split('::'); 6800 if (dual.length > 1){ 6801 el.$tmp.myTitle = dual[0].trim(); 6802 el.$tmp.myText = dual[1].trim(); 6803 } else { 6804 el.$tmp.myText = el.title; 6805 } 6806 el.removeAttribute('title'); 6807 } else { 6808 el.$tmp.myText = false; 6809 } 6810 if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "…"; 6811 el.addEvent('mouseenter', function(event){ 6812 this.start(el); 6813 if (!this.options.fixed) this.locate(event); 6814 else this.position(el); 6815 }.bind(this)); 6816 if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this)); 6817 var end = this.end.bind(this); 6818 el.addEvent('mouseleave', end); 6819 el.addEvent('trash', end); 6820 }, 6821 6822 start: function(el){ 6823 this.wrapper.empty(); 6824 if (el.$tmp.myTitle){ 6825 this.title = new Element('span').inject(new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)).setHTML(el.$tmp.myTitle); 6826 } 6827 if (el.$tmp.myText){ 6828 this.text = new Element('span').inject(new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)).setHTML(el.$tmp.myText); 6829 } 6830 $clear(this.timer); 6831 this.timer = this.show.delay(this.options.showDelay, this); 6832 }, 6833 6834 end: function(event){ 6835 $clear(this.timer); 6836 this.timer = this.hide.delay(this.options.hideDelay, this); 6837 }, 6838 6839 position: function(element){ 6840 var pos = element.getPosition(); 6841 this.toolTip.setStyles({ 6842 'left': pos.x + this.options.offsets.x, 6843 'top': pos.y + this.options.offsets.y 6844 }); 6845 }, 6846 6847 locate: function(event){ 6848 var win = {'x': window.getWidth(), 'y': window.getHeight()}; 6849 var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()}; 6850 var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight}; 6851 var prop = {'x': 'left', 'y': 'top'}; 6852 for (var z in prop){ 6853 var pos = event.page[z] + this.options.offsets[z]; 6854 if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z]; 6855 this.toolTip.setStyle(prop[z], pos); 6856 }; 6857 }, 6858 6859 show: function(){ 6860 if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this); 6861 this.fireEvent('onShow', [this.toolTip]); 6862 }, 6863 6864 hide: function(){ 6865 this.fireEvent('onHide', [this.toolTip]); 6866 } 6867 6868}); 6869 6870Tips.implement(new Events, new Options); 6871 6872/* 6873Script: Group.js 6874 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. 6875 6876License: 6877 MIT-style license. 6878*/ 6879 6880/* 6881Class: Group 6882 An "Utility" Class. 6883 6884Arguments: 6885 List of Class instances 6886 6887Example: 6888 (start code) 6889 xhr1 = new Ajax('data.js', {evalScript: true}); 6890 xhr2 = new Ajax('abstraction.js', {evalScript: true}); 6891 xhr3 = new Ajax('template.js', {evalScript: true}); 6892 6893 var group = new Group(xhr1, xhr2, xhr3); 6894 group.addEvent('onComplete', function(){ 6895 alert('All Scripts loaded'); 6896 }); 6897 6898 xhr1.request(); 6899 xhr2.request(); 6900 xhr3.request(); 6901 (end) 6902 6903*/ 6904 6905var Group = new Class({ 6906 6907 initialize: function(){ 6908 this.instances = $A(arguments); 6909 this.events = {}; 6910 this.checker = {}; 6911 }, 6912 6913 /* 6914 Property: addEvent 6915 adds an event to the stack of events of the Class instances. 6916 6917 Arguments: 6918 type - string; the event name (e.g. 'onComplete') 6919 fn - function to execute when all instances fired this event 6920 */ 6921 6922 addEvent: function(type, fn){ 6923 this.checker[type] = this.checker[type] || {}; 6924 this.events[type] = this.events[type] || []; 6925 if (this.events[type].contains(fn)) return false; 6926 else this.events[type].push(fn); 6927 this.instances.each(function(instance, i){ 6928 instance.addEvent(type, this.check.bind(this, [type, instance, i])); 6929 }, this); 6930 return this; 6931 }, 6932 6933 check: function(type, instance, i){ 6934 this.checker[type][i] = true; 6935 var every = this.instances.every(function(current, j){ 6936 return this.checker[type][j] || false; 6937 }, this); 6938 if (!every) return; 6939 this.checker[type] = {}; 6940 this.events[type].each(function(event){ 6941 event.call(this, this.instances, instance); 6942 }, this); 6943 } 6944 6945}); 6946 6947/* 6948Script: Accordion.js 6949 Contains <Accordion> 6950 6951License: 6952 MIT-style license. 6953*/ 6954 6955/* 6956Class: Accordion 6957 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. 6958 Inherits methods, properties, options and events from <Fx.Elements>. 6959 6960Note: 6961 The Accordion requires an XHTML doctype. 6962 6963Arguments: 6964 togglers - required, a collection of elements, the elements handlers that will be clickable. 6965 elements - required, a collection of elements the transitions will be applied to. 6966 options - optional, see options below, and <Fx.Base> options and events. 6967 6968Options: 6969 show - integer, the Index of the element to show at start. 6970 display - integer, the Index of the element to show at start (with a transition). defaults to 0. 6971 fixedHeight - integer, if you want the elements to have a fixed height. defaults to false. 6972 fixedWidth - integer, if you want the elements to have a fixed width. defaults to false. 6973 height - boolean, will add a height transition to the accordion if true. defaults to true. 6974 opacity - boolean, will add an opacity transition to the accordion if true. defaults to true. 6975 width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work! 6976 alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false. 6977 6978Events: 6979 onActive - function to execute when an element starts to show
6980 onBackground - function to execute when an element starts to hide 6981*/ 6982 6983var Accordion = Fx.Elements.extend({ 6984 6985 options: { 6986 onActive: Class.empty, 6987 onBackground: Class.empty, 6988 display: 0, 6989 show: false, 6990 height: true, 6991 width: false, 6992 opacity: true, 6993 fixedHeight: false, 6994 fixedWidth: false, 6995 wait: false, 6996 alwaysHide: false 6997 }, 6998 6999 initialize: function(){ 7000 var options, togglers, elements, container; 7001 $each(arguments, function(argument, i){ 7002 switch($type(argument)){ 7003 case 'object': options = argument; break; 7004 case 'element': container = $(argument); break; 7005 default: 7006 var temp = $$(argument); 7007 if (!togglers) togglers = temp; 7008 else elements = temp; 7009 } 7010 }); 7011 this.togglers = togglers || []; 7012 this.elements = elements || []; 7013 this.container = $(container); 7014 this.setOptions(options); 7015 this.previous = -1; 7016 if (this.options.alwaysHide) this.options.wait = true; 7017 if ($chk(this.options.show)){ 7018 this.options.display = false; 7019 this.previous = this.options.show; 7020 } 7021 if (this.options.start){ 7022 this.options.display = false; 7023 this.options.show = false; 7024 } 7025 this.effects = {}; 7026 if (this.options.opacity) this.effects.opacity = 'fullOpacity'; 7027 if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth'; 7028 if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight'; 7029 for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]); 7030 this.elements.each(function(el, i){ 7031 if (this.options.show === i){ 7032 this.fireEvent('onActive', [this.togglers[i], el]); 7033 } else { 7034 for (var fx in this.effects) el.setStyle(fx, 0); 7035 } 7036 }, this); 7037 this.parent(this.elements); 7038 if ($chk(this.options.display)) this.display(this.options.display); 7039 }, 7040 7041 /* 7042 Property: addSection 7043 Dynamically adds a new section into the accordion at the specified position. 7044 7045 Arguments: 7046 toggler - (dom element) the element that toggles the accordion section open. 7047 element - (dom element) the element that stretches open when the toggler is clicked. 7048 pos - (integer) the index where these objects are to be inserted within the accordion. 7049 */ 7050 7051 addSection: function(toggler, element, pos){ 7052 toggler = $(toggler); 7053 element = $(element); 7054 var test = this.togglers.contains(toggler); 7055 var len = this.togglers.length; 7056 this.togglers.include(toggler); 7057 this.elements.include(element); 7058 if (len && (!test || pos)){ 7059 pos = $pick(pos, len - 1); 7060 toggler.injectBefore(this.togglers[pos]); 7061 element.injectAfter(toggler); 7062 } else if (this.container && !test){ 7063 toggler.inject(this.container); 7064 element.inject(this.container); 7065 } 7066 var idx = this.togglers.indexOf(toggler); 7067 toggler.addEvent('click', this.display.bind(this, idx)); 7068 if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'}); 7069 if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'}); 7070 element.fullOpacity = 1; 7071 if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth; 7072 if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight; 7073 element.setStyle('overflow', 'hidden'); 7074 if (!test){ 7075 for (var fx in this.effects) element.setStyle(fx, 0); 7076 } 7077 return this; 7078 }, 7079 7080 /* 7081 Property: display 7082 Shows a specific section and hides all others. Useful when triggering an accordion from outside. 7083 7084 Arguments: 7085 index - integer, the index of the item to show, or the actual element to show. 7086 */ 7087 7088 display: function(index){ 7089 index = ($type(index) == 'element') ? this.elements.indexOf(index) : index; 7090 if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this; 7091 this.previous = index; 7092 var obj = {}; 7093 this.elements.each(function(el, i){ 7094 obj[i] = {}; 7095 var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0)); 7096 this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]); 7097 for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]]; 7098 }, this); 7099 return this.start(obj); 7100 }, 7101 7102 showThisHideOpen: function(index){return this.display(index);} 7103 7104}); 7105 7106Fx.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.