1/* 2--- 3MooTools: the javascript framework 4 5web build: 6 - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7 7 8packager build: 9 - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff 10 11/* 12--- 13 14name: Core 15 16description: The heart of MooTools. 17 18license: MIT-style license. 19 20copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/). 21 22authors: The MooTools production team (http://mootools.net/developers/) 23 24inspiration: 25 - 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) 26 - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) 27 28provides: [Core, MooTools, Type, typeOf, instanceOf, Native] 29 30... 31*/ 32 33(function(){ 34 35this.MooTools = { 36 version: '1.3.2', 37 build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587' 38}; 39 40// typeOf, instanceOf 41 42var typeOf = this.typeOf = function(item){ 43 if (item == null) return 'null'; 44 if (item.$family) return item.$family(); 45 46 if (item.nodeName){ 47 if (item.nodeType == 1) return 'element'; 48 if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; 49 } else if (typeof item.length == 'number'){ 50 if (item.callee) return 'arguments'; 51 if ('item' in item) return 'collection'; 52 } 53 54 return typeof item; 55}; 56 57var instanceOf = this.instanceOf = function(item, object){ 58 if (item == null) return false; 59 var constructor = item.$constructor || item.constructor; 60 while (constructor){ 61 if (constructor === object) return true; 62 constructor = constructor.parent; 63 } 64 return item instanceof object; 65}; 66 67// Function overloading 68 69var Function = this.Function; 70 71var enumerables = true; 72for (var i in {toString: 1}) enumerables = null; 73if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; 74 75Function.prototype.overloadSetter = function(usePlural){ 76 var self = this; 77 return function(a, b){ 78 if (a == null) return this; 79 if (usePlural || typeof a != 'string'){ 80 for (var k in a) self.call(this, k, a[k]); 81 if (enumerables) for (var i = enumerables.length; i--;){ 82 k = enumerables[i]; 83 if (a.hasOwnProperty(k)) self.call(this, k, a[k]); 84 } 85 } else { 86 self.call(this, a, b); 87 } 88 return this; 89 }; 90}; 91 92Function.prototype.overloadGetter = function(usePlural){ 93 var self = this; 94 return function(a){ 95 var args, result; 96 if (usePlural || typeof a != 'string') args = a; 97 else if (arguments.length > 1) args = arguments; 98 if (args){ 99 result = {}; 100 for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); 101 } else { 102 result = self.call(this, a); 103 } 104 return result; 105 }; 106}; 107 108Function.prototype.extend = function(key, value){ 109 this[key] = value; 110}.overloadSetter(); 111 112Function.prototype.implement = function(key, value){ 113 this.prototype[key] = value; 114}.overloadSetter(); 115 116// From 117 118var slice = Array.prototype.slice; 119 120Function.from = function(item){ 121 return (typeOf(item) == 'function') ? item : function(){ 122 return item; 123 }; 124}; 125 126Array.from = function(item){ 127 if (item == null) return []; 128 return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; 129}; 130 131Number.from = function(item){ 132 var number = parseFloat(item); 133 return isFinite(number) ? number : null; 134}; 135 136String.from = function(item){ 137 return item + ''; 138}; 139 140// hide, protect 141 142Function.implement({ 143 144 hide: function(){ 145 this.$hidden = true; 146 return this; 147 }, 148 149 protect: function(){ 150 this.$protected = true; 151 return this; 152 } 153 154}); 155 156// Type 157 158var Type = this.Type = function(name, object){ 159 if (name){ 160 var lower = name.toLowerCase(); 161 var typeCheck = function(item){ 162 return (typeOf(item) == lower); 163 }; 164 165 Type['is' + name] = typeCheck; 166 if (object != null){ 167 object.prototype.$family = (function(){ 168 return lower; 169 }).hide(); 170 //<1.2compat> 171 object.type = typeCheck; 172 //</1.2compat> 173 } 174 } 175 176 if (object == null) return null; 177 178 object.extend(this); 179 object.$constructor = Type; 180 object.prototype.$constructor = object; 181 182 return object; 183}; 184 185var toString = Object.prototype.toString; 186 187Type.isEnumerable = function(item){ 188 return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); 189}; 190 191var hooks = {}; 192 193var hooksOf = function(object){ 194 var type = typeOf(object.prototype); 195 return hooks[type] || (hooks[type] = []); 196}; 197 198var implement = function(name, method){ 199 if (method && method.$hidden) return; 200 201 var hooks = hooksOf(this); 202 203 for (var i = 0; i < hooks.length; i++){ 204 var hook = hooks[i]; 205 if (typeOf(hook) == 'type') implement.call(hook, name, method); 206 else hook.call(this, name, method); 207 } 208 209 var previous = this.prototype[name]; 210 if (previous == null || !previous.$protected) this.prototype[name] = method; 211 212 if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ 213 return method.apply(item, slice.call(arguments, 1)); 214 }); 215}; 216 217var extend = function(name, method){ 218 if (method && method.$hidden) return; 219 var previous = this[name]; 220 if (previous == null || !previous.$protected) this[name] = method; 221}; 222 223Type.implement({ 224 225 implement: implement.overloadSetter(), 226 227 extend: extend.overloadSetter(), 228 229 alias: function(name, existing){ 230 implement.call(this, name, this.prototype[existing]); 231 }.overloadSetter(), 232 233 mirror: function(hook){ 234 hooksOf(this).push(hook); 235 return this; 236 } 237 238}); 239 240new Type('Type', Type); 241 242// Default Types 243 244var force = function(name, object, methods){ 245 var isType = (object != Object), 246 prototype = object.prototype; 247 248 if (isType) object = new Type(name, object); 249 250 for (var i = 0, l = methods.length; i < l; i++){ 251 var key = methods[i], 252 generic = object[key], 253 proto = prototype[key]; 254 255 if (generic) generic.protect(); 256 257 if (isType && proto){ 258 delete prototype[key]; 259 prototype[key] = proto.protect(); 260 } 261 } 262 263 if (isType) object.implement(prototype); 264 265 return force; 266}; 267 268force('String', String, [ 269 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', 270 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase' 271])('Array', Array, [ 272 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 273 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' 274])('Number', Number, [
275 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' 276])('Function', Function, [ 277 'apply', 'call', 'bind' 278])('RegExp', RegExp, [ 279 'exec', 'test' 280])('Object', Object, [ 281 'create', 'defineProperty', 'defineProperties', 'keys', 282 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 283 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' 284])('Date', Date, ['now']); 285 286Object.extend = extend.overloadSetter(); 287 288Date.extend('now', function(){ 289 return +(new Date); 290}); 291 292new Type('Boolean', Boolean); 293 294// fixes NaN returning as Number 295 296Number.prototype.$family = function(){ 297 return isFinite(this) ? 'number' : 'null'; 298}.hide(); 299 300// Number.random 301 302Number.extend('random', function(min, max){ 303 return Math.floor(Math.random() * (max - min + 1) + min); 304}); 305 306// forEach, each 307 308var hasOwnProperty = Object.prototype.hasOwnProperty; 309Object.extend('forEach', function(object, fn, bind){ 310 for (var key in object){ 311 if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); 312 } 313}); 314 315Object.each = Object.forEach; 316 317Array.implement({ 318 319 forEach: function(fn, bind){ 320 for (var i = 0, l = this.length; i < l; i++){ 321 if (i in this) fn.call(bind, this[i], i, this); 322 } 323 }, 324 325 each: function(fn, bind){ 326 Array.forEach(this, fn, bind); 327 return this; 328 } 329 330}); 331 332// Array & Object cloning, Object merging and appending 333 334var cloneOf = function(item){ 335 switch (typeOf(item)){ 336 case 'array': return item.clone(); 337 case 'object': return Object.clone(item); 338 default: return item; 339 } 340}; 341 342Array.implement('clone', function(){ 343 var i = this.length, clone = new Array(i); 344 while (i--) clone[i] = cloneOf(this[i]); 345 return clone; 346}); 347 348var mergeOne = function(source, key, current){ 349 switch (typeOf(current)){ 350 case 'object': 351 if (typeOf(source[key]) == 'object') Object.merge(source[key], current); 352 else source[key] = Object.clone(current); 353 break; 354 case 'array': source[key] = current.clone(); break; 355 default: source[key] = current; 356 } 357 return source; 358}; 359 360Object.extend({ 361 362 merge: function(source, k, v){ 363 if (typeOf(k) == 'string') return mergeOne(source, k, v); 364 for (var i = 1, l = arguments.length; i < l; i++){ 365 var object = arguments[i]; 366 for (var key in object) mergeOne(source, key, object[key]); 367 } 368 return source; 369 }, 370 371 clone: function(object){ 372 var clone = {}; 373 for (var key in object) clone[key] = cloneOf(object[key]); 374 return clone; 375 }, 376 377 append: function(original){ 378 for (var i = 1, l = arguments.length; i < l; i++){ 379 var extended = arguments[i] || {}; 380 for (var key in extended) original[key] = extended[key]; 381 } 382 return original; 383 } 384 385}); 386 387// Object-less types 388 389['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ 390 new Type(name); 391}); 392 393// Unique ID 394 395var UID = Date.now(); 396 397String.extend('uniqueID', function(){ 398 return (UID++).toString(36); 399}); 400 401//<1.2compat> 402 403var Hash = this.Hash = new Type('Hash', function(object){ 404 if (typeOf(object) == 'hash') object = Object.clone(object.getClean()); 405 for (var key in object) this[key] = object[key]; 406 return this; 407}); 408 409Hash.implement({ 410 411 forEach: function(fn, bind){ 412 Object.forEach(this, fn, bind); 413 }, 414 415 getClean: function(){ 416 var clean = {}; 417 for (var key in this){ 418 if (this.hasOwnProperty(key)) clean[key] = this[key]; 419 } 420 return clean; 421 }, 422 423 getLength: function(){ 424 var length = 0; 425 for (var key in this){ 426 if (this.hasOwnProperty(key)) length++; 427 } 428 return length; 429 } 430 431}); 432 433Hash.alias('each', 'forEach'); 434 435Object.type = Type.isObject; 436 437var Native = this.Native = function(properties){ 438 return new Type(properties.name, properties.initialize); 439}; 440 441Native.type = Type.type; 442 443Native.implement = function(objects, methods){ 444 for (var i = 0; i < objects.length; i++) objects[i].implement(methods); 445 return Native; 446}; 447 448var arrayType = Array.type; 449Array.type = function(item){ 450 return instanceOf(item, Array) || arrayType(item); 451}; 452 453this.$A = function(item){ 454 return Array.from(item).slice(); 455}; 456 457this.$arguments = function(i){ 458 return function(){ 459 return arguments[i]; 460 }; 461}; 462 463this.$chk = function(obj){ 464 return !!(obj || obj === 0); 465}; 466 467this.$clear = function(timer){
468 clearTimeout(timer); 469 clearInterval(timer); 470 return null; 471}; 472 473this.$defined = function(obj){ 474 return (obj != null); 475}; 476 477this.$each = function(iterable, fn, bind){ 478 var type = typeOf(iterable); 479 ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind); 480}; 481 482this.$empty = function(){}; 483 484this.$extend = function(original, extended){ 485 return Object.append(original, extended); 486}; 487 488this.$H = function(object){ 489 return new Hash(object); 490}; 491 492this.$merge = function(){ 493 var args = Array.slice(arguments); 494 args.unshift({}); 495 return Object.merge.apply(null, args); 496}; 497 498this.$lambda = Function.from; 499this.$mixin = Object.merge; 500this.$random = Number.random; 501this.$splat = Array.from; 502this.$time = Date.now; 503 504this.$type = function(object){ 505 var type = typeOf(object); 506 if (type == 'elements') return 'array'; 507 return (type == 'null') ? false : type; 508}; 509 510this.$unlink = function(object){ 511 switch (typeOf(object)){ 512 case 'object': return Object.clone(object); 513 case 'array': return Array.clone(object); 514 case 'hash': return new Hash(object); 515 default: return object; 516 } 517}; 518 519//</1.2compat> 520 521})(); 522 523 524/* 525--- 526 527name: Array 528 529description: Contains Array Prototypes like each, contains, and erase. 530 531license: MIT-style license. 532 533requires: Type 534 535provides: Array 536 537... 538*/ 539 540Array.implement({ 541 542 /*<!ES5>*/ 543 every: function(fn, bind){ 544 for (var i = 0, l = this.length; i < l; i++){ 545 if ((i in this) && !fn.call(bind, this[i], i, this)) return false; 546 } 547 return true; 548 }, 549 550 filter: function(fn, bind){ 551 var results = []; 552 for (var i = 0, l = this.length; i < l; i++){ 553 if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); 554 } 555 return results; 556 }, 557 558 indexOf: function(item, from){ 559 var len = this.length; 560 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ 561 if (this[i] === item) return i; 562 } 563 return -1; 564 }, 565 566 map: function(fn, bind){ 567 var results = []; 568 for (var i = 0, l = this.length; i < l; i++){ 569 if (i in this) results[i] = fn.call(bind, this[i], i, this); 570 } 571 return results; 572 }, 573 574 some: function(fn, bind){ 575 for (var i = 0, l = this.length; i < l; i++){ 576 if ((i in this) && fn.call(bind, this[i], i, this)) return true; 577 } 578 return false; 579 }, 580 /*</!ES5>*/ 581 582 clean: function(){ 583 return this.filter(function(item){ 584 return item != null; 585 }); 586 }, 587 588 invoke: function(methodName){ 589 var args = Array.slice(arguments, 1); 590 return this.map(function(item){ 591 return item[methodName].apply(item, args); 592 }); 593 }, 594 595 associate: function(keys){ 596 var obj = {}, length = Math.min(this.length, keys.length); 597 for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; 598 return obj; 599 }, 600 601 link: function(object){ 602 var result = {}; 603 for (var i = 0, l = this.length; i < l; i++){ 604 for (var key in object){ 605 if (object[key](this[i])){ 606 result[key] = this[i]; 607 delete object[key]; 608 break; 609 } 610 } 611 } 612 return result; 613 }, 614 615 contains: function(item, from){ 616 return this.indexOf(item, from) != -1; 617 }, 618 619 append: function(array){ 620 this.push.apply(this, array); 621 return this; 622 }, 623 624 getLast: function(){ 625 return (this.length) ? this[this.length - 1] : null; 626 }, 627 628 getRandom: function(){ 629 return (this.length) ? this[Number.random(0, this.length - 1)] : null; 630 }, 631 632 include: function(item){ 633 if (!this.contains(item)) this.push(item); 634 return this; 635 }, 636 637 combine: function(array){ 638 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 639 return this; 640 }, 641 642 erase: function(item){ 643 for (var i = this.length; i--;){ 644 if (this[i] === item) this.splice(i, 1); 645 } 646 return this; 647 }, 648 649 empty: function(){ 650 this.length = 0; 651 return this; 652 }, 653 654 flatten: function(){ 655 var array = []; 656 for (var i = 0, l = this.length; i < l; i++){ 657 var type = typeOf(this[i]); 658 if (type == 'null') continue; 659 array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); 660 } 661 return array; 662 }, 663 664 pick: function(){ 665 for (var i = 0, l = this.length; i < l; i++){ 666 if (this[i] != null) return this[i]; 667 } 668 return null; 669 }, 670 671 hexToRgb: function(array){ 672 if (this.length != 3) return null; 673 var rgb = this.map(function(value){ 674 if (value.length == 1) value += value; 675 return value.toInt(16); 676 }); 677 return (array) ? rgb : 'rgb(' + rgb + ')'; 678 }, 679 680 rgbToHex: function(array){ 681 if (this.length < 3) return null; 682 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 683 var hex = []; 684 for (var i = 0; i < 3; i++){ 685 var bit = (this[i] - 0).toString(16); 686 hex.push((bit.length == 1) ? '0' + bit : bit); 687 } 688 return (array) ? hex : '#' + hex.join(''); 689 } 690 691}); 692 693//<1.2compat> 694 695Array.alias('extend', 'append'); 696 697var $pick = function(){ 698 return Array.from(arguments).pick(); 699}; 700 701//</1.2compat> 702 703 704/* 705--- 706 707name: String 708
709description: Contains String Prototypes like camelCase, capitalize, test, and toInt. 710 711license: MIT-style license. 712 713requires: Type 714 715provides: String 716 717... 718*/ 719 720String.implement({ 721 722 test: function(regex, params){ 723 return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); 724 }, 725 726 contains: function(string, separator){ 727 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; 728 }, 729 730 trim: function(){ 731 return this.replace(/^\s+|\s+$/g, ''); 732 }, 733 734 clean: function(){ 735 return this.replace(/\s+/g, ' ').trim(); 736 }, 737 738 camelCase: function(){ 739 return this.replace(/-\D/g, function(match){ 740 return match.charAt(1).toUpperCase(); 741 }); 742 }, 743 744 hyphenate: function(){ 745 return this.replace(/[A-Z]/g, function(match){ 746 return ('-' + match.charAt(0).toLowerCase()); 747 }); 748 }, 749 750 capitalize: function(){ 751 return this.replace(/\b[a-z]/g, function(match){ 752 return match.toUpperCase(); 753 }); 754 }, 755 756 escapeRegExp: function(){ 757 return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); 758 }, 759 760 toInt: function(base){ 761 return parseInt(this, base || 10); 762 }, 763 764 toFloat: function(){ 765 return parseFloat(this); 766 }, 767 768 hexToRgb: function(array){ 769 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 770 return (hex) ? hex.slice(1).hexToRgb(array) : null; 771 }, 772 773 rgbToHex: function(array){ 774 var rgb = this.match(/\d{1,3}/g); 775 return (rgb) ? rgb.rgbToHex(array) : null; 776 }, 777 778 substitute: function(object, regexp){ 779 return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ 780 if (match.charAt(0) == '\\') return match.slice(1); 781 return (object[name] != null) ? object[name] : ''; 782 }); 783 } 784 785}); 786 787 788/* 789--- 790 791name: Number 792 793description: Contains Number Prototypes like limit, round, times, and ceil. 794 795license: MIT-style license. 796 797requires: Type 798 799provides: Number 800 801... 802*/ 803 804Number.implement({ 805 806 limit: function(min, max){ 807 return Math.min(max, Math.max(min, this)); 808 }, 809 810 round: function(precision){ 811 precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); 812 return Math.round(this * precision) / precision; 813 }, 814 815 times: function(fn, bind){ 816 for (var i = 0; i < this; i++) fn.call(bind, i, this); 817 }, 818 819 toFloat: function(){ 820 return parseFloat(this); 821 }, 822 823 toInt: function(base){ 824 return parseInt(this, base || 10); 825 } 826 827}); 828 829Number.alias('each', 'times'); 830 831(function(math){ 832 var methods = {}; 833 math.each(function(name){ 834 if (!Number[name]) methods[name] = function(){ 835 return Math[name].apply(null, [this].concat(Array.from(arguments))); 836 }; 837 }); 838 Number.implement(methods); 839})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); 840 841 842/* 843--- 844 845name: Function 846 847description: Contains Function Prototypes like create, bind, pass, and delay. 848 849license: MIT-style license. 850 851requires: Type 852 853provides: Function 854 855... 856*/ 857 858Function.extend({ 859 860 attempt: function(){ 861 for (var i = 0, l = arguments.length; i < l; i++){ 862 try { 863 return arguments[i](); 864 } catch (e){} 865 } 866 return null; 867 } 868 869}); 870 871Function.implement({ 872 873 attempt: function(args, bind){ 874 try { 875 return this.apply(bind, Array.from(args)); 876 } catch (e){} 877 878 return null; 879 }, 880 881 /*<!ES5>*/ 882 bind: function(bind){ 883 var self = this, 884 args = (arguments.length > 1) ? Array.slice(arguments, 1) : null; 885 886 return function(){ 887 if (!args && !arguments.length) return self.call(bind); 888 if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments))); 889 return self.apply(bind, args || arguments); 890 }; 891 }, 892 /*</!ES5>*/ 893 894 pass: function(args, bind){ 895 var self = this; 896 if (args != null) args = Array.from(args); 897 return function(){ 898 return self.apply(bind, args || arguments); 899 }; 900 }, 901 902 delay: function(delay, bind, args){ 903 return setTimeout(this.pass((args == null ? [] : args), bind), delay); 904 }, 905 906 periodical: function(periodical, bind, args){ 907 return setInterval(this.pass((args == null ? [] : args), bind), periodical); 908 } 909 910}); 911 912//<1.2compat> 913/* ADD THIS LINE --> */ Function.prototype._nativebind = Function.prototype.bind; 914delete Function.prototype.bind; 915 916Function.implement({ 917 918 create: function(options){ 919 var self = this; 920 options = options || {}; 921 return function(event){ 922 var args = options.arguments; 923 args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0); 924 if (options.event) args = [event || window.event].extend(args); 925 var returns = function(){
926 return self.apply(options.bind || null, args); 927 }; 928 if (options.delay) return setTimeout(returns, options.delay); 929 if (options.periodical) return setInterval(returns, options.periodical); 930 if (options.attempt) return Function.attempt(returns); 931 return returns(); 932 }; 933 }, 934 935 bind: function(bind, args){ 936 /* ADD THIS LINE --> */ if( new Error().stack.match(/recaptcha/) ) return this._nativebind(bind, args); 937 var self = this; 938 if (args != null) args = Array.from(args); 939 return function(){ 940 return self.apply(bind, args || arguments); 941 }; 942 }, 943 944 bindWithEvent: function(bind, args){ 945 var self = this; 946 if (args != null) args = Array.from(args); 947 return function(event){ 948 return self.apply(bind, (args == null) ? arguments : [event].concat(args)); 949 }; 950 }, 951 952 run: function(args, bind){ 953 return this.apply(bind, Array.from(args)); 954 } 955 956}); 957 958var $try = Function.attempt; 959 960//</1.2compat> 961 962 963/* 964--- 965 966name: Object 967 968description: Object generic methods 969 970license: MIT-style license. 971 972requires: Type 973 974provides: [Object, Hash] 975 976... 977*/ 978 979(function(){ 980 981var hasOwnProperty = Object.prototype.hasOwnProperty; 982 983Object.extend({ 984 985 subset: function(object, keys){ 986 var results = {}; 987 for (var i = 0, l = keys.length; i < l; i++){ 988 var k = keys[i]; 989 if (k in object) results[k] = object[k]; 990 } 991 return results; 992 }, 993 994 map: function(object, fn, bind){ 995 var results = {}; 996 for (var key in object){ 997 if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); 998 } 999 return results; 1000 }, 1001 1002 filter: function(object, fn, bind){ 1003 var results = {}; 1004 for (var key in object){ 1005 var value = object[key]; 1006 if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; 1007 } 1008 return results; 1009 }, 1010 1011 every: function(object, fn, bind){ 1012 for (var key in object){ 1013 if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; 1014 } 1015 return true; 1016 }, 1017 1018 some: function(object, fn, bind){ 1019 for (var key in object){ 1020 if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; 1021 } 1022 return false; 1023 }, 1024 1025 keys: function(object){ 1026 var keys = []; 1027 for (var key in object){ 1028 if (hasOwnProperty.call(object, key)) keys.push(key); 1029 } 1030 return keys; 1031 }, 1032 1033 values: function(object){ 1034 var values = []; 1035 for (var key in object){ 1036 if (hasOwnProperty.call(object, key)) values.push(object[key]); 1037 } 1038 return values; 1039 }, 1040 1041 getLength: function(object){ 1042 return Object.keys(object).length; 1043 }, 1044 1045 keyOf: function(object, value){ 1046 for (var key in object){ 1047 if (hasOwnProperty.call(object, key) && object[key] === value) return key; 1048 } 1049 return null; 1050 }, 1051 1052 contains: function(object, value){ 1053 return Object.keyOf(object, value) != null; 1054 }, 1055 1056 toQueryString: function(object, base){ 1057 var queryString = []; 1058 1059 Object.each(object, function(value, key){ 1060 if (base) key = base + '[' + key + ']'; 1061 var result; 1062 switch (typeOf(value)){ 1063 case 'object': result = Object.toQueryString(value, key); break; 1064 case 'array': 1065 var qs = {}; 1066 value.each(function(val, i){ 1067 qs[i] = val; 1068 }); 1069 result = Object.toQueryString(qs, key); 1070 break; 1071 default: result = key + '=' + encodeURIComponent(value); 1072 } 1073 if (value != null) queryString.push(result); 1074 }); 1075 1076 return queryString.join('&'); 1077 } 1078 1079}); 1080 1081})(); 1082 1083//<1.2compat> 1084 1085Hash.implement({ 1086 1087 has: Object.prototype.hasOwnProperty, 1088 1089 keyOf: function(value){ 1090 return Object.keyOf(this, value); 1091 }, 1092 1093 hasValue: function(value){ 1094 return Object.contains(this, value); 1095 }, 1096 1097 extend: function(properties){ 1098 Hash.each(properties || {}, function(value, key){ 1099 Hash.set(this, key, value); 1100 }, this); 1101 return this; 1102 }, 1103 1104 combine: function(properties){ 1105 Hash.each(properties || {}, function(value, key){ 1106 Hash.include(this, key, value); 1107 }, this); 1108 return this; 1109 }, 1110 1111 erase: function(key){ 1112 if (this.hasOwnProperty(key)) delete this[key]; 1113 return this; 1114 }, 1115 1116 get: function(key){ 1117 return (this.hasOwnProperty(key)) ? this[key] : null; 1118 }, 1119 1120 set: function(key, value){ 1121 if (!this[key] || this.hasOwnProperty(key)) this[key] = value; 1122 return this; 1123 }, 1124 1125 empty: function(){ 1126 Hash.each(this, function(value, key){ 1127 delete this[key]; 1128 }, this); 1129 return this; 1130 }, 1131 1132 include: function(key, value){ 1133 if (this[key] == null) this[key] = value; 1134 return this; 1135 }, 1136 1137 map: function(fn, bind){ 1138 return new Hash(Object.map(this, fn, bind)); 1139 }, 1140 1141 filter: function(fn, bind){ 1142 return new Hash(Object.filter(this, fn, bind)); 1143 }, 1144 1145 every: function(fn, bind){ 1146 return Object.every(this, fn, bind); 1147 }, 1148 1149 some: function(fn, bind){ 1150 return Object.some(this, fn, bind); 1151 }, 1152 1153 getKeys: function(){ 1154 return Object.keys(this); 1155 }, 1156 1157 getValues: function(){ 1158 return Object.values(this); 1159 }, 1160 1161 toQueryString: function(base){ 1162 return Object.toQueryString(this, base); 1163 } 1164 1165}); 1166 1167Hash.extend = Object.append; 1168 1169Hash.alias({indexOf: 'keyOf', contains: 'hasValue'}); 1170 1171//</1.2compat> 1172 1173 1174/* 1175--- 1176 1177name: Browser 1178 1179description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. 1180 1181license: MIT-style license. 1182 1183requires: [Array, Function, Number, String] 1184 1185provides: [Browser, Window, Document] 1186 1187... 1188*/ 1189 1190(function(){ 1191 1192var document = this.document; 1193var window = document.window = this; 1194 1195var UID = 1; 1196 1197this.$uid = (window.ActiveXObject) ? function(item){ 1198 return (item.uid || (item.uid = [UID++]))[0]; 1199} : function(item){ 1200 return item.uid || (item.uid = UID++); 1201}; 1202 1203$uid(window); 1204$uid(document); 1205 1206var ua = navigator.userAgent.toLowerCase(), 1207 platform = navigator.platform.toLowerCase(), 1208 UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], 1209 mode = UA[1] == 'ie' && document.documentMode; 1210 1211var Browser = this.Browser = { 1212 1213 extend: Function.prototype.extend, 1214 1215 name: (UA[1] == 'version') ? UA[3] : UA[1], 1216 1217 version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), 1218 1219 Platform: { 1220 name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] 1221 }, 1222 1223 Features: { 1224 xpath: !!(document.evaluate), 1225 air: !!(window.runtime), 1226 query: !!(document.querySelector), 1227 json: !!(window.JSON) 1228 }, 1229 1230 Plugins: {} 1231 1232}; 1233 1234Browser[Browser.name] = true; 1235Browser[Browser.name + parseInt(Browser.version, 10)] = true; 1236Browser.Platform[Browser.Platform.name] = true; 1237 1238// Request 1239 1240Browser.Request = (function(){ 1241 1242 var XMLHTTP = function(){ 1243 return new XMLHttpRequest(); 1244 }; 1245 1246 var MSXML2 = function(){ 1247 return new ActiveXObject('MSXML2.XMLHTTP'); 1248 }; 1249 1250 var MSXML = function(){ 1251 return new ActiveXObject('Microsoft.XMLHTTP'); 1252 }; 1253 1254 return Function.attempt(function(){ 1255 XMLHTTP(); 1256 return XMLHTTP; 1257 }, function(){ 1258 MSXML2(); 1259 return MSXML2; 1260 }, function(){ 1261 MSXML(); 1262 return MSXML; 1263 }); 1264 1265})(); 1266 1267Browser.Features.xhr = !!(Browser.Request); 1268 1269// Flash detection 1270 1271var version = (Function.attempt(function(){ 1272 return navigator.plugins['Shockwave Flash'].description; 1273}, function(){ 1274 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 1275}) || '0 r0').match(/\d+/g); 1276 1277Browser.Plugins.Flash = { 1278 version: Number(version[0] || '0.' + version[1]) || 0, 1279 build: Number(version[2]) || 0 1280}; 1281 1282// String scripts 1283 1284Browser.exec = function(text){ 1285 if (!text) return text; 1286 if (window.execScript){ 1287 window.execScript(text); 1288 } else { 1289 var script = document.createElement('script'); 1290 script.setAttribute('type', 'text/javascript'); 1291 script.text = text; 1292 document.head.appendChild(script); 1293 document.head.removeChild(script); 1294 } 1295 return text; 1296}; 1297 1298String.implement('stripScripts', function(exec){ 1299 var scripts = ''; 1300 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ 1301 scripts += code + '\n'; 1302 return ''; 1303 }); 1304 if (exec === true) Browser.exec(scripts); 1305 else if (typeOf(exec) == 'function') exec(scripts, text); 1306 return text; 1307}); 1308 1309// Window, Document 1310 1311Browser.extend({ 1312 Document: this.Document, 1313 Window: this.Window, 1314 Element: this.Element, 1315 Event: this.Event 1316}); 1317 1318this.Window = this.$constructor = new Type('Window', function(){}); 1319 1320this.$family = Function.from('window').hide(); 1321 1322Window.mirror(function(name, method){ 1323 window[name] = method; 1324}); 1325 1326this.Document = document.$constructor = new Type('Document', function(){}); 1327
1328document.$family = Function.from('document').hide(); 1329 1330Document.mirror(function(name, method){ 1331 document[name] = method; 1332}); 1333 1334document.html = document.documentElement; 1335if (!document.head) document.head = document.getElementsByTagName('head')[0]; 1336 1337if (document.execCommand) try { 1338 document.execCommand("BackgroundImageCache", false, true); 1339} catch (e){} 1340 1341/*<ltIE9>*/ 1342if (this.attachEvent && !this.addEventListener){ 1343 var unloadEvent = function(){ 1344 this.detachEvent('onunload', unloadEvent); 1345 document.head = document.html = document.window = null; 1346 }; 1347 this.attachEvent('onunload', unloadEvent); 1348} 1349 1350// IE fails on collections and <select>.options (refers to <select>) 1351var arrayFrom = Array.from; 1352try { 1353 arrayFrom(document.html.childNodes); 1354} catch(e){ 1355 Array.from = function(item){ 1356 if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ 1357 var i = item.length, array = new Array(i); 1358 while (i--) array[i] = item[i]; 1359 return array; 1360 } 1361 return arrayFrom(item); 1362 }; 1363 1364 var prototype = Array.prototype, 1365 slice = prototype.slice; 1366 ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ 1367 var method = prototype[name]; 1368 Array[name] = function(item){ 1369 return method.apply(Array.from(item), slice.call(arguments, 1)); 1370 }; 1371 }); 1372} 1373/*</ltIE9>*/ 1374 1375//<1.2compat> 1376 1377if (Browser.Platform.ios) Browser.Platform.ipod = true; 1378 1379Browser.Engine = {}; 1380 1381var setEngine = function(name, version){ 1382 Browser.Engine.name = name; 1383 Browser.Engine[name + version] = true; 1384 Browser.Engine.version = version; 1385}; 1386 1387if (Browser.ie){ 1388 Browser.Engine.trident = true; 1389 1390 switch (Browser.version){ 1391 case 6: setEngine('trident', 4); break; 1392 case 7: setEngine('trident', 5); break; 1393 case 8: setEngine('trident', 6); 1394 } 1395} 1396 1397if (Browser.firefox){ 1398 Browser.Engine.gecko = true; 1399 1400 if (Browser.version >= 3) setEngine('gecko', 19); 1401 else setEngine('gecko', 18); 1402} 1403 1404if (Browser.safari || Browser.chrome){ 1405 Browser.Engine.webkit = true; 1406 1407 switch (Browser.version){ 1408 case 2: setEngine('webkit', 419); break; 1409 case 3: setEngine('webkit', 420); break; 1410 case 4: setEngine('webkit', 525); 1411 } 1412} 1413 1414if (Browser.opera){ 1415 Browser.Engine.presto = true; 1416 1417 if (Browser.version >= 9.6) setEngine('presto', 960); 1418 else if (Browser.version >= 9.5) setEngine('presto', 950); 1419 else setEngine('presto', 925); 1420} 1421 1422if (Browser.name == 'unknown'){ 1423 switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){ 1424 case 'webkit': 1425 case 'khtml': 1426 Browser.Engine.webkit = true; 1427 break; 1428 case 'gecko': 1429 Browser.Engine.gecko = true; 1430 } 1431} 1432 1433this.$exec = Browser.exec; 1434 1435//</1.2compat> 1436 1437})(); 1438 1439 1440/* 1441--- 1442 1443name: Event 1444 1445description: Contains the Event Class, to make the event object cross-browser. 1446 1447license: MIT-style license. 1448 1449requires: [Window, Document, Array, Function, String, Object] 1450 1451provides: Event 1452 1453... 1454*/ 1455 1456var Event = new Type('Event', function(event, win){ 1457 if (!win) win = window; 1458 var doc = win.document; 1459 event = event || win.event; 1460 if (event.$extended) return event; 1461 this.$extended = true; 1462 var type = event.type, 1463 target = event.target || event.srcElement, 1464 page = {}, 1465 client = {}, 1466 related = null, 1467 rightClick, wheel, code, key; 1468 while (target && target.nodeType == 3) target = target.parentNode; 1469 1470 if (type.indexOf('key') != -1){ 1471 code = event.which || event.keyCode; 1472 key = Object.keyOf(Event.Keys, code); 1473 if (type == 'keydown'){ 1474 var fKey = code - 111; 1475 if (fKey > 0 && fKey < 13) key = 'f' + fKey; 1476 } 1477 if (!key) key = String.fromCharCode(code).toLowerCase(); 1478 } else if ((/click|mouse|menu/i).test(type)){ 1479 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 1480 page = { 1481 x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, 1482 y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop 1483 }; 1484 client = { 1485 x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, 1486 y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY 1487 }; 1488 if ((/DOMMouseScroll|mousewheel/).test(type)){ 1489 wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; 1490 } 1491 rightClick = (event.which == 3) || (event.button == 2); 1492 if ((/over|out/).test(type)){ 1493 related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; 1494 var testRelated = function(){ 1495 while (related && related.nodeType == 3) related = related.parentNode; 1496 return true; 1497 }; 1498 var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated(); 1499 related = (hasRelated) ? related : null; 1500 } 1501 } else if ((/gesture|touch/i).test(type)){ 1502 this.rotation = event.rotation; 1503 this.scale = event.scale; 1504 this.targetTouches = event.targetTouches; 1505 this.changedTouches = event.changedTouches; 1506 var touches = this.touches = event.touches; 1507 if (touches && touches[0]){ 1508 var touch = touches[0]; 1509 page = {x: touch.pageX, y: touch.pageY}; 1510 client = {x: touch.clientX, y: touch.clientY}; 1511 } 1512 } 1513 1514 return Object.append(this, { 1515 event: event, 1516 type: type, 1517 1518 page: page, 1519 client: client, 1520 rightClick: rightClick, 1521 1522 wheel: wheel, 1523 1524 relatedTarget: document.id(related), 1525 target: document.id(target), 1526 1527 code: code, 1528 key: key, 1529 1530 shift: event.shiftKey, 1531 control: event.ctrlKey, 1532 alt: event.altKey, 1533 meta: event.metaKey 1534 }); 1535}); 1536 1537Event.Keys = { 1538 'enter': 13, 1539 'up': 38, 1540 'down': 40, 1541 'left': 37, 1542 'right': 39, 1543 'esc': 27, 1544 'space': 32, 1545 'backspace': 8, 1546 'tab': 9, 1547 'delete': 46 1548}; 1549 1550//<1.2compat> 1551 1552Event.Keys = new Hash(Event.Keys); 1553 1554//</1.2compat> 1555 1556Event.implement({ 1557 1558 stop: function(){ 1559 return this.stopPropagation().preventDefault(); 1560 }, 1561 1562 stopPropagation: function(){ 1563 if (this.event.stopPropagation) this.event.stopPropagation(); 1564 else this.event.cancelBubble = true; 1565 return this; 1566 }, 1567 1568 preventDefault: function(){ 1569 if (this.event.preventDefault) this.event.preventDefault(); 1570 else this.event.returnValue = false; 1571 return this; 1572 } 1573 1574}); 1575 1576 1577/* 1578--- 1579 1580name: Class 1581 1582description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. 1583 1584license: MIT-style license. 1585 1586requires: [Array, String, Function, Number] 1587 1588provides: Class 1589 1590... 1591*/ 1592 1593(function(){ 1594 1595var Class = this.Class = new Type('Class', function(params){ 1596 if (instanceOf(params, Function)) params = {initialize: params}; 1597 1598 var newClass = function(){ 1599 reset(this); 1600 if (newClass.$prototyping) return this; 1601 this.$caller = null; 1602 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; 1603 this.$caller = this.caller = null; 1604 return value; 1605 }.extend(this).implement(params); 1606 1607 newClass.$constructor = Class; 1608 newClass.prototype.$constructor = newClass; 1609 newClass.prototype.parent = parent; 1610 1611 return newClass; 1612}); 1613 1614var parent = function(){
1615 if (!this.$caller) throw new Error('The method "parent" cannot be called.'); 1616 var name = this.$caller.$name, 1617 parent = this.$caller.$owner.parent, 1618 previous = (parent) ? parent.prototype[name] : null; 1619 if (!previous) throw new Error('The method "' + name + '" has no parent.'); 1620 return previous.apply(this, arguments); 1621}; 1622 1623var reset = function(object){ 1624 for (var key in object){ 1625 var value = object[key]; 1626 switch (typeOf(value)){ 1627 case 'object': 1628 var F = function(){}; 1629 F.prototype = value; 1630 object[key] = reset(new F); 1631 break; 1632 case 'array': object[key] = value.clone(); break; 1633 } 1634 } 1635 return object; 1636}; 1637 1638var wrap = function(self, key, method){ 1639 if (method.$origin) method = method.$origin; 1640 var wrapper = function(){ 1641 if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); 1642 var caller = this.caller, current = this.$caller; 1643 this.caller = current; this.$caller = wrapper; 1644 var result = method.apply(this, arguments); 1645 this.$caller = current; this.caller = caller; 1646 return result; 1647 }.extend({$owner: self, $origin: method, $name: key}); 1648 return wrapper; 1649}; 1650 1651var implement = function(key, value, retain){ 1652 if (Class.Mutators.hasOwnProperty(key)){ 1653 value = Class.Mutators[key].call(this, value); 1654 if (value == null) return this; 1655 } 1656 1657 if (typeOf(value) == 'function'){ 1658 if (value.$hidden) return this; 1659 this.prototype[key] = (retain) ? value : wrap(this, key, value); 1660 } else { 1661 Object.merge(this.prototype, key, value); 1662 } 1663 1664 return this; 1665}; 1666 1667var getInstance = function(klass){ 1668 klass.$prototyping = true; 1669 var proto = new klass; 1670 delete klass.$prototyping; 1671 return proto; 1672}; 1673 1674Class.implement('implement', implement.overloadSetter()); 1675 1676Class.Mutators = { 1677 1678 Extends: function(parent){ 1679 this.parent = parent; 1680 this.prototype = getInstance(parent); 1681 }, 1682 1683 Implements: function(items){ 1684 Array.from(items).each(function(item){ 1685 var instance = new item; 1686 for (var key in instance) implement.call(this, key, instance[key], true); 1687 }, this); 1688 } 1689}; 1690 1691})(); 1692 1693 1694/* 1695--- 1696 1697name: Class.Extras 1698 1699description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. 1700 1701license: MIT-style license. 1702 1703requires: Class 1704 1705provides: [Class.Extras, Chain, Events, Options] 1706 1707... 1708*/ 1709 1710(function(){ 1711 1712this.Chain = new Class({ 1713 1714 $chain: [], 1715 1716 chain: function(){ 1717 this.$chain.append(Array.flatten(arguments)); 1718 return this; 1719 }, 1720 1721 callChain: function(){ 1722 return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; 1723 }, 1724 1725 clearChain: function(){ 1726 this.$chain.empty(); 1727 return this; 1728 } 1729 1730}); 1731 1732var removeOn = function(string){ 1733 return string.replace(/^on([A-Z])/, function(full, first){ 1734 return first.toLowerCase(); 1735 }); 1736}; 1737 1738this.Events = new Class({ 1739 1740 $events: {}, 1741 1742 addEvent: function(type, fn, internal){ 1743 type = removeOn(type); 1744 1745 /*<1.2compat>*/ 1746 if (fn == $empty) return this; 1747 /*</1.2compat>*/ 1748 1749 this.$events[type] = (this.$events[type] || []).include(fn); 1750 if (internal) fn.internal = true; 1751 return this; 1752 }, 1753 1754 addEvents: function(events){ 1755 for (var type in events) this.addEvent(type, events[type]); 1756 return this; 1757 }, 1758 1759 fireEvent: function(type, args, delay){ 1760 type = removeOn(type); 1761 var events = this.$events[type]; 1762 if (!events) return this; 1763 args = Array.from(args); 1764 events.each(function(fn){ 1765 if (delay) fn.delay(delay, this, args); 1766 else fn.apply(this, args); 1767 }, this); 1768 return this; 1769 }, 1770 1771 removeEvent: function(type, fn){ 1772 type = removeOn(type); 1773 var events = this.$events[type]; 1774 if (events && !fn.internal){ 1775 var index = events.indexOf(fn); 1776 if (index != -1) delete events[index]; 1777 } 1778 return this; 1779 }, 1780 1781 removeEvents: function(events){ 1782 var type; 1783 if (typeOf(events) == 'object'){ 1784 for (type in events) this.removeEvent(type, events[type]); 1785 return this; 1786 } 1787 if (events) events = removeOn(events); 1788 for (type in this.$events){ 1789 if (events && events != type) continue; 1790 var fns = this.$events[type]; 1791 for (var i = fns.length; i--;) if (i in fns){ 1792 this.removeEvent(type, fns[i]); 1793 } 1794 } 1795 return this; 1796 } 1797 1798}); 1799 1800this.Options = new Class({ 1801 1802 setOptions: function(){ 1803 var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); 1804 if (this.addEvent) for (var option in options){ 1805 if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; 1806 this.addEvent(option, options[option]); 1807 delete options[option]; 1808 } 1809 return this; 1810 } 1811 1812}); 1813 1814})(); 1815 1816 1817/* 1818--- 1819name: Slick.Parser 1820description: Standalone CSS3 Selector parser 1821provides: Slick.Parser 1822... 1823*/ 1824 1825;(function(){ 1826 1827var parsed, 1828 separatorIndex, 1829 combinatorIndex, 1830 reversed, 1831 cache = {}, 1832 reverseCache = {}, 1833 reUnescape = /\\/g; 1834 1835var parse = function(expression, isReversed){ 1836 if (expression == null) return null; 1837 if (expression.Slick === true) return expression; 1838 expression = ('' + expression).replace(/^\s+|\s+$/g, ''); 1839 reversed = !!isReversed; 1840 var currentCache = (reversed) ? reverseCache : cache; 1841 if (currentCache[expression]) return currentCache[expression]; 1842 parsed = { 1843 Slick: true, 1844 expressions: [], 1845 raw: expression, 1846 reverse: function(){ 1847 return parse(this.raw, true); 1848 } 1849 }; 1850 separatorIndex = -1; 1851 while (expression != (expression = expression.replace(regexp, parser))); 1852 parsed.length = parsed.expressions.length; 1853 return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; 1854};
1855 1856var reverseCombinator = function(combinator){ 1857 if (combinator === '!') return ' '; 1858 else if (combinator === ' ') return '!'; 1859 else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); 1860 else return '!' + combinator; 1861}; 1862 1863var reverse = function(expression){ 1864 var expressions = expression.expressions; 1865 for (var i = 0; i < expressions.length; i++){ 1866 var exp = expressions[i]; 1867 var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; 1868 1869 for (var j = 0; j < exp.length; j++){ 1870 var cexp = exp[j]; 1871 if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; 1872 cexp.combinator = cexp.reverseCombinator; 1873 delete cexp.reverseCombinator; 1874 } 1875 1876 exp.reverse().push(last); 1877 } 1878 return expression; 1879}; 1880 1881var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License 1882 return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ 1883 return '\\' + match; 1884 }); 1885}; 1886 1887var regexp = new RegExp( 1888/* 1889#!/usr/bin/env ruby 1890puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') 1891__END__ 1892 "(?x)^(?:\ 1893 \\s* ( , ) \\s* # Separator \n\ 1894 | \\s* ( <combinator>+ ) \\s* # Combinator \n\ 1895 | ( \\s+ ) # CombinatorChildren \n\ 1896 | ( <unicode>+ | \\* ) # Tag \n\ 1897 | \\# ( <unicode>+ ) # ID \n\ 1898 | \\. ( <unicode>+ ) # ClassName \n\ 1899 | # Attribute \n\ 1900 \\[ \ 1901 \\s* (<unicode1>+) (?: \ 1902 \\s* ([*^$!~|]?=) (?: \ 1903 \\s* (?:\ 1904 ([\"']?)(.*?)\\9 \ 1905 )\ 1906 ) \ 1907 )? \\s* \ 1908 \\](?!\\]) \n\ 1909 | :+ ( <unicode>+ )(?:\ 1910 \\( (?:\ 1911 (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ 1912 ) \\)\ 1913 )?\ 1914 )" 1915*/ 1916 "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" 1917 .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') 1918 .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') 1919 .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') 1920); 1921 1922function parser( 1923 rawMatch, 1924 1925 separator, 1926 combinator, 1927 combinatorChildren, 1928 1929 tagName, 1930 id, 1931 className, 1932 1933 attributeKey, 1934 attributeOperator, 1935 attributeQuote, 1936 attributeValue, 1937 1938 pseudoMarker, 1939 pseudoClass, 1940 pseudoQuote, 1941 pseudoClassQuotedValue, 1942 pseudoClassValue 1943){ 1944 if (separator || separatorIndex === -1){ 1945 parsed.expressions[++separatorIndex] = []; 1946 combinatorIndex = -1; 1947 if (separator) return ''; 1948 } 1949 1950 if (combinator || combinatorChildren || combinatorIndex === -1){ 1951 combinator = combinator || ' '; 1952 var currentSeparator = parsed.expressions[separatorIndex]; 1953 if (reversed && currentSeparator[combinatorIndex]) 1954 currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); 1955 currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; 1956 } 1957 1958 var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; 1959 1960 if (tagName){ 1961 currentParsed.tag = tagName.replace(reUnescape, ''); 1962 1963 } else if (id){ 1964 currentParsed.id = id.replace(reUnescape, ''); 1965 1966 } else if (className){ 1967 className = className.replace(reUnescape, ''); 1968 1969 if (!currentParsed.classList) currentParsed.classList = []; 1970 if (!currentParsed.classes) currentParsed.classes = []; 1971 currentParsed.classList.push(className); 1972 currentParsed.classes.push({ 1973 value: className, 1974 regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') 1975 }); 1976 1977 } else if (pseudoClass){ 1978 pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; 1979 pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; 1980 1981 if (!currentParsed.pseudos) currentParsed.pseudos = []; 1982 currentParsed.pseudos.push({ 1983 key: pseudoClass.replace(reUnescape, ''), 1984 value: pseudoClassValue, 1985 type: pseudoMarker.length == 1 ? 'class' : 'element'
1986 }); 1987 1988 } else if (attributeKey){ 1989 attributeKey = attributeKey.replace(reUnescape, ''); 1990 attributeValue = (attributeValue || '').replace(reUnescape, ''); 1991 1992 var test, regexp; 1993 1994 switch (attributeOperator){ 1995 case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; 1996 case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; 1997 case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; 1998 case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; 1999 case '=' : test = function(value){ 2000 return attributeValue == value; 2001 }; break; 2002 case '*=' : test = function(value){ 2003 return value && value.indexOf(attributeValue) > -1; 2004 }; break; 2005 case '!=' : test = function(value){ 2006 return attributeValue != value; 2007 }; break; 2008 default : test = function(value){ 2009 return !!value; 2010 }; 2011 } 2012 2013 if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ 2014 return false; 2015 }; 2016 2017 if (!test) test = function(value){ 2018 return value && regexp.test(value); 2019 }; 2020 2021 if (!currentParsed.attributes) currentParsed.attributes = []; 2022 currentParsed.attributes.push({ 2023 key: attributeKey, 2024 operator: attributeOperator, 2025 value: attributeValue, 2026 test: test 2027 }); 2028 2029 } 2030 2031 return ''; 2032}; 2033 2034// Slick NS 2035 2036var Slick = (this.Slick || {}); 2037 2038Slick.parse = function(expression){ 2039 return parse(expression); 2040}; 2041 2042Slick.escapeRegExp = escapeRegExp; 2043 2044if (!this.Slick) this.Slick = Slick; 2045 2046}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); 2047 2048 2049/* 2050--- 2051name: Slick.Finder 2052description: The new, superfast css selector engine. 2053provides: Slick.Finder 2054requires: Slick.Parser 2055... 2056*/ 2057 2058;(function(){ 2059 2060var local = {}, 2061 featuresCache = {}, 2062 toString = Object.prototype.toString; 2063 2064// Feature / Bug detection 2065 2066local.isNativeCode = function(fn){ 2067 return (/\{\s*\[native code\]\s*\}/).test('' + fn); 2068}; 2069 2070local.isXML = function(document){ 2071 return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || 2072 (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); 2073}; 2074 2075local.setDocument = function(document){ 2076 2077 // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. 2078 var nodeType = document.nodeType; 2079 if (nodeType == 9); // document 2080 else if (nodeType) document = document.ownerDocument; // node 2081 else if (document.navigator) document = document.document; // window 2082 else return; 2083 2084 // check if it's the old document 2085 2086 if (this.document === document) return; 2087 this.document = document; 2088 2089 // check if we have done feature detection on this document before 2090 2091 var root = document.documentElement, 2092 rootUid = this.getUIDXML(root), 2093 features = featuresCache[rootUid], 2094 feature; 2095 2096 if (features){ 2097 for (feature in features){ 2098 this[feature] = features[feature]; 2099 } 2100 return; 2101 } 2102 2103 features = featuresCache[rootUid] = {}; 2104 2105 features.root = root; 2106 features.isXMLDocument = this.isXML(document); 2107 2108 features.brokenStarGEBTN 2109 = features.starSelectsClosedQSA 2110 = features.idGetsName 2111 = features.brokenMixedCaseQSA 2112 = features.brokenGEBCN 2113 = features.brokenCheckedQSA 2114 = features.brokenEmptyAttributeQSA 2115 = features.isHTMLDocument 2116 = features.nativeMatchesSelector 2117 = false; 2118 2119 var starSelectsClosed, starSelectsComments, 2120 brokenSecondClassNameGEBCN, cachedGetElementsByClassName, 2121 brokenFormAttributeGetter; 2122 2123 var selected, id = 'slick_uniqueid'; 2124 var testNode = document.createElement('div'); 2125 2126 var testRoot = document.body || document.getElementsByTagName('body')[0] || root; 2127 testRoot.appendChild(testNode); 2128 2129 // on non-HTML documents innerHTML and getElementsById doesnt work properly 2130 try { 2131 testNode.innerHTML = '<a id="'+id+'"></a>'; 2132 features.isHTMLDocument = !!document.getElementById(id); 2133 } catch(e){}; 2134 2135 if (features.isHTMLDocument){ 2136 2137 testNode.style.display = 'none'; 2138 2139 // IE returns comment nodes for getElementsByTagName('*') for some documents 2140 testNode.appendChild(document.createComment('')); 2141 starSelectsComments = (testNode.getElementsByTagName('*').length > 1); 2142 2143 // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents 2144 try { 2145 testNode.innerHTML = 'foo</foo>'; 2146 selected = testNode.getElementsByTagName('*'); 2147 starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); 2148 } catch(e){}; 2149 2150 features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; 2151 2152 // IE returns elements with the name instead of just id for getElementsById for some documents 2153 try { 2154 testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; 2155 features.idGetsName = document.getElementById(id) === testNode.firstChild; 2156 } catch(e){}; 2157 2158 if (testNode.getElementsByClassName){ 2159 2160 // Safari 3.2 getElementsByClassName caches results 2161 try { 2162 testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; 2163 testNode.getElementsByClassName('b').length; 2164 testNode.firstChild.className = 'b'; 2165 cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); 2166 } catch(e){}; 2167 2168 // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one 2169 try { 2170 testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; 2171 brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); 2172 } catch(e){}; 2173
2174 features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; 2175 } 2176 2177 if (testNode.querySelectorAll){ 2178 // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents 2179 try { 2180 testNode.innerHTML = 'foo</foo>'; 2181 selected = testNode.querySelectorAll('*'); 2182 features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); 2183 } catch(e){}; 2184 2185 // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode 2186 try { 2187 testNode.innerHTML = '<a class="MiX"></a>'; 2188 features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; 2189 } catch(e){}; 2190 2191 // Webkit and Opera dont return selected options on querySelectorAll 2192 try { 2193 testNode.innerHTML = '<select><option selected="selected">a</option></select>'; 2194 features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); 2195 } catch(e){}; 2196 2197 // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll 2198 try { 2199 testNode.innerHTML = '<a class=""></a>'; 2200 features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); 2201 } catch(e){}; 2202 2203 } 2204 2205 // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input 2206 try { 2207 testNode.innerHTML = '<form action="s"><input id="action"/></form>'; 2208 brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); 2209 } catch(e){}; 2210 2211 // native matchesSelector function 2212 2213 features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; 2214 if (features.nativeMatchesSelector) try { 2215 // if matchesSelector trows errors on incorrect sintaxes we can use it 2216 features.nativeMatchesSelector.call(root, ':slick'); 2217 features.nativeMatchesSelector = null; 2218 } catch(e){}; 2219 2220 } 2221 2222 try { 2223 root.slick_expando = 1; 2224 delete root.slick_expando; 2225 features.getUID = this.getUIDHTML; 2226 } catch(e) { 2227 features.getUID = this.getUIDXML; 2228 } 2229 2230 testRoot.removeChild(testNode); 2231 testNode = selected = testRoot = null; 2232 2233 // getAttribute 2234 2235 features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ 2236 var method = this.attributeGetters[name]; 2237 if (method) return method.call(node); 2238 var attributeNode = node.getAttributeNode(name); 2239 return (attributeNode) ? attributeNode.nodeValue : null; 2240 } : function(node, name){ 2241 var method = this.attributeGetters[name]; 2242 return (method) ? method.call(node) : node.getAttribute(name); 2243 }; 2244 2245 // hasAttribute 2246 2247 features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { 2248 return node.hasAttribute(attribute); 2249 } : function(node, attribute) { 2250 node = node.getAttributeNode(attribute); 2251 return !!(node && (node.specified || node.nodeValue)); 2252 }; 2253 2254 // contains 2255 // FIXME: Add specs: local.contains should be different for xml and html documents? 2256 features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){ 2257 return context.contains(node); 2258 } : (root && root.compareDocumentPosition) ? function(context, node){ 2259 return context === node || !!(context.compareDocumentPosition(node) & 16); 2260 } : function(context, node){ 2261 if (node) do { 2262 if (node === context) return true; 2263 } while ((node = node.parentNode)); 2264 return false; 2265 }; 2266 2267 // document order sorting 2268 // credits to Sizzle (http://sizzlejs.com/) 2269 2270 features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ 2271 if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; 2272 return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 2273 } : ('sourceIndex' in root) ? function(a, b){ 2274 if (!a.sourceIndex || !b.sourceIndex) return 0; 2275 return a.sourceIndex - b.sourceIndex; 2276 } : (document.createRange) ? function(a, b){ 2277 if (!a.ownerDocument || !b.ownerDocument) return 0; 2278 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 2279 aRange.setStart(a, 0); 2280 aRange.setEnd(a, 0); 2281 bRange.setStart(b, 0); 2282 bRange.setEnd(b, 0); 2283 return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); 2284 } : null ; 2285 2286 root = null; 2287 2288 for (feature in features){ 2289 this[feature] = features[feature]; 2290 } 2291}; 2292 2293// Main Method 2294 2295var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, 2296 reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, 2297 qsaFailExpCache = {}; 2298 2299local.search = function(context, expression, append, first){ 2300 2301 var found = this.found = (first) ? null : (append || []); 2302 2303 if (!context) return found; 2304 else if (context.navigator) context = context.document; // Convert the node from a window to a document 2305 else if (!context.nodeType) return found; 2306 2307 // setup 2308 2309 var parsed, i, 2310 uniques = this.uniques = {}, 2311 hasOthers = !!(append && append.length), 2312 contextIsDocument = (context.nodeType == 9); 2313 2314 if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); 2315 2316 // avoid duplicating items already in the append array 2317 if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; 2318 2319 // expression checks 2320 2321 if (typeof expression == 'string'){ // expression is a string 2322 2323 /*<simple-selectors-override>*/ 2324 var simpleSelector = expression.match(reSimpleSelector); 2325 simpleSelectors: if (simpleSelector) { 2326 2327 var symbol = simpleSelector[1], 2328 name = simpleSelector[2], 2329 node, nodes; 2330 2331 if (!symbol){ 2332 2333 if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; 2334 nodes = context.getElementsByTagName(name); 2335 if (first) return nodes[0] || null; 2336 for (i = 0; node = nodes[i++];){ 2337 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); 2338 } 2339 2340 } else if (symbol == '#'){ 2341 2342 if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; 2343 node = context.getElementById(name); 2344 if (!node) return found; 2345 if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; 2346 if (first) return node || null; 2347 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); 2348 2349 } else if (symbol == '.'){ 2350 2351 if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; 2352 if (context.getElementsByClassName && !this.brokenGEBCN){ 2353 nodes = context.getElementsByClassName(name); 2354 if (first) return nodes[0] || null; 2355 for (i = 0; node = nodes[i++];){ 2356 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); 2357 } 2358 } else { 2359 var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); 2360 nodes = context.getElementsByTagName('*'); 2361 for (i = 0; node = nodes[i++];){
2362 className = node.className; 2363 if (!(className && matchClass.test(className))) continue; 2364 if (first) return node; 2365 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); 2366 } 2367 } 2368 2369 } 2370 2371 if (hasOthers) this.sort(found); 2372 return (first) ? null : found; 2373 2374 } 2375 /*</simple-selectors-override>*/ 2376 2377 /*<query-selector-override>*/ 2378 querySelector: if (context.querySelectorAll) { 2379 2380 if (!this.isHTMLDocument 2381 || qsaFailExpCache[expression] 2382 //TODO: only skip when expression is actually mixed case 2383 || this.brokenMixedCaseQSA 2384 || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) 2385 || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) 2386 || (!contextIsDocument //Abort when !contextIsDocument and... 2387 // there are multiple expressions in the selector 2388 // since we currently only fix non-document rooted QSA for single expression selectors 2389 && expression.indexOf(',') > -1 2390 ) 2391 || Slick.disableQSA 2392 ) break querySelector; 2393 2394 var _expression = expression, _context = context; 2395 if (!contextIsDocument){ 2396 // non-document rooted QSA 2397 // credits to Andrew Dupont 2398 var currentId = _context.getAttribute('id'), slickid = 'slickid__'; 2399 _context.setAttribute('id', slickid); 2400 _expression = '#' + slickid + ' ' + _expression; 2401 context = _context.parentNode; 2402 } 2403 2404 try { 2405 if (first) return context.querySelector(_expression) || null; 2406 else nodes = context.querySelectorAll(_expression); 2407 } catch(e) { 2408 qsaFailExpCache[expression] = 1; 2409 break querySelector; 2410 } finally { 2411 if (!contextIsDocument){ 2412 if (currentId) _context.setAttribute('id', currentId); 2413 else _context.removeAttribute('id'); 2414 context = _context; 2415 } 2416 } 2417 2418 if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ 2419 if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); 2420 } else for (i = 0; node = nodes[i++];){ 2421 if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); 2422 } 2423 2424 if (hasOthers) this.sort(found); 2425 return found; 2426 2427 } 2428 /*</query-selector-override>*/ 2429 2430 parsed = this.Slick.parse(expression); 2431 if (!parsed.length) return found; 2432 } else if (expression == null){ // there is no expression 2433 return found; 2434 } else if (expression.Slick){ // expression is a parsed Slick object 2435 parsed = expression; 2436 } else if (this.contains(context.documentElement || context, expression)){ // expression is a node 2437 (found) ? found.push(expression) : found = expression; 2438 return found; 2439 } else { // other junk 2440 return found; 2441 } 2442 2443 /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ 2444 2445 // cache elements for the nth selectors 2446 2447 this.posNTH = {}; 2448 this.posNTHLast = {}; 2449 this.posNTHType = {}; 2450 this.posNTHTypeLast = {}; 2451 2452 /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ 2453 2454 // if append is null and there is only a single selector with one expression use pushArray, else use pushUID 2455 this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; 2456 2457 if (found == null) found = []; 2458 2459 // default engine 2460 2461 var j, m, n; 2462 var combinator, tag, id, classList, classes, attributes, pseudos; 2463 var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; 2464 2465 search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ 2466 2467 combinator = 'combinator:' + currentBit.combinator; 2468 if (!this[combinator]) continue search; 2469 2470 tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); 2471 id = currentBit.id; 2472 classList = currentBit.classList; 2473 classes = currentBit.classes; 2474 attributes = currentBit.attributes; 2475 pseudos = currentBit.pseudos; 2476 lastBit = (j === (currentExpression.length - 1)); 2477 2478 this.bitUniques = {}; 2479 2480 if (lastBit){ 2481 this.uniques = uniques; 2482 this.found = found; 2483 } else { 2484 this.uniques = {}; 2485 this.found = []; 2486 } 2487 2488 if (j === 0){ 2489 this[combinator](context, tag, id, classes, attributes, pseudos, classList); 2490 if (first && lastBit && found.length) break search; 2491 } else { 2492 if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ 2493 this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); 2494 if (found.length) break search; 2495 } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); 2496 } 2497 2498 currentItems = this.found; 2499 } 2500 2501 // should sort if there are nodes in append and if you pass multiple expressions. 2502 if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); 2503 2504 return (first) ? (found[0] || null) : found; 2505}; 2506 2507// Utils 2508 2509local.uidx = 1; 2510local.uidk = 'slick-uniqueid'; 2511 2512local.getUIDXML = function(node){ 2513 var uid = node.getAttribute(this.uidk);
2514 if (!uid){ 2515 uid = this.uidx++; 2516 node.setAttribute(this.uidk, uid); 2517 } 2518 return uid; 2519}; 2520 2521local.getUIDHTML = function(node){ 2522 return node.uniqueNumber || (node.uniqueNumber = this.uidx++); 2523}; 2524 2525// sort based on the setDocument documentSorter method. 2526 2527local.sort = function(results){ 2528 if (!this.documentSorter) return results; 2529 results.sort(this.documentSorter); 2530 return results; 2531}; 2532 2533/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ 2534 2535local.cacheNTH = {}; 2536 2537local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; 2538 2539local.parseNTHArgument = function(argument){ 2540 var parsed = argument.match(this.matchNTH); 2541 if (!parsed) return false; 2542 var special = parsed[2] || false; 2543 var a = parsed[1] || 1; 2544 if (a == '-') a = -1; 2545 var b = +parsed[3] || 0; 2546 parsed = 2547 (special == 'n') ? {a: a, b: b} : 2548 (special == 'odd') ? {a: 2, b: 1} : 2549 (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; 2550 2551 return (this.cacheNTH[argument] = parsed); 2552}; 2553 2554local.createNTHPseudo = function(child, sibling, positions, ofType){ 2555 return function(node, argument){ 2556 var uid = this.getUID(node); 2557 if (!this[positions][uid]){ 2558 var parent = node.parentNode; 2559 if (!parent) return false; 2560 var el = parent[child], count = 1; 2561 if (ofType){ 2562 var nodeName = node.nodeName; 2563 do { 2564 if (el.nodeName != nodeName) continue; 2565 this[positions][this.getUID(el)] = count++; 2566 } while ((el = el[sibling])); 2567 } else { 2568 do { 2569 if (el.nodeType != 1) continue; 2570 this[positions][this.getUID(el)] = count++; 2571 } while ((el = el[sibling])); 2572 } 2573 } 2574 argument = argument || 'n'; 2575 var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); 2576 if (!parsed) return false; 2577 var a = parsed.a, b = parsed.b, pos = this[positions][uid]; 2578 if (a == 0) return b == pos; 2579 if (a > 0){ 2580 if (pos < b) return false; 2581 } else { 2582 if (b < pos) return false; 2583 } 2584 return ((pos - b) % a) == 0; 2585 }; 2586}; 2587 2588/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ 2589 2590local.pushArray = function(node, tag, id, classes, attributes, pseudos){ 2591 if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); 2592}; 2593 2594local.pushUID = function(node, tag, id, classes, attributes, pseudos){ 2595 var uid = this.getUID(node); 2596 if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ 2597 this.uniques[uid] = true; 2598 this.found.push(node); 2599 } 2600}; 2601 2602local.matchNode = function(node, selector){ 2603 if (this.isHTMLDocument && this.nativeMatchesSelector){ 2604 try { 2605 return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); 2606 } catch(matchError) {} 2607 } 2608 2609 var parsed = this.Slick.parse(selector); 2610 if (!parsed) return true; 2611 2612 // simple (single) selectors 2613 var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i; 2614 for (i = 0; (currentExpression = expressions[i]); i++){ 2615 if (currentExpression.length == 1){ 2616 var exp = currentExpression[0]; 2617 if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; 2618 simpleExpCounter++; 2619 } 2620 } 2621 2622 if (simpleExpCounter == parsed.length) return false; 2623 2624 var nodes = this.search(this.document, parsed), item; 2625 for (i = 0; item = nodes[i++];){ 2626 if (item === node) return true; 2627 } 2628 return false; 2629}; 2630 2631local.matchPseudo = function(node, name, argument){ 2632 var pseudoName = 'pseudo:' + name; 2633 if (this[pseudoName]) return this[pseudoName](node, argument); 2634 var attribute = this.getAttribute(node, name); 2635 return (argument) ? argument == attribute : !!attribute; 2636}; 2637 2638local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ 2639 if (tag){ 2640 var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); 2641 if (tag == '*'){ 2642 if (nodeName < '@') return false; // Fix for comment nodes and closed nodes 2643 } else { 2644 if (nodeName != tag) return false; 2645 } 2646 } 2647 2648 if (id && node.getAttribute('id') != id) return false; 2649 2650 var i, part, cls; 2651 if (classes) for (i = classes.length; i--;){ 2652 cls = node.getAttribute('class') || node.className; 2653 if (!(cls && classes[i].regexp.test(cls))) return false; 2654 } 2655 if (attributes) for (i = attributes.length; i--;){ 2656 part = attributes[i]; 2657 if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; 2658 } 2659 if (pseudos) for (i = pseudos.length; i--;){ 2660 part = pseudos[i]; 2661 if (!this.matchPseudo(node, part.key, part.value)) return false; 2662 } 2663 return true; 2664}; 2665 2666var combinators = { 2667 2668 ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level 2669 2670 var i, item, children; 2671 2672 if (this.isHTMLDocument){ 2673 getById: if (id){ 2674 item = this.document.getElementById(id); 2675 if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ 2676 // all[id] returns all the elements with that name or id inside node 2677 // if theres just one it will return the element, else it will be a collection 2678 children = node.all[id]; 2679 if (!children) return; 2680 if (!children[0]) children = [children]; 2681 for (i = 0; item = children[i++];){ 2682 var idNode = item.getAttributeNode('id'); 2683 if (idNode && idNode.nodeValue == id){ 2684 this.push(item, tag, null, classes, attributes, pseudos); 2685 break; 2686 } 2687 } 2688 return; 2689 } 2690 if (!item){ 2691 // if the context is in the dom we return, else we will try GEBTN, breaking the getById label 2692 if (this.contains(this.root, node)) return; 2693 else break getById; 2694 } else if (this.document !== node && !this.contains(node, item)) return; 2695 this.push(item, tag, null, classes, attributes, pseudos); 2696 return; 2697 } 2698 getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ 2699 children = node.getElementsByClassName(classList.join(' '));
2700 if (!(children && children.length)) break getByClass; 2701 for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); 2702 return; 2703 } 2704 } 2705 getByTag: { 2706 children = node.getElementsByTagName(tag); 2707 if (!(children && children.length)) break getByTag; 2708 if (!this.brokenStarGEBTN) tag = null; 2709 for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); 2710 } 2711 }, 2712 2713 '>': function(node, tag, id, classes, attributes, pseudos){ // direct children 2714 if ((node = node.firstChild)) do { 2715 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); 2716 } while ((node = node.nextSibling)); 2717 }, 2718 2719 '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling 2720 while ((node = node.nextSibling)) if (node.nodeType == 1){ 2721 this.push(node, tag, id, classes, attributes, pseudos); 2722 break; 2723 } 2724 }, 2725 2726 '^': function(node, tag, id, classes, attributes, pseudos){ // first child 2727 node = node.firstChild; 2728 if (node){ 2729 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); 2730 else this['combinator:+'](node, tag, id, classes, attributes, pseudos); 2731 } 2732 }, 2733 2734 '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings 2735 while ((node = node.nextSibling)){ 2736 if (node.nodeType != 1) continue; 2737 var uid = this.getUID(node); 2738 if (this.bitUniques[uid]) break; 2739 this.bitUniques[uid] = true; 2740 this.push(node, tag, id, classes, attributes, pseudos); 2741 } 2742 }, 2743 2744 '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling 2745 this['combinator:+'](node, tag, id, classes, attributes, pseudos); 2746 this['combinator:!+'](node, tag, id, classes, attributes, pseudos); 2747 }, 2748 2749 '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings 2750 this['combinator:~'](node, tag, id, classes, attributes, pseudos); 2751 this['combinator:!~'](node, tag, id, classes, attributes, pseudos); 2752 }, 2753 2754 '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document 2755 while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); 2756 }, 2757 2758 '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) 2759 node = node.parentNode; 2760 if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); 2761 }, 2762 2763 '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling 2764 while ((node = node.previousSibling)) if (node.nodeType == 1){ 2765 this.push(node, tag, id, classes, attributes, pseudos); 2766 break; 2767 } 2768 }, 2769 2770 '!^': function(node, tag, id, classes, attributes, pseudos){ // last child 2771 node = node.lastChild; 2772 if (node){ 2773 if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); 2774 else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); 2775 } 2776 }, 2777 2778 '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings 2779 while ((node = node.previousSibling)){ 2780 if (node.nodeType != 1) continue; 2781 var uid = this.getUID(node); 2782 if (this.bitUniques[uid]) break; 2783 this.bitUniques[uid] = true; 2784 this.push(node, tag, id, classes, attributes, pseudos); 2785 } 2786 } 2787 2788}; 2789 2790for (var c in combinators) local['combinator:' + c] = combinators[c]; 2791 2792var pseudos = { 2793 2794 /*<pseudo-selectors>*/ 2795 2796 'empty': function(node){ 2797 var child = node.firstChild; 2798 return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; 2799 }, 2800 2801 'not': function(node, expression){ 2802 return !this.matchNode(node, expression); 2803 }, 2804 2805 'contains': function(node, text){ 2806 return (node.innerText || node.textContent || '').indexOf(text) > -1; 2807 }, 2808 2809 'first-child': function(node){ 2810 while ((node = node.previousSibling)) if (node.nodeType == 1) return false; 2811 return true; 2812 }, 2813 2814 'last-child': function(node){ 2815 while ((node = node.nextSibling)) if (node.nodeType == 1) return false; 2816 return true; 2817 }, 2818 2819 'only-child': function(node){ 2820 var prev = node; 2821 while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; 2822 var next = node; 2823 while ((next = next.nextSibling)) if (next.nodeType == 1) return false; 2824 return true; 2825 }, 2826 2827 /*<nth-pseudo-selectors>*/ 2828 2829 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), 2830 2831 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), 2832 2833 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), 2834 2835 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), 2836 2837 'index': function(node, index){ 2838 return this['pseudo:nth-child'](node, '' + index + 1); 2839 }, 2840 2841 'even': function(node){ 2842 return this['pseudo:nth-child'](node, '2n'); 2843 }, 2844 2845 'odd': function(node){ 2846 return this['pseudo:nth-child'](node, '2n+1'); 2847 }, 2848 2849 /*</nth-pseudo-selectors>*/ 2850 2851 /*<of-type-pseudo-selectors>*/ 2852 2853 'first-of-type': function(node){ 2854 var nodeName = node.nodeName; 2855 while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; 2856 return true; 2857 }, 2858 2859 'last-of-type': function(node){ 2860 var nodeName = node.nodeName; 2861 while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; 2862 return true; 2863 }, 2864 2865 'only-of-type': function(node){ 2866 var prev = node, nodeName = node.nodeName; 2867 while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; 2868 var next = node; 2869 while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; 2870 return true; 2871 }, 2872 2873 /*</of-type-pseudo-selectors>*/ 2874 2875 // custom pseudos 2876 2877 'enabled': function(node){ 2878 return !node.disabled; 2879 }, 2880 2881 'disabled': function(node){ 2882 return node.disabled; 2883 }, 2884 2885 'checked': function(node){ 2886 return node.checked || node.selected; 2887 }, 2888 2889 'focus': function(node){ 2890 return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); 2891 }, 2892 2893 'root': function(node){ 2894 return (node === this.root); 2895 }, 2896 2897 'selected': function(node){ 2898 return node.selected; 2899 } 2900 2901 /*</pseudo-selectors>*/ 2902}; 2903 2904for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; 2905 2906// attributes methods 2907 2908local.attributeGetters = { 2909 2910 'class': function(){ 2911 return this.getAttribute('class') || this.className; 2912 }, 2913 2914 'for': function(){ 2915 return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); 2916 }, 2917 2918 'href': function(){ 2919 return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); 2920 }, 2921 2922 'style': function(){ 2923 return (this.style) ? this.style.cssText : this.getAttribute('style'); 2924 }, 2925 2926 'tabindex': function(){ 2927 var attributeNode = this.getAttributeNode('tabindex'); 2928 return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; 2929 }, 2930 2931 'type': function(){ 2932 return this.getAttribute('type'); 2933 } 2934 2935}; 2936 2937// Slick 2938 2939var Slick = local.Slick = (this.Slick || {}); 2940 2941Slick.version = '1.1.5'; 2942 2943// Slick finder 2944 2945Slick.search = function(context, expression, append){ 2946 return local.search(context, expression, append); 2947}; 2948 2949Slick.find = function(context, expression){ 2950 return local.search(context, expression, null, true); 2951}; 2952 2953// Slick containment checker 2954 2955Slick.contains = function(container, node){ 2956 local.setDocument(container); 2957 return local.contains(container, node); 2958};
2959 2960// Slick attribute getter 2961 2962Slick.getAttribute = function(node, name){ 2963 return local.getAttribute(node, name); 2964}; 2965 2966// Slick matcher 2967 2968Slick.match = function(node, selector){ 2969 if (!(node && selector)) return false; 2970 if (!selector || selector === node) return true; 2971 local.setDocument(node); 2972 return local.matchNode(node, selector); 2973}; 2974 2975// Slick attribute accessor 2976 2977Slick.defineAttributeGetter = function(name, fn){ 2978 local.attributeGetters[name] = fn; 2979 return this; 2980}; 2981 2982Slick.lookupAttributeGetter = function(name){ 2983 return local.attributeGetters[name]; 2984}; 2985 2986// Slick pseudo accessor 2987 2988Slick.definePseudo = function(name, fn){ 2989 local['pseudo:' + name] = function(node, argument){ 2990 return fn.call(node, argument); 2991 }; 2992 return this; 2993}; 2994 2995Slick.lookupPseudo = function(name){ 2996 var pseudo = local['pseudo:' + name]; 2997 if (pseudo) return function(argument){ 2998 return pseudo.call(this, argument); 2999 }; 3000 return null; 3001}; 3002 3003// Slick overrides accessor 3004 3005Slick.override = function(regexp, fn){ 3006 local.override(regexp, fn); 3007 return this; 3008}; 3009 3010Slick.isXML = local.isXML; 3011 3012Slick.uidOf = function(node){ 3013 return local.getUIDHTML(node); 3014}; 3015 3016if (!this.Slick) this.Slick = Slick; 3017 3018}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); 3019 3020 3021/* 3022--- 3023 3024name: Element 3025 3026description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. 3027 3028license: MIT-style license. 3029 3030requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder] 3031 3032provides: [Element, Elements, $, $$, Iframe, Selectors] 3033 3034... 3035*/ 3036 3037var Element = function(tag, props){ 3038 var konstructor = Element.Constructors[tag]; 3039 if (konstructor) return konstructor(props); 3040 if (typeof tag != 'string') return document.id(tag).set(props); 3041 3042 if (!props) props = {}; 3043 3044 if (!(/^[\w-]+$/).test(tag)){ 3045 var parsed = Slick.parse(tag).expressions[0][0]; 3046 tag = (parsed.tag == '*') ? 'div' : parsed.tag; 3047 if (parsed.id && props.id == null) props.id = parsed.id; 3048 3049 var attributes = parsed.attributes; 3050 if (attributes) for (var i = 0, l = attributes.length; i < l; i++){ 3051 var attr = attributes[i]; 3052 if (props[attr.key] != null) continue; 3053 3054 if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; 3055 else if (!attr.value && !attr.operator) props[attr.key] = true; 3056 } 3057 3058 if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); 3059 } 3060 3061 return document.newElement(tag, props); 3062}; 3063 3064if (Browser.Element) Element.prototype = Browser.Element.prototype; 3065 3066new Type('Element', Element).mirror(function(name){ 3067 if (Array.prototype[name]) return; 3068 3069 var obj = {}; 3070 obj[name] = function(){ 3071 var results = [], args = arguments, elements = true; 3072 for (var i = 0, l = this.length; i < l; i++){ 3073 var element = this[i], result = results[i] = element[name].apply(element, args); 3074 elements = (elements && typeOf(result) == 'element'); 3075 } 3076 return (elements) ? new Elements(results) : results; 3077 }; 3078 3079 Elements.implement(obj); 3080}); 3081 3082if (!Browser.Element){ 3083 Element.parent = Object; 3084 3085 Element.Prototype = {'$family': Function.from('element').hide()}; 3086 3087 Element.mirror(function(name, method){ 3088 Element.Prototype[name] = method; 3089 }); 3090} 3091 3092Element.Constructors = {}; 3093 3094//<1.2compat> 3095 3096Element.Constructors = new Hash; 3097 3098//</1.2compat> 3099 3100var IFrame = new Type('IFrame', function(){ 3101 var params = Array.link(arguments, { 3102 properties: Type.isObject, 3103 iframe: function(obj){ 3104 return (obj != null); 3105 } 3106 }); 3107 3108 var props = params.properties || {}, iframe; 3109 if (params.iframe) iframe = document.id(params.iframe); 3110 var onload = props.onload || function(){}; 3111 delete props.onload; 3112 props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); 3113 iframe = new Element(iframe || 'iframe', props); 3114 3115 var onLoad = function(){ 3116 onload.call(iframe.contentWindow); 3117 }; 3118 3119 if (window.frames[props.id]) onLoad(); 3120 else iframe.addListener('load', onLoad); 3121 return iframe; 3122}); 3123 3124var Elements = this.Elements = function(nodes){ 3125 if (nodes && nodes.length){ 3126 var uniques = {}, node; 3127 for (var i = 0; node = nodes[i++];){ 3128 var uid = Slick.uidOf(node); 3129 if (!uniques[uid]){ 3130 uniques[uid] = true; 3131 this.push(node); 3132 } 3133 } 3134 } 3135}; 3136 3137Elements.prototype = {length: 0}; 3138Elements.parent = Array; 3139 3140new Type('Elements', Elements).implement({ 3141 3142 filter: function(filter, bind){ 3143 if (!filter) return this; 3144 return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ 3145 return item.match(filter); 3146 } : filter, bind)); 3147 }.protect(), 3148 3149 push: function(){ 3150 var length = this.length; 3151 for (var i = 0, l = arguments.length; i < l; i++){ 3152 var item = document.id(arguments[i]); 3153 if (item) this[length++] = item; 3154 } 3155 return (this.length = length); 3156 }.protect(), 3157 3158 unshift: function(){ 3159 var items = []; 3160 for (var i = 0, l = arguments.length; i < l; i++){ 3161 var item = document.id(arguments[i]); 3162 if (item) items.push(item); 3163 } 3164 return Array.prototype.unshift.apply(this, items); 3165 }.protect(), 3166 3167 concat: function(){ 3168 var newElements = new Elements(this); 3169 for (var i = 0, l = arguments.length; i < l; i++){ 3170 var item = arguments[i]; 3171 if (Type.isEnumerable(item)) newElements.append(item); 3172 else newElements.push(item); 3173 } 3174 return newElements; 3175 }.protect(), 3176 3177 append: function(collection){ 3178 for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); 3179 return this; 3180 }.protect(), 3181 3182 empty: function(){ 3183 while (this.length) delete this[--this.length]; 3184 return this; 3185 }.protect() 3186 3187}); 3188 3189//<1.2compat> 3190 3191Elements.alias('extend', 'append'); 3192 3193//</1.2compat> 3194 3195(function(){ 3196 3197// FF, IE 3198var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; 3199 3200splice.call(object, 1, 1); 3201if (object[1] == 1) Elements.implement('splice', function(){ 3202 var length = this.length; 3203 splice.apply(this, arguments); 3204 while (length >= this.length) delete this[length--]; 3205 return this; 3206}.protect()); 3207 3208Elements.implement(Array.prototype); 3209 3210Array.mirror(Elements); 3211 3212/*<ltIE8>*/ 3213var createElementAcceptsHTML; 3214try { 3215 var x = document.createElement('<input name=x>'); 3216 createElementAcceptsHTML = (x.name == 'x'); 3217} catch(e){} 3218 3219var escapeQuotes = function(html){ 3220 return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); 3221};
3222/*</ltIE8>*/ 3223 3224Document.implement({ 3225 3226 newElement: function(tag, props){ 3227 if (props && props.checked != null) props.defaultChecked = props.checked; 3228 /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 3229 if (createElementAcceptsHTML && props){ 3230 tag = '<' + tag; 3231 if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; 3232 if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; 3233 tag += '>'; 3234 delete props.name; 3235 delete props.type; 3236 } 3237 /*</ltIE8>*/ 3238 return this.id(this.createElement(tag)).set(props); 3239 } 3240 3241}); 3242 3243})(); 3244 3245Document.implement({ 3246 3247 newTextNode: function(text){ 3248 return this.createTextNode(text); 3249 }, 3250 3251 getDocument: function(){ 3252 return this; 3253 }, 3254 3255 getWindow: function(){ 3256 return this.window; 3257 }, 3258 3259 id: (function(){ 3260 3261 var types = { 3262 3263 string: function(id, nocash, doc){ 3264 id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); 3265 return (id) ? types.element(id, nocash) : null; 3266 }, 3267 3268 element: function(el, nocash){ 3269 $uid(el); 3270 if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ 3271 Object.append(el, Element.Prototype); 3272 } 3273 return el; 3274 }, 3275 3276 object: function(obj, nocash, doc){ 3277 if (obj.toElement) return types.element(obj.toElement(doc), nocash); 3278 return null; 3279 } 3280 3281 }; 3282 3283 types.textnode = types.whitespace = types.window = types.document = function(zero){ 3284 return zero; 3285 }; 3286 3287 return function(el, nocash, doc){ 3288 if (el && el.$family && el.uid) return el; 3289 var type = typeOf(el); 3290 return (types[type]) ? types[type](el, nocash, doc || document) : null; 3291 }; 3292 3293 })() 3294 3295}); 3296 3297if (window.$ == null) Window.implement('$', function(el, nc){ 3298 return document.id(el, nc, this.document); 3299}); 3300 3301Window.implement({ 3302 3303 getDocument: function(){ 3304 return this.document; 3305 }, 3306 3307 getWindow: function(){ 3308 return this; 3309 } 3310 3311}); 3312 3313[Document, Element].invoke('implement', { 3314 3315 getElements: function(expression){ 3316 return Slick.search(this, expression, new Elements); 3317 }, 3318 3319 getElement: function(expression){ 3320 return document.id(Slick.find(this, expression)); 3321 } 3322 3323}); 3324 3325//<1.2compat> 3326 3327(function(search, find, match){ 3328 3329 this.Selectors = {}; 3330 var pseudos = this.Selectors.Pseudo = new Hash(); 3331 3332 var addSlickPseudos = function(){ 3333 for (var name in pseudos) if (pseudos.hasOwnProperty(name)){ 3334 Slick.definePseudo(name, pseudos[name]); 3335 delete pseudos[name]; 3336 } 3337 }; 3338 3339 Slick.search = function(context, expression, append){ 3340 addSlickPseudos(); 3341 return search.call(this, context, expression, append); 3342 }; 3343 3344 Slick.find = function(context, expression){ 3345 addSlickPseudos(); 3346 return find.call(this, context, expression); 3347 }; 3348 3349 Slick.match = function(node, selector){ 3350 addSlickPseudos(); 3351 return match.call(this, node, selector); 3352 }; 3353 3354})(Slick.search, Slick.find, Slick.match); 3355 3356if (window.$$ == null) Window.implement('$$', function(selector){ 3357 var elements = new Elements; 3358 if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements); 3359 var args = Array.flatten(arguments); 3360 for (var i = 0, l = args.length; i < l; i++){ 3361 var item = args[i]; 3362 switch (typeOf(item)){ 3363 case 'element': elements.push(item); break; 3364 case 'string': Slick.search(this.document, item, elements); 3365 } 3366 } 3367 return elements; 3368}); 3369 3370//</1.2compat> 3371 3372if (window.$$ == null) Window.implement('$$', function(selector){ 3373 if (arguments.length == 1){ 3374 if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); 3375 else if (Type.isEnumerable(selector)) return new Elements(selector); 3376 } 3377 return new Elements(arguments); 3378}); 3379 3380(function(){ 3381 3382var collected = {}, storage = {}; 3383var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; 3384 3385var get = function(uid){ 3386 return (storage[uid] || (storage[uid] = {})); 3387}; 3388 3389var clean = function(item){ 3390 var uid = item.uid; 3391 if (item.removeEvents) item.removeEvents(); 3392 if (item.clearAttributes) item.clearAttributes(); 3393 if (uid != null){ 3394 delete collected[uid]; 3395 delete storage[uid]; 3396 } 3397 return item; 3398}; 3399 3400var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 3401 'rowSpan', 'tabIndex', 'useMap' 3402]; 3403var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', 3404 'noresize', 'defer', 'defaultChecked' 3405]; 3406 var attributes = { 3407 'html': 'innerHTML', 3408 'class': 'className', 3409 'for': 'htmlFor',
3410 'text': (function(){ 3411 var temp = document.createElement('div'); 3412 return (temp.textContent == null) ? 'innerText' : 'textContent'; 3413 })() 3414}; 3415var readOnly = ['type']; 3416var expandos = ['value', 'defaultValue']; 3417var uriAttrs = /^(?:href|src|usemap)$/i; 3418 3419bools = bools.associate(bools); 3420camels = camels.associate(camels.map(String.toLowerCase)); 3421readOnly = readOnly.associate(readOnly); 3422 3423Object.append(attributes, expandos.associate(expandos)); 3424 3425var inserters = { 3426 3427 before: function(context, element){ 3428 var parent = element.parentNode; 3429 if (parent) parent.insertBefore(context, element); 3430 }, 3431 3432 after: function(context, element){ 3433 var parent = element.parentNode; 3434 if (parent) parent.insertBefore(context, element.nextSibling); 3435 }, 3436 3437 bottom: function(context, element){ 3438 element.appendChild(context); 3439 }, 3440 3441 top: function(context, element){ 3442 element.insertBefore(context, element.firstChild); 3443 } 3444 3445}; 3446 3447inserters.inside = inserters.bottom; 3448 3449//<1.2compat> 3450 3451Object.each(inserters, function(inserter, where){ 3452 3453 where = where.capitalize(); 3454 3455 var methods = {}; 3456 3457 methods['inject' + where] = function(el){ 3458 inserter(this, document.id(el, true)); 3459 return this; 3460 }; 3461 3462 methods['grab' + where] = function(el){ 3463 inserter(document.id(el, true), this); 3464 return this; 3465 }; 3466 3467 Element.implement(methods); 3468 3469}); 3470 3471//</1.2compat> 3472 3473var injectCombinator = function(expression, combinator){ 3474 if (!expression) return combinator; 3475 3476 expression = Object.clone(Slick.parse(expression)); 3477 3478 var expressions = expression.expressions; 3479 for (var i = expressions.length; i--;) 3480 expressions[i][0].combinator = combinator; 3481 3482 return expression; 3483}; 3484 3485Element.implement({ 3486 3487 set: function(prop, value){ 3488 var property = Element.Properties[prop]; 3489 (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); 3490 }.overloadSetter(), 3491 3492 get: function(prop){ 3493 var property = Element.Properties[prop]; 3494 return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); 3495 }.overloadGetter(), 3496 3497 erase: function(prop){ 3498 var property = Element.Properties[prop]; 3499 (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); 3500 return this; 3501 }, 3502 3503 setProperty: function(attribute, value){ 3504 attribute = camels[attribute] || attribute; 3505 if (value == null) return this.removeProperty(attribute); 3506 var key = attributes[attribute]; 3507 (key) ? this[key] = value : 3508 (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value); 3509 return this; 3510 }, 3511 3512 setProperties: function(attributes){ 3513 for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); 3514 return this; 3515 }, 3516 3517 getProperty: function(attribute){ 3518 attribute = camels[attribute] || attribute; 3519 var key = attributes[attribute] || readOnly[attribute]; 3520 return (key) ? this[key] : 3521 (bools[attribute]) ? !!this[attribute] : 3522 (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) : 3523 (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null; 3524 }, 3525 3526 getProperties: function(){ 3527 var args = Array.from(arguments); 3528 return args.map(this.getProperty, this).associate(args); 3529 }, 3530 3531 removeProperty: function(attribute){ 3532 attribute = camels[attribute] || attribute; 3533 var key = attributes[attribute]; 3534 (key) ? this[key] = '' : 3535 (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute); 3536 return this; 3537 }, 3538 3539 removeProperties: function(){ 3540 Array.each(arguments, this.removeProperty, this); 3541 return this; 3542 }, 3543 3544 hasClass: function(className){ 3545 return this.className.clean().contains(className, ' '); 3546 }, 3547 3548 addClass: function(className){ 3549 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 3550 return this; 3551 }, 3552 3553 removeClass: function(className){ 3554 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); 3555 return this; 3556 }, 3557 3558 toggleClass: function(className, force){ 3559 if (force == null) force = !this.hasClass(className); 3560 return (force) ? this.addClass(className) : this.removeClass(className); 3561 }, 3562 3563 adopt: function(){ 3564 var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; 3565 if (length > 1) parent = fragment = document.createDocumentFragment(); 3566 3567 for (var i = 0; i < length; i++){ 3568 var element = document.id(elements[i], true); 3569 if (element) parent.appendChild(element); 3570 } 3571 3572 if (fragment) this.appendChild(fragment); 3573 3574 return this; 3575 }, 3576 3577 appendText: function(text, where){ 3578 return this.grab(this.getDocument().newTextNode(text), where); 3579 }, 3580 3581 grab: function(el, where){ 3582 inserters[where || 'bottom'](document.id(el, true), this); 3583 return this; 3584 }, 3585 3586 inject: function(el, where){ 3587 inserters[where || 'bottom'](this, document.id(el, true)); 3588 return this; 3589 }, 3590 3591 replaces: function(el){ 3592 el = document.id(el, true); 3593 el.parentNode.replaceChild(this, el); 3594 return this; 3595 }, 3596 3597 wraps: function(el, where){ 3598 el = document.id(el, true); 3599 return this.replaces(el).grab(el, where); 3600 }, 3601 3602 getPrevious: function(expression){ 3603 return document.id(Slick.find(this, injectCombinator(expression, '!~'))); 3604 }, 3605 3606 getAllPrevious: function(expression){ 3607 return Slick.search(this, injectCombinator(expression, '!~'), new Elements); 3608 }, 3609 3610 getNext: function(expression){ 3611 return document.id(Slick.find(this, injectCombinator(expression, '~'))); 3612 }, 3613 3614 getAllNext: function(expression){ 3615 return Slick.search(this, injectCombinator(expression, '~'), new Elements); 3616 }, 3617 3618 getFirst: function(expression){ 3619 return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); 3620 }, 3621 3622 getLast: function(expression){ 3623 return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); 3624 }, 3625 3626 getParent: function(expression){ 3627 return document.id(Slick.find(this, injectCombinator(expression, '!'))); 3628 }, 3629 3630 getParents: function(expression){ 3631 return Slick.search(this, injectCombinator(expression, '!'), new Elements); 3632 }, 3633 3634 getSiblings: function(expression){ 3635 return Slick.search(this, injectCombinator(expression, '~~'), new Elements); 3636 }, 3637 3638 getChildren: function(expression){ 3639 return Slick.search(this, injectCombinator(expression, '>'), new Elements); 3640 }, 3641 3642 getWindow: function(){ 3643 return this.ownerDocument.window; 3644 }, 3645 3646 getDocument: function(){ 3647 return this.ownerDocument; 3648 }, 3649 3650 getElementById: function(id){ 3651 return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); 3652 }, 3653 3654 getSelected: function(){ 3655 this.selectedIndex; // Safari 3.2.1 3656 return new Elements(Array.from(this.options).filter(function(option){ 3657 return option.selected; 3658 })); 3659 }, 3660 3661 toQueryString: function(){ 3662 var queryString = []; 3663 this.getElements('input, select, textarea').each(function(el){ 3664 var type = el.type; 3665 if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; 3666 3667 var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ 3668 // IE 3669 return document.id(opt).get('value'); 3670 }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); 3671 3672 Array.from(value).each(function(val){ 3673 if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); 3674 }); 3675 }); 3676 return queryString.join('&'); 3677 }, 3678 3679 destroy: function(){ 3680 var children = clean(this).getElementsByTagName('*'); 3681 Array.each(children, clean); 3682 Element.dispose(this); 3683 return null; 3684 }, 3685 3686 empty: function(){ 3687 Array.from(this.childNodes).each(Element.dispose); 3688 return this; 3689 }, 3690 3691 dispose: function(){ 3692 return (this.parentNode) ? this.parentNode.removeChild(this) : this; 3693 }, 3694 3695 match: function(expression){ 3696 return !expression || Slick.match(this, expression); 3697 } 3698 3699}); 3700 3701var cleanClone = function(node, element, keepid){ 3702 if (!keepid) node.setAttributeNode(document.createAttribute('id')); 3703 if (node.clearAttributes){ 3704 node.clearAttributes(); 3705 node.mergeAttributes(element); 3706 node.removeAttribute('uid'); 3707 if (node.options){ 3708 var no = node.options, eo = element.options; 3709 for (var i = no.length; i--;) no[i].selected = eo[i].selected; 3710 } 3711 } 3712 3713 var prop = formProps[element.tagName.toLowerCase()]; 3714 if (prop && element[prop]) node[prop] = element[prop]; 3715}; 3716 3717Element.implement('clone', function(contents, keepid){ 3718 contents = contents !== false; 3719 var clone = this.cloneNode(contents), i; 3720 3721 if (contents){ 3722 var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); 3723 for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid); 3724 } 3725 3726 cleanClone(clone, this, keepid); 3727 3728 if (Browser.ie){ 3729 var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); 3730 for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; 3731 } 3732 return document.id(clone); 3733}); 3734 3735var contains = {contains: function(element){ 3736 return Slick.contains(this, element); 3737}}; 3738 3739if (!document.contains) Document.implement(contains); 3740if (!document.createElement('div').contains) Element.implement(contains); 3741 3742//<1.2compat> 3743 3744Element.implement('hasChild', function(element){ 3745 return this !== element && this.contains(element); 3746}); 3747 3748//</1.2compat> 3749 3750[Element, Window, Document].invoke('implement', { 3751
3752 addListener: function(type, fn){ 3753 if (type == 'unload'){ 3754 var old = fn, self = this; 3755 fn = function(){ 3756 self.removeListener('unload', fn); 3757 old(); 3758 }; 3759 } else { 3760 collected[$uid(this)] = this; 3761 } 3762 if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); 3763 else this.attachEvent('on' + type, fn); 3764 return this; 3765 }, 3766 3767 removeListener: function(type, fn){ 3768 if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); 3769 else this.detachEvent('on' + type, fn); 3770 return this; 3771 }, 3772 3773 retrieve: function(property, dflt){ 3774 var storage = get($uid(this)), prop = storage[property]; 3775 if (dflt != null && prop == null) prop = storage[property] = dflt; 3776 return prop != null ? prop : null; 3777 }, 3778 3779 store: function(property, value){ 3780 var storage = get($uid(this)); 3781 storage[property] = value; 3782 return this; 3783 }, 3784 3785 eliminate: function(property){ 3786 var storage = get($uid(this)); 3787 delete storage[property]; 3788 return this; 3789 } 3790 3791}); 3792 3793/*<ltIE9>*/ 3794if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){ 3795 Object.each(collected, clean); 3796 if (window.CollectGarbage) CollectGarbage(); 3797}); 3798/*</ltIE9>*/ 3799 3800})(); 3801 3802Element.Properties = {}; 3803 3804//<1.2compat> 3805 3806Element.Properties = new Hash; 3807 3808//</1.2compat> 3809 3810Element.Properties.style = { 3811 3812 set: function(style){ 3813 this.style.cssText = style; 3814 }, 3815 3816 get: function(){ 3817 return this.style.cssText; 3818 }, 3819 3820 erase: function(){ 3821 this.style.cssText = ''; 3822 } 3823 3824}; 3825 3826Element.Properties.tag = { 3827 3828 get: function(){ 3829 return this.tagName.toLowerCase(); 3830 } 3831 3832}; 3833 3834/*<ltIE9>*/ 3835(function(maxLength){ 3836 if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = { 3837 get: function(){ 3838 var maxlength = this.getAttribute('maxLength'); 3839 return maxlength == maxLength ? null : maxlength; 3840 } 3841 }; 3842})(document.createElement('input').getAttribute('maxLength')); 3843/*</ltIE9>*/ 3844 3845/*<!webkit>*/ 3846Element.Properties.html = (function(){ 3847 3848 var tableTest = Function.attempt(function(){ 3849 var table = document.createElement('table'); 3850 table.innerHTML = '<tr><td></td></tr>'; 3851 }); 3852 3853 var wrapper = document.createElement('div'); 3854 3855 var translations = { 3856 table: [1, '<table>', '</table>'], 3857 select: [1, '<select>', '</select>'], 3858 tbody: [2, '<table><tbody>', '</tbody></table>'], 3859 tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] 3860 }; 3861 translations.thead = translations.tfoot = translations.tbody; 3862 3863 var html = { 3864 set: function(){ 3865 var html = Array.flatten(arguments).join(''); 3866 var wrap = (!tableTest && translations[this.get('tag')]); 3867 if (wrap){ 3868 var first = wrapper; 3869 first.innerHTML = wrap[1] + html + wrap[2]; 3870 for (var i = wrap[0]; i--;) first = first.firstChild; 3871 this.empty().adopt(first.childNodes); 3872 } else { 3873 this.innerHTML = html; 3874 } 3875 } 3876 }; 3877 3878 html.erase = html.set; 3879 3880 return html; 3881})(); 3882/*</!webkit>*/ 3883 3884 3885/* 3886--- 3887 3888name: Element.Style 3889 3890description: Contains methods for interacting with the styles of Elements in a fashionable way. 3891 3892license: MIT-style license. 3893 3894requires: Element 3895 3896provides: Element.Style 3897 3898... 3899*/ 3900 3901(function(){ 3902 3903var html = document.html; 3904 3905Element.Properties.styles = {set: function(styles){ 3906 this.setStyles(styles); 3907}}; 3908 3909var hasOpacity = (html.style.opacity != null); 3910var reAlpha = /alpha\(opacity=([\d.]+)\)/i; 3911 3912var setOpacity = function(element, opacity){ 3913 if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; 3914 if (hasOpacity){ 3915 element.style.opacity = opacity; 3916 } else { 3917 opacity = (opacity * 100).limit(0, 100).round(); 3918 opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; 3919 var filter = element.style.filter || element.getComputedStyle('filter') || ''; 3920 element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; 3921 } 3922}; 3923 3924Element.Properties.opacity = { 3925 3926 set: function(opacity){ 3927 var visibility = this.style.visibility; 3928 if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden'; 3929 else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible'; 3930 3931 setOpacity(this, opacity); 3932 }, 3933 3934 get: (hasOpacity) ? function(){ 3935 var opacity = this.style.opacity || this.getComputedStyle('opacity'); 3936 return (opacity == '') ? 1 : opacity; 3937 } : function(){ 3938 var opacity, filter = (this.style.filter || this.getComputedStyle('filter')); 3939 if (filter) opacity = filter.match(reAlpha); 3940 return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); 3941 } 3942 3943}; 3944 3945var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat'; 3946 3947Element.implement({ 3948 3949 getComputedStyle: function(property){ 3950 if (this.currentStyle) return this.currentStyle[property.camelCase()]; 3951 var defaultView = Element.getDocument(this).defaultView, 3952 computed = defaultView ? defaultView.getComputedStyle(this, null) : null; 3953 return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null; 3954 }, 3955 3956 setOpacity: function(value){ 3957 setOpacity(this, value); 3958 return this; 3959 }, 3960 3961 getOpacity: function(){ 3962 return this.get('opacity'); 3963 }, 3964 3965 setStyle: function(property, value){ 3966 switch (property){ 3967 case 'opacity': return this.set('opacity', parseFloat(value)); 3968 case 'float': property = floatName; 3969 } 3970 property = property.camelCase(); 3971 if (typeOf(value) != 'string'){ 3972 var map = (Element.Styles[property] || '@').split(' '); 3973 value = Array.from(value).map(function(val, i){ 3974 if (!map[i]) return ''; 3975 return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; 3976 }).join(' '); 3977 } else if (value == String(Number(value))){ 3978 value = Math.round(value); 3979 } 3980 this.style[property] = value; 3981 return this; 3982 }, 3983 3984 getStyle: function(property){ 3985 switch (property){ 3986 case 'opacity': return this.get('opacity'); 3987 case 'float': property = floatName; 3988 } 3989 property = property.camelCase(); 3990 var result = this.style[property]; 3991 if (!result || property == 'zIndex'){ 3992 result = []; 3993 for (var style in Element.ShortStyles){ 3994 if (property != style) continue; 3995 for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); 3996 return result.join(' '); 3997 } 3998 result = this.getComputedStyle(property); 3999 } 4000 if (result){ 4001 result = String(result); 4002 var color = result.match(/rgba?\([\d\s,]+\)/); 4003 if (color) result = result.replace(color[0], color[0].rgbToHex()); 4004 } 4005 if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){ 4006 if ((/^(height|width)$/).test(property)){ 4007 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; 4008 values.each(function(value){
4009 size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); 4010 }, this); 4011 return this['offset' + property.capitalize()] - size + 'px'; 4012 } 4013 if (Browser.opera && String(result).indexOf('px') != -1) return result; 4014 if ((/^border(.+)Width|margin|padding/).test(property)) return '0px'; 4015 } 4016 return result; 4017 }, 4018 4019 setStyles: function(styles){ 4020 for (var style in styles) this.setStyle(style, styles[style]); 4021 return this; 4022 }, 4023 4024 getStyles: function(){ 4025 var result = {}; 4026 Array.flatten(arguments).each(function(key){ 4027 result[key] = this.getStyle(key); 4028 }, this); 4029 return result; 4030 } 4031 4032}); 4033 4034Element.Styles = { 4035 left: '@px', top: '@px', bottom: '@px', right: '@px', 4036 width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', 4037 backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', 4038 fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', 4039 margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', 4040 borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', 4041 zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' 4042}; 4043 4044//<1.2compat> 4045 4046Element.Styles = new Hash(Element.Styles); 4047 4048//</1.2compat> 4049 4050Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; 4051 4052['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ 4053 var Short = Element.ShortStyles; 4054 var All = Element.Styles; 4055 ['margin', 'padding'].each(function(style){ 4056 var sd = style + direction; 4057 Short[style][sd] = All[sd] = '@px'; 4058 }); 4059 var bd = 'border' + direction; 4060 Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; 4061 var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; 4062 Short[bd] = {}; 4063 Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; 4064 Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; 4065 Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; 4066}); 4067 4068})(); 4069 4070 4071/* 4072--- 4073 4074name: Element.Event 4075 4076description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events. 4077 4078license: MIT-style license. 4079 4080requires: [Element, Event] 4081 4082provides: Element.Event 4083 4084... 4085*/ 4086 4087(function(){ 4088 4089Element.Properties.events = {set: function(events){ 4090 this.addEvents(events); 4091}}; 4092 4093[Element, Window, Document].invoke('implement', { 4094 4095 addEvent: function(type, fn){ 4096 var events = this.retrieve('events', {}); 4097 if (!events[type]) events[type] = {keys: [], values: []}; 4098 if (events[type].keys.contains(fn)) return this; 4099 events[type].keys.push(fn); 4100 var realType = type, 4101 custom = Element.Events[type], 4102 condition = fn, 4103 self = this; 4104 if (custom){ 4105 if (custom.onAdd) custom.onAdd.call(this, fn); 4106 if (custom.condition){ 4107 condition = function(event){ 4108 if (custom.condition.call(this, event)) return fn.call(this, event); 4109 return true; 4110 }; 4111 } 4112 realType = custom.base || realType; 4113 } 4114 var defn = function(){ 4115 return fn.call(self); 4116 }; 4117 var nativeEvent = Element.NativeEvents[realType]; 4118 if (nativeEvent){ 4119 if (nativeEvent == 2){ 4120 defn = function(event){ 4121 event = new Event(event, self.getWindow()); 4122 if (condition.call(self, event) === false) event.stop(); 4123 }; 4124 } 4125 this.addListener(realType, defn, arguments[2]); 4126 } 4127 events[type].values.push(defn); 4128 return this; 4129 }, 4130 4131 removeEvent: function(type, fn){ 4132 var events = this.retrieve('events'); 4133 if (!events || !events[type]) return this; 4134 var list = events[type]; 4135 var index = list.keys.indexOf(fn); 4136 if (index == -1) return this; 4137 var value = list.values[index]; 4138 delete list.keys[index]; 4139 delete list.values[index]; 4140 var custom = Element.Events[type]; 4141 if (custom){ 4142 if (custom.onRemove) custom.onRemove.call(this, fn); 4143 type = custom.base || type; 4144 } 4145 return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; 4146 }, 4147 4148 addEvents: function(events){ 4149 for (var event in events) this.addEvent(event, events[event]);
4150 return this; 4151 }, 4152 4153 removeEvents: function(events){ 4154 var type; 4155 if (typeOf(events) == 'object'){ 4156 for (type in events) this.removeEvent(type, events[type]); 4157 return this; 4158 } 4159 var attached = this.retrieve('events'); 4160 if (!attached) return this; 4161 if (!events){ 4162 for (type in attached) this.removeEvents(type); 4163 this.eliminate('events'); 4164 } else if (attached[events]){ 4165 attached[events].keys.each(function(fn){ 4166 this.removeEvent(events, fn); 4167 }, this); 4168 delete attached[events]; 4169 } 4170 return this; 4171 }, 4172 4173 fireEvent: function(type, args, delay){ 4174 var events = this.retrieve('events'); 4175 if (!events || !events[type]) return this; 4176 args = Array.from(args); 4177 4178 events[type].keys.each(function(fn){ 4179 if (delay) fn.delay(delay, this, args); 4180 else fn.apply(this, args); 4181 }, this); 4182 return this; 4183 }, 4184 4185 cloneEvents: function(from, type){ 4186 from = document.id(from); 4187 var events = from.retrieve('events'); 4188 if (!events) return this; 4189 if (!type){ 4190 for (var eventType in events) this.cloneEvents(from, eventType); 4191 } else if (events[type]){ 4192 events[type].keys.each(function(fn){ 4193 this.addEvent(type, fn); 4194 }, this); 4195 } 4196 return this; 4197 } 4198 4199}); 4200 4201Element.NativeEvents = { 4202 click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons 4203 mousewheel: 2, DOMMouseScroll: 2, //mouse wheel 4204 mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement 4205 keydown: 2, keypress: 2, keyup: 2, //keyboard 4206 orientationchange: 2, // mobile 4207 touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch 4208 gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture 4209 focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements 4210 load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window 4211 error: 1, abort: 1, scroll: 1 //misc 4212}; 4213 4214var check = function(event){ 4215 var related = event.relatedTarget; 4216 if (related == null) return true; 4217 if (!related) return false; 4218 return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); 4219}; 4220 4221Element.Events = { 4222 4223 mouseenter: { 4224 base: 'mouseover', 4225 condition: check 4226 }, 4227 4228 mouseleave: { 4229 base: 'mouseout', 4230 condition: check 4231 }, 4232 4233 mousewheel: { 4234 base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel' 4235 } 4236 4237}; 4238 4239//<1.2compat> 4240 4241Element.Events = new Hash(Element.Events); 4242 4243//</1.2compat> 4244 4245})(); 4246 4247 4248/* 4249--- 4250 4251name: Element.Dimensions 4252 4253description: Contains methods to work with size, scroll, or positioning of Elements and the window object. 4254 4255license: MIT-style license. 4256 4257credits: 4258 - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). 4259 - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). 4260 4261requires: [Element, Element.Style] 4262 4263provides: [Element.Dimensions] 4264 4265... 4266*/ 4267 4268(function(){ 4269 4270var element = document.createElement('div'), 4271 child = document.createElement('div'); 4272element.style.height = '0'; 4273element.appendChild(child); 4274var brokenOffsetParent = (child.offsetParent === element); 4275element = child = null; 4276 4277var isOffset = function(el){ 4278 return styleString(el, 'position') != 'static' || isBody(el); 4279}; 4280 4281var isOffsetStatic = function(el){ 4282 return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); 4283}; 4284 4285Element.implement({ 4286 4287 scrollTo: function(x, y){ 4288 if (isBody(this)){ 4289 this.getWindow().scrollTo(x, y); 4290 } else { 4291 this.scrollLeft = x; 4292 this.scrollTop = y; 4293 } 4294 return this; 4295 }, 4296 4297 getSize: function(){ 4298 if (isBody(this)) return this.getWindow().getSize(); 4299 return {x: this.offsetWidth, y: this.offsetHeight}; 4300 }, 4301 4302 getScrollSize: function(){ 4303 if (isBody(this)) return this.getWindow().getScrollSize(); 4304 return {x: this.scrollWidth, y: this.scrollHeight}; 4305 }, 4306 4307 getScroll: function(){ 4308 if (isBody(this)) return this.getWindow().getScroll(); 4309 return {x: this.scrollLeft, y: this.scrollTop}; 4310 }, 4311 4312 getScrolls: function(){ 4313 var element = this.parentNode, position = {x: 0, y: 0}; 4314 while (element && !isBody(element)){ 4315 position.x += element.scrollLeft; 4316 position.y += element.scrollTop; 4317 element = element.parentNode; 4318 } 4319 return position; 4320 }, 4321 4322 getOffsetParent: brokenOffsetParent ? function(){ 4323 var element = this;
4324 if (isBody(element) || styleString(element, 'position') == 'fixed') return null; 4325 4326 var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; 4327 while ((element = element.parentNode)){ 4328 if (isOffsetCheck(element)) return element; 4329 } 4330 return null; 4331 } : function(){ 4332 var element = this; 4333 if (isBody(element) || styleString(element, 'position') == 'fixed') return null; 4334 4335 try { 4336 return element.offsetParent; 4337 } catch(e) {} 4338 return null; 4339 }, 4340 4341 getOffsets: function(){ 4342 if (this.getBoundingClientRect && !Browser.Platform.ios){ 4343 var bound = this.getBoundingClientRect(), 4344 html = document.id(this.getDocument().documentElement), 4345 htmlScroll = html.getScroll(), 4346 elemScrolls = this.getScrolls(), 4347 isFixed = (styleString(this, 'position') == 'fixed'); 4348 4349 return { 4350 x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, 4351 y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop 4352 }; 4353 } 4354 4355 var element = this, position = {x: 0, y: 0}; 4356 if (isBody(this)) return position; 4357 4358 while (element && !isBody(element)){ 4359 position.x += element.offsetLeft; 4360 position.y += element.offsetTop; 4361 4362 if (Browser.firefox){ 4363 if (!borderBox(element)){ 4364 position.x += leftBorder(element); 4365 position.y += topBorder(element); 4366 } 4367 var parent = element.parentNode; 4368 if (parent && styleString(parent, 'overflow') != 'visible'){ 4369 position.x += leftBorder(parent); 4370 position.y += topBorder(parent); 4371 } 4372 } else if (element != this && Browser.safari){ 4373 position.x += leftBorder(element); 4374 position.y += topBorder(element); 4375 } 4376 4377 element = element.offsetParent; 4378 } 4379 if (Browser.firefox && !borderBox(this)){ 4380 position.x -= leftBorder(this); 4381 position.y -= topBorder(this); 4382 } 4383 return position; 4384 }, 4385 4386 getPosition: function(relative){ 4387 if (isBody(this)) return {x: 0, y: 0}; 4388 var offset = this.getOffsets(), 4389 scroll = this.getScrolls(); 4390 var position = { 4391 x: offset.x - scroll.x, 4392 y: offset.y - scroll.y 4393 }; 4394 4395 if (relative && (relative = document.id(relative))){ 4396 var relativePosition = relative.getPosition(); 4397 return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; 4398 } 4399 return position; 4400 }, 4401 4402 getCoordinates: function(element){ 4403 if (isBody(this)) return this.getWindow().getCoordinates(); 4404 var position = this.getPosition(element), 4405 size = this.getSize(); 4406 var obj = { 4407 left: position.x, 4408 top: position.y, 4409 width: size.x, 4410 height: size.y 4411 }; 4412 obj.right = obj.left + obj.width; 4413 obj.bottom = obj.top + obj.height; 4414 return obj; 4415 }, 4416 4417 computePosition: function(obj){ 4418 return { 4419 left: obj.x - styleNumber(this, 'margin-left'), 4420 top: obj.y - styleNumber(this, 'margin-top') 4421 }; 4422 }, 4423 4424 setPosition: function(obj){ 4425 return this.setStyles(this.computePosition(obj)); 4426 } 4427 4428}); 4429 4430 4431[Document, Window].invoke('implement', { 4432 4433 getSize: function(){ 4434 var doc = getCompatElement(this); 4435 return {x: doc.clientWidth, y: doc.clientHeight}; 4436 }, 4437 4438 getScroll: function(){ 4439 var win = this.getWindow(), doc = getCompatElement(this); 4440 return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; 4441 }, 4442 4443 getScrollSize: function(){ 4444 var doc = getCompatElement(this), 4445 min = this.getSize(), 4446 body = this.getDocument().body; 4447 4448 return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; 4449 }, 4450 4451 getPosition: function(){ 4452 return {x: 0, y: 0}; 4453 }, 4454 4455 getCoordinates: function(){ 4456 var size = this.getSize(); 4457 return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; 4458 } 4459 4460}); 4461 4462// private methods 4463
4464var styleString = Element.getComputedStyle; 4465 4466function styleNumber(element, style){ 4467 return styleString(element, style).toInt() || 0; 4468} 4469 4470function borderBox(element){ 4471 return styleString(element, '-moz-box-sizing') == 'border-box'; 4472} 4473 4474function topBorder(element){ 4475 return styleNumber(element, 'border-top-width'); 4476} 4477 4478function leftBorder(element){ 4479 return styleNumber(element, 'border-left-width'); 4480} 4481 4482function isBody(element){ 4483 return (/^(?:body|html)$/i).test(element.tagName); 4484} 4485 4486function getCompatElement(element){ 4487 var doc = element.getDocument(); 4488 return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; 4489} 4490 4491})(); 4492 4493//aliases 4494Element.alias({position: 'setPosition'}); //compatability 4495 4496[Window, Document, Element].invoke('implement', { 4497 4498 getHeight: function(){ 4499 return this.getSize().y; 4500 }, 4501 4502 getWidth: function(){ 4503 return this.getSize().x; 4504 }, 4505 4506 getScrollTop: function(){ 4507 return this.getScroll().y; 4508 }, 4509 4510 getScrollLeft: function(){ 4511 return this.getScroll().x; 4512 }, 4513 4514 getScrollHeight: function(){ 4515 return this.getScrollSize().y; 4516 }, 4517 4518 getScrollWidth: function(){ 4519 return this.getScrollSize().x; 4520 }, 4521 4522 getTop: function(){ 4523 return this.getPosition().y; 4524 }, 4525 4526 getLeft: function(){ 4527 return this.getPosition().x; 4528 } 4529 4530}); 4531 4532 4533/* 4534--- 4535 4536name: Fx 4537 4538description: Contains the basic animation logic to be extended by all other Fx Classes. 4539 4540license: MIT-style license. 4541 4542requires: [Chain, Events, Options] 4543 4544provides: Fx 4545 4546... 4547*/ 4548 4549(function(){ 4550 4551var Fx = this.Fx = new Class({ 4552 4553 Implements: [Chain, Events, Options], 4554 4555 options: { 4556 /* 4557 onStart: nil, 4558 onCancel: nil, 4559 onComplete: nil, 4560 */ 4561 fps: 60, 4562 unit: false, 4563 duration: 500, 4564 frames: null, 4565 frameSkip: true, 4566 link: 'ignore' 4567 }, 4568 4569 initialize: function(options){ 4570 this.subject = this.subject || this; 4571 this.setOptions(options); 4572 }, 4573 4574 getTransition: function(){ 4575 return function(p){ 4576 return -(Math.cos(Math.PI * p) - 1) / 2; 4577 }; 4578 }, 4579 4580 step: function(now){ 4581 if (this.options.frameSkip){ 4582 var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; 4583 this.time = now; 4584 this.frame += frames; 4585 } else { 4586 this.frame++; 4587 } 4588 4589 if (this.frame < this.frames){ 4590 var delta = this.transition(this.frame / this.frames); 4591 this.set(this.compute(this.from, this.to, delta)); 4592 } else { 4593 this.frame = this.frames; 4594 this.set(this.compute(this.from, this.to, 1)); 4595 this.stop(); 4596 } 4597 }, 4598 4599 set: function(now){ 4600 return now; 4601 }, 4602 4603 compute: function(from, to, delta){ 4604 return Fx.compute(from, to, delta); 4605 }, 4606 4607 check: function(){ 4608 if (!this.isRunning()) return true; 4609 switch (this.options.link){ 4610 case 'cancel': this.cancel(); return true; 4611 case 'chain': this.chain(this.caller.pass(arguments, this)); return false; 4612 } 4613 return false; 4614 }, 4615 4616 start: function(from, to){ 4617 if (!this.check(from, to)) return this; 4618 this.from = from; 4619 this.to = to; 4620 this.frame = (this.options.frameSkip) ? 0 : -1; 4621 this.time = null; 4622 this.transition = this.getTransition(); 4623 var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; 4624 this.duration = Fx.Durations[duration] || duration.toInt(); 4625 this.frameInterval = 1000 / fps; 4626 this.frames = frames || Math.round(this.duration / this.frameInterval); 4627 this.fireEvent('start', this.subject); 4628 pushInstance.call(this, fps); 4629 return this; 4630 }, 4631 4632 stop: function(){ 4633 if (this.isRunning()){ 4634 this.time = null; 4635 pullInstance.call(this, this.options.fps); 4636 if (this.frames == this.frame){ 4637 this.fireEvent('complete', this.subject); 4638 if (!this.callChain()) this.fireEvent('chainComplete', this.subject); 4639 } else { 4640 this.fireEvent('stop', this.subject); 4641 } 4642 } 4643 return this; 4644 }, 4645 4646 cancel: function(){ 4647 if (this.isRunning()){ 4648 this.time = null; 4649 pullInstance.call(this, this.options.fps); 4650 this.frame = this.frames; 4651 this.fireEvent('cancel', this.subject).clearChain(); 4652 } 4653 return this; 4654 }, 4655 4656 pause: function(){ 4657 if (this.isRunning()){ 4658 this.time = null; 4659 pullInstance.call(this, this.options.fps);
4660 } 4661 return this; 4662 }, 4663 4664 resume: function(){ 4665 if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps); 4666 return this; 4667 }, 4668 4669 isRunning: function(){ 4670 var list = instances[this.options.fps]; 4671 return list && list.contains(this); 4672 } 4673 4674}); 4675 4676Fx.compute = function(from, to, delta){ 4677 return (to - from) * delta + from; 4678}; 4679 4680Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; 4681 4682// global timers 4683 4684var instances = {}, timers = {}; 4685 4686var loop = function(){ 4687 var now = Date.now(); 4688 for (var i = this.length; i--;){ 4689 var instance = this[i]; 4690 if (instance) instance.step(now); 4691 } 4692}; 4693 4694var pushInstance = function(fps){ 4695 var list = instances[fps] || (instances[fps] = []); 4696 list.push(this); 4697 if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); 4698}; 4699 4700var pullInstance = function(fps){ 4701 var list = instances[fps]; 4702 if (list){ 4703 list.erase(this); 4704 if (!list.length && timers[fps]){ 4705 delete instances[fps]; 4706 timers[fps] = clearInterval(timers[fps]); 4707 } 4708 } 4709}; 4710 4711})(); 4712 4713 4714/* 4715--- 4716 4717name: Fx.CSS 4718 4719description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. 4720 4721license: MIT-style license. 4722 4723requires: [Fx, Element.Style] 4724 4725provides: Fx.CSS 4726 4727... 4728*/ 4729 4730Fx.CSS = new Class({ 4731 4732 Extends: Fx, 4733 4734 //prepares the base from/to object 4735 4736 prepare: function(element, property, values){ 4737 values = Array.from(values); 4738 if (values[1] == null){ 4739 values[1] = values[0]; 4740 values[0] = element.getStyle(property); 4741 } 4742 var parsed = values.map(this.parse); 4743 return {from: parsed[0], to: parsed[1]}; 4744 }, 4745 4746 //parses a value into an array 4747 4748 parse: function(value){ 4749 value = Function.from(value)(); 4750 value = (typeof value == 'string') ? value.split(' ') : Array.from(value); 4751 return value.map(function(val){ 4752 val = String(val); 4753 var found = false; 4754 Object.each(Fx.CSS.Parsers, function(parser, key){ 4755 if (found) return; 4756 var parsed = parser.parse(val); 4757 if (parsed || parsed === 0) found = {value: parsed, parser: parser}; 4758 }); 4759 found = found || {value: val, parser: Fx.CSS.Parsers.String}; 4760 return found; 4761 }); 4762 }, 4763 4764 //computes by a from and to prepared objects, using their parsers. 4765 4766 compute: function(from, to, delta){ 4767 var computed = []; 4768 (Math.min(from.length, to.length)).times(function(i){ 4769 computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); 4770 }); 4771 computed.$family = Function.from('fx:css:value'); 4772 return computed; 4773 }, 4774 4775 //serves the value as settable 4776 4777 serve: function(value, unit){ 4778 if (typeOf(value) != 'fx:css:value') value = this.parse(value); 4779 var returned = []; 4780 value.each(function(bit){ 4781 returned = returned.concat(bit.parser.serve(bit.value, unit)); 4782 }); 4783 return returned; 4784 }, 4785 4786 //renders the change to an element 4787 4788 render: function(element, property, value, unit){ 4789 element.setStyle(property, this.serve(value, unit)); 4790 }, 4791 4792 //searches inside the page css to find the values for a selector 4793 4794 search: function(selector){ 4795 if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; 4796 var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); 4797 Array.each(document.styleSheets, function(sheet, j){ 4798 var href = sheet.href; 4799 if (href && href.contains('://') && !href.contains(document.domain)) return; 4800 var rules = sheet.rules || sheet.cssRules; 4801 Array.each(rules, function(rule, i){ 4802 if (!rule.style) return; 4803 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ 4804 return m.toLowerCase(); 4805 }) : null; 4806 if (!selectorText || !selectorTest.test(selectorText)) return; 4807 Object.each(Element.Styles, function(value, style){ 4808 if (!rule.style[style] || Element.ShortStyles[style]) return; 4809 value = String(rule.style[style]); 4810 to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; 4811 }); 4812 }); 4813 }); 4814 return Fx.CSS.Cache[selector] = to; 4815 } 4816 4817}); 4818 4819Fx.CSS.Cache = {}; 4820 4821Fx.CSS.Parsers = { 4822 4823 Color: { 4824 parse: function(value){ 4825 if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); 4826 return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; 4827 }, 4828 compute: function(from, to, delta){ 4829 return from.map(function(value, i){ 4830 return Math.round(Fx.compute(from[i], to[i], delta)); 4831 }); 4832 }, 4833 serve: function(value){ 4834 return value.map(Number); 4835 } 4836 }, 4837 4838 Number: { 4839 parse: parseFloat, 4840 compute: Fx.compute, 4841 serve: function(value, unit){ 4842 return (unit) ? value + unit : value; 4843 } 4844 }, 4845 4846 String: { 4847 parse: Function.from(false), 4848 compute: function(zero, one){ 4849 return one; 4850 }, 4851 serve: function(zero){ 4852 return zero; 4853 } 4854 } 4855 4856}; 4857 4858//<1.2compat> 4859 4860Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers); 4861 4862//</1.2compat> 4863 4864 4865/* 4866--- 4867 4868name: Fx.Tween 4869 4870description: Formerly Fx.Style, effect to transition any CSS property for an element. 4871 4872license: MIT-style license. 4873 4874requires: Fx.CSS 4875 4876provides: [Fx.Tween, Element.fade, Element.highlight] 4877 4878... 4879*/ 4880 4881Fx.Tween = new Class({ 4882 4883 Extends: Fx.CSS, 4884 4885 initialize: function(element, options){ 4886 this.element = this.subject = document.id(element); 4887 this.parent(options); 4888 }, 4889 4890 set: function(property, now){ 4891 if (arguments.length == 1){ 4892 now = property; 4893 property = this.property || this.options.property; 4894 } 4895 this.render(this.element, property, now, this.options.unit); 4896 return this; 4897 }, 4898 4899 start: function(property, from, to){ 4900 if (!this.check(property, from, to)) return this; 4901 var args = Array.flatten(arguments); 4902 this.property = this.options.property || args.shift(); 4903 var parsed = this.prepare(this.element, this.property, args); 4904 return this.parent(parsed.from, parsed.to); 4905 } 4906 4907}); 4908 4909Element.Properties.tween = { 4910 4911 set: function(options){ 4912 this.get('tween').cancel().setOptions(options); 4913 return this; 4914 }, 4915 4916 get: function(){ 4917 var tween = this.retrieve('tween'); 4918 if (!tween){ 4919 tween = new Fx.Tween(this, {link: 'cancel'}); 4920 this.store('tween', tween); 4921 } 4922 return tween; 4923 } 4924 4925}; 4926 4927Element.implement({ 4928 4929 tween: function(property, from, to){ 4930 this.get('tween').start(arguments); 4931 return this; 4932 }, 4933 4934 fade: function(how){ 4935 var fade = this.get('tween'), o = 'opacity', toggle; 4936 how = [how, 'toggle'].pick(); 4937 switch (how){ 4938 case 'in': fade.start(o, 1); break; 4939 case 'out': fade.start(o, 0); break; 4940 case 'show': fade.set(o, 1); break; 4941 case 'hide': fade.set(o, 0); break; 4942 case 'toggle': 4943 var flag = this.retrieve('fade:flag', this.get('opacity') == 1); 4944 fade.start(o, (flag) ? 0 : 1); 4945 this.store('fade:flag', !flag); 4946 toggle = true; 4947 break; 4948 default: fade.start(o, arguments); 4949 } 4950 if (!toggle) this.eliminate('fade:flag'); 4951 return this; 4952 }, 4953 4954 highlight: function(start, end){ 4955 if (!end){
4956 end = this.retrieve('highlight:original', this.getStyle('background-color')); 4957 end = (end == 'transparent') ? '#fff' : end; 4958 } 4959 var tween = this.get('tween'); 4960 tween.start('background-color', start || '#ffff88', end).chain(function(){ 4961 this.setStyle('background-color', this.retrieve('highlight:original')); 4962 tween.callChain(); 4963 }.bind(this)); 4964 return this; 4965 } 4966 4967}); 4968 4969 4970/* 4971--- 4972 4973name: Fx.Morph 4974 4975description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. 4976 4977license: MIT-style license. 4978 4979requires: Fx.CSS 4980 4981provides: Fx.Morph 4982 4983... 4984*/ 4985 4986Fx.Morph = new Class({ 4987 4988 Extends: Fx.CSS, 4989 4990 initialize: function(element, options){ 4991 this.element = this.subject = document.id(element); 4992 this.parent(options); 4993 }, 4994 4995 set: function(now){ 4996 if (typeof now == 'string') now = this.search(now); 4997 for (var p in now) this.render(this.element, p, now[p], this.options.unit); 4998 return this; 4999 }, 5000 5001 compute: function(from, to, delta){ 5002 var now = {}; 5003 for (var p in from) now[p] = this.parent(from[p], to[p], delta); 5004 return now; 5005 }, 5006 5007 start: function(properties){ 5008 if (!this.check(properties)) return this; 5009 if (typeof properties == 'string') properties = this.search(properties); 5010 var from = {}, to = {}; 5011 for (var p in properties){ 5012 var parsed = this.prepare(this.element, p, properties[p]); 5013 from[p] = parsed.from; 5014 to[p] = parsed.to; 5015 } 5016 return this.parent(from, to); 5017 } 5018 5019}); 5020 5021Element.Properties.morph = { 5022 5023 set: function(options){ 5024 this.get('morph').cancel().setOptions(options); 5025 return this; 5026 }, 5027 5028 get: function(){ 5029 var morph = this.retrieve('morph'); 5030 if (!morph){ 5031 morph = new Fx.Morph(this, {link: 'cancel'}); 5032 this.store('morph', morph); 5033 } 5034 return morph; 5035 } 5036 5037}; 5038 5039Element.implement({ 5040 5041 morph: function(props){ 5042 this.get('morph').start(props); 5043 return this; 5044 } 5045 5046}); 5047 5048 5049/* 5050--- 5051 5052name: Fx.Transitions 5053 5054description: Contains a set of advanced transitions to be used with any of the Fx Classes. 5055 5056license: MIT-style license. 5057 5058credits: 5059 - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. 5060 5061requires: Fx 5062 5063provides: Fx.Transitions 5064 5065... 5066*/ 5067 5068Fx.implement({ 5069 5070 getTransition: function(){ 5071 var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; 5072 if (typeof trans == 'string'){ 5073 var data = trans.split(':'); 5074 trans = Fx.Transitions; 5075 trans = trans[data[0]] || trans[data[0].capitalize()]; 5076 if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; 5077 } 5078 return trans; 5079 } 5080 5081}); 5082 5083Fx.Transition = function(transition, params){ 5084 params = Array.from(params); 5085 var easeIn = function(pos){ 5086 return transition(pos, params); 5087 }; 5088 return Object.append(easeIn, { 5089 easeIn: easeIn, 5090 easeOut: function(pos){ 5091 return 1 - transition(1 - pos, params); 5092 }, 5093 easeInOut: function(pos){ 5094 return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; 5095 } 5096 }); 5097}; 5098 5099Fx.Transitions = { 5100 5101 linear: function(zero){ 5102 return zero; 5103 } 5104 5105}; 5106 5107//<1.2compat> 5108 5109Fx.Transitions = new Hash(Fx.Transitions); 5110 5111//</1.2compat> 5112 5113Fx.Transitions.extend = function(transitions){ 5114 for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 5115}; 5116 5117Fx.Transitions.extend({ 5118 5119 Pow: function(p, x){ 5120 return Math.pow(p, x && x[0] || 6); 5121 }, 5122 5123 Expo: function(p){ 5124 return Math.pow(2, 8 * (p - 1)); 5125 }, 5126 5127 Circ: function(p){ 5128 return 1 - Math.sin(Math.acos(p)); 5129 }, 5130 5131 Sine: function(p){ 5132 return 1 - Math.cos(p * Math.PI / 2); 5133 }, 5134 5135 Back: function(p, x){ 5136 x = x && x[0] || 1.618; 5137 return Math.pow(p, 2) * ((x + 1) * p - x); 5138 }, 5139 5140 Bounce: function(p){ 5141 var value; 5142 for (var a = 0, b = 1; 1; a += b, b /= 2){ 5143 if (p >= (7 - 4 * a) / 11){ 5144 value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); 5145 break; 5146 } 5147 } 5148 return value; 5149 }, 5150 5151 Elastic: function(p, x){ 5152 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); 5153 } 5154 5155}); 5156 5157['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ 5158 Fx.Transitions[transition] = new Fx.Transition(function(p){ 5159 return Math.pow(p, i + 2); 5160 }); 5161}); 5162 5163 5164/* 5165--- 5166 5167name: Request 5168 5169description: Powerful all purpose Request Class. Uses XMLHTTPRequest. 5170 5171license: MIT-style license. 5172 5173requires: [Object, Element, Chain, Events, Options, Browser] 5174 5175provides: Request 5176 5177... 5178*/ 5179 5180(function(){ 5181 5182var empty = function(){}, 5183 progressSupport = ('onprogress' in new Browser.Request); 5184 5185var Request = this.Request = new Class({ 5186 5187 Implements: [Chain, Events, Options], 5188 5189 options: {/* 5190 onRequest: function(){}, 5191 onLoadstart: function(event, xhr){}, 5192 onProgress: function(event, xhr){}, 5193 onComplete: function(){}, 5194 onCancel: function(){}, 5195 onSuccess: function(responseText, responseXML){}, 5196 onFailure: function(xhr){}, 5197 onException: function(headerName, value){}, 5198 onTimeout: function(){}, 5199 user: '', 5200 password: '',*/ 5201 url: '', 5202 data: '', 5203 headers: { 5204 'X-Requested-With': 'XMLHttpRequest', 5205 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 5206 }, 5207 async: true, 5208 format: false, 5209 method: 'post', 5210 link: 'ignore', 5211 isSuccess: null, 5212 emulation: true, 5213 urlEncoded: true, 5214 encoding: 'utf-8', 5215 evalScripts: false, 5216 evalResponse: false, 5217 timeout: 0, 5218 noCache: false 5219 }, 5220 5221 initialize: function(options){
5222 this.xhr = new Browser.Request(); 5223 this.setOptions(options); 5224 this.headers = this.options.headers; 5225 }, 5226 5227 onStateChange: function(){ 5228 var xhr = this.xhr; 5229 if (xhr.readyState != 4 || !this.running) return; 5230 this.running = false; 5231 this.status = 0; 5232 Function.attempt(function(){ 5233 var status = xhr.status; 5234 this.status = (status == 1223) ? 204 : status; 5235 }.bind(this)); 5236 xhr.onreadystatechange = empty; 5237 if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; 5238 clearTimeout(this.timer); 5239 5240 this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; 5241 if (this.options.isSuccess.call(this, this.status)) 5242 this.success(this.response.text, this.response.xml); 5243 else 5244 this.failure(); 5245 }, 5246 5247 isSuccess: function(){ 5248 var status = this.status; 5249 return (status >= 200 && status < 300); 5250 }, 5251 5252 isRunning: function(){ 5253 return !!this.running; 5254 }, 5255 5256 processScripts: function(text){ 5257 if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); 5258 return text.stripScripts(this.options.evalScripts); 5259 }, 5260 5261 success: function(text, xml){ 5262 this.onSuccess(this.processScripts(text), xml); 5263 }, 5264 5265 onSuccess: function(){ 5266 this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); 5267 }, 5268 5269 failure: function(){ 5270 this.onFailure(); 5271 }, 5272 5273 onFailure: function(){ 5274 this.fireEvent('complete').fireEvent('failure', this.xhr); 5275 }, 5276 5277 loadstart: function(event){ 5278 this.fireEvent('loadstart', [event, this.xhr]); 5279 }, 5280 5281 progress: function(event){ 5282 this.fireEvent('progress', [event, this.xhr]); 5283 }, 5284 5285 timeout: function(){ 5286 this.fireEvent('timeout', this.xhr); 5287 }, 5288 5289 setHeader: function(name, value){ 5290 this.headers[name] = value; 5291 return this; 5292 }, 5293 5294 getHeader: function(name){ 5295 return Function.attempt(function(){ 5296 return this.xhr.getResponseHeader(name); 5297 }.bind(this)); 5298 }, 5299 5300 check: function(){ 5301 if (!this.running) return true; 5302 switch (this.options.link){ 5303 case 'cancel': this.cancel(); return true; 5304 case 'chain': this.chain(this.caller.pass(arguments, this)); return false; 5305 } 5306 return false; 5307 }, 5308 5309 send: function(options){ 5310 if (!this.check(options)) return this; 5311 5312 this.options.isSuccess = this.options.isSuccess || this.isSuccess; 5313 this.running = true; 5314 5315 var type = typeOf(options); 5316 if (type == 'string' || type == 'element') options = {data: options}; 5317 5318 var old = this.options; 5319 options = Object.append({data: old.data, url: old.url, method: old.method}, options); 5320 var data = options.data, url = String(options.url), method = options.method.toLowerCase(); 5321 5322 switch (typeOf(data)){ 5323 case 'element': data = document.id(data).toQueryString(); break; 5324 case 'object': case 'hash': data = Object.toQueryString(data); 5325 } 5326 5327 if (this.options.format){ 5328 var format = 'format=' + this.options.format; 5329 data = (data) ? format + '&' + data : format; 5330 } 5331 5332 if (this.options.emulation && !['get', 'post'].contains(method)){ 5333 var _method = '_method=' + method; 5334 data = (data) ? _method + '&' + data : _method; 5335 method = 'post'; 5336 } 5337 5338 if (this.options.urlEncoded && ['post', 'put'].contains(method)){ 5339 var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; 5340 this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; 5341 } 5342 5343 if (!url) url = document.location.pathname; 5344 5345 var trimPosition = url.lastIndexOf('/'); 5346 if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); 5347 5348 if (this.options.noCache) 5349 url += (url.contains('?') ? '&' : '?') + String.uniqueID(); 5350 5351 if (data && method == 'get'){ 5352 url += (url.contains('?') ? '&' : '?') + data; 5353 data = null; 5354 } 5355 5356 var xhr = this.xhr; 5357 if (progressSupport){ 5358 xhr.onloadstart = this.loadstart.bind(this); 5359 xhr.onprogress = this.progress.bind(this); 5360 } 5361 5362 xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); 5363 if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; 5364 5365 xhr.onreadystatechange = this.onStateChange.bind(this); 5366 5367 Object.each(this.headers, function(value, key){ 5368 try { 5369 xhr.setRequestHeader(key, value); 5370 } catch (e){ 5371 this.fireEvent('exception', [key, value]); 5372 } 5373 }, this); 5374 5375 this.fireEvent('request'); 5376 xhr.send(data); 5377 if (!this.options.async) this.onStateChange(); 5378 if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); 5379 return this; 5380 }, 5381 5382 cancel: function(){ 5383 if (!this.running) return this; 5384 this.running = false; 5385 var xhr = this.xhr; 5386 xhr.abort(); 5387 clearTimeout(this.timer); 5388 xhr.onreadystatechange = empty; 5389 if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
5390 this.xhr = new Browser.Request(); 5391 this.fireEvent('cancel'); 5392 return this; 5393 } 5394 5395}); 5396 5397var methods = {}; 5398['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ 5399 methods[method] = function(data){ 5400 var object = { 5401 method: method 5402 }; 5403 if (data != null) object.data = data; 5404 return this.send(object); 5405 }; 5406}); 5407 5408Request.implement(methods); 5409 5410Element.Properties.send = { 5411 5412 set: function(options){ 5413 var send = this.get('send').cancel(); 5414 send.setOptions(options); 5415 return this; 5416 }, 5417 5418 get: function(){ 5419 var send = this.retrieve('send'); 5420 if (!send){ 5421 send = new Request({ 5422 data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') 5423 }); 5424 this.store('send', send); 5425 } 5426 return send; 5427 } 5428 5429}; 5430 5431Element.implement({ 5432 5433 send: function(url){ 5434 var sender = this.get('send'); 5435 sender.send({data: this, url: url || sender.options.url}); 5436 return this; 5437 } 5438 5439}); 5440 5441})(); 5442 5443/* 5444--- 5445 5446name: Request.HTML 5447 5448description: Extends the basic Request Class with additional methods for interacting with HTML responses. 5449 5450license: MIT-style license. 5451 5452requires: [Element, Request] 5453 5454provides: Request.HTML 5455 5456... 5457*/ 5458 5459Request.HTML = new Class({ 5460 5461 Extends: Request, 5462 5463 options: { 5464 update: false, 5465 append: false, 5466 evalScripts: true, 5467 filter: false, 5468 headers: { 5469 Accept: 'text/html, application/xml, text/xml, */*' 5470 } 5471 }, 5472 5473 success: function(text){ 5474 var options = this.options, response = this.response; 5475 5476 response.html = text.stripScripts(function(script){ 5477 response.javascript = script; 5478 }); 5479 5480 var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); 5481 if (match) response.html = match[1]; 5482 var temp = new Element('div').set('html', response.html); 5483 5484 response.tree = temp.childNodes; 5485 response.elements = temp.getElements('*'); 5486 5487 if (options.filter) response.tree = response.elements.filter(options.filter); 5488 if (options.update) document.id(options.update).empty().set('html', response.html); 5489 else if (options.append) document.id(options.append).adopt(temp.getChildren()); 5490 if (options.evalScripts) Browser.exec(response.javascript); 5491 5492 this.onSuccess(response.tree, response.elements, response.html, response.javascript); 5493 } 5494 5495}); 5496 5497Element.Properties.load = { 5498 5499 set: function(options){ 5500 var load = this.get('load').cancel(); 5501 load.setOptions(options); 5502 return this; 5503 }, 5504 5505 get: function(){ 5506 var load = this.retrieve('load'); 5507 if (!load){ 5508 load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); 5509 this.store('load', load); 5510 } 5511 return load; 5512 } 5513 5514}; 5515 5516Element.implement({ 5517 5518 load: function(){ 5519 this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); 5520 return this; 5521 } 5522 5523}); 5524 5525 5526/* 5527--- 5528 5529name: JSON 5530 5531description: JSON encoder and decoder. 5532 5533license: MIT-style license. 5534 5535See Also: <http://www.json.org/> 5536 5537requires: [Array, String, Number, Function] 5538 5539provides: JSON 5540 5541... 5542*/ 5543 5544if (typeof JSON == 'undefined') this.JSON = {}; 5545 5546//<1.2compat> 5547 5548JSON = new Hash({ 5549 stringify: JSON.stringify, 5550 parse: JSON.parse 5551}); 5552 5553//</1.2compat> 5554 5555(function(){ 5556 5557var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; 5558 5559var escape = function(chr){ 5560 return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); 5561}; 5562 5563JSON.validate = function(string){ 5564 string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 5565 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 5566 replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 5567 5568 return (/^[\],:{}\s]*$/).test(string); 5569}; 5570 5571JSON.encode = JSON.stringify ? function(obj){ 5572 return JSON.stringify(obj); 5573} : function(obj){ 5574 if (obj && obj.toJSON) obj = obj.toJSON(); 5575 5576 switch (typeOf(obj)){ 5577 case 'string': 5578 return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; 5579 case 'array': 5580 return '[' + obj.map(JSON.encode).clean() + ']'; 5581 case 'object': case 'hash': 5582 var string = []; 5583 Object.each(obj, function(value, key){ 5584 var json = JSON.encode(value); 5585 if (json) string.push(JSON.encode(key) + ':' + json); 5586 }); 5587 return '{' + string + '}'; 5588 case 'number': case 'boolean': return '' + obj;
5589 case 'null': return 'null'; 5590 } 5591 5592 return null; 5593}; 5594 5595JSON.decode = function(string, secure){ 5596 if (!string || typeOf(string) != 'string') return null; 5597 5598 if (secure || JSON.secure){ 5599 if (JSON.parse) return JSON.parse(string); 5600 if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); 5601 } 5602 5603 return eval('(' + string + ')'); 5604}; 5605 5606})(); 5607 5608 5609/* 5610--- 5611 5612name: Request.JSON 5613 5614description: Extends the basic Request Class with additional methods for sending and receiving JSON data. 5615 5616license: MIT-style license. 5617 5618requires: [Request, JSON] 5619 5620provides: Request.JSON 5621 5622... 5623*/ 5624 5625Request.JSON = new Class({ 5626 5627 Extends: Request, 5628 5629 options: { 5630 /*onError: function(text, error){},*/ 5631 secure: true 5632 }, 5633 5634 initialize: function(options){ 5635 this.parent(options); 5636 Object.append(this.headers, { 5637 'Accept': 'application/json', 5638 'X-Request': 'JSON' 5639 }); 5640 }, 5641 5642 success: function(text){ 5643 var json; 5644 try { 5645 json = this.response.json = JSON.decode(text, this.options.secure); 5646 } catch (error){ 5647 this.fireEvent('error', [text, error]); 5648 return; 5649 } 5650 if (json == null) this.onFailure(); 5651 else this.onSuccess(json, text); 5652 } 5653 5654}); 5655 5656 5657/* 5658--- 5659 5660name: Cookie 5661 5662description: Class for creating, reading, and deleting browser Cookies. 5663 5664license: MIT-style license. 5665 5666credits: 5667 - Based on the functions by Peter-Paul Koch (http://quirksmode.org). 5668 5669requires: [Options, Browser] 5670 5671provides: Cookie 5672 5673... 5674*/ 5675 5676var Cookie = new Class({ 5677 5678 Implements: Options, 5679 5680 options: { 5681 path: '/', 5682 domain: false, 5683 duration: false, 5684 secure: false, 5685 document: document, 5686 encode: true 5687 }, 5688 5689 initialize: function(key, options){ 5690 this.key = key; 5691 this.setOptions(options); 5692 }, 5693 5694 write: function(value){ 5695 if (this.options.encode) value = encodeURIComponent(value); 5696 if (this.options.domain) value += '; domain=' + this.options.domain; 5697 if (this.options.path) value += '; path=' + this.options.path; 5698 if (this.options.duration){ 5699 var date = new Date(); 5700 date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); 5701 value += '; expires=' + date.toGMTString(); 5702 } 5703 if (this.options.secure) value += '; secure'; 5704 this.options.document.cookie = this.key + '=' + value; 5705 return this; 5706 }, 5707 5708 read: function(){ 5709 var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); 5710 return (value) ? decodeURIComponent(value[1]) : null; 5711 }, 5712 5713 dispose: function(){ 5714 new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); 5715 return this; 5716 } 5717 5718}); 5719 5720Cookie.write = function(key, value, options){ 5721 return new Cookie(key, options).write(value); 5722}; 5723 5724Cookie.read = function(key){ 5725 return new Cookie(key).read(); 5726}; 5727 5728Cookie.dispose = function(key, options){ 5729 return new Cookie(key, options).dispose(); 5730}; 5731 5732 5733/* 5734--- 5735 5736name: DOMReady 5737 5738description: Contains the custom event domready. 5739 5740license: MIT-style license. 5741 5742requires: [Browser, Element, Element.Event] 5743 5744provides: [DOMReady, DomReady] 5745 5746... 5747*/ 5748 5749(function(window, document){ 5750 5751var ready, 5752 loaded, 5753 checks = [], 5754 shouldPoll, 5755 timer, 5756 testElement = document.createElement('div'); 5757 5758var domready = function(){ 5759 clearTimeout(timer); 5760 if (ready) return; 5761 Browser.loaded = ready = true; 5762 document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); 5763 5764 document.fireEvent('domready'); 5765 window.fireEvent('domready'); 5766}; 5767 5768var check = function(){ 5769 for (var i = checks.length; i--;) if (checks[i]()){ 5770 domready(); 5771 return true; 5772 } 5773 return false; 5774}; 5775 5776var poll = function(){ 5777 clearTimeout(timer); 5778 if (!check()) timer = setTimeout(poll, 10); 5779}; 5780 5781document.addListener('DOMContentLoaded', domready); 5782 5783/*<ltIE8>*/ 5784// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ 5785// testElement.doScroll() throws when the DOM is not ready, only in the top window 5786var doScrollWorks = function(){ 5787 try { 5788 testElement.doScroll(); 5789 return true; 5790 } catch (e){} 5791 return false; 5792} 5793// If doScroll works already, it can't be used to determine domready 5794// e.g. in an iframe 5795if (testElement.doScroll && !doScrollWorks()){ 5796 checks.push(doScrollWorks); 5797 shouldPoll = true; 5798} 5799/*</ltIE8>*/ 5800 5801if (document.readyState) checks.push(function(){ 5802 var state = document.readyState; 5803 return (state == 'loaded' || state == 'complete'); 5804}); 5805 5806if ('onreadystatechange' in document) document.addListener('readystatechange', check); 5807else shouldPoll = true; 5808 5809if (shouldPoll) poll(); 5810 5811Element.Events.domready = { 5812 onAdd: function(fn){ 5813 if (ready) fn.call(this); 5814 } 5815}; 5816 5817// Make sure that domready fires before load 5818Element.Events.load = { 5819 base: 'load', 5820 onAdd: function(fn){ 5821 if (loaded && this == window) fn.call(this); 5822 }, 5823 condition: function(){ 5824 if (this == window){ 5825 domready(); 5826 delete Element.Events.load; 5827 } 5828 return true; 5829 } 5830}; 5831 5832// This is based on the custom load event 5833window.addEvent('load', function(){ 5834 loaded = true; 5835}); 5836 5837})(window, document); 5838 5839 5840/* 5841--- 5842 5843name: Swiff 5844 5845description: Wrapper for embedding SWF movies. Supports External Interface Communication. 5846 5847license: MIT-style license. 5848 5849credits: 5850 - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. 5851 5852requires: [Options, Object, Element] 5853 5854provides: Swiff 5855 5856... 5857*/ 5858 5859(function(){ 5860 5861var Swiff = this.Swiff = new Class({ 5862 5863 Implements: Options, 5864 5865 options: { 5866 id: null, 5867 height: 1, 5868 width: 1, 5869 container: null, 5870 properties: {}, 5871 params: { 5872 quality: 'high', 5873 allowScriptAccess: 'always', 5874 wMode: 'window', 5875 swLiveConnect: true 5876 }, 5877 callBacks: {}, 5878 vars: {} 5879 }, 5880 5881 toElement: function(){ 5882 return this.object; 5883 }, 5884 5885 initialize: function(path, options){ 5886 this.instance = 'Swiff_' + String.uniqueID(); 5887 5888 this.setOptions(options); 5889 options = this.options; 5890 var id = this.id = options.id || this.instance; 5891 var container = document.id(options.container); 5892 5893 Swiff.CallBacks[this.instance] = {}; 5894 5895 var params = options.params, vars = options.vars, callBacks = options.callBacks; 5896 var properties = Object.append({height: options.height, width: options.width}, options.properties); 5897 5898 var self = this; 5899 5900 for (var callBack in callBacks){
5901 Swiff.CallBacks[this.instance][callBack] = (function(option){ 5902 return function(){ 5903 return option.apply(self.object, arguments); 5904 }; 5905 })(callBacks[callBack]); 5906 vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; 5907 } 5908 5909 params.flashVars = Object.toQueryString(vars); 5910 if (Browser.ie){ 5911 properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; 5912 params.movie = path; 5913 } else { 5914 properties.type = 'application/x-shockwave-flash'; 5915 } 5916 properties.data = path; 5917 5918 var build = '<object id="' + id + '"'; 5919 for (var property in properties) build += ' ' + property + '="' + properties[property] + '"'; 5920 build += '>'; 5921 for (var param in params){ 5922 if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'; 5923 } 5924 build += '</object>'; 5925 this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; 5926 }, 5927 5928 replaces: function(element){ 5929 element = document.id(element, true); 5930 element.parentNode.replaceChild(this.toElement(), element); 5931 return this; 5932 }, 5933 5934 inject: function(element){ 5935 document.id(element, true).appendChild(this.toElement()); 5936 return this; 5937 }, 5938 5939 remote: function(){ 5940 return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments)); 5941 } 5942 5943}); 5944 5945Swiff.CallBacks = {}; 5946 5947Swiff.remote = function(obj, fn){ 5948 var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>'); 5949 return eval(rs); 5950}; 5951 5952})(); 5953
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.