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