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