1/* 2Script: Core.js 3 MooTools - My Object Oriented JavaScript Tools. 4 5License: 6 MIT-style license. 7 8Copyright: 9 Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/). 10 11Code & Documentation: 12 [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*/ 18 19var MooTools = { 20 'version': '1.2.0', 21 'build': '' 22}; 23 24var Native = function(options){ 25 options = options || {}; 26 27 var afterImplement = options.afterImplement || function(){}; 28 var generics = options.generics; 29 generics = (generics !== false); 30 var legacy = options.legacy; 31 var initialize = options.initialize; 32 var protect = options.protect; 33 var name = options.name; 34 35 var object = initialize || legacy; 36 37 object.constructor = Native; 38 object.$family = {name: 'native'}; 39 if (legacy && initialize) object.prototype = legacy.prototype; 40 object.prototype.constructor = object; 41 42 if (name){ 43 var family = name.toLowerCase(); 44 object.prototype.$family = {name: family}; 45 Native.typize(object, family); 46 } 47 48 var add = function(obj, name, method, force){ 49 if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method; 50 if (generics) Native.genericize(obj, name, protect); 51 afterImplement.call(obj, name, method); 52 return obj; 53 }; 54 55 object.implement = function(a1, a2, a3){ 56 if (typeof a1 == 'string') return add(this, a1, a2, a3); 57 for (var p in a1) add(this, p, a1[p], a2); 58 return this; 59 }; 60 61 object.alias = function(a1, a2, a3){ 62 if (typeof a1 == 'string'){ 63 a1 = this.prototype[a1]; 64 if (a1) add(this, a2, a1, a3); 65 } else { 66 for (var a in a1) this.alias(a, a1[a], a2); 67 } 68 return this; 69 }; 70 71 return object; 72}; 73 74Native.implement = function(objects, properties){ 75 for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties); 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.typize = function(object, family){ 86 if (!object.type) object.type = function(item){ 87 return ($type(item) === family); 88 }; 89}; 90 91Native.alias = function(objects, a1, a2, a3){ 92 for (var i = 0, j = objects.length; i < j; i++) objects[i].alias(a1, a2, a3); 93}; 94 95(function(objects){ 96 for (var name in objects) Native.typize(objects[name], name); 97})({'boolean': Boolean, 'native': Native, 'object': Object}); 98 99(function(objects){ 100 for (var name in objects) new Native({name: name, initialize: objects[name], protect: true}); 101})({'String': String, 'Function': Function, 'Number': Number, 'Array': Array, 'RegExp': RegExp, 'Date': Date}); 102 103(function(object, methods){ 104 for (var i = methods.length; i--; i) Native.genericize(object, methods[i], true); 105 return arguments.callee; 106}) 107(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf']) 108(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']); 109 110function $chk(obj){ 111 return !!(obj || obj === 0); 112}; 113 114function $clear(timer){ 115 clearTimeout(timer); 116 clearInterval(timer); 117 return null; 118}; 119 120function $defined(obj){ 121 return (obj != undefined); 122}; 123 124function $empty(){}; 125 126function $arguments(i){ 127 return function(){ 128 return arguments[i]; 129 }; 130}; 131 132function $lambda(value){ 133 return (typeof value == 'function') ? value : function(){ 134 return value; 135 }; 136}; 137 138function $extend(original, extended){ 139 for (var key in (extended || {})) original[key] = extended[key]; 140 return original; 141}; 142 143function $unlink(object){ 144 var unlinked; 145 146 switch ($type(object)){ 147 case 'object': 148 unlinked = {}; 149 for (var p in object) unlinked[p] = $unlink(object[p]); 150 break; 151 case 'hash': 152 unlinked = $unlink(object.getClean()); 153 break; 154 case 'array': 155 unlinked = []; 156 for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]); 157 break; 158 default: return object; 159 } 160 161 return unlinked; 162}; 163 164function $merge(){ 165 var mix = {}; 166 for (var i = 0, l = arguments.length; i < l; i++){ 167 var object = arguments[i]; 168 if ($type(object) != 'object') continue; 169 for (var key in object){
170 var op = object[key], mp = mix[key]; 171 mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op); 172 } 173 } 174 return mix; 175}; 176 177function $pick(){ 178 for (var i = 0, l = arguments.length; i < l; i++){ 179 if (arguments[i] != undefined) return arguments[i]; 180 } 181 return null; 182}; 183 184function $random(min, max){ 185 return Math.floor(Math.random() * (max - min + 1) + min); 186}; 187 188function $splat(obj){ 189 var type = $type(obj); 190 return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : []; 191}; 192 193var $time = Date.now || function(){ 194 return new Date().getTime(); 195}; 196 197function $try(){ 198 for (var i = 0, l = arguments.length; i < l; i++){ 199 try { 200 return arguments[i](); 201 } catch(e){} 202 } 203 return null; 204}; 205 206function $type(obj){ 207 if (obj == undefined) return false; 208 if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name; 209 if (obj.nodeName){ 210 switch (obj.nodeType){ 211 case 1: return 'element'; 212 case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace'; 213 } 214 } else if (typeof obj.length == 'number'){ 215 if (obj.callee) return 'arguments'; 216 else if (obj.item) return 'collection'; 217 } 218 return typeof obj; 219}; 220 221var Hash = new Native({ 222 223 name: 'Hash', 224 225 initialize: function(object){ 226 if ($type(object) == 'hash') object = $unlink(object.getClean()); 227 for (var key in object) this[key] = object[key]; 228 return this; 229 } 230 231}); 232 233Hash.implement({ 234 235 getLength: function(){ 236 var length = 0; 237 for (var key in this){ 238 if (this.hasOwnProperty(key)) length++; 239 } 240 return length; 241 }, 242 243 forEach: function(fn, bind){ 244 for (var key in this){ 245 if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this); 246 } 247 }, 248 249 getClean: function(){ 250 var clean = {}; 251 for (var key in this){ 252 if (this.hasOwnProperty(key)) clean[key] = this[key]; 253 } 254 return clean; 255 } 256 257}); 258 259Hash.alias('forEach', 'each'); 260 261function $H(object){ 262 return new Hash(object); 263}; 264 265Array.implement({ 266 267 forEach: function(fn, bind){ 268 for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this); 269 } 270 271}); 272 273Array.alias('forEach', 'each'); 274 275function $A(iterable){ 276 if (iterable.item){ 277 var array = []; 278 for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i]; 279 return array; 280 } 281 return Array.prototype.slice.call(iterable); 282}; 283 284function $each(iterable, fn, bind){ 285 var type = $type(iterable); 286 ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind); 287}; 288 289 290/* 291Script: Browser.js 292 The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash. 293 294License: 295 MIT-style license. 296*/ 297 298var Browser = new Hash({ 299 Engine: {name: 'unknown', version: ''}, 300 Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}, 301 Features: {xpath: !!(document.evaluate), air: !!(window.runtime)}, 302 Plugins: {} 303}); 304 305if (window.opera) Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925}; 306else if (window.ActiveXObject) Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4}; 307else if (!navigator.taintEnabled) Browser.Engine = {name: 'webkit', version: (Browser.Features.xpath) ? 420 : 419}; 308else if (document.getBoxObjectFor != null) Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18}; 309Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true; 310 311if (window.orientation != undefined) Browser.Platform.name = 'ipod'; 312 313Browser.Platform[Browser.Platform.name] = true; 314 315Browser.Request = function(){ 316 return $try(function(){ 317 return new XMLHttpRequest(); 318 }, function(){ 319 return new ActiveXObject('MSXML2.XMLHTTP'); 320 }); 321}; 322 323Browser.Features.xhr = !!(Browser.Request()); 324 325Browser.Plugins.Flash = (function(){ 326 var version = ($try(function(){ 327 return navigator.plugins['Shockwave Flash'].description; 328 }, function(){ 329 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 330 }) || '0 r0').match(/\d+/g); 331 return {version: parseInt(version[0] || 0 + '.' + version[1] || 0), build: parseInt(version[2] || 0)}; 332})(); 333 334function $exec(text){ 335 if (!text) return text; 336 if (window.execScript){ 337 window.execScript(text); 338 } else { 339 var script = document.createElement('script'); 340 script.setAttribute('type', 'text/javascript'); 341 script.text = text; 342 document.head.appendChild(script); 343 document.head.removeChild(script); 344 } 345 return text; 346}; 347 348Native.UID = 1; 349 350var $uid = (Browser.Engine.trident) ? function(item){ 351 return (item.uid || (item.uid = [Native.UID++]))[0]; 352} : function(item){ 353 return item.uid || (item.uid = Native.UID++); 354}; 355 356var Window = new Native({ 357
358 name: 'Window', 359 360 legacy: (Browser.Engine.trident) ? null: window.Window, 361 362 initialize: function(win){ 363 $uid(win); 364 if (!win.Element){ 365 win.Element = $empty; 366 if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2 367 win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {}; 368 } 369 return $extend(win, Window.Prototype); 370 }, 371 372 afterImplement: function(property, value){ 373 window[property] = Window.Prototype[property] = value; 374 } 375 376}); 377 378Window.Prototype = {$family: {name: 'window'}}; 379 380new Window(window); 381 382var Document = new Native({ 383 384 name: 'Document', 385 386 legacy: (Browser.Engine.trident) ? null: window.Document, 387 388 initialize: function(doc){ 389 $uid(doc); 390 doc.head = doc.getElementsByTagName('head')[0]; 391 doc.html = doc.getElementsByTagName('html')[0]; 392 doc.window = doc.defaultView || doc.parentWindow; 393 if (Browser.Engine.trident4) $try(function(){ 394 doc.execCommand("BackgroundImageCache", false, true); 395 }); 396 return $extend(doc, Document.Prototype); 397 }, 398 399 afterImplement: function(property, value){ 400 document[property] = Document.Prototype[property] = value; 401 } 402 403}); 404 405Document.Prototype = {$family: {name: 'document'}}; 406 407new Document(document); 408 409/* 410Script: Array.js 411 Contains Array Prototypes like copy, each, contains, and remove. 412 413License: 414 MIT-style license. 415*/ 416 417Array.implement({ 418 419 every: function(fn, bind){ 420 for (var i = 0, l = this.length; i < l; i++){ 421 if (!fn.call(bind, this[i], i, this)) return false; 422 } 423 return true; 424 }, 425 426 filter: function(fn, bind){ 427 var results = []; 428 for (var i = 0, l = this.length; i < l; i++){ 429 if (fn.call(bind, this[i], i, this)) results.push(this[i]); 430 } 431 return results; 432 }, 433 434 clean: function() { 435 return this.filter($defined); 436 }, 437 438 indexOf: function(item, from){ 439 var len = this.length; 440 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ 441 if (this[i] === item) return i; 442 } 443 return -1; 444 }, 445 446 map: function(fn, bind){ 447 var results = []; 448 for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this); 449 return results; 450 }, 451 452 some: function(fn, bind){ 453 for (var i = 0, l = this.length; i < l; i++){ 454 if (fn.call(bind, this[i], i, this)) return true; 455 } 456 return false; 457 }, 458 459 associate: function(keys){ 460 var obj = {}, length = Math.min(this.length, keys.length); 461 for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; 462 return obj; 463 }, 464 465 link: function(object){ 466 var result = {}; 467 for (var i = 0, l = this.length; i < l; i++){ 468 for (var key in object){ 469 if (object[key](this[i])){ 470 result[key] = this[i]; 471 delete object[key]; 472 break; 473 } 474 } 475 } 476 return result; 477 }, 478 479 contains: function(item, from){ 480 return this.indexOf(item, from) != -1; 481 }, 482 483 extend: function(array){ 484 for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); 485 return this; 486 }, 487 488 getLast: function(){ 489 return (this.length) ? this[this.length - 1] : null; 490 }, 491 492 getRandom: function(){ 493 return (this.length) ? this[$random(0, this.length - 1)] : null; 494 }, 495 496 include: function(item){ 497 if (!this.contains(item)) this.push(item); 498 return this; 499 }, 500 501 combine: function(array){ 502 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 503 return this; 504 }, 505 506 erase: function(item){ 507 for (var i = this.length; i--; i){ 508 if (this[i] === item) this.splice(i, 1); 509 } 510 return this; 511 }, 512 513 empty: function(){ 514 this.length = 0; 515 return this; 516 }, 517 518 flatten: function(){ 519 var array = []; 520 for (var i = 0, l = this.length; i < l; i++){ 521 var type = $type(this[i]); 522 if (!type) continue; 523 array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]); 524 } 525 return array; 526 }, 527 528 hexToRgb: function(array){ 529 if (this.length != 3) return null; 530 var rgb = this.map(function(value){ 531 if (value.length == 1) value += value; 532 return value.toInt(16); 533 }); 534 return (array) ? rgb : 'rgb(' + rgb + ')'; 535 }, 536 537 rgbToHex: function(array){ 538 if (this.length < 3) return null; 539 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 540 var hex = []; 541 for (var i = 0; i < 3; i++){ 542 var bit = (this[i] - 0).toString(16); 543 hex.push((bit.length == 1) ? '0' + bit : bit); 544 } 545 return (array) ? hex : '#' + hex.join(''); 546 } 547 548}); 549 550/* 551Script: Function.js 552 Contains Function Prototypes like create, bind, pass, and delay. 553 554License: 555 MIT-style license. 556*/ 557 558Function.implement({ 559 560 extend: function(properties){ 561 for (var property in properties) this[property] = properties[property]; 562 return this; 563 }, 564 565 create: function(options){ 566 var self = this; 567 options = options || {}; 568 return function(event){ 569 var args = options.arguments; 570 args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0); 571 if (options.event) args = [event || window.event].extend(args); 572 var returns = function(){
573 return self.apply(options.bind || null, args); 574 }; 575 if (options.delay) return setTimeout(returns, options.delay); 576 if (options.periodical) return setInterval(returns, options.periodical); 577 if (options.attempt) return $try(returns); 578 return returns(); 579 }; 580 }, 581 582 pass: function(args, bind){ 583 return this.create({arguments: args, bind: bind}); 584 }, 585 586 attempt: function(args, bind){ 587 return this.create({arguments: args, bind: bind, attempt: true})(); 588 }, 589 590 bind: function(bind, args){ 591 return this.create({bind: bind, arguments: args}); 592 }, 593 594 bindWithEvent: function(bind, args){ 595 return this.create({bind: bind, event: true, arguments: args}); 596 }, 597 598 delay: function(delay, bind, args){ 599 return this.create({delay: delay, bind: bind, arguments: args})(); 600 }, 601 602 periodical: function(interval, bind, args){ 603 return this.create({periodical: interval, bind: bind, arguments: args})(); 604 }, 605 606 run: function(args, bind){ 607 return this.apply(bind, $splat(args)); 608 } 609 610}); 611 612/* 613Script: Number.js 614 Contains Number Prototypes like limit, round, times, and ceil. 615 616License: 617 MIT-style license. 618*/ 619 620Number.implement({ 621 622 limit: function(min, max){ 623 return Math.min(max, Math.max(min, this)); 624 }, 625 626 round: function(precision){ 627 precision = Math.pow(10, precision || 0); 628 return Math.round(this * precision) / precision; 629 }, 630 631 times: function(fn, bind){ 632 for (var i = 0; i < this; i++) fn.call(bind, i, this); 633 }, 634 635 toFloat: function(){ 636 return parseFloat(this); 637 }, 638 639 toInt: function(base){ 640 return parseInt(this, base || 10); 641 } 642 643}); 644 645Number.alias('times', 'each'); 646 647(function(math){ 648 var methods = {}; 649 math.each(function(name){ 650 if (!Number[name]) methods[name] = function(){ 651 return Math[name].apply(null, [this].concat($A(arguments))); 652 }; 653 }); 654 Number.implement(methods); 655})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); 656 657/* 658Script: String.js 659 Contains String Prototypes like camelCase, capitalize, test, and toInt. 660 661License: 662 MIT-style license. 663*/ 664 665String.implement({ 666 667 test: function(regex, params){ 668 return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this); 669 }, 670 671 contains: function(string, separator){ 672 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; 673 }, 674 675 trim: function(){ 676 return this.replace(/^\s+|\s+$/g, ''); 677 }, 678 679 clean: function(){ 680 return this.replace(/\s+/g, ' ').trim(); 681 }, 682 683 camelCase: function(){ 684 return this.replace(/-\D/g, function(match){ 685 return match.charAt(1).toUpperCase(); 686 }); 687 }, 688 689 hyphenate: function(){ 690 return this.replace(/[A-Z]/g, function(match){ 691 return ('-' + match.charAt(0).toLowerCase()); 692 }); 693 }, 694 695 capitalize: function(){ 696 return this.replace(/\b[a-z]/g, function(match){ 697 return match.toUpperCase(); 698 }); 699 }, 700 701 escapeRegExp: function(){ 702 return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); 703 }, 704 705 toInt: function(base){ 706 return parseInt(this, base || 10); 707 }, 708 709 toFloat: function(){ 710 return parseFloat(this); 711 }, 712 713 hexToRgb: function(array){ 714 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 715 return (hex) ? hex.slice(1).hexToRgb(array) : null; 716 }, 717 718 rgbToHex: function(array){ 719 var rgb = this.match(/\d{1,3}/g); 720 return (rgb) ? rgb.rgbToHex(array) : null; 721 }, 722 723 stripScripts: function(option){ 724 var scripts = ''; 725 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){ 726 scripts += arguments[1] + '\n'; 727 return ''; 728 }); 729 if (option === true) $exec(scripts); 730 else if ($type(option) == 'function') option(scripts, text); 731 return text; 732 }, 733 734 substitute: function(object, regexp){ 735 return this.replace(regexp || (/\\?\{([^}]+)\}/g), function(match, name){ 736 if (match.charAt(0) == '\\') return match.slice(1); 737 return (object[name] != undefined) ? object[name] : ''; 738 }); 739 } 740 741}); 742 743/* 744Script: Hash.js 745 Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. 746 747License: 748 MIT-style license. 749*/ 750 751Hash.implement({ 752 753 has: Object.prototype.hasOwnProperty, 754 755 keyOf: function(value){ 756 for (var key in this){ 757 if (this.hasOwnProperty(key) && this[key] === value) return key; 758 } 759 return null; 760 }, 761 762 hasValue: function(value){ 763 return (Hash.keyOf(this, value) !== null); 764 }, 765 766 extend: function(properties){ 767 Hash.each(properties, function(value, key){ 768 Hash.set(this, key, value); 769 }, this); 770 return this; 771 }, 772 773 combine: function(properties){ 774 Hash.each(properties, function(value, key){ 775 Hash.include(this, key, value); 776 }, this); 777 return this; 778 }, 779 780 erase: function(key){ 781 if (this.hasOwnProperty(key)) delete this[key]; 782 return this; 783 }, 784 785 get: function(key){ 786 return (this.hasOwnProperty(key)) ? this[key] : null; 787 }, 788 789 set: function(key, value){ 790 if (!this[key] || this.hasOwnProperty(key)) this[key] = value; 791 return this; 792 }, 793 794 empty: function(){ 795 Hash.each(this, function(value, key){ 796 delete this[key]; 797 }, this); 798 return this; 799 }, 800 801 include: function(key, value){ 802 var k = this[key]; 803 if (k == undefined) this[key] = value; 804 return this; 805 }, 806 807 map: function(fn, bind){ 808 var results = new Hash; 809 Hash.each(this, function(value, key){ 810 results.set(key, fn.call(bind, value, key, this)); 811 }, this); 812 return results; 813 }, 814 815 filter: function(fn, bind){ 816 var results = new Hash; 817 Hash.each(this, function(value, key){ 818 if (fn.call(bind, value, key, this)) results.set(key, value); 819 }, this); 820 return results; 821 }, 822 823 every: function(fn, bind){ 824 for (var key in this){ 825 if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
826 } 827 return true; 828 }, 829 830 some: function(fn, bind){ 831 for (var key in this){ 832 if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true; 833 } 834 return false; 835 }, 836 837 getKeys: function(){ 838 var keys = []; 839 Hash.each(this, function(value, key){ 840 keys.push(key); 841 }); 842 return keys; 843 }, 844 845 getValues: function(){ 846 var values = []; 847 Hash.each(this, function(value){ 848 values.push(value); 849 }); 850 return values; 851 }, 852 853 toQueryString: function(base){ 854 var queryString = []; 855 Hash.each(this, function(value, key){ 856 if (base) key = base + '[' + key + ']'; 857 var result; 858 switch ($type(value)){ 859 case 'object': result = Hash.toQueryString(value, key); break; 860 case 'array': 861 var qs = {}; 862 value.each(function(val, i){ 863 qs[i] = val; 864 }); 865 result = Hash.toQueryString(qs, key); 866 break; 867 default: result = key + '=' + encodeURIComponent(value); 868 } 869 if (value != undefined) queryString.push(result); 870 }); 871 872 return queryString.join('&'); 873 } 874 875}); 876 877Hash.alias({keyOf: 'indexOf', hasValue: 'contains'}); 878 879/* 880Script: Event.js 881 Contains the Event Native, to make the event object completely crossbrowser. 882 883License: 884 MIT-style license. 885*/ 886 887var Event = new Native({ 888 889 name: 'Event', 890 891 initialize: function(event, win){ 892 win = win || window; 893 var doc = win.document; 894 event = event || win.event; 895 if (event.$extended) return event; 896 this.$extended = true; 897 var type = event.type; 898 var target = event.target || event.srcElement; 899 while (target && target.nodeType == 3) target = target.parentNode; 900 901 if (type.test(/key/)){ 902 var code = event.which || event.keyCode; 903 var key = Event.Keys.keyOf(code); 904 if (type == 'keydown'){ 905 var fKey = code - 111; 906 if (fKey > 0 && fKey < 13) key = 'f' + fKey; 907 } 908 key = key || String.fromCharCode(code).toLowerCase(); 909 } else if (type.match(/(click|mouse|menu)/i)){ 910 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 911 var page = { 912 x: event.pageX || event.clientX + doc.scrollLeft, 913 y: event.pageY || event.clientY + doc.scrollTop 914 }; 915 var client = { 916 x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX, 917 y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY 918 }; 919 if (type.match(/DOMMouseScroll|mousewheel/)){ 920 var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; 921 } 922 var rightClick = (event.which == 3) || (event.button == 2); 923 var related = null; 924 if (type.match(/over|out/)){ 925 switch (type){ 926 case 'mouseover': related = event.relatedTarget || event.fromElement; break; 927 case 'mouseout': related = event.relatedTarget || event.toElement; 928 } 929 if (!(function(){ 930 while (related && related.nodeType == 3) related = related.parentNode; 931 return true; 932 }).create({attempt: Browser.Engine.gecko})()) related = false; 933 } 934 } 935 936 return $extend(this, { 937 event: event, 938 type: type, 939 940 page: page, 941 client: client, 942 rightClick: rightClick, 943 944 wheel: wheel, 945 946 relatedTarget: related, 947 target: target, 948 949 code: code, 950 key: key, 951 952 shift: event.shiftKey, 953 control: event.ctrlKey, 954 alt: event.altKey, 955 meta: event.metaKey 956 }); 957 } 958 959}); 960 961Event.Keys = new Hash({ 962 'enter': 13, 963 'up': 38, 964 'down': 40, 965 'left': 37, 966 'right': 39, 967 'esc': 27, 968 'space': 32, 969 'backspace': 8, 970 'tab': 9, 971 'delete': 46 972}); 973 974Event.implement({ 975 976 stop: function(){ 977 return this.stopPropagation().preventDefault(); 978 }, 979 980 stopPropagation: function(){ 981 if (this.event.stopPropagation) this.event.stopPropagation(); 982 else this.event.cancelBubble = true; 983 return this; 984 }, 985 986 preventDefault: function(){ 987 if (this.event.preventDefault) this.event.preventDefault(); 988 else this.event.returnValue = false; 989 return this; 990 } 991 992}); 993 994/* 995Script: Class.js 996 Contains the Class Function for easily creating, extending, and implementing reusable Classes. 997 998License: 999 MIT-style license. 1000*/ 1001 1002var Class = new Native({ 1003 1004 name: 'Class', 1005 1006 initialize: function(properties){ 1007 properties = properties || {}; 1008 var klass = function(empty){ 1009 for (var key in this) this[key] = $unlink(this[key]); 1010 for (var mutator in Class.Mutators){ 1011 if (!this[mutator]) continue; 1012 Class.Mutators[mutator](this, this[mutator]); 1013 delete this[mutator]; 1014 } 1015 1016 this.constructor = klass; 1017 if (empty === $empty) return this; 1018 1019 var self = (this.initialize) ? this.initialize.apply(this, arguments) : this; 1020 if (this.options && this.options.initialize) this.options.initialize.call(this); 1021 return self; 1022 }; 1023 1024 $extend(klass, this); 1025 klass.constructor = Class; 1026 klass.prototype = properties; 1027 return klass; 1028 } 1029 1030}); 1031 1032Class.implement({ 1033 1034 implement: function(){ 1035 Class.Mutators.Implements(this.prototype, Array.slice(arguments)); 1036 return this; 1037 } 1038 1039}); 1040 1041Class.Mutators = { 1042 1043 Implements: function(self, klasses){ 1044 $splat(klasses).each(function(klass){ 1045 $extend(self, ($type(klass) == 'class') ? new klass($empty) : klass); 1046 }); 1047 }, 1048
1049 Extends: function(self, klass){ 1050 var instance = new klass($empty); 1051 delete instance.parent; 1052 delete instance.parentOf; 1053 1054 for (var key in instance){ 1055 var current = self[key], previous = instance[key]; 1056 if (current == undefined){ 1057 self[key] = previous; 1058 continue; 1059 } 1060 1061 var ctype = $type(current), ptype = $type(previous); 1062 if (ctype != ptype) continue; 1063 1064 switch (ctype){ 1065 case 'function': 1066 // this code will be only executed if the current browser does not support function.caller (currently only opera). 1067 // we replace the function code with brute force. Not pretty, but it will only be executed if function.caller is not supported. 1068 1069 if (!arguments.callee.caller) self[key] = eval('(' + String(current).replace(/\bthis\.parent\(\s*(\))?/g, function(full, close){ 1070 return 'arguments.callee._parent_.call(this' + (close || ', '); 1071 }) + ')'); 1072 1073 // end "opera" code 1074 self[key]._parent_ = previous; 1075 break; 1076 case 'object': self[key] = $merge(previous, current); 1077 } 1078 1079 } 1080 1081 self.parent = function(){ 1082 return arguments.callee.caller._parent_.apply(this, arguments); 1083 }; 1084 1085 self.parentOf = function(descendant){ 1086 return descendant._parent_.apply(this, Array.slice(arguments, 1)); 1087 }; 1088 } 1089 1090}; 1091 1092 1093/* 1094Script: Class.Extras.js 1095 Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. 1096 1097License: 1098 MIT-style license. 1099*/ 1100 1101var Chain = new Class({ 1102 1103 chain: function(){ 1104 this.$chain = (this.$chain || []).extend(arguments); 1105 return this; 1106 }, 1107 1108 callChain: function(){ 1109 return (this.$chain && this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; 1110 }, 1111 1112 clearChain: function(){ 1113 if (this.$chain) this.$chain.empty(); 1114 return this; 1115 } 1116 1117}); 1118 1119var Events = new Class({ 1120 1121 addEvent: function(type, fn, internal){ 1122 type = Events.removeOn(type); 1123 if (fn != $empty){ 1124 this.$events = this.$events || {}; 1125 this.$events[type] = this.$events[type] || []; 1126 this.$events[type].include(fn); 1127 if (internal) fn.internal = true; 1128 } 1129 return this; 1130 }, 1131 1132 addEvents: function(events){ 1133 for (var type in events) this.addEvent(type, events[type]); 1134 return this; 1135 }, 1136 1137 fireEvent: function(type, args, delay){ 1138 type = Events.removeOn(type); 1139 if (!this.$events || !this.$events[type]) return this; 1140 this.$events[type].each(function(fn){ 1141 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 1142 }, this); 1143 return this; 1144 }, 1145 1146 removeEvent: function(type, fn){ 1147 type = Events.removeOn(type); 1148 if (!this.$events || !this.$events[type]) return this; 1149 if (!fn.internal) this.$events[type].erase(fn); 1150 return this; 1151 }, 1152 1153 removeEvents: function(type){ 1154 for (var e in this.$events){ 1155 if (type && type != e) continue; 1156 var fns = this.$events[e]; 1157 for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]); 1158 } 1159 return this; 1160 } 1161 1162}); 1163 1164Events.removeOn = function(string){ 1165 return string.replace(/^on([A-Z])/, function(full, first) { 1166 return first.toLowerCase(); 1167 }); 1168}; 1169 1170var Options = new Class({ 1171 1172 setOptions: function(){ 1173 this.options = $merge.run([this.options].extend(arguments)); 1174 if (!this.addEvent) return this; 1175 for (var option in this.options){ 1176 if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; 1177 this.addEvent(option, this.options[option]); 1178 delete this.options[option]; 1179 } 1180 return this; 1181 } 1182 1183}); 1184 1185/* 1186Script: Element.js 1187 One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, 1188 time-saver methods to let you easily work with HTML Elements. 1189 1190License: 1191 MIT-style license. 1192*/ 1193 1194Document.implement({ 1195 1196 newElement: function(tag, props){ 1197 if (Browser.Engine.trident && props){ 1198 ['name', 'type', 'checked'].each(function(attribute){ 1199 if (!props[attribute]) return; 1200 tag += ' ' + attribute + '="' + props[attribute] + '"'; 1201 if (attribute != 'checked') delete props[attribute]; 1202 }); 1203 tag = '<' + tag + '>'; 1204 } 1205 return $.element(this.createElement(tag)).set(props); 1206 }, 1207 1208 newTextNode: function(text){ 1209 return this.createTextNode(text); 1210 }, 1211 1212 getDocument: function(){ 1213 return this; 1214 }, 1215
1216 getWindow: function(){ 1217 return this.defaultView || this.parentWindow; 1218 }, 1219 1220 purge: function(){ 1221 var elements = this.getElementsByTagName('*'); 1222 for (var i = 0, l = elements.length; i < l; i++) Browser.freeMem(elements[i]); 1223 } 1224 1225}); 1226 1227var Element = new Native({ 1228 1229 name: 'Element', 1230 1231 legacy: window.Element, 1232 1233 initialize: function(tag, props){ 1234 var konstructor = Element.Constructors.get(tag); 1235 if (konstructor) return konstructor(props); 1236 if (typeof tag == 'string') return document.newElement(tag, props); 1237 return $(tag).set(props); 1238 }, 1239 1240 afterImplement: function(key, value){ 1241 if (!Array[key]) Elements.implement(key, Elements.multi(key)); 1242 Element.Prototype[key] = value; 1243 } 1244 1245}); 1246 1247Element.Prototype = {$family: {name: 'element'}}; 1248 1249Element.Constructors = new Hash; 1250 1251var IFrame = new Native({ 1252 1253 name: 'IFrame', 1254 1255 generics: false, 1256 1257 initialize: function(){ 1258 var params = Array.link(arguments, {properties: Object.type, iframe: $defined}); 1259 var props = params.properties || {}; 1260 var iframe = $(params.iframe) || false; 1261 var onload = props.onload || $empty; 1262 delete props.onload; 1263 props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time()); 1264 iframe = new Element(iframe || 'iframe', props); 1265 var onFrameLoad = function(){ 1266 var host = $try(function(){ 1267 return iframe.contentWindow.location.host; 1268 }); 1269 if (host && host == window.location.host){ 1270 var win = new Window(iframe.contentWindow); 1271 var doc = new Document(iframe.contentWindow.document); 1272 $extend(win.Element.prototype, Element.Prototype); 1273 } 1274 onload.call(iframe.contentWindow, iframe.contentWindow.document); 1275 }; 1276 (!window.frames[props.id]) ? iframe.addListener('load', onFrameLoad) : onFrameLoad(); 1277 return iframe; 1278 } 1279 1280}); 1281 1282var Elements = new Native({ 1283 1284 initialize: function(elements, options){ 1285 options = $extend({ddup: true, cash: true}, options); 1286 elements = elements || []; 1287 if (options.ddup || options.cash){ 1288 var uniques = {}, returned = []; 1289 for (var i = 0, l = elements.length; i < l; i++){ 1290 var el = $.element(elements[i], !options.cash); 1291 if (options.ddup){ 1292 if (uniques[el.uid]) continue; 1293 uniques[el.uid] = true; 1294 } 1295 returned.push(el); 1296 } 1297 elements = returned; 1298 } 1299 return (options.cash) ? $extend(elements, this) : elements; 1300 } 1301 1302}); 1303 1304Elements.implement({ 1305 1306 filter: function(filter, bind){ 1307 if (!filter) return this; 1308 return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){ 1309 return item.match(filter); 1310 } : filter, bind)); 1311 } 1312 1313}); 1314 1315Elements.multi = function(property){ 1316 return function(){ 1317 var items = []; 1318 var elements = true; 1319 for (var i = 0, j = this.length; i < j; i++){ 1320 var returns = this[i][property].apply(this[i], arguments); 1321 items.push(returns); 1322 if (elements) elements = ($type(returns) == 'element'); 1323 } 1324 return (elements) ? new Elements(items) : items; 1325 }; 1326}; 1327 1328Window.implement({ 1329 1330 $: function(el, nocash){ 1331 if (el && el.$family && el.uid) return el; 1332 var type = $type(el); 1333 return ($[type]) ? $[type](el, nocash, this.document) : null; 1334 }, 1335 1336 $$: function(selector){ 1337 if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector); 1338 var elements = []; 1339 var args = Array.flatten(arguments); 1340 for (var i = 0, l = args.length; i < l; i++){ 1341 var item = args[i]; 1342 switch ($type(item)){ 1343 case 'element': item = [item]; break; 1344 case 'string': item = this.document.getElements(item, true); break; 1345 default: item = false; 1346 } 1347 if (item) elements.extend(item); 1348 } 1349 return new Elements(elements); 1350 }, 1351 1352 getDocument: function(){ 1353 return this.document; 1354 }, 1355 1356 getWindow: function(){ 1357 return this; 1358 } 1359 1360}); 1361 1362$.string = function(id, nocash, doc){ 1363 id = doc.getElementById(id); 1364 return (id) ? $.element(id, nocash) : null; 1365}; 1366 1367$.element = function(el, nocash){ 1368 $uid(el); 1369 if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){ 1370 var proto = Element.Prototype; 1371 for (var p in proto) el[p] = proto[p]; 1372 }; 1373 return el; 1374}; 1375 1376$.object = function(obj, nocash, doc){ 1377 if (obj.toElement) return $.element(obj.toElement(doc), nocash); 1378 return null; 1379}; 1380 1381$.textnode = $.whitespace = $.window = $.document = $arguments(0); 1382 1383Native.implement([Element, Document], {
1384 1385 getElement: function(selector, nocash){ 1386 return $(this.getElements(selector, true)[0] || null, nocash); 1387 }, 1388 1389 getElements: function(tags, nocash){ 1390 tags = tags.split(','); 1391 var elements = []; 1392 var ddup = (tags.length > 1); 1393 tags.each(function(tag){ 1394 var partial = this.getElementsByTagName(tag.trim()); 1395 (ddup) ? elements.extend(partial) : elements = partial; 1396 }, this); 1397 return new Elements(elements, {ddup: ddup, cash: !nocash}); 1398 } 1399 1400}); 1401 1402Element.Storage = { 1403 1404 get: function(uid){ 1405 return (this[uid] || (this[uid] = {})); 1406 } 1407 1408}; 1409 1410Element.Inserters = new Hash({ 1411 1412 before: function(context, element){ 1413 if (element.parentNode) element.parentNode.insertBefore(context, element); 1414 }, 1415 1416 after: function(context, element){ 1417 if (!element.parentNode) return; 1418 var next = element.nextSibling; 1419 (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context); 1420 }, 1421 1422 bottom: function(context, element){ 1423 element.appendChild(context); 1424 }, 1425 1426 top: function(context, element){ 1427 var first = element.firstChild; 1428 (first) ? element.insertBefore(context, first) : element.appendChild(context); 1429 } 1430 1431}); 1432 1433Element.Inserters.inside = Element.Inserters.bottom; 1434 1435Element.Inserters.each(function(value, key){ 1436 1437 var Key = key.capitalize(); 1438 1439 Element.implement('inject' + Key, function(el){ 1440 value(this, $(el, true)); 1441 return this; 1442 }); 1443 1444 Element.implement('grab' + Key, function(el){ 1445 value($(el, true), this); 1446 return this; 1447 }); 1448 1449}); 1450 1451Element.implement({ 1452 1453 getDocument: function(){ 1454 return this.ownerDocument; 1455 }, 1456 1457 getWindow: function(){ 1458 return this.ownerDocument.getWindow(); 1459 }, 1460 1461 getElementById: function(id, nocash){ 1462 var el = this.ownerDocument.getElementById(id); 1463 if (!el) return null; 1464 for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ 1465 if (!parent) return null; 1466 } 1467 return $.element(el, nocash); 1468 }, 1469 1470 set: function(prop, value){ 1471 switch ($type(prop)){ 1472 case 'object': 1473 for (var p in prop) this.set(p, prop[p]); 1474 break; 1475 case 'string': 1476 var property = Element.Properties.get(prop); 1477 (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value); 1478 } 1479 return this; 1480 }, 1481 1482 get: function(prop){ 1483 var property = Element.Properties.get(prop); 1484 return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop); 1485 }, 1486 1487 erase: function(prop){ 1488 var property = Element.Properties.get(prop); 1489 (property && property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop); 1490 return this; 1491 }, 1492 1493 match: function(tag){ 1494 return (!tag || Element.get(this, 'tag') == tag); 1495 }, 1496 1497 inject: function(el, where){ 1498 Element.Inserters.get(where || 'bottom')(this, $(el, true)); 1499 return this; 1500 }, 1501 1502 wraps: function(el, where){ 1503 el = $(el, true); 1504 return this.replaces(el).grab(el, where); 1505 }, 1506 1507 grab: function(el, where){ 1508 Element.Inserters.get(where || 'bottom')($(el, true), this); 1509 return this; 1510 }, 1511 1512 appendText: function(text, where){ 1513 return this.grab(this.getDocument().newTextNode(text), where); 1514 }, 1515 1516 adopt: function(){ 1517 Array.flatten(arguments).each(function(element){ 1518 element = $(element, true); 1519 if (element) this.appendChild(element); 1520 }, this); 1521 return this; 1522 }, 1523 1524 dispose: function(){ 1525 return (this.parentNode) ? this.parentNode.removeChild(this) : this; 1526 }, 1527 1528 clone: function(contents, keepid){ 1529 switch ($type(this)){ 1530 case 'element': 1531 var attributes = {}; 1532 for (var j = 0, l = this.attributes.length; j < l; j++){ 1533 var attribute = this.attributes[j], key = attribute.nodeName.toLowerCase(); 1534 if (Browser.Engine.trident && (/input/i).test(this.tagName) && (/width|height/).test(key)) continue; 1535 var value = (key == 'style' && this.style) ? this.style.cssText : attribute.nodeValue; 1536 if (!$chk(value) || key == 'uid' || (key == 'id' && !keepid)) continue; 1537 if (value != 'inherit' && ['string', 'number'].contains($type(value))) attributes[key] = value; 1538 } 1539 var element = new Element(this.nodeName.toLowerCase(), attributes); 1540 if (contents !== false){ 1541 for (var i = 0, k = this.childNodes.length; i < k; i++){ 1542 var child = Element.clone(this.childNodes[i], true, keepid); 1543 if (child) element.grab(child); 1544 } 1545 } 1546 return element; 1547 case 'textnode': return document.newTextNode(this.nodeValue); 1548 } 1549 return null; 1550 }, 1551 1552 replaces: function(el){ 1553 el = $(el, true); 1554 el.parentNode.replaceChild(this, el); 1555 return this; 1556 }, 1557 1558 hasClass: function(className){ 1559 return this.className.contains(className, ' '); 1560 }, 1561 1562 addClass: function(className){ 1563 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 1564 return this; 1565 }, 1566 1567 removeClass: function(className){ 1568 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean(); 1569 return this; 1570 }, 1571 1572 toggleClass: function(className){ 1573 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); 1574 }, 1575 1576 getComputedStyle: function(property){ 1577 if (this.currentStyle) return this.currentStyle[property.camelCase()]; 1578 var computed = this.getWindow().getComputedStyle(this, null); 1579 return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null; 1580 }, 1581 1582 empty: function(){ 1583 $A(this.childNodes).each(function(node){ 1584 Browser.freeMem(node); 1585 Element.empty(node); 1586 Element.dispose(node); 1587 }, this); 1588 return this; 1589 }, 1590 1591 destroy: function(){ 1592 Browser.freeMem(this.empty().dispose()); 1593 return null; 1594 }, 1595 1596 getSelected: function(){ 1597 return new Elements($A(this.options).filter(function(option){ 1598 return option.selected; 1599 })); 1600 }, 1601 1602 toQueryString: function(){ 1603 var queryString = []; 1604 this.getElements('input, select, textarea').each(function(el){ 1605 if (!el.name || el.disabled) return; 1606 var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){ 1607 return opt.value; 1608 }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value; 1609 $splat(value).each(function(val){ 1610 if (val) queryString.push(el.name + '=' + encodeURIComponent(val)); 1611 }); 1612 }); 1613 return queryString.join('&'); 1614 }, 1615 1616 getProperty: function(attribute){ 1617 var EA = Element.Attributes, key = EA.Props[attribute]; 1618 var value = (key) ? this[key] : this.getAttribute(attribute, 2); 1619 return (EA.Bools[attribute]) ? !!value : (key) ? value : value || null; 1620 }, 1621 1622 getProperties: function(){ 1623 var args = $A(arguments); 1624 return args.map(function(attr){ 1625 return this.getProperty(attr); 1626 }, this).associate(args); 1627 }, 1628 1629 setProperty: function(attribute, value){ 1630 var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value); 1631 if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;
1632 else if (!hasValue) return this.removeProperty(attribute); 1633 (key) ? this[key] = value : this.setAttribute(attribute, value); 1634 return this; 1635 }, 1636 1637 setProperties: function(attributes){ 1638 for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); 1639 return this; 1640 }, 1641 1642 removeProperty: function(attribute){ 1643 var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]); 1644 (key) ? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute); 1645 return this; 1646 }, 1647 1648 removeProperties: function(){ 1649 Array.each(arguments, this.removeProperty, this); 1650 return this; 1651 } 1652 1653}); 1654 1655(function(){ 1656 1657var walk = function(element, walk, start, match, all, nocash){ 1658 var el = element[start || walk]; 1659 var elements = []; 1660 while (el){ 1661 if (el.nodeType == 1 && (!match || Element.match(el, match))){ 1662 elements.push(el); 1663 if (!all) break; 1664 } 1665 el = el[walk]; 1666 } 1667 return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : $(elements[0], nocash); 1668}; 1669 1670Element.implement({ 1671 1672 getPrevious: function(match, nocash){ 1673 return walk(this, 'previousSibling', null, match, false, nocash); 1674 }, 1675 1676 getAllPrevious: function(match, nocash){ 1677 return walk(this, 'previousSibling', null, match, true, nocash); 1678 }, 1679 1680 getNext: function(match, nocash){ 1681 return walk(this, 'nextSibling', null, match, false, nocash); 1682 }, 1683 1684 getAllNext: function(match, nocash){ 1685 return walk(this, 'nextSibling', null, match, true, nocash); 1686 }, 1687 1688 getFirst: function(match, nocash){ 1689 return walk(this, 'nextSibling', 'firstChild', match, false, nocash); 1690 }, 1691 1692 getLast: function(match, nocash){ 1693 return walk(this, 'previousSibling', 'lastChild', match, false, nocash); 1694 }, 1695 1696 getParent: function(match, nocash){ 1697 return walk(this, 'parentNode', null, match, false, nocash); 1698 }, 1699 1700 getParents: function(match, nocash){ 1701 return walk(this, 'parentNode', null, match, true, nocash); 1702 }, 1703 1704 getChildren: function(match, nocash){ 1705 return walk(this, 'nextSibling', 'firstChild', match, true, nocash); 1706 }, 1707 1708 hasChild: function(el){ 1709 el = $(el, true); 1710 return (!!el && $A(this.getElementsByTagName(el.tagName)).contains(el)); 1711 } 1712 1713}); 1714 1715})(); 1716 1717Element.Properties = new Hash; 1718 1719Element.Properties.style = { 1720 1721 set: function(style){ 1722 this.style.cssText = style; 1723 }, 1724 1725 get: function(){ 1726 return this.style.cssText; 1727 }, 1728 1729 erase: function(){ 1730 this.style.cssText = ''; 1731 } 1732 1733}; 1734 1735Element.Properties.tag = {get: function(){ 1736 return this.tagName.toLowerCase(); 1737}}; 1738 1739Element.Properties.href = {get: function(){ 1740 return (!this.href) ? null : this.href.replace(new RegExp('^' + document.location.protocol + '\/\/' + document.location.host), ''); 1741}}; 1742 1743Element.Properties.html = {set: function(){ 1744 return this.innerHTML = Array.flatten(arguments).join(''); 1745}}; 1746 1747Native.implement([Element, Window, Document], { 1748 1749 addListener: function(type, fn){ 1750 if (this.addEventListener) this.addEventListener(type, fn, false); 1751 else this.attachEvent('on' + type, fn); 1752 return this; 1753 }, 1754 1755 removeListener: function(type, fn){ 1756 if (this.removeEventListener) this.removeEventListener(type, fn, false); 1757 else this.detachEvent('on' + type, fn); 1758 return this; 1759 }, 1760 1761 retrieve: function(property, dflt){ 1762 var storage = Element.Storage.get(this.uid); 1763 var prop = storage[property]; 1764 if ($defined(dflt) && !$defined(prop)) prop = storage[property] = dflt; 1765 return $pick(prop); 1766 }, 1767 1768 store: function(property, value){ 1769 var storage = Element.Storage.get(this.uid); 1770 storage[property] = value; 1771 return this; 1772 }, 1773 1774 eliminate: function(property){ 1775 var storage = Element.Storage.get(this.uid); 1776 delete storage[property]; 1777 return this; 1778 } 1779 1780}); 1781 1782Element.Attributes = new Hash({ 1783 Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (Browser.Engine.trident) ? 'innerText' : 'textContent'}, 1784 Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'], 1785 Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap'] 1786}); 1787 1788Browser.freeMem = function(item){ 1789 if (!item) return; 1790 if (Browser.Engine.trident && (/object/i).test(item.tagName)){ 1791 for (var p in item){ 1792 if (typeof item[p] == 'function') item[p] = $empty; 1793 } 1794 Element.dispose(item); 1795 } 1796 if (item.uid && item.removeEvents) item.removeEvents(); 1797}; 1798 1799(function(EA){ 1800 1801 var EAB = EA.Bools, EAC = EA.Camels; 1802 EA.Bools = EAB = EAB.associate(EAB); 1803 Hash.extend(Hash.combine(EA.Props, EAB), EAC.associate(EAC.map(function(v){ 1804 return v.toLowerCase(); 1805 }))); 1806 EA.erase('Camels'); 1807 1808})(Element.Attributes); 1809 1810window.addListener('unload', function(){ 1811 window.removeListener('unload', arguments.callee); 1812 document.purge(); 1813 if (Browser.Engine.trident) CollectGarbage(); 1814}); 1815 1816/* 1817Script: Element.Event.js 1818 Contains Element methods for dealing with events, and custom Events. 1819 1820License: 1821 MIT-style license. 1822*/ 1823
1824Element.Properties.events = {set: function(events){ 1825 this.addEvents(events); 1826}}; 1827 1828Native.implement([Element, Window, Document], { 1829 1830 addEvent: function(type, fn){ 1831 var events = this.retrieve('events', {}); 1832 events[type] = events[type] || {'keys': [], 'values': []}; 1833 if (events[type].keys.contains(fn)) return this; 1834 events[type].keys.push(fn); 1835 var realType = type, custom = Element.Events.get(type), condition = fn, self = this; 1836 if (custom){ 1837 if (custom.onAdd) custom.onAdd.call(this, fn); 1838 if (custom.condition){ 1839 condition = function(event){ 1840 if (custom.condition.call(this, event)) return fn.call(this, event); 1841 return false; 1842 }; 1843 } 1844 realType = custom.base || realType; 1845 } 1846 var defn = function(){ 1847 return fn.call(self); 1848 }; 1849 var nativeEvent = Element.NativeEvents[realType] || 0; 1850 if (nativeEvent){ 1851 if (nativeEvent == 2){ 1852 defn = function(event){ 1853 event = new Event(event, self.getWindow()); 1854 if (condition.call(self, event) === false) event.stop(); 1855 }; 1856 } 1857 this.addListener(realType, defn); 1858 } 1859 events[type].values.push(defn); 1860 return this; 1861 }, 1862 1863 removeEvent: function(type, fn){ 1864 var events = this.retrieve('events'); 1865 if (!events || !events[type]) return this; 1866 var pos = events[type].keys.indexOf(fn); 1867 if (pos == -1) return this; 1868 var key = events[type].keys.splice(pos, 1)[0]; 1869 var value = events[type].values.splice(pos, 1)[0]; 1870 var custom = Element.Events.get(type); 1871 if (custom){ 1872 if (custom.onRemove) custom.onRemove.call(this, fn); 1873 type = custom.base || type; 1874 } 1875 return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this; 1876 }, 1877 1878 addEvents: function(events){ 1879 for (var event in events) this.addEvent(event, events[event]); 1880 return this; 1881 }, 1882 1883 removeEvents: function(type){ 1884 var events = this.retrieve('events'); 1885 if (!events) return this; 1886 if (!type){ 1887 for (var evType in events) this.removeEvents(evType); 1888 events = null; 1889 } else if (events[type]){ 1890 while (events[type].keys[0]) this.removeEvent(type, events[type].keys[0]); 1891 events[type] = null; 1892 } 1893 return this; 1894 }, 1895 1896 fireEvent: function(type, args, delay){ 1897 var events = this.retrieve('events'); 1898 if (!events || !events[type]) return this; 1899 events[type].keys.each(function(fn){ 1900 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 1901 }, this); 1902 return this; 1903 }, 1904 1905 cloneEvents: function(from, type){ 1906 from = $(from); 1907 var fevents = from.retrieve('events'); 1908 if (!fevents) return this; 1909 if (!type){ 1910 for (var evType in fevents) this.cloneEvents(from, evType); 1911 } else if (fevents[type]){ 1912 fevents[type].keys.each(function(fn){ 1913 this.addEvent(type, fn); 1914 }, this); 1915 } 1916 return this; 1917 } 1918 1919}); 1920 1921Element.NativeEvents = { 1922 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons 1923 mousewheel: 2, DOMMouseScroll: 2, //mouse wheel 1924 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement 1925 keydown: 2, keypress: 2, keyup: 2, //keyboard 1926 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements 1927 load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window 1928 error: 1, abort: 1, scroll: 1 //misc 1929}; 1930 1931(function(){ 1932 1933var $check = function(event){ 1934 var related = event.relatedTarget; 1935 if (related == undefined) return true; 1936 if (related === false) return false; 1937 return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related)); 1938}; 1939 1940Element.Events = new Hash({ 1941 1942 mouseenter: { 1943 base: 'mouseover', 1944 condition: $check 1945 }, 1946 1947 mouseleave: { 1948 base: 'mouseout', 1949 condition: $check 1950 }, 1951 1952 mousewheel: { 1953 base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel' 1954 } 1955 1956}); 1957 1958})(); 1959 1960/* 1961Script: Element.Style.js 1962 Contains methods for interacting with the styles of Elements in a fashionable way. 1963 1964License: 1965 MIT-style license. 1966*/ 1967 1968Element.Properties.styles = {set: function(styles){ 1969 this.setStyles(styles); 1970}}; 1971 1972Element.Properties.opacity = { 1973 1974 set: function(opacity, novisibility){ 1975 if (!novisibility){ 1976 if (opacity == 0){ 1977 if (this.style.visibility != 'hidden') this.style.visibility = 'hidden'; 1978 } else { 1979 if (this.style.visibility != 'visible') this.style.visibility = 'visible'; 1980 } 1981 } 1982 if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1; 1983 if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')'; 1984 this.style.opacity = opacity; 1985 this.store('opacity', opacity); 1986 }, 1987 1988 get: function(){ 1989 return this.retrieve('opacity', 1); 1990 } 1991 1992}; 1993 1994Element.implement({ 1995 1996 setOpacity: function(value){ 1997 return this.set('opacity', value, true); 1998 }, 1999 2000 getOpacity: function(){ 2001 return this.get('opacity'); 2002 }, 2003 2004 setStyle: function(property, value){ 2005 switch (property){ 2006 case 'opacity': return this.set('opacity', parseFloat(value)); 2007 case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat'; 2008 } 2009 property = property.camelCase(); 2010 if ($type(value) != 'string'){ 2011 var map = (Element.Styles.get(property) || '@').split(' '); 2012 value = $splat(value).map(function(val, i){ 2013 if (!map[i]) return ''; 2014 return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; 2015 }).join(' '); 2016 } else if (value == String(Number(value))){ 2017 value = Math.round(value); 2018 } 2019 this.style[property] = value; 2020 return this; 2021 }, 2022 2023 getStyle: function(property){ 2024 switch (property){ 2025 case 'opacity': return this.get('opacity'); 2026 case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat'; 2027 } 2028 property = property.camelCase(); 2029 var result = this.style[property]; 2030 if (!$chk(result)){ 2031 result = []; 2032 for (var style in Element.ShortStyles){ 2033 if (property != style) continue; 2034 for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); 2035 return result.join(' '); 2036 } 2037 result = this.getComputedStyle(property); 2038 } 2039 if (result){ 2040 result = String(result); 2041 var color = result.match(/rgba?\([\d\s,]+\)/); 2042 if (color) result = result.replace(color[0], color[0].rgbToHex()); 2043 } 2044 if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result)))){ 2045 if (property.test(/^(height|width)$/)){ 2046 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; 2047 values.each(function(value){
2048 size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); 2049 }, this); 2050 return this['offset' + property.capitalize()] - size + 'px'; 2051 } 2052 if (Browser.Engine.presto && String(result).test('px')) return result; 2053 if (property.test(/(border(.+)Width|margin|padding)/)) return '0px'; 2054 } 2055 return result; 2056 }, 2057 2058 setStyles: function(styles){ 2059 for (var style in styles) this.setStyle(style, styles[style]); 2060 return this; 2061 }, 2062 2063 getStyles: function(){ 2064 var result = {}; 2065 Array.each(arguments, function(key){ 2066 result[key] = this.getStyle(key); 2067 }, this); 2068 return result; 2069 } 2070 2071}); 2072 2073Element.Styles = new Hash({ 2074 left: '@px', top: '@px', bottom: '@px', right: '@px', 2075 width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', 2076 backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', 2077 fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', 2078 margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', 2079 borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', 2080 zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' 2081}); 2082 2083Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; 2084 2085['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ 2086 var Short = Element.ShortStyles; 2087 var All = Element.Styles; 2088 ['margin', 'padding'].each(function(style){ 2089 var sd = style + direction; 2090 Short[style][sd] = All[sd] = '@px'; 2091 }); 2092 var bd = 'border' + direction; 2093 Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; 2094 var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; 2095 Short[bd] = {}; 2096 Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; 2097 Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; 2098 Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; 2099}); 2100 2101 2102/* 2103Script: Element.Dimensions.js 2104 Contains methods to work with size, scroll, or positioning of Elements and the window object. 2105 2106License: 2107 MIT-style license. 2108 2109Credits: 2110 - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). 2111 - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). 2112*/ 2113 2114(function(){ 2115 2116Element.implement({ 2117 2118 scrollTo: function(x, y){ 2119 if (isBody(this)){ 2120 this.getWindow().scrollTo(x, y); 2121 } else { 2122 this.scrollLeft = x; 2123 this.scrollTop = y; 2124 } 2125 return this; 2126 }, 2127 2128 getSize: function(){ 2129 if (isBody(this)) return this.getWindow().getSize(); 2130 return {x: this.offsetWidth, y: this.offsetHeight}; 2131 }, 2132 2133 getScrollSize: function(){ 2134 if (isBody(this)) return this.getWindow().getScrollSize(); 2135 return {x: this.scrollWidth, y: this.scrollHeight}; 2136 }, 2137 2138 getScroll: function(){ 2139 if (isBody(this)) return this.getWindow().getScroll(); 2140 return {x: this.scrollLeft, y: this.scrollTop}; 2141 }, 2142 2143 getScrolls: function(){ 2144 var element = this, position = {x: 0, y: 0}; 2145 while (element && !isBody(element)){ 2146 position.x += element.scrollLeft; 2147 position.y += element.scrollTop; 2148 element = element.parentNode; 2149 } 2150 return position; 2151 }, 2152 2153 getOffsetParent: function(){ 2154 var element = this; 2155 if (isBody(element)) return null; 2156 if (!Browser.Engine.trident) return element.offsetParent; 2157 while ((element = element.parentNode) && !isBody(element)){ 2158 if (styleString(element, 'position') != 'static') return element; 2159 } 2160 return null; 2161 }, 2162 2163 getOffsets: function(){ 2164 var element = this, position = {x: 0, y: 0}; 2165 if (isBody(this)) return position; 2166 2167 while (element && !isBody(element)){ 2168 position.x += element.offsetLeft; 2169 position.y += element.offsetTop; 2170 2171 if (Browser.Engine.gecko){ 2172 if (!borderBox(element)){ 2173 position.x += leftBorder(element); 2174 position.y += topBorder(element); 2175 } 2176 var parent = element.parentNode;
2177 if (parent && styleString(parent, 'overflow') != 'visible'){ 2178 position.x += leftBorder(parent); 2179 position.y += topBorder(parent); 2180 } 2181 } else if (element != this && (Browser.Engine.trident || Browser.Engine.webkit)){ 2182 position.x += leftBorder(element); 2183 position.y += topBorder(element); 2184 } 2185 2186 element = element.offsetParent; 2187 if (Browser.Engine.trident){ 2188 while (element && !element.currentStyle.hasLayout) element = element.offsetParent; 2189 } 2190 } 2191 if (Browser.Engine.gecko && !borderBox(this)){ 2192 position.x -= leftBorder(this); 2193 position.y -= topBorder(this); 2194 } 2195 return position; 2196 }, 2197 2198 getPosition: function(relative){ 2199 if (isBody(this)) return {x: 0, y: 0}; 2200 var offset = this.getOffsets(), scroll = this.getScrolls(); 2201 var position = {x: offset.x - scroll.x, y: offset.y - scroll.y}; 2202 var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0}; 2203 return {x: position.x - relativePosition.x, y: position.y - relativePosition.y}; 2204 }, 2205 2206 getCoordinates: function(element){ 2207 if (isBody(this)) return this.getWindow().getCoordinates(); 2208 var position = this.getPosition(element), size = this.getSize(); 2209 var obj = {left: position.x, top: position.y, width: size.x, height: size.y}; 2210 obj.right = obj.left + obj.width; 2211 obj.bottom = obj.top + obj.height; 2212 return obj; 2213 }, 2214 2215 computePosition: function(obj){ 2216 return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')}; 2217 }, 2218 2219 position: function(obj){ 2220 return this.setStyles(this.computePosition(obj)); 2221 } 2222 2223}); 2224 2225Native.implement([Document, Window], { 2226 2227 getSize: function(){ 2228 var win = this.getWindow(); 2229 if (Browser.Engine.presto || Browser.Engine.webkit) return {x: win.innerWidth, y: win.innerHeight}; 2230 var doc = getCompatElement(this); 2231 return {x: doc.clientWidth, y: doc.clientHeight}; 2232 }, 2233 2234 getScroll: function(){ 2235 var win = this.getWindow(); 2236 var doc = getCompatElement(this); 2237 return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; 2238 }, 2239 2240 getScrollSize: function(){ 2241 var doc = getCompatElement(this); 2242 var min = this.getSize(); 2243 return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)}; 2244 }, 2245 2246 getPosition: function(){ 2247 return {x: 0, y: 0}; 2248 }, 2249 2250 getCoordinates: function(){ 2251 var size = this.getSize(); 2252 return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; 2253 } 2254 2255}); 2256 2257// private methods 2258
2259var styleString = Element.getComputedStyle; 2260 2261function styleNumber(element, style){ 2262 return styleString(element, style).toInt() || 0; 2263}; 2264 2265function borderBox(element){ 2266 return styleString(element, '-moz-box-sizing') == 'border-box'; 2267}; 2268 2269function topBorder(element){ 2270 return styleNumber(element, 'border-top-width'); 2271}; 2272 2273function leftBorder(element){ 2274 return styleNumber(element, 'border-left-width'); 2275}; 2276 2277function isBody(element){ 2278 return (/^(?:body|html)$/i).test(element.tagName); 2279}; 2280 2281function getCompatElement(element){ 2282 var doc = element.getDocument(); 2283 return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 2284}; 2285 2286})(); 2287 2288//aliases 2289 2290Native.implement([Window, Document, Element], { 2291 2292 getHeight: function(){ 2293 return this.getSize().y; 2294 }, 2295 2296 getWidth: function(){ 2297 return this.getSize().x; 2298 }, 2299 2300 getScrollTop: function(){ 2301 return this.getScroll().y; 2302 }, 2303 2304 getScrollLeft: function(){ 2305 return this.getScroll().x; 2306 }, 2307 2308 getScrollHeight: function(){ 2309 return this.getScrollSize().y; 2310 }, 2311 2312 getScrollWidth: function(){ 2313 return this.getScrollSize().x; 2314 }, 2315 2316 getTop: function(){ 2317 return this.getPosition().y; 2318 }, 2319 2320 getLeft: function(){ 2321 return this.getPosition().x; 2322 } 2323 2324}); 2325 2326/* 2327Script: Selectors.js 2328 Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support. 2329 2330License: 2331 MIT-style license. 2332*/ 2333 2334Native.implement([Document, Element], { 2335 2336 getElements: function(expression, nocash){ 2337 expression = expression.split(','); 2338 var items, local = {}; 2339 for (var i = 0, l = expression.length; i < l; i++){ 2340 var selector = expression[i], elements = Selectors.Utils.search(this, selector, local); 2341 if (i != 0 && elements.item) elements = $A(elements); 2342 items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements); 2343 } 2344 return new Elements(items, {ddup: (expression.length > 1), cash: !nocash}); 2345 } 2346 2347}); 2348 2349Element.implement({ 2350 2351 match: function(selector){ 2352 if (!selector) return true; 2353 var tagid = Selectors.Utils.parseTagAndID(selector); 2354 var tag = tagid[0], id = tagid[1]; 2355 if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false; 2356 var parsed = Selectors.Utils.parseSelector(selector); 2357 return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true; 2358 } 2359 2360}); 2361 2362var Selectors = {Cache: {nth: {}, parsed: {}}}; 2363 2364Selectors.RegExps = { 2365 id: (/#([\w-]+)/), 2366 tag: (/^(\w+|\*)/), 2367 quick: (/^(\w+|\*)$/), 2368 splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g), 2369 combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g) 2370}; 2371 2372Selectors.Utils = { 2373 2374 chk: function(item, uniques){ 2375 if (!uniques) return true; 2376 var uid = $uid(item); 2377 if (!uniques[uid]) return uniques[uid] = true; 2378 return false; 2379 }, 2380 2381 parseNthArgument: function(argument){ 2382 if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument]; 2383 var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/); 2384 if (!parsed) return false; 2385 var inta = parseInt(parsed[1]); 2386 var a = (inta || inta === 0) ? inta : 1; 2387 var special = parsed[2] || false; 2388 var b = parseInt(parsed[3]) || 0; 2389 if (a != 0){ 2390 b--; 2391 while (b < 1) b += a; 2392 while (b >= a) b -= a; 2393 } else { 2394 a = b; 2395 special = 'index'; 2396 } 2397 switch (special){ 2398 case 'n': parsed = {a: a, b: b, special: 'n'}; break; 2399 case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break; 2400 case 'even': parsed = {a: 2, b: 1, special: 'n'}; break; 2401 case 'first': parsed = {a: 0, special: 'index'}; break; 2402 case 'last': parsed = {special: 'last-child'}; break; 2403 case 'only': parsed = {special: 'only-child'}; break; 2404 default: parsed = {a: (a - 1), special: 'index'}; 2405 } 2406 2407 return Selectors.Cache.nth[argument] = parsed; 2408 }, 2409 2410 parseSelector: function(selector){ 2411 if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector]; 2412 var m, parsed = {classes: [], pseudos: [], attributes: []}; 2413 while ((m = Selectors.RegExps.combined.exec(selector))){ 2414 var cn = m[1], an = m[2], ao = m[3], av = m[4], pn = m[5], pa = m[6]; 2415 if (cn){ 2416 parsed.classes.push(cn); 2417 } else if (pn){ 2418 var parser = Selectors.Pseudo.get(pn); 2419 if (parser) parsed.pseudos.push({parser: parser, argument: pa}); 2420 else parsed.attributes.push({name: pn, operator: '=', value: pa}); 2421 } else if (an){ 2422 parsed.attributes.push({name: an, operator: ao, value: av}); 2423 } 2424 } 2425 if (!parsed.classes.length) delete parsed.classes; 2426 if (!parsed.attributes.length) delete parsed.attributes; 2427 if (!parsed.pseudos.length) delete parsed.pseudos; 2428 if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null; 2429 return Selectors.Cache.parsed[selector] = parsed; 2430 }, 2431 2432 parseTagAndID: function(selector){ 2433 var tag = selector.match(Selectors.RegExps.tag); 2434 var id = selector.match(Selectors.RegExps.id); 2435 return [(tag) ? tag[1] : '*', (id) ? id[1] : false]; 2436 }, 2437 2438 filter: function(item, parsed, local){ 2439 var i; 2440 if (parsed.classes){ 2441 for (i = parsed.classes.length; i--; i){ 2442 var cn = parsed.classes[i]; 2443 if (!Selectors.Filters.byClass(item, cn)) return false;
2444 } 2445 } 2446 if (parsed.attributes){ 2447 for (i = parsed.attributes.length; i--; i){ 2448 var att = parsed.attributes[i]; 2449 if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false; 2450 } 2451 } 2452 if (parsed.pseudos){ 2453 for (i = parsed.pseudos.length; i--; i){ 2454 var psd = parsed.pseudos[i]; 2455 if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false; 2456 } 2457 } 2458 return true; 2459 }, 2460 2461 getByTagAndID: function(ctx, tag, id){ 2462 if (id){ 2463 var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true); 2464 return (item && Selectors.Filters.byTag(item, tag)) ? [item] : []; 2465 } else { 2466 return ctx.getElementsByTagName(tag); 2467 } 2468 }, 2469 2470 search: function(self, expression, local){ 2471 var splitters = []; 2472 2473 var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){ 2474 splitters.push(m1); 2475 return ':)' + m2; 2476 }).split(':)'); 2477 2478 var items, match, filtered, item; 2479 2480 for (var i = 0, l = selectors.length; i < l; i++){ 2481 2482 var selector = selectors[i]; 2483 2484 if (i == 0 && Selectors.RegExps.quick.test(selector)){ 2485 items = self.getElementsByTagName(selector); 2486 continue; 2487 } 2488 2489 var splitter = splitters[i - 1]; 2490 2491 var tagid = Selectors.Utils.parseTagAndID(selector); 2492 var tag = tagid[0], id = tagid[1]; 2493 2494 if (i == 0){ 2495 items = Selectors.Utils.getByTagAndID(self, tag, id); 2496 } else { 2497 var uniques = {}, found = []; 2498 for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques); 2499 items = found; 2500 } 2501 2502 var parsed = Selectors.Utils.parseSelector(selector); 2503 2504 if (parsed){ 2505 filtered = []; 2506 for (var m = 0, n = items.length; m < n; m++){ 2507 item = items[m]; 2508 if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item); 2509 } 2510 items = filtered; 2511 } 2512 2513 } 2514 2515 return items; 2516 2517 } 2518 2519}; 2520 2521Selectors.Getters = { 2522 2523 ' ': function(found, self, tag, id, uniques){ 2524 var items = Selectors.Utils.getByTagAndID(self, tag, id); 2525 for (var i = 0, l = items.length; i < l; i++){ 2526 var item = items[i]; 2527 if (Selectors.Utils.chk(item, uniques)) found.push(item); 2528 } 2529 return found; 2530 }, 2531 2532 '>': function(found, self, tag, id, uniques){ 2533 var children = Selectors.Utils.getByTagAndID(self, tag, id); 2534 for (var i = 0, l = children.length; i < l; i++){ 2535 var child = children[i]; 2536 if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child); 2537 } 2538 return found; 2539 }, 2540 2541 '+': function(found, self, tag, id, uniques){ 2542 while ((self = self.nextSibling)){ 2543 if (self.nodeType == 1){ 2544 if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self); 2545 break; 2546 } 2547 } 2548 return found; 2549 }, 2550 2551 '~': function(found, self, tag, id, uniques){ 2552 2553 while ((self = self.nextSibling)){ 2554 if (self.nodeType == 1){ 2555 if (!Selectors.Utils.chk(self, uniques)) break; 2556 if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self); 2557 } 2558 } 2559 return found; 2560 } 2561 2562}; 2563 2564Selectors.Filters = { 2565 2566 byTag: function(self, tag){ 2567 return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag)); 2568 }, 2569 2570 byID: function(self, id){ 2571 return (!id || (self.id && self.id == id)); 2572 }, 2573 2574 byClass: function(self, klass){ 2575 return (self.className && self.className.contains(klass, ' ')); 2576 }, 2577 2578 byPseudo: function(self, parser, argument, local){ 2579 return parser.call(self, argument, local); 2580 }, 2581 2582 byAttribute: function(self, name, operator, value){ 2583 var result = Element.prototype.getProperty.call(self, name); 2584 if (!result) return false; 2585 if (!operator || value == undefined) return true; 2586 switch (operator){ 2587 case '=': return (result == value); 2588 case '*=': return (result.contains(value)); 2589 case '^=': return (result.substr(0, value.length) == value); 2590 case '$=': return (result.substr(result.length - value.length) == value); 2591 case '!=': return (result != value); 2592 case '~=': return result.contains(value, ' '); 2593 case '|=': return result.contains(value, '-'); 2594 } 2595 return false;
2596 } 2597 2598}; 2599 2600Selectors.Pseudo = new Hash({ 2601 2602 // w3c pseudo selectors 2603 2604 empty: function(){ 2605 return !(this.innerText || this.textContent || '').length; 2606 }, 2607 2608 not: function(selector){ 2609 return !Element.match(this, selector); 2610 }, 2611 2612 contains: function(text){ 2613 return (this.innerText || this.textContent || '').contains(text); 2614 }, 2615 2616 'first-child': function(){ 2617 return Selectors.Pseudo.index.call(this, 0); 2618 }, 2619 2620 'last-child': function(){ 2621 var element = this; 2622 while ((element = element.nextSibling)){ 2623 if (element.nodeType == 1) return false; 2624 } 2625 return true; 2626 }, 2627 2628 'only-child': function(){ 2629 var prev = this; 2630 while ((prev = prev.previousSibling)){ 2631 if (prev.nodeType == 1) return false; 2632 } 2633 var next = this; 2634 while ((next = next.nextSibling)){ 2635 if (next.nodeType == 1) return false; 2636 } 2637 return true; 2638 }, 2639 2640 'nth-child': function(argument, local){ 2641 argument = (argument == undefined) ? 'n' : argument; 2642 var parsed = Selectors.Utils.parseNthArgument(argument); 2643 if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local); 2644 var count = 0; 2645 local.positions = local.positions || {}; 2646 var uid = $uid(this); 2647 if (!local.positions[uid]){ 2648 var self = this; 2649 while ((self = self.previousSibling)){ 2650 if (self.nodeType != 1) continue; 2651 count ++; 2652 var position = local.positions[$uid(self)]; 2653 if (position != undefined){ 2654 count = position + count; 2655 break; 2656 } 2657 } 2658 local.positions[uid] = count; 2659 } 2660 return (local.positions[uid] % parsed.a == parsed.b); 2661 }, 2662 2663 // custom pseudo selectors 2664 2665 index: function(index){ 2666 var element = this, count = 0; 2667 while ((element = element.previousSibling)){ 2668 if (element.nodeType == 1 && ++count > index) return false; 2669 } 2670 return (count == index); 2671 }, 2672 2673 even: function(argument, local){ 2674 return Selectors.Pseudo['nth-child'].call(this, '2n+1', local); 2675 }, 2676 2677 odd: function(argument, local){ 2678 return Selectors.Pseudo['nth-child'].call(this, '2n', local); 2679 } 2680 2681}); 2682 2683/* 2684Script: Domready.js 2685 Contains the domready custom event. 2686 2687License: 2688 MIT-style license. 2689*/ 2690 2691Element.Events.domready = { 2692 2693 onAdd: function(fn){ 2694 if (Browser.loaded) fn.call(this); 2695 } 2696 2697}; 2698 2699(function(){ 2700 2701 var domready = function(){ 2702 if (Browser.loaded) return; 2703 Browser.loaded = true; 2704 window.fireEvent('domready'); 2705 document.fireEvent('domready'); 2706 }; 2707 2708 switch (Browser.Engine.name){ 2709 2710 case 'webkit': (function(){ 2711 (['loaded', 'complete'].contains(document.readyState)) ? domready() : arguments.callee.delay(50); 2712 })(); break; 2713 2714 case 'trident': 2715 var temp = document.createElement('div'); 2716 (function(){ 2717 ($try(function(){ 2718 temp.doScroll('left'); 2719 return $(temp).inject(document.body).set('html', 'temp').dispose(); 2720 })) ? domready() : arguments.callee.delay(50); 2721 })(); 2722 break; 2723 2724 default: 2725 window.addEvent('load', domready); 2726 document.addEvent('DOMContentLoaded', domready); 2727 2728 } 2729 2730})(); 2731 2732/* 2733Script: JSON.js 2734 JSON encoder and decoder. 2735 2736License: 2737 MIT-style license. 2738 2739See Also: 2740 <http://www.json.org/> 2741*/ 2742 2743var JSON = new Hash({ 2744 2745 encode: function(obj){ 2746 switch ($type(obj)){ 2747 case 'string': 2748 return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"'; 2749 case 'array': 2750 return '[' + String(obj.map(JSON.encode).filter($defined)) + ']'; 2751 case 'object': case 'hash': 2752 var string = []; 2753 Hash.each(obj, function(value, key){ 2754 var json = JSON.encode(value); 2755 if (json) string.push(JSON.encode(key) + ':' + json); 2756 }); 2757 return '{' + string + '}'; 2758 case 'number': case 'boolean': return String(obj); 2759 case false: return 'null'; 2760 } 2761 return null; 2762 }, 2763 2764 $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}, 2765 2766 $replaceChars: function(chr){ 2767 return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16); 2768 }, 2769 2770 decode: function(string, secure){ 2771 if ($type(string) != 'string' || !string.length) return null; 2772 if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null; 2773 return eval('(' + string + ')'); 2774 } 2775 2776}); 2777 2778Native.implement([Hash, Array, String, Number], { 2779 2780 toJSON: function(){ 2781 return JSON.encode(this); 2782 } 2783 2784}); 2785 2786 2787/* 2788Script: Cookie.js 2789 Class for creating, loading, and saving browser Cookies. 2790 2791License: 2792 MIT-style license. 2793 2794Credits: 2795 Based on the functions by Peter-Paul Koch (http://quirksmode.org). 2796*/ 2797 2798var Cookie = new Class({ 2799 2800 Implements: Options, 2801 2802 options: { 2803 path: false,
2804 domain: false, 2805 duration: false, 2806 secure: false, 2807 document: document 2808 }, 2809 2810 initialize: function(key, options){ 2811 this.key = key; 2812 this.setOptions(options); 2813 }, 2814 2815 write: function(value){ 2816 value = encodeURIComponent(value); 2817 if (this.options.domain) value += '; domain=' + this.options.domain; 2818 if (this.options.path) value += '; path=' + this.options.path; 2819 if (this.options.duration){ 2820 var date = new Date(); 2821 date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); 2822 value += '; expires=' + date.toGMTString(); 2823 } 2824 if (this.options.secure) value += '; secure'; 2825 this.options.document.cookie = this.key + '=' + value; 2826 return this; 2827 }, 2828 2829 read: function(){ 2830 var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); 2831 return (value) ? decodeURIComponent(value[1]) : null; 2832 }, 2833 2834 dispose: function(){ 2835 new Cookie(this.key, $merge(this.options, {duration: -1})).write(''); 2836 return this; 2837 } 2838 2839}); 2840 2841Cookie.write = function(key, value, options){ 2842 return new Cookie(key, options).write(value); 2843}; 2844 2845Cookie.read = function(key){ 2846 return new Cookie(key).read(); 2847}; 2848 2849Cookie.dispose = function(key, options){ 2850 return new Cookie(key, options).dispose(); 2851}; 2852 2853/* 2854Script: Swiff.js 2855 Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication. 2856 2857License: 2858 MIT-style license. 2859 2860Credits: 2861 Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. 2862*/ 2863 2864var Swiff = new Class({ 2865 2866 Implements: [Options], 2867 2868 options: { 2869 id: null, 2870 height: 1, 2871 width: 1, 2872 container: null, 2873 properties: {}, 2874 params: { 2875 quality: 'high', 2876 allowScriptAccess: 'always', 2877 wMode: 'transparent', 2878 swLiveConnect: true 2879 }, 2880 callBacks: {}, 2881 vars: {} 2882 }, 2883 2884 toElement: function(){ 2885 return this.object; 2886 }, 2887 2888 initialize: function(path, options){ 2889 this.instance = 'Swiff_' + $time(); 2890 2891 this.setOptions(options); 2892 options = this.options; 2893 var id = this.id = options.id || this.instance; 2894 var container = $(options.container); 2895 2896 Swiff.CallBacks[this.instance] = {}; 2897 2898 var params = options.params, vars = options.vars, callBacks = options.callBacks; 2899 var properties = $extend({height: options.height, width: options.width}, options.properties); 2900 2901 var self = this; 2902 2903 for (var callBack in callBacks){ 2904 Swiff.CallBacks[this.instance][callBack] = (function(option){ 2905 return function(){ 2906 return option.apply(self.object, arguments); 2907 }; 2908 })(callBacks[callBack]); 2909 vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; 2910 } 2911 2912 params.flashVars = Hash.toQueryString(vars); 2913 if (Browser.Engine.trident){ 2914 properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; 2915 params.movie = path; 2916 } else { 2917 properties.type = 'application/x-shockwave-flash'; 2918 properties.data = path; 2919 } 2920 var build = '<object id="' + id + '"'; 2921 for (var property in properties) build += ' ' + property + '="' + properties[property] + '"'; 2922 build += '>'; 2923 for (var param in params){ 2924 if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'; 2925 } 2926 build += '</object>'; 2927 this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; 2928 }, 2929 2930 replaces: function(element){ 2931 element = $(element, true); 2932 element.parentNode.replaceChild(this.toElement(), element); 2933 return this; 2934 }, 2935 2936 inject: function(element){ 2937 $(element, true).appendChild(this.toElement()); 2938 return this; 2939 }, 2940 2941 remote: function(){ 2942 return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments)); 2943 } 2944 2945}); 2946 2947Swiff.CallBacks = {}; 2948 2949Swiff.remote = function(obj, fn){ 2950 var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>'); 2951 return eval(rs); 2952}; 2953 2954/* 2955Script: Fx.js 2956 Contains the basic animation logic to be extended by all other Fx Classes. 2957 2958License: 2959 MIT-style license. 2960*/ 2961 2962var Fx = new Class({ 2963 2964 Implements: [Chain, Events, Options], 2965 2966 options: { 2967 /* 2968 onStart: $empty, 2969 onCancel: $empty, 2970 onComplete: $empty, 2971 */ 2972 fps: 50, 2973 unit: false, 2974 duration: 500, 2975 link: 'ignore', 2976 transition: function(p){ 2977 return -(Math.cos(Math.PI * p) - 1) / 2; 2978 } 2979 }, 2980 2981 initialize: function(options){ 2982 this.subject = this.subject || this; 2983 this.setOptions(options); 2984 this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt(); 2985 var wait = this.options.wait; 2986 if (wait === false) this.options.link = 'cancel'; 2987 }, 2988 2989 step: function(){ 2990 var time = $time(); 2991 if (time < this.time + this.options.duration){ 2992 var delta = this.options.transition((time - this.time) / this.options.duration); 2993 this.set(this.compute(this.from, this.to, delta)); 2994 } else { 2995 this.set(this.compute(this.from, this.to, 1)); 2996 this.complete(); 2997 } 2998 }, 2999 3000 set: function(now){ 3001 return now; 3002 }, 3003 3004 compute: function(from, to, delta){ 3005 return Fx.compute(from, to, delta); 3006 }, 3007 3008 check: function(caller){ 3009 if (!this.timer) return true; 3010 switch (this.options.link){ 3011 case 'cancel': this.cancel(); return true; 3012 case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false; 3013 } 3014 return false; 3015 }, 3016 3017 start: function(from, to){ 3018 if (!this.check(arguments.callee, from, to)) return this; 3019 this.from = from; 3020 this.to = to; 3021 this.time = 0; 3022 this.startTimer(); 3023 this.onStart(); 3024 return this; 3025 }, 3026 3027 complete: function(){ 3028 if (this.stopTimer()) this.onComplete(); 3029 return this; 3030 }, 3031 3032 cancel: function(){ 3033 if (this.stopTimer()) this.onCancel(); 3034 return this; 3035 }, 3036 3037 onStart: function(){ 3038 this.fireEvent('start', this.subject); 3039 }, 3040 3041 onComplete: function(){ 3042 this.fireEvent('complete', this.subject); 3043 if (!this.callChain()) this.fireEvent('chainComplete', this.subject); 3044 }, 3045 3046 onCancel: function(){ 3047 this.fireEvent('cancel', this.subject).clearChain(); 3048 }, 3049 3050 pause: function(){ 3051 this.stopTimer(); 3052 return this; 3053 }, 3054 3055 resume: function(){ 3056 this.startTimer(); 3057 return this; 3058 }, 3059 3060 stopTimer: function(){ 3061 if (!this.timer) return false; 3062 this.time = $time() - this.time; 3063 this.timer = $clear(this.timer); 3064 return true; 3065 }, 3066 3067 startTimer: function(){ 3068 if (this.timer) return false; 3069 this.time = $time() - this.time; 3070 this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); 3071 return true; 3072 } 3073 3074}); 3075 3076Fx.compute = function(from, to, delta){ 3077 return (to - from) * delta + from; 3078}; 3079 3080Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; 3081 3082 3083/* 3084Script: Fx.CSS.js 3085 Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. 3086 3087License: 3088 MIT-style license. 3089*/ 3090 3091Fx.CSS = new Class({ 3092 3093 Extends: Fx, 3094 3095 //prepares the base from/to object 3096 3097 prepare: function(element, property, values){ 3098 values = $splat(values); 3099 var values1 = values[1]; 3100 if (!$chk(values1)){ 3101 values[1] = values[0]; 3102 values[0] = element.getStyle(property); 3103 } 3104 var parsed = values.map(this.parse); 3105 return {from: parsed[0], to: parsed[1]}; 3106 }, 3107 3108 //parses a value into an array 3109 3110 parse: function(value){ 3111 value = $lambda(value)(); 3112 value = (typeof value == 'string') ? value.split(' ') : $splat(value); 3113 return value.map(function(val){ 3114 val = String(val); 3115 var found = false;
3116 Fx.CSS.Parsers.each(function(parser, key){ 3117 if (found) return; 3118 var parsed = parser.parse(val); 3119 if ($chk(parsed)) found = {value: parsed, parser: parser}; 3120 }); 3121 found = found || {value: val, parser: Fx.CSS.Parsers.String}; 3122 return found; 3123 }); 3124 }, 3125 3126 //computes by a from and to prepared objects, using their parsers. 3127 3128 compute: function(from, to, delta){ 3129 var computed = []; 3130 (Math.min(from.length, to.length)).times(function(i){ 3131 computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); 3132 }); 3133 computed.$family = {name: 'fx:css:value'}; 3134 return computed; 3135 }, 3136 3137 //serves the value as settable 3138 3139 serve: function(value, unit){ 3140 if ($type(value) != 'fx:css:value') value = this.parse(value); 3141 var returned = []; 3142 value.each(function(bit){ 3143 returned = returned.concat(bit.parser.serve(bit.value, unit)); 3144 }); 3145 return returned; 3146 }, 3147 3148 //renders the change to an element 3149 3150 render: function(element, property, value, unit){ 3151 element.setStyle(property, this.serve(value, unit)); 3152 }, 3153 3154 //searches inside the page css to find the values for a selector 3155 3156 search: function(selector){ 3157 if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; 3158 var to = {}; 3159 Array.each(document.styleSheets, function(sheet, j){ 3160 var href = sheet.href; 3161 if (href && href.contains('://') && !href.contains(document.domain)) return; 3162 var rules = sheet.rules || sheet.cssRules; 3163 Array.each(rules, function(rule, i){ 3164 if (!rule.style) return; 3165 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ 3166 return m.toLowerCase(); 3167 }) : null; 3168 if (!selectorText || !selectorText.test('^' + selector + '$')) return; 3169 Element.Styles.each(function(value, style){ 3170 if (!rule.style[style] || Element.ShortStyles[style]) return; 3171 value = String(rule.style[style]); 3172 to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value; 3173 }); 3174 }); 3175 }); 3176 return Fx.CSS.Cache[selector] = to; 3177 } 3178 3179}); 3180 3181Fx.CSS.Cache = {}; 3182 3183Fx.CSS.Parsers = new Hash({ 3184 3185 Color: { 3186 parse: function(value){ 3187 if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); 3188 return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; 3189 }, 3190 compute: function(from, to, delta){ 3191 return from.map(function(value, i){ 3192 return Math.round(Fx.compute(from[i], to[i], delta)); 3193 }); 3194 }, 3195 serve: function(value){ 3196 return value.map(Number); 3197 } 3198 }, 3199 3200 Number: { 3201 parse: parseFloat, 3202 compute: Fx.compute, 3203 serve: function(value, unit){ 3204 return (unit) ? value + unit : value; 3205 } 3206 }, 3207 3208 String: { 3209 parse: $lambda(false), 3210 compute: $arguments(1), 3211 serve: $arguments(0) 3212 } 3213 3214}); 3215 3216 3217/* 3218Script: Fx.Tween.js 3219 Formerly Fx.Style, effect to transition any CSS property for an element. 3220 3221License: 3222 MIT-style license. 3223*/ 3224 3225Fx.Tween = new Class({ 3226 3227 Extends: Fx.CSS, 3228 3229 initialize: function(element, options){ 3230 this.element = this.subject = $(element); 3231 this.parent(options); 3232 }, 3233 3234 set: function(property, now){ 3235 if (arguments.length == 1){ 3236 now = property; 3237 property = this.property || this.options.property; 3238 } 3239 this.render(this.element, property, now, this.options.unit); 3240 return this; 3241 }, 3242 3243 start: function(property, from, to){ 3244 if (!this.check(arguments.callee, property, from, to)) return this; 3245 var args = Array.flatten(arguments); 3246 this.property = this.options.property || args.shift(); 3247 var parsed = this.prepare(this.element, this.property, args); 3248 return this.parent(parsed.from, parsed.to); 3249 } 3250 3251}); 3252 3253Element.Properties.tween = { 3254 3255 set: function(options){ 3256 var tween = this.retrieve('tween'); 3257 if (tween) tween.cancel(); 3258 return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options)); 3259 }, 3260 3261 get: function(options){ 3262 if (options || !this.retrieve('tween')){ 3263 if (options || !this.retrieve('tween:options')) this.set('tween', options); 3264 this.store('tween', new Fx.Tween(this, this.retrieve('tween:options'))); 3265 } 3266 return this.retrieve('tween'); 3267 } 3268 3269}; 3270 3271Element.implement({ 3272 3273 tween: function(property, from, to){ 3274 this.get('tween').start(arguments); 3275 return this; 3276 }, 3277 3278 fade: function(how){ 3279 var fade = this.get('tween'), o = 'opacity', toggle; 3280 how = $pick(how, 'toggle'); 3281 switch (how){ 3282 case 'in': fade.start(o, 1); break; 3283 case 'out': fade.start(o, 0); break; 3284 case 'show': fade.set(o, 1); break; 3285 case 'hide': fade.set(o, 0); break; 3286 case 'toggle': 3287 var flag = this.retrieve('fade:flag', this.get('opacity') == 1); 3288 fade.start(o, (flag) ? 0 : 1); 3289 this.store('fade:flag', !flag); 3290 toggle = true; 3291 break; 3292 default: fade.start(o, arguments); 3293 } 3294 if (!toggle) this.eliminate('fade:flag'); 3295 return this; 3296 }, 3297 3298 highlight: function(start, end){ 3299 if (!end){
3300 end = this.retrieve('highlight:original', this.getStyle('background-color')); 3301 end = (end == 'transparent') ? '#fff' : end; 3302 } 3303 var tween = this.get('tween'); 3304 tween.start('background-color', start || '#ffff88', end).chain(function(){ 3305 this.setStyle('background-color', this.retrieve('highlight:original')); 3306 tween.callChain(); 3307 }.bind(this)); 3308 return this; 3309 } 3310 3311}); 3312 3313 3314/* 3315Script: Fx.Morph.js 3316 Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. 3317 3318License: 3319 MIT-style license. 3320*/ 3321 3322Fx.Morph = new Class({ 3323 3324 Extends: Fx.CSS, 3325 3326 initialize: function(element, options){ 3327 this.element = this.subject = $(element); 3328 this.parent(options); 3329 }, 3330 3331 set: function(now){ 3332 if (typeof now == 'string') now = this.search(now); 3333 for (var p in now) this.render(this.element, p, now[p], this.options.unit); 3334 return this; 3335 }, 3336 3337 compute: function(from, to, delta){ 3338 var now = {}; 3339 for (var p in from) now[p] = this.parent(from[p], to[p], delta); 3340 return now; 3341 }, 3342 3343 start: function(properties){ 3344 if (!this.check(arguments.callee, properties)) return this; 3345 if (typeof properties == 'string') properties = this.search(properties); 3346 var from = {}, to = {}; 3347 for (var p in properties){ 3348 var parsed = this.prepare(this.element, p, properties[p]); 3349 from[p] = parsed.from; 3350 to[p] = parsed.to; 3351 } 3352 return this.parent(from, to); 3353 } 3354 3355}); 3356 3357Element.Properties.morph = { 3358 3359 set: function(options){ 3360 var morph = this.retrieve('morph'); 3361 if (morph) morph.cancel(); 3362 return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options)); 3363 }, 3364 3365 get: function(options){ 3366 if (options || !this.retrieve('morph')){ 3367 if (options || !this.retrieve('morph:options')) this.set('morph', options); 3368 this.store('morph', new Fx.Morph(this, this.retrieve('morph:options'))); 3369 } 3370 return this.retrieve('morph'); 3371 } 3372 3373}; 3374 3375Element.implement({ 3376 3377 morph: function(props){ 3378 this.get('morph').start(props); 3379 return this; 3380 } 3381 3382}); 3383 3384/* 3385Script: Fx.Transitions.js 3386 Contains a set of advanced transitions to be used with any of the Fx Classes. 3387 3388License: 3389 MIT-style license. 3390 3391Credits: 3392 Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. 3393*/ 3394 3395(function(){ 3396 3397 var old = Fx.prototype.initialize; 3398 3399 Fx.prototype.initialize = function(options){ 3400 old.call(this, options); 3401 var trans = this.options.transition; 3402 if (typeof trans == 'string' && (trans = trans.split(':'))){ 3403 var base = Fx.Transitions; 3404 base = base[trans[0]] || base[trans[0].capitalize()]; 3405 if (trans[1]) base = base['ease' + trans[1].capitalize() + (trans[2] ? trans[2].capitalize() : '')]; 3406 this.options.transition = base; 3407 } 3408 }; 3409 3410})(); 3411 3412Fx.Transition = function(transition, params){ 3413 params = $splat(params); 3414 return $extend(transition, { 3415 easeIn: function(pos){ 3416 return transition(pos, params); 3417 }, 3418 easeOut: function(pos){ 3419 return 1 - transition(1 - pos, params); 3420 }, 3421 easeInOut: function(pos){ 3422 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2; 3423 } 3424 }); 3425}; 3426 3427Fx.Transitions = new Hash({ 3428 3429 linear: $arguments(0) 3430 3431}); 3432 3433Fx.Transitions.extend = function(transitions){ 3434 for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 3435}; 3436 3437Fx.Transitions.extend({ 3438 3439 Pow: function(p, x){ 3440 return Math.pow(p, x[0] || 6); 3441 }, 3442 3443 Expo: function(p){ 3444 return Math.pow(2, 8 * (p - 1)); 3445 }, 3446 3447 Circ: function(p){ 3448 return 1 - Math.sin(Math.acos(p)); 3449 }, 3450 3451 Sine: function(p){ 3452 return 1 - Math.sin((1 - p) * Math.PI / 2); 3453 }, 3454 3455 Back: function(p, x){ 3456 x = x[0] || 1.618; 3457 return Math.pow(p, 2) * ((x + 1) * p - x); 3458 }, 3459 3460 Bounce: function(p){ 3461 var value; 3462 for (var a = 0, b = 1; 1; a += b, b /= 2){ 3463 if (p >= (7 - 4 * a) / 11){ 3464 value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b; 3465 break; 3466 } 3467 } 3468 return value; 3469 }, 3470 3471 Elastic: function(p, x){ 3472 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3); 3473 } 3474 3475}); 3476 3477['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ 3478 Fx.Transitions[transition] = new Fx.Transition(function(p){ 3479 return Math.pow(p, [i + 2]); 3480 }); 3481}); 3482 3483 3484/* 3485Script: Request.js 3486 Powerful all purpose Request Class. Uses XMLHTTPRequest. 3487 3488License: 3489 MIT-style license. 3490*/ 3491 3492var Request = new Class({ 3493 3494 Implements: [Chain, Events, Options], 3495 3496 options: { 3497 /*onRequest: $empty, 3498 onSuccess: $empty, 3499 onFailure: $empty, 3500 onException: $empty,*/ 3501 url: '', 3502 data: '', 3503 headers: { 3504 'X-Requested-With': 'XMLHttpRequest', 3505 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 3506 }, 3507 async: true, 3508 format: false, 3509 method: 'post', 3510 link: 'ignore', 3511 isSuccess: null, 3512 emulation: true, 3513 urlEncoded: true, 3514 encoding: 'utf-8', 3515 evalScripts: false, 3516 evalResponse: false 3517 }, 3518 3519 initialize: function(options){
3520 this.xhr = new Browser.Request(); 3521 this.setOptions(options); 3522 this.options.isSuccess = this.options.isSuccess || this.isSuccess; 3523 this.headers = new Hash(this.options.headers); 3524 }, 3525 3526 onStateChange: function(){ 3527 if (this.xhr.readyState != 4 || !this.running) return; 3528 this.running = false; 3529 this.status = 0; 3530 $try(function(){ 3531 this.status = this.xhr.status; 3532 }.bind(this)); 3533 if (this.options.isSuccess.call(this, this.status)){ 3534 this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML}; 3535 this.success(this.response.text, this.response.xml); 3536 } else { 3537 this.response = {text: null, xml: null}; 3538 this.failure(); 3539 } 3540 this.xhr.onreadystatechange = $empty; 3541 }, 3542 3543 isSuccess: function(){ 3544 return ((this.status >= 200) && (this.status < 300)); 3545 }, 3546 3547 processScripts: function(text){ 3548 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text); 3549 return text.stripScripts(this.options.evalScripts); 3550 }, 3551 3552 success: function(text, xml){ 3553 this.onSuccess(this.processScripts(text), xml); 3554 }, 3555 3556 onSuccess: function(){ 3557 this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); 3558 }, 3559 3560 failure: function(){ 3561 this.onFailure(); 3562 }, 3563 3564 onFailure: function(){ 3565 this.fireEvent('complete').fireEvent('failure', this.xhr); 3566 }, 3567 3568 setHeader: function(name, value){ 3569 this.headers.set(name, value); 3570 return this; 3571 }, 3572 3573 getHeader: function(name){ 3574 return $try(function(){ 3575 return this.xhr.getResponseHeader(name); 3576 }.bind(this)); 3577 }, 3578 3579 check: function(caller){ 3580 if (!this.running) return true; 3581 switch (this.options.link){ 3582 case 'cancel': this.cancel(); return true; 3583 case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false; 3584 } 3585 return false; 3586 }, 3587 3588 send: function(options){ 3589 if (!this.check(arguments.callee, options)) return this; 3590 this.running = true; 3591 3592 var type = $type(options); 3593 if (type == 'string' || type == 'element') options = {data: options}; 3594 3595 var old = this.options; 3596 options = $extend({data: old.data, url: old.url, method: old.method}, options); 3597 var data = options.data, url = options.url, method = options.method; 3598 3599 switch ($type(data)){ 3600 case 'element': data = $(data).toQueryString(); break; 3601 case 'object': case 'hash': data = Hash.toQueryString(data); 3602 } 3603 3604 if (this.options.format){ 3605 var format = 'format=' + this.options.format; 3606 data = (data) ? format + '&' + data : format; 3607 } 3608 3609 if (this.options.emulation && ['put', 'delete'].contains(method)){ 3610 var _method = '_method=' + method; 3611 data = (data) ? _method + '&' + data : _method; 3612 method = 'post'; 3613 } 3614 3615 if (this.options.urlEncoded && method == 'post'){ 3616 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; 3617 this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding); 3618 } 3619 3620 if (data && method == 'get'){ 3621 url = url + (url.contains('?') ? '&' : '?') + data; 3622 data = null; 3623 } 3624 3625 this.xhr.open(method.toUpperCase(), url, this.options.async); 3626 3627 this.xhr.onreadystatechange = this.onStateChange.bind(this); 3628 3629 this.headers.each(function(value, key){ 3630 if (!$try(function(){ 3631 this.xhr.setRequestHeader(key, value); 3632 return true; 3633 }.bind(this))) this.fireEvent('exception', [key, value]); 3634 }, this); 3635 3636 this.fireEvent('request'); 3637 this.xhr.send(data); 3638 if (!this.options.async) this.onStateChange(); 3639 return this; 3640 }, 3641 3642 cancel: function(){ 3643 if (!this.running) return this; 3644 this.running = false; 3645 this.xhr.abort(); 3646 this.xhr.onreadystatechange = $empty; 3647 this.xhr = new Browser.Request(); 3648 this.fireEvent('cancel'); 3649 return this; 3650 } 3651 3652}); 3653 3654(function(){ 3655 3656var methods = {}; 3657['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ 3658 methods[method] = function(){ 3659 var params = Array.link(arguments, {url: String.type, data: $defined}); 3660 return this.send($extend(params, {method: method.toLowerCase()})); 3661 }; 3662}); 3663 3664Request.implement(methods); 3665 3666})(); 3667 3668Element.Properties.send = { 3669 3670 set: function(options){ 3671 var send = this.retrieve('send'); 3672 if (send) send.cancel(); 3673 return this.eliminate('send').store('send:options', $extend({ 3674 data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') 3675 }, options)); 3676 }, 3677 3678 get: function(options){ 3679 if (options || !this.retrieve('send')){ 3680 if (options || !this.retrieve('send:options')) this.set('send', options);
3681 this.store('send', new Request(this.retrieve('send:options'))); 3682 } 3683 return this.retrieve('send'); 3684 } 3685 3686}; 3687 3688Element.implement({ 3689 3690 send: function(url){ 3691 var sender = this.get('send'); 3692 sender.send({data: this, url: url || sender.options.url}); 3693 return this; 3694 } 3695 3696}); 3697 3698 3699/* 3700Script: Request.HTML.js 3701 Extends the basic Request Class with additional methods for interacting with HTML responses. 3702 3703License: 3704 MIT-style license. 3705*/ 3706 3707Request.HTML = new Class({ 3708 3709 Extends: Request, 3710 3711 options: { 3712 update: false, 3713 evalScripts: true, 3714 filter: false 3715 }, 3716 3717 processHTML: function(text){ 3718 var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i); 3719 text = (match) ? match[1] : text; 3720 3721 var container = new Element('div'); 3722 3723 return $try(function(){ 3724 var root = '<root>' + text + '</root>', doc; 3725 if (Browser.Engine.trident){ 3726 doc = new ActiveXObject('Microsoft.XMLDOM'); 3727 doc.async = false; 3728 doc.loadXML(root); 3729 } else { 3730 doc = new DOMParser().parseFromString(root, 'text/xml'); 3731 } 3732 root = doc.getElementsByTagName('root')[0]; 3733 for (var i = 0, k = root.childNodes.length; i < k; i++){ 3734 var child = Element.clone(root.childNodes[i], true, true); 3735 if (child) container.grab(child); 3736 } 3737 return container; 3738 }) || container.set('html', text); 3739 }, 3740 3741 success: function(text){ 3742 var options = this.options, response = this.response; 3743 3744 response.html = text.stripScripts(function(script){ 3745 response.javascript = script; 3746 }); 3747 3748 var temp = this.processHTML(response.html); 3749 3750 response.tree = temp.childNodes; 3751 response.elements = temp.getElements('*'); 3752 3753 if (options.filter) response.tree = response.elements.filter(options.filter); 3754 if (options.update) $(options.update).empty().adopt(response.tree); 3755 if (options.evalScripts) $exec(response.javascript); 3756 3757 this.onSuccess(response.tree, response.elements, response.html, response.javascript); 3758 } 3759 3760}); 3761 3762Element.Properties.load = { 3763 3764 set: function(options){ 3765 var load = this.retrieve('load'); 3766 if (load) send.cancel(); 3767 return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options)); 3768 }, 3769 3770 get: function(options){ 3771 if (options || ! this.retrieve('load')){ 3772 if (options || !this.retrieve('load:options')) this.set('load', options); 3773 this.store('load', new Request.HTML(this.retrieve('load:options'))); 3774 } 3775 return this.retrieve('load'); 3776 } 3777 3778}; 3779 3780Element.implement({ 3781 3782 load: function(){ 3783 this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type})); 3784 return this; 3785 } 3786 3787}); 3788 3789 3790/* 3791Script: Request.JSON.js 3792 Extends the basic Request Class with additional methods for sending and receiving JSON data. 3793 3794License: 3795 MIT-style license. 3796*/ 3797 3798Request.JSON = new Class({ 3799 3800 Extends: Request, 3801 3802 options: { 3803 secure: true 3804 }, 3805 3806 initialize: function(options){ 3807 this.parent(options); 3808 this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'}); 3809 }, 3810 3811 success: function(text){ 3812 this.response.json = JSON.decode(text, this.options.secure); 3813 this.onSuccess(this.response.json, text); 3814 } 3815 3816});
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.