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