1//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License. 2 3var MooTools = { 4 version: '1.11' 5}; 6 7function $defined(obj){ 8 return (obj != undefined); 9}; 10 11function $type(obj){ 12 if (!$defined(obj)) return false; 13 if (obj.htmlElement) return 'element'; 14 var type = typeof obj; 15 if (type == 'object' && obj.nodeName){ 16 switch(obj.nodeType){ 17 case 1: return 'element'; 18 case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace'; 19 } 20 } 21 if (type == 'object' || type == 'function'){ 22 switch(obj.constructor){ 23 case Array: return 'array'; 24 case RegExp: return 'regexp'; 25 case Class: return 'class'; 26 } 27 if (typeof obj.length == 'number'){ 28 if (obj.item) return 'collection'; 29 if (obj.callee) return 'arguments'; 30 } 31 } 32 return type; 33}; 34 35function $merge(){ 36 var mix = {}; 37 for (var i = 0; i < arguments.length; i++){ 38 for (var property in arguments[i]){ 39 var ap = arguments[i][property]; 40 var mp = mix[property]; 41 if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap); 42 else mix[property] = ap; 43 } 44 } 45 return mix; 46}; 47 48var $extend = function(){ 49 var args = arguments; 50 if (!args[1]) args = [this, args[0]]; 51 for (var property in args[1]) args[0][property] = args[1][property]; 52 return args[0]; 53}; 54 55var $native = function(){ 56 for (var i = 0, l = arguments.length; i < l; i++){ 57 arguments[i].extend = function(props){ 58 for (var prop in props){ 59 if (!this.prototype[prop]) this.prototype[prop] = props[prop]; 60 if (!this[prop]) this[prop] = $native.generic(prop); 61 } 62 }; 63 } 64}; 65 66$native.generic = function(prop){ 67 return function(bind){ 68 return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1)); 69 }; 70}; 71 72$native(Function, Array, String, Number); 73 74function $chk(obj){ 75 return !!(obj || obj === 0); 76}; 77 78function $pick(obj, picked){ 79 return $defined(obj) ? obj : picked; 80}; 81 82function $random(min, max){ 83 return Math.floor(Math.random() * (max - min + 1) + min); 84}; 85 86function $time(){ 87 return new Date().getTime(); 88}; 89 90function $clear(timer){ 91 clearTimeout(timer); 92 clearInterval(timer); 93 return null; 94}; 95 96var Abstract = function(obj){ 97 obj = obj || {}; 98 obj.extend = $extend; 99 return obj; 100}; 101 102var Window = new Abstract(window); 103var Document = new Abstract(document); 104document.head = document.getElementsByTagName('head')[0]; 105 106window.xpath = !!(document.evaluate); 107if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true; 108else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true; 109else if (document.getBoxObjectFor != null) window.gecko = true; 110 111window.khtml = window.webkit; 112 113Object.extend = $extend; 114 115if (typeof HTMLElement == 'undefined'){ 116 var HTMLElement = function(){}; 117 if (window.webkit) document.createElement("iframe"); 118 HTMLElement.prototype = (window.webkit) ? window["[[DOMElement.prototype]]"] : {}; 119} 120HTMLElement.prototype.htmlElement = function(){}; 121 122if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){}; 123 124var Class = function(properties){ 125 var klass = function(){ 126 return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this; 127 }; 128 $extend(klass, this); 129 klass.prototype = properties; 130 klass.constructor = Class; 131 return klass; 132}; 133 134Class.empty = function(){}; 135 136Class.prototype = { 137 138 extend: function(properties){ 139 var proto = new this(null); 140 for (var property in properties){ 141 var pp = proto[property]; 142 proto[property] = Class.Merge(pp, properties[property]); 143 } 144 return new Class(proto); 145 }, 146 147 implement: function(){ 148 for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]); 149 } 150 151}; 152 153Class.Merge = function(previous, current){ 154 if (previous && previous != current){ 155 var type = $type(current); 156 if (type != $type(previous)) return current; 157 switch(type){ 158 case 'function': 159 var merged = function(){ 160 this.parent = arguments.callee.parent; 161 return current.apply(this, arguments); 162 }; 163 merged.parent = previous; 164 return merged; 165 case 'object': return $merge(previous, current); 166 } 167 } 168 return current; 169}; 170 171var Chain = new Class({ 172 173 chain: function(fn){ 174 this.chains = this.chains || []; 175 this.chains.push(fn); 176 return this; 177 }, 178 179 callChain: function(){ 180 if (this.chains && this.chains.length) this.chains.shift().delay(10, this); 181 }, 182 183 clearChain: function(){ 184 this.chains = []; 185 } 186 187}); 188 189var Events = new Class({ 190
191 addEvent: function(type, fn){ 192 if (fn != Class.empty){ 193 this.$events = this.$events || {}; 194 this.$events[type] = this.$events[type] || []; 195 this.$events[type].include(fn); 196 } 197 return this; 198 }, 199 200 fireEvent: function(type, args, delay){ 201 if (this.$events && this.$events[type]){ 202 this.$events[type].each(function(fn){ 203 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 204 }, this); 205 } 206 return this; 207 }, 208 209 removeEvent: function(type, fn){ 210 if (this.$events && this.$events[type]) this.$events[type].remove(fn); 211 return this; 212 } 213 214}); 215 216var Options = new Class({ 217 218 setOptions: function(){ 219 this.options = $merge.apply(null, [this.options].extend(arguments)); 220 if (this.addEvent){ 221 for (var option in this.options){ 222 if ($type(this.options[option] == 'function') && (/^on[A-Z]/).test(option)) this.addEvent(option, this.options[option]); 223 } 224 } 225 return this; 226 } 227 228}); 229 230Array.extend({ 231 232 forEach: function(fn, bind){ 233 for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this); 234 }, 235 236 filter: function(fn, bind){ 237 var results = []; 238 for (var i = 0, j = this.length; i < j; i++){ 239 if (fn.call(bind, this[i], i, this)) results.push(this[i]); 240 } 241 return results; 242 }, 243 244 map: function(fn, bind){ 245 var results = []; 246 for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this); 247 return results; 248 }, 249 250 every: function(fn, bind){ 251 for (var i = 0, j = this.length; i < j; i++){ 252 if (!fn.call(bind, this[i], i, this)) return false; 253 } 254 return true; 255 }, 256 257 some: function(fn, bind){ 258 for (var i = 0, j = this.length; i < j; i++){ 259 if (fn.call(bind, this[i], i, this)) return true; 260 } 261 return false; 262 }, 263 264 indexOf: function(item, from){ 265 var len = this.length; 266 for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ 267 if (this[i] === item) return i; 268 } 269 return -1; 270 }, 271 272 copy: function(start, length){ 273 start = start || 0; 274 if (start < 0) start = this.length + start; 275 length = length || (this.length - start); 276 var newArray = []; 277 for (var i = 0; i < length; i++) newArray[i] = this[start++]; 278 return newArray; 279 }, 280 281 remove: function(item){ 282 var i = 0; 283 var len = this.length; 284 while (i < len){ 285 if (this[i] === item){ 286 this.splice(i, 1); 287 len--; 288 } else { 289 i++; 290 } 291 } 292 return this; 293 }, 294 295 contains: function(item, from){ 296 return this.indexOf(item, from) != -1; 297 }, 298 299 associate: function(keys){ 300 var obj = {}, length = Math.min(this.length, keys.length); 301 for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; 302 return obj; 303 }, 304 305 extend: function(array){ 306 for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); 307 return this; 308 }, 309 310 merge: function(array){ 311 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 312 return this; 313 }, 314 315 include: function(item){ 316 if (!this.contains(item)) this.push(item); 317 return this; 318 }, 319 320 getRandom: function(){ 321 return this[$random(0, this.length - 1)] || null; 322 }, 323 324 getLast: function(){ 325 return this[this.length - 1] || null; 326 } 327 328}); 329 330Array.prototype.each = Array.prototype.forEach; 331Array.each = Array.forEach; 332 333function $A(array){ 334 return Array.copy(array); 335}; 336 337function $each(iterable, fn, bind){ 338 if (iterable && typeof iterable.length == 'number' && $type(iterable) != 'object'){ 339 Array.forEach(iterable, fn, bind); 340 } else { 341 for (var name in iterable) fn.call(bind || iterable, iterable[name], name); 342 } 343}; 344 345Array.prototype.test = Array.prototype.contains; 346 347String.extend({ 348 349 test: function(regex, params){ 350 return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this); 351 }, 352 353 toInt: function(){ 354 return parseInt(this, 10); 355 }, 356 357 toFloat: function(){ 358 return parseFloat(this); 359 }, 360 361 camelCase: function(){ 362 return this.replace(/-\D/g, function(match){ 363 return match.charAt(1).toUpperCase(); 364 }); 365 }, 366 367 hyphenate: function(){ 368 return this.replace(/\w[A-Z]/g, function(match){ 369 return (match.charAt(0) + '-' + match.charAt(1).toLowerCase()); 370 }); 371 }, 372 373 capitalize: function(){ 374 return this.replace(/\b[a-z]/g, function(match){ 375 return match.toUpperCase(); 376 }); 377 }, 378 379 trim: function(){ 380 return this.replace(/^\s+|\s+$/g, ''); 381 }, 382 383 clean: function(){ 384 return this.replace(/\s{2,}/g, ' ').trim(); 385 }, 386 387 rgbToHex: function(array){ 388 var rgb = this.match(/\d{1,3}/g); 389 return (rgb) ? rgb.rgbToHex(array) : false;
390 }, 391 392 hexToRgb: function(array){ 393 var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 394 return (hex) ? hex.slice(1).hexToRgb(array) : false; 395 }, 396 397 contains: function(string, s){ 398 return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1; 399 }, 400 401 escapeRegExp: function(){ 402 return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); 403 } 404 405}); 406 407Array.extend({ 408 409 rgbToHex: function(array){ 410 if (this.length < 3) return false; 411 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 412 var hex = []; 413 for (var i = 0; i < 3; i++){ 414 var bit = (this[i] - 0).toString(16); 415 hex.push((bit.length == 1) ? '0' + bit : bit); 416 } 417 return array ? hex : '#' + hex.join(''); 418 }, 419 420 hexToRgb: function(array){ 421 if (this.length != 3) return false; 422 var rgb = []; 423 for (var i = 0; i < 3; i++){ 424 rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16)); 425 } 426 return array ? rgb : 'rgb(' + rgb.join(',') + ')'; 427 } 428 429}); 430 431Function.extend({ 432 433 create: function(options){ 434 var fn = this; 435 options = $merge({ 436 'bind': fn, 437 'event': false, 438 'arguments': null, 439 'delay': false, 440 'periodical': false, 441 'attempt': false 442 }, options); 443 if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments]; 444 return function(event){ 445 var args; 446 if (options.event){ 447 event = event || window.event; 448 args = [(options.event === true) ? event : new options.event(event)]; 449 if (options.arguments) args.extend(options.arguments); 450 } 451 else args = options.arguments || arguments; 452 var returns = function(){ 453 return fn.apply($pick(options.bind, fn), args); 454 }; 455 if (options.delay) return setTimeout(returns, options.delay); 456 if (options.periodical) return setInterval(returns, options.periodical); 457 if (options.attempt) try {return returns();} catch(err){return false;}; 458 return returns(); 459 }; 460 }, 461 462 pass: function(args, bind){ 463 return this.create({'arguments': args, 'bind': bind}); 464 }, 465 466 attempt: function(args, bind){ 467 return this.create({'arguments': args, 'bind': bind, 'attempt': true})(); 468 }, 469 470 bind: function(bind, args){ 471 return this.create({'bind': bind, 'arguments': args}); 472 }, 473 474 bindAsEventListener: function(bind, args){ 475 return this.create({'bind': bind, 'event': true, 'arguments': args}); 476 }, 477 478 delay: function(delay, bind, args){ 479 return this.create({'delay': delay, 'bind': bind, 'arguments': args})(); 480 }, 481 482 periodical: function(interval, bind, args){ 483 return this.create({'periodical': interval, 'bind': bind, 'arguments': args})(); 484 } 485 486}); 487 488Number.extend({ 489 490 toInt: function(){ 491 return parseInt(this); 492 }, 493 494 toFloat: function(){ 495 return parseFloat(this); 496 }, 497 498 limit: function(min, max){ 499 return Math.min(max, Math.max(min, this)); 500 }, 501 502 round: function(precision){ 503 precision = Math.pow(10, precision || 0); 504 return Math.round(this * precision) / precision; 505 }, 506 507 times: function(fn){ 508 for (var i = 0; i < this; i++) fn(i); 509 } 510 511}); 512 513var Element = new Class({ 514 515 initialize: function(el, props){ 516 if ($type(el) == 'string'){ 517 if (window.ie && props && (props.name || props.type)){ 518 var name = (props.name) ? ' name="' + props.name + '"' : ''; 519 var type = (props.type) ? ' type="' + props.type + '"' : ''; 520 delete props.name; 521 delete props.type; 522 el = '<' + el + name + type + '>'; 523 } 524 el = document.createElement(el); 525 } 526 el = $(el); 527 return (!props || !el) ? el : el.set(props); 528 } 529 530}); 531 532var Elements = new Class({ 533 534 initialize: function(elements){ 535 return (elements) ? $extend(elements, this) : this; 536 } 537 538}); 539 540Elements.extend = function(props){ 541 for (var prop in props){ 542 this.prototype[prop] = props[prop]; 543 this[prop] = $native.generic(prop); 544 } 545}; 546 547function $(el){ 548 if (!el) return null; 549 if (el.htmlElement) return Garbage.collect(el); 550 if ([window, document].contains(el)) return el; 551 var type = $type(el); 552 if (type == 'string'){ 553 el = document.getElementById(el); 554 type = (el) ? 'element' : false;
555 } 556 if (type != 'element') return null; 557 if (el.htmlElement) return Garbage.collect(el); 558 if (['object', 'embed'].contains(el.tagName.toLowerCase())) return el; 559 $extend(el, Element.prototype); 560 el.htmlElement = function(){}; 561 return Garbage.collect(el); 562}; 563 564document.getElementsBySelector = document.getElementsByTagName; 565 566function $$(){ 567 var elements = []; 568 for (var i = 0, j = arguments.length; i < j; i++){ 569 var selector = arguments[i]; 570 switch($type(selector)){ 571 case 'element': elements.push(selector); 572 case 'boolean': break; 573 case false: break; 574 case 'string': selector = document.getElementsBySelector(selector, true); 575 default: elements.extend(selector); 576 } 577 } 578 return $$.unique(elements); 579}; 580 581$$.unique = function(array){ 582 var elements = []; 583 for (var i = 0, l = array.length; i < l; i++){ 584 if (array[i].$included) continue; 585 var element = $(array[i]); 586 if (element && !element.$included){ 587 element.$included = true; 588 elements.push(element); 589 } 590 } 591 for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null; 592 return new Elements(elements); 593}; 594 595Elements.Multi = function(property){ 596 return function(){ 597 var args = arguments; 598 var items = []; 599 var elements = true; 600 for (var i = 0, j = this.length, returns; i < j; i++){ 601 returns = this[i][property].apply(this[i], args); 602 if ($type(returns) != 'element') elements = false; 603 items.push(returns); 604 }; 605 return (elements) ? $$.unique(items) : items; 606 }; 607}; 608 609Element.extend = function(properties){ 610 for (var property in properties){ 611 HTMLElement.prototype[property] = properties[property]; 612 Element.prototype[property] = properties[property]; 613 Element[property] = $native.generic(property); 614 var elementsProperty = (Array.prototype[property]) ? property + 'Elements' : property; 615 Elements.prototype[elementsProperty] = Elements.Multi(property); 616 } 617}; 618 619Element.extend({ 620 621 set: function(props){ 622 for (var prop in props){ 623 var val = props[prop]; 624 switch(prop){ 625 case 'styles': this.setStyles(val); break; 626 case 'events': if (this.addEvents) this.addEvents(val); break; 627 case 'properties': this.setProperties(val); break; 628 default: this.setProperty(prop, val); 629 } 630 } 631 return this; 632 }, 633 634 inject: function(el, where){ 635 el = $(el); 636 switch(where){ 637 case 'before': el.parentNode.insertBefore(this, el); break; 638 case 'after': 639 var next = el.getNext(); 640 if (!next) el.parentNode.appendChild(this); 641 else el.parentNode.insertBefore(this, next); 642 break; 643 case 'top': 644 var first = el.firstChild; 645 if (first){ 646 el.insertBefore(this, first); 647 break; 648 } 649 default: el.appendChild(this); 650 } 651 return this; 652 }, 653 654 injectBefore: function(el){ 655 return this.inject(el, 'before'); 656 }, 657 658 injectAfter: function(el){ 659 return this.inject(el, 'after'); 660 }, 661 662 injectInside: function(el){ 663 return this.inject(el, 'bottom'); 664 }, 665 666 injectTop: function(el){ 667 return this.inject(el, 'top'); 668 }, 669 670 adopt: function(){ 671 var elements = []; 672 $each(arguments, function(argument){ 673 elements = elements.concat(argument); 674 }); 675 $$(elements).inject(this); 676 return this; 677 }, 678 679 remove: function(){ 680 return this.parentNode.removeChild(this); 681 }, 682 683 clone: function(contents){ 684 var el = $(this.cloneNode(contents !== false)); 685 if (!el.$events) return el; 686 el.$events = {}; 687 for (var type in this.$events) el.$events[type] = { 688 'keys': $A(this.$events[type].keys), 689 'values': $A(this.$events[type].values) 690 }; 691 return el.removeEvents(); 692 }, 693 694 replaceWith: function(el){ 695 el = $(el); 696 this.parentNode.replaceChild(el, this); 697 return el; 698 }, 699 700 appendText: function(text){ 701 this.appendChild(document.createTextNode(text)); 702 return this; 703 }, 704 705 hasClass: function(className){ 706 return this.className.contains(className, ' '); 707 }, 708 709 addClass: function(className){ 710 if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); 711 return this; 712 }, 713 714 removeClass: function(className){ 715 this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean(); 716 return this; 717 }, 718 719 toggleClass: function(className){ 720 return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); 721 }, 722 723 setStyle: function(property, value){ 724 switch(property){ 725 case 'opacity': return this.setOpacity(parseFloat(value)); 726 case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat'; 727 } 728 property = property.camelCase(); 729 switch($type(value)){ 730 case 'number': if (!['zIndex', 'zoom'].contains(property)) value += 'px'; break; 731 case 'array': value = 'rgb(' + value.join(',') + ')'; 732 } 733 this.style[property] = value; 734 return this; 735 }, 736 737 setStyles: function(source){ 738 switch($type(source)){ 739 case 'object': Element.setMany(this, 'setStyle', source); break; 740 case 'string': this.style.cssText = source; 741 } 742 return this; 743 }, 744 745 setOpacity: function(opacity){ 746 if (opacity == 0){ 747 if (this.style.visibility != "hidden") this.style.visibility = "hidden"; 748 } else { 749 if (this.style.visibility != "visible") this.style.visibility = "visible"; 750 } 751 if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1; 752 if (window.ie) this.style.filter = (opacity == 1) ? '' : "alpha(opacity=" + opacity * 100 + ")"; 753 this.style.opacity = this.$tmp.opacity = opacity; 754 return this; 755 }, 756 757 getStyle: function(property){ 758 property = property.camelCase(); 759 var result = this.style[property]; 760 if (!$chk(result)){ 761 if (property == 'opacity') return this.$tmp.opacity; 762 result = []; 763 for (var style in Element.Styles){ 764 if (property == style){ 765 Element.Styles[style].each(function(s){
766 var style = this.getStyle(s); 767 result.push(parseInt(style) ? style : '0px'); 768 }, this); 769 if (property == 'border'){ 770 var every = result.every(function(bit){ 771 return (bit == result[0]); 772 }); 773 return (every) ? result[0] : false; 774 } 775 return result.join(' '); 776 } 777 } 778 if (property.contains('border')){ 779 if (Element.Styles.border.contains(property)){ 780 return ['Width', 'Style', 'Color'].map(function(p){ 781 return this.getStyle(property + p); 782 }, this).join(' '); 783 } else if (Element.borderShort.contains(property)){ 784 return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){ 785 return this.getStyle('border' + p + property.replace('border', '')); 786 }, this).join(' '); 787 } 788 } 789 if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate()); 790 else if (this.currentStyle) result = this.currentStyle[property]; 791 } 792 if (window.ie) result = Element.fixStyle(property, result, this); 793 if (result && property.test(/color/i) && result.contains('rgb')){ 794 return result.split('rgb').splice(1,4).map(function(color){ 795 return color.rgbToHex(); 796 }).join(' '); 797 } 798 return result; 799 }, 800 801 getStyles: function(){ 802 return Element.getMany(this, 'getStyle', arguments); 803 }, 804 805 walk: function(brother, start){ 806 brother += 'Sibling'; 807 var el = (start) ? this[start] : this[brother]; 808 while (el && $type(el) != 'element') el = el[brother]; 809 return $(el); 810 }, 811 812 getPrevious: function(){ 813 return this.walk('previous'); 814 }, 815 816 getNext: function(){ 817 return this.walk('next'); 818 }, 819 820 getFirst: function(){ 821 return this.walk('next', 'firstChild'); 822 }, 823 824 getLast: function(){ 825 return this.walk('previous', 'lastChild'); 826 }, 827 828 getParent: function(){ 829 return $(this.parentNode); 830 }, 831 832 getChildren: function(){ 833 return $$(this.childNodes); 834 }, 835 836 hasChild: function(el){ 837 return !!$A(this.getElementsByTagName('*')).contains(el); 838 }, 839 840 getProperty: function(property){ 841 var index = Element.Properties[property]; 842 if (index) return this[index]; 843 var flag = Element.PropertiesIFlag[property] || 0; 844 if (!window.ie || flag) return this.getAttribute(property, flag); 845 var node = this.attributes[property]; 846 return (node) ? node.nodeValue : null; 847 }, 848 849 removeProperty: function(property){ 850 var index = Element.Properties[property]; 851 if (index) this[index] = ''; 852 else this.removeAttribute(property); 853 return this; 854 }, 855 856 getProperties: function(){ 857 return Element.getMany(this, 'getProperty', arguments); 858 }, 859 860 setProperty: function(property, value){ 861 var index = Element.Properties[property]; 862 if (index) this[index] = value; 863 else this.setAttribute(property, value); 864 return this; 865 }, 866 867 setProperties: function(source){ 868 return Element.setMany(this, 'setProperty', source); 869 }, 870 871 setHTML: function(){ 872 this.innerHTML = $A(arguments).join(''); 873 return this; 874 }, 875 876 setText: function(text){ 877 var tag = this.getTag(); 878 if (['style', 'script'].contains(tag)){ 879 if (window.ie){ 880 if (tag == 'style') this.styleSheet.cssText = text; 881 else if (tag == 'script') this.setProperty('text', text); 882 return this; 883 } else { 884 this.removeChild(this.firstChild); 885 return this.appendText(text); 886 } 887 } 888 this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text; 889 return this; 890 }, 891 892 getText: function(){ 893 var tag = this.getTag(); 894 if (['style', 'script'].contains(tag)){ 895 if (window.ie){ 896 if (tag == 'style') return this.styleSheet.cssText; 897 else if (tag == 'script') return this.getProperty('text'); 898 } else { 899 return this.innerHTML; 900 } 901 } 902 return ($pick(this.innerText, this.textContent)); 903 }, 904 905 getTag: function(){ 906 return this.tagName.toLowerCase(); 907 }, 908 909 empty: function(){ 910 Garbage.trash(this.getElementsByTagName('*')); 911 return this.setHTML(''); 912 } 913 914}); 915 916Element.fixStyle = function(property, result, element){ 917 if ($chk(parseInt(result))) return result; 918 if (['height', 'width'].contains(property)){ 919 var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom']; 920 var size = 0; 921 values.each(function(value){ 922 size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt(); 923 }); 924 return element['offset' + property.capitalize()] - size + 'px'; 925 } else if (property.test(/border(.+)Width|margin|padding/)){ 926 return '0px'; 927 } 928 return result; 929}; 930 931Element.Styles = {'border': [], 'padding': [], 'margin': []}; 932['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ 933 for (var style in Element.Styles) Element.Styles[style].push(style + direction); 934}); 935 936Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor']; 937 938Element.getMany = function(el, method, keys){ 939 var result = {}; 940 $each(keys, function(key){ 941 result[key] = el[method](key); 942 }); 943 return result; 944}; 945 946Element.setMany = function(el, method, pairs){ 947 for (var key in pairs) el[method](key, pairs[key]); 948 return el; 949}; 950 951Element.Properties = new Abstract({ 952 'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan', 953 'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength', 954 'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value', 955 'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected' 956}); 957Element.PropertiesIFlag = { 958 'href': 2, 'src': 2 959}; 960 961Element.Methods = { 962 Listeners: {
963 addListener: function(type, fn){ 964 if (this.addEventListener) this.addEventListener(type, fn, false); 965 else this.attachEvent('on' + type, fn); 966 return this; 967 }, 968 969 removeListener: function(type, fn){ 970 if (this.removeEventListener) this.removeEventListener(type, fn, false); 971 else this.detachEvent('on' + type, fn); 972 return this; 973 } 974 } 975}; 976 977window.extend(Element.Methods.Listeners); 978document.extend(Element.Methods.Listeners); 979Element.extend(Element.Methods.Listeners); 980 981var Garbage = { 982 983 elements: [], 984 985 collect: function(el){ 986 if (!el.$tmp){ 987 Garbage.elements.push(el); 988 el.$tmp = {'opacity': 1}; 989 } 990 return el; 991 }, 992 993 trash: function(elements){ 994 for (var i = 0, j = elements.length, el; i < j; i++){ 995 if (!(el = elements[i]) || !el.$tmp) continue; 996 if (el.$events) el.fireEvent('trash').removeEvents(); 997 for (var p in el.$tmp) el.$tmp[p] = null; 998 for (var d in Element.prototype) el[d] = null; 999 Garbage.elements[Garbage.elements.indexOf(el)] = null; 1000 el.htmlElement = el.$tmp = el = null; 1001 } 1002 Garbage.elements.remove(null); 1003 }, 1004 1005 empty: function(){ 1006 Garbage.collect(window); 1007 Garbage.collect(document); 1008 Garbage.trash(Garbage.elements); 1009 } 1010 1011}; 1012 1013window.addListener('beforeunload', function(){ 1014 window.addListener('unload', Garbage.empty); 1015 if (window.ie) window.addListener('unload', CollectGarbage); 1016}); 1017 1018var Event = new Class({ 1019 1020 initialize: function(event){ 1021 if (event && event.$extended) return event; 1022 this.$extended = true; 1023 event = event || window.event; 1024 this.event = event; 1025 this.type = event.type; 1026 this.target = event.target || event.srcElement; 1027 if (this.target.nodeType == 3) this.target = this.target.parentNode; 1028 this.shift = event.shiftKey; 1029 this.control = event.ctrlKey; 1030 this.alt = event.altKey; 1031 this.meta = event.metaKey; 1032 if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){ 1033 this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; 1034 } else if (this.type.contains('key')){ 1035 this.code = event.which || event.keyCode; 1036 for (var name in Event.keys){ 1037 if (Event.keys[name] == this.code){ 1038 this.key = name; 1039 break; 1040 } 1041 } 1042 if (this.type == 'keydown'){ 1043 var fKey = this.code - 111; 1044 if (fKey > 0 && fKey < 13) this.key = 'f' + fKey; 1045 } 1046 this.key = this.key || String.fromCharCode(this.code).toLowerCase(); 1047 } else if (this.type.test(/(click|mouse|menu)/)){ 1048 this.page = { 1049 'x': event.pageX || event.clientX + document.documentElement.scrollLeft, 1050 'y': event.pageY || event.clientY + document.documentElement.scrollTop 1051 }; 1052 this.client = { 1053 'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX, 1054 'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY 1055 }; 1056 this.rightClick = (event.which == 3) || (event.button == 2); 1057 switch(this.type){ 1058 case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break; 1059 case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement; 1060 } 1061 this.fixRelatedTarget(); 1062 } 1063 return this; 1064 }, 1065 1066 stop: function(){ 1067 return this.stopPropagation().preventDefault(); 1068 }, 1069 1070 stopPropagation: function(){ 1071 if (this.event.stopPropagation) this.event.stopPropagation(); 1072 else this.event.cancelBubble = true; 1073 return this; 1074 }, 1075 1076 preventDefault: function(){ 1077 if (this.event.preventDefault) this.event.preventDefault(); 1078 else this.event.returnValue = false; 1079 return this; 1080 } 1081 1082}); 1083 1084Event.fix = { 1085 1086 relatedTarget: function(){ 1087 if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode; 1088 }, 1089 1090 relatedTargetGecko: function(){ 1091 try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;} 1092 } 1093 1094}; 1095 1096Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget; 1097 1098Event.keys = new Abstract({ 1099 'enter': 13, 1100 'up': 38, 1101 'down': 40, 1102 'left': 37, 1103 'right': 39, 1104 'esc': 27, 1105 'space': 32, 1106 'backspace': 8, 1107 'tab': 9, 1108 'delete': 46 1109}); 1110 1111Element.Methods.Events = { 1112 1113 addEvent: function(type, fn){ 1114 this.$events = this.$events || {}; 1115 this.$events[type] = this.$events[type] || {'keys': [], 'values': []}; 1116 if (this.$events[type].keys.contains(fn)) return this; 1117 this.$events[type].keys.push(fn); 1118 var realType = type; 1119 var custom = Element.Events[type]; 1120 if (custom){ 1121 if (custom.add) custom.add.call(this, fn); 1122 if (custom.map) fn = custom.map; 1123 if (custom.type) realType = custom.type; 1124 } 1125 if (!this.addEventListener) fn = fn.create({'bind': this, 'event': true}); 1126 this.$events[type].values.push(fn); 1127 return (Element.NativeEvents.contains(realType)) ? this.addListener(realType, fn
1127) : this; 1128 }, 1129 1130 removeEvent: function(type, fn){ 1131 if (!this.$events || !this.$events[type]) return this; 1132 var pos = this.$events[type].keys.indexOf(fn); 1133 if (pos == -1) return this; 1134 var key = this.$events[type].keys.splice(pos,1)[0]; 1135 var value = this.$events[type].values.splice(pos,1)[0]; 1136 var custom = Element.Events[type]; 1137 if (custom){ 1138 if (custom.remove) custom.remove.call(this, fn); 1139 if (custom.type) type = custom.type; 1140 } 1141 return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this; 1142 }, 1143 1144 addEvents: function(source){ 1145 return Element.setMany(this, 'addEvent', source); 1146 }, 1147 1148 removeEvents: function(type){ 1149 if (!this.$events) return this; 1150 if (!type){ 1151 for (var evType in this.$events) this.removeEvents(evType); 1152 this.$events = null; 1153 } else if (this.$events[type]){ 1154 this.$events[type].keys.each(function(fn){ 1155 this.removeEvent(type, fn); 1156 }, this); 1157 this.$events[type] = null; 1158 } 1159 return this; 1160 }, 1161 1162 fireEvent: function(type, args, delay){ 1163 if (this.$events && this.$events[type]){ 1164 this.$events[type].keys.each(function(fn){ 1165 fn.create({'bind': this, 'delay': delay, 'arguments': args})(); 1166 }, this); 1167 } 1168 return this; 1169 }, 1170 1171 cloneEvents: function(from, type){ 1172 if (!from.$events) return this; 1173 if (!type){ 1174 for (var evType in from.$events) this.cloneEvents(from, evType); 1175 } else if (from.$events[type]){ 1176 from.$events[type].keys.each(function(fn){ 1177 this.addEvent(type, fn); 1178 }, this); 1179 } 1180 return this; 1181 } 1182 1183}; 1184 1185window.extend(Element.Methods.Events); 1186document.extend(Element.Methods.Events); 1187Element.extend(Element.Methods.Events); 1188 1189Element.Events = new Abstract({ 1190 1191 'mouseenter': { 1192 type: 'mouseover', 1193 map: function(event){ 1194 event = new Event(event); 1195 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event); 1196 } 1197 }, 1198 1199 'mouseleave': { 1200 type: 'mouseout', 1201 map: function(event){ 1202 event = new Event(event); 1203 if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event); 1204 } 1205 }, 1206 1207 'mousewheel': { 1208 type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel' 1209 } 1210 1211}); 1212 1213Element.NativeEvents = [ 1214 'click', 'dblclick', 'mouseup', 'mousedown', 1215 'mousewheel', 'DOMMouseScroll', 1216 'mouseover', 'mouseout', 'mousemove', 1217 'keydown', 'keypress', 'keyup', 1218 'load', 'unload', 'beforeunload', 'resize', 'move', 1219 'focus', 'blur', 'change', 'submit', 'reset', 'select', 1220 'error', 'abort', 'contextmenu', 'scroll' 1221]; 1222 1223Function.extend({ 1224 1225 bindWithEvent: function(bind, args){ 1226 return this.create({'bind': bind, 'arguments': args, 'event': Event}); 1227 } 1228 1229}); 1230 1231Elements.extend({ 1232 1233 filterByTag: function(tag){ 1234 return new Elements(this.filter(function(el){ 1235 return (Element.getTag(el) == tag); 1236 })); 1237 }, 1238 1239 filterByClass: function(className, nocash){ 1240 var elements = this.filter(function(el){ 1241 return (el.className && el.className.contains(className, ' ')); 1242 }); 1243 return (nocash) ? elements : new Elements(elements); 1244 }, 1245 1246 filterById: function(id, nocash){ 1247 var elements = this.filter(function(el){ 1248 return (el.id == id); 1249 }); 1250 return (nocash) ? elements : new Elements(elements); 1251 }, 1252 1253 filterByAttribute: function(name, operator, value, nocash){ 1254 var elements = this.filter(function(el){ 1255 var current = Element.getProperty(el, name); 1256 if (!current) return false; 1257 if (!operator) return true; 1258 switch(operator){ 1259 case '=': return (current == value); 1260 case '*=': return (current.contains(value)); 1261 case '^=': return (current.substr(0, value.length) == value); 1262 case '$=': return (current.substr(current.length - value.length) == value); 1263 case '!=': return (current != value); 1264 case '~=': return current.contains(value, ' '); 1265 } 1266 return false; 1267 }); 1268 return (nocash) ? elements : new Elements(elements); 1269 } 1270 1271}); 1272 1273function $E(selector, filter){ 1274 return ($(filter) || document).getElement(selector); 1275}; 1276 1277function $ES(selector, filter){ 1278 return ($(filter) || document).getElementsBySelector(selector); 1279}; 1280 1281$$.shared = { 1282 1283 'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/, 1284 1285 'xpath': { 1286 1287 getParam: function(items, context, param, i){ 1288 var temp = [context.namespaceURI ? 'xhtml:' : '', param[1]]; 1289 if (param[2]) temp.push('[@id="', param[2], '"]'); 1290 if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]'); 1291 if (param[4]){ 1292 if (param[5] && param[6]){ 1293 switch(param[5]){ 1294 case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break; 1295 case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break; 1296 case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break; 1297 case '=': temp.push('[@', param[4], '="', param[6], '"]'); break; 1298 case '!=': temp.push('[@', param[4], '!="', param[6], '"]'); 1299 } 1300 } else { 1301 temp.push('[@', param[4], ']'); 1302 } 1303 } 1304 items.push(temp.join('')); 1305 return items; 1306 }, 1307 1308 getItems: function(items, context, nocash){ 1309 var elements = []; 1310 var xpath = document.evaluate('.//' + items.join('//'), context, $$.shared.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 1311 for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements.push(xpath.snapshotItem(i)); 1312 return (nocash) ? elements : new Elements(elements.map($)); 1313 } 1314 1315 }, 1316 1317 'normal': { 1318 1319 getParam: function(items, context, param, i){ 1320 if (i == 0){ 1321 if (param[2]){ 1322 var el = context.getElementById(param[2]); 1323 if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false;
1324 items = [el]; 1325 } else { 1326 items = $A(context.getElementsByTagName(param[1])); 1327 } 1328 } else { 1329 items = $$.shared.getElementsByTagName(items, param[1]); 1330 if (param[2]) items = Elements.filterById(items, param[2], true); 1331 } 1332 if (param[3]) items = Elements.filterByClass(items, param[3], true); 1333 if (param[4]) items = Elements.filterByAttribute(items, param[4], param[5], param[6], true); 1334 return items; 1335 }, 1336 1337 getItems: function(items, context, nocash){ 1338 return (nocash) ? items : $$.unique(items); 1339 } 1340 1341 }, 1342 1343 resolver: function(prefix){ 1344 return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false; 1345 }, 1346 1347 getElementsByTagName: function(context, tagName){ 1348 var found = []; 1349 for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName)); 1350 return found; 1351 } 1352 1353}; 1354 1355$$.shared.method = (window.xpath) ? 'xpath' : 'normal'; 1356 1357Element.Methods.Dom = { 1358 1359 getElements: function(selector, nocash){ 1360 var items = []; 1361 selector = selector.trim().split(' '); 1362 for (var i = 0, j = selector.length; i < j; i++){ 1363 var sel = selector[i]; 1364 var param = sel.match($$.shared.regexp); 1365 if (!param) break; 1366 param[1] = param[1] || '*'; 1367 var temp = $$.shared[$$.shared.method].getParam(items, this, param, i); 1368 if (!temp) break; 1369 items = temp; 1370 } 1371 return $$.shared[$$.shared.method].getItems(items, this, nocash); 1372 }, 1373 1374 getElement: function(selector){ 1375 return $(this.getElements(selector, true)[0] || false); 1376 }, 1377 1378 getElementsBySelector: function(selector, nocash){ 1379 var elements = []; 1380 selector = selector.split(','); 1381 for (var i = 0, j = selector.length; i < j; i++) elements = elements.concat(this.getElements(selector[i], true)); 1382 return (nocash) ? elements : $$.unique(elements); 1383 } 1384 1385}; 1386 1387Element.extend({ 1388 1389 getElementById: function(id){ 1390 var el = document.getElementById(id); 1391 if (!el) return false; 1392 for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ 1393 if (!parent) return false; 1394 } 1395 return el; 1396 }/*compatibility*/, 1397 1398 getElementsByClassName: function(className){ 1399 return this.getElements('.' + className); 1400 } 1401 1402}); 1403 1404document.extend(Element.Methods.Dom); 1405Element.extend(Element.Methods.Dom); 1406 1407Element.extend({ 1408 1409 getValue: function(){ 1410 switch(this.getTag()){ 1411 case 'select': 1412 var values = []; 1413 $each(this.options, function(option){ 1414 if (option.selected) values.push($pick(option.value, option.text)); 1415 }); 1416 return (this.multiple) ? values : values[0]; 1417 case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break; 1418 case 'textarea': return this.value; 1419 } 1420 return false; 1421 }, 1422 1423 getFormElements: function(){ 1424 return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea')); 1425 }, 1426 1427 toQueryString: function(){ 1428 var queryString = []; 1429 this.getFormElements().each(function(el){ 1430 var name = el.name; 1431 var value = el.getValue(); 1432 if (value === false || !name || el.disabled) return; 1433 var qs = function(val){ 1434 queryString.push(name + '=' + encodeURIComponent(val)); 1435 }; 1436 if ($type(value) == 'array') value.each(qs); 1437 else qs(value); 1438 }); 1439 return queryString.join('&'); 1440 } 1441 1442}); 1443 1444Element.extend({ 1445 1446 scrollTo: function(x, y){ 1447 this.scrollLeft = x; 1448 this.scrollTop = y; 1449 }, 1450 1451 getSize: function(){ 1452 return { 1453 'scroll': {'x': this.scrollLeft, 'y': this.scrollTop}, 1454 'size': {'x': this.offsetWidth, 'y': this.offsetHeight}, 1455 'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight} 1456 }; 1457 }, 1458 1459 getPosition: function(overflown){ 1460 overflown = overflown || []; 1461 var el = this, left = 0, top = 0; 1462 do { 1463 left += el.offsetLeft || 0; 1464 top += el.offsetTop || 0; 1465 el = el.offsetParent; 1466 } while (el); 1467 overflown.each(function(element){ 1468 left -= element.scrollLeft || 0; 1469 top -= element.scrollTop || 0; 1470 }); 1471 return {'x': left, 'y': top}; 1472 }, 1473 1474 getTop: function(overflown){ 1475 return this.getPosition(overflown).y; 1476 }, 1477 1478 getLeft: function(overflown){ 1479 return this.getPosition(overflown).x; 1480 }, 1481 1482 getCoordinates: function(overflown){ 1483 var position = this.getPosition(overflown); 1484 var obj = { 1485 'width': this.offsetWidth, 1486 'height': this.offsetHeight, 1487 'left': position.x, 1488 'top': position.y 1489 }; 1490 obj.right = obj.left + obj.width; 1491 obj.bottom = obj.top + obj.height; 1492 return obj; 1493 } 1494 1495}); 1496 1497Element.Events.domready = { 1498 1499 add: function(fn){ 1500 if (window.loaded){ 1501 fn.call(this); 1502 return; 1503 } 1504 var domReady = function(){ 1505 if (window.loaded) return; 1506 window.loaded = true; 1507 window.timer = $clear(window.timer); 1508 this.fireEvent('domready'); 1509 }.bind(this); 1510 if (document.readyState && window.webkit){ 1511 window.timer = function(){ 1512 if (['loaded','complete'].contains(document.readyState)) domReady(); 1513 }.periodical(50); 1514 } else if (document.readyState && window.ie){ 1515 if (!$('ie_ready')){ 1516 var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
1517 document.write('<script id="ie_ready" defer src="' + src + '"><\/script>'); 1518 $('ie_ready').onreadystatechange = function(){ 1519 if (this.readyState == 'complete') domReady(); 1520 }; 1521 } 1522 } else { 1523 window.addListener("load", domReady); 1524 document.addListener("DOMContentLoaded", domReady); 1525 } 1526 } 1527 1528}; 1529 1530window.onDomReady = function(fn){ 1531 return this.addEvent('domready', fn); 1532}; 1533 1534window.extend({ 1535 1536 getWidth: function(){ 1537 if (this.webkit419) return this.innerWidth; 1538 if (this.opera) return document.body.clientWidth; 1539 return document.documentElement.clientWidth; 1540 }, 1541 1542 getHeight: function(){ 1543 if (this.webkit419) return this.innerHeight; 1544 if (this.opera) return document.body.clientHeight; 1545 return document.documentElement.clientHeight; 1546 }, 1547 1548 getScrollWidth: function(){ 1549 if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth); 1550 if (this.webkit) return document.body.scrollWidth; 1551 return document.documentElement.scrollWidth; 1552 }, 1553 1554 getScrollHeight: function(){ 1555 if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight); 1556 if (this.webkit) return document.body.scrollHeight; 1557 return document.documentElement.scrollHeight; 1558 }, 1559 1560 getScrollLeft: function(){ 1561 return this.pageXOffset || document.documentElement.scrollLeft; 1562 }, 1563 1564 getScrollTop: function(){ 1565 return this.pageYOffset || document.documentElement.scrollTop; 1566 }, 1567 1568 getSize: function(){ 1569 return { 1570 'size': {'x': this.getWidth(), 'y': this.getHeight()}, 1571 'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()}, 1572 'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()} 1573 }; 1574 }, 1575 getPosition: function(){return {'x': 0, 'y': 0};} 1576 1577}); 1578 1579var Fx = {}; 1580 1581Fx.Base = new Class({ 1582 1583 options: { 1584 onStart: Class.empty, 1585 onComplete: Class.empty, 1586 onCancel: Class.empty, 1587 transition: function(p){ 1588 return -(Math.cos(Math.PI * p) - 1) / 2; 1589 }, 1590 duration: 500, 1591 unit: 'px', 1592 wait: true, 1593 fps: 50 1594 }, 1595 1596 initialize: function(options){ 1597 this.element = this.element || null; 1598 this.setOptions(options); 1599 if (this.options.initialize) this.options.initialize.call(this); 1600 }, 1601 1602 step: function(){ 1603 var time = $time(); 1604 if (time < this.time + this.options.duration){ 1605 this.delta = this.options.transition((time - this.time) / this.options.duration); 1606 this.setNow(); 1607 this.increase(); 1608 } else { 1609 this.stop(true); 1610 this.set(this.to); 1611 this.fireEvent('onComplete', this.element, 10); 1612 this.callChain(); 1613 } 1614 }, 1615 1616 set: function(to){ 1617 this.now = to; 1618 this.increase(); 1619 return this; 1620 }, 1621 1622 setNow: function(){ 1623 this.now = this.compute(this.from, this.to); 1624 }, 1625 1626 compute: function(from, to){ 1627 return (to - from) * this.delta + from; 1628 }, 1629 1630 start: function(from, to){ 1631 if (!this.options.wait) this.stop(); 1632 else if (this.timer) return this; 1633 this.from = from; 1634 this.to = to; 1635 this.change = this.to - this.from; 1636 this.time = $time(); 1637 this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this); 1638 this.fireEvent('onStart', this.element); 1639 return this; 1640 }, 1641 1642 stop: function(end){ 1643 if (!this.timer) return this; 1644 this.timer = $clear(this.timer); 1645 if (!end) this.fireEvent('onCancel', this.element); 1646 return this; 1647 }/*compatibility*/, 1648 1649 custom: function(from, to){ 1650 return this.start(from, to); 1651 }, 1652 1653 clearTimer: function(end){ 1654 return this.stop(end); 1655 } 1656 1657}); 1658 1659Fx.Base.implement(new Chain, new Events, new Options); 1660 1661Fx.CSS = { 1662 1663 select: function(property, to){ 1664 if (property.test(/color/i)) return this.Color; 1665 var type = $type(to); 1666 if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi; 1667 return this.Single; 1668 }, 1669 1670 parse: function(el, property, fromTo){ 1671 if (!fromTo.push) fromTo = [fromTo]; 1672 var from = fromTo[0], to = fromTo[1]; 1673 if (!$chk(to)){ 1674 to = from; 1675 from = el.getStyle(property); 1676 } 1677 var css = this.select(property, to); 1678 return {'from': css.parse(from), 'to': css.parse(to), 'css': css}; 1679 } 1680 1681}; 1682 1683Fx.CSS.Single = { 1684 1685 parse: function(value){ 1686 return parseFloat(value); 1687 }, 1688 1689 getNow: function(from, to, fx){ 1690 return fx.compute(from, to); 1691 }, 1692 1693 getValue: function(value, unit, property){ 1694 if (unit == 'px' && property != 'opacity') value = Math.round(value); 1695 return value + unit; 1696 } 1697 1698}; 1699 1700Fx.CSS.Multi = { 1701 1702 parse: function(value){ 1703 return value.push ? value : value.split(' ').map(function(v){ 1704 return parseFloat(v); 1705 }); 1706 }, 1707 1708 getNow: function(from, to, fx){ 1709 var now = []; 1710 for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]); 1711 return now; 1712 }, 1713 1714 getValue: function(value, unit, property){ 1715 if (unit == 'px' && property != 'opacity') value = value.map(Math.round); 1716 return value.join(unit + ' ') + unit; 1717 } 1718 1719}; 1720 1721Fx.CSS.Color = { 1722 1723 parse: function(value){ 1724 return value.push ? value : value.hexToRgb(true); 1725 }, 1726 1727 getNow: function(from, to, fx){ 1728 var now = []; 1729 for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i])); 1730 return now; 1731 }, 1732 1733 getValue: function(value){ 1734 return 'rgb(' + value.join(',') + ')'; 1735 } 1736 1737}; 1738 1739Fx.Style = Fx.Base.extend({ 1740 1741 initialize: function(el, property, options){ 1742 this.element = $(el); 1743 this.property = property; 1744 this.parent(options); 1745 }, 1746 1747 hide: function(){ 1748 return this.set(0); 1749 }, 1750 1751 setNow: function(){ 1752 this.now = this.css.getNow(this.from, this.to, this); 1753 }, 1754 1755 set: function(to){ 1756 this.css = Fx.CSS.select(this.property, to); 1757 return this.parent(this.css.parse(to)); 1758 }, 1759 1760 start: function(from, to){ 1761 if (this.timer && this.options.wait) return this; 1762 var parsed = Fx.CSS.parse(this.element, this.property, [from, to]); 1763 this.css = parsed.css; 1764 return this.parent(parsed.from, parsed.to); 1765 }, 1766 1767 increase: function(){ 1768 this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property)); 1769 } 1770 1771}); 1772 1773Element.extend({ 1774 1775 effect: function(property, options){ 1776 return new Fx.Style(this, property, options); 1777 } 1778 1779}); 1780 1781Fx.Styles = Fx.Base.extend({ 1782 1783 initialize: function(el, options){ 1784 this.element = $(el); 1785 this.parent(options); 1786 }, 1787 1788 setNow: function(){ 1789 for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this); 1790 }, 1791 1792 set: function(to){ 1793 var parsed = {}; 1794 this.css = {}; 1795 for (var p in to){ 1796 this.css[p] = Fx.CSS.select(p, to[p]); 1797 parsed[p] = this.css[p].parse(to[p]); 1798 } 1799 return this.parent(parsed); 1800 }, 1801 1802 start: function(obj){ 1803 if (this.timer && this.options.wait) return this; 1804 this.now = {}; 1805 this.css = {}; 1806 var from = {}, to = {}; 1807 for (var p in obj){ 1808 var parsed = Fx.CSS.parse(this.element, p, obj[p]); 1809 from[p] = parsed.from; 1810 to[p] = parsed.to; 1811 this.css[p] = parsed.css; 1812 } 1813 return this.parent(from, to); 1814 }, 1815 1816 increase: function(){ 1817 for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit, p)); 1818 } 1819 1820}); 1821 1822Element.extend({ 1823 1824 effects: function(options){ 1825 return new Fx.Styles(this, options); 1826 } 1827 1828}); 1829 1830Fx.Elements = Fx.Base.extend({ 1831 1832 initialize: function(elements, options){ 1833 this.elements = $$(elements); 1834 this.parent(options); 1835 }, 1836 1837 setNow: function(){ 1838 for (var i in this.from){ 1839 var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {}; 1840 for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this); 1841 } 1842 }, 1843 1844 set: function(to){ 1845 var parsed = {}; 1846 this.css = {}; 1847 for (var i in to){ 1848 var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {}; 1849 for (var p in iTo){ 1850 iCss[p] = Fx.CSS.select(p, iTo[p]); 1851 iParsed[p] = iCss[p].parse(iTo[p]); 1852 } 1853 } 1854 return this.parent(parsed); 1855 }, 1856 1857 start: function(obj){ 1858 if (this.timer && this.options.wait) return this; 1859 this.now = {}; 1860 this.css = {}; 1861 var from = {}, to = {}; 1862 for (var i in obj){ 1863 var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {}; 1864 for (var p in iProps){ 1865 var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]); 1866 iFrom[p] = parsed.from; 1867 iTo[p] = parsed.to; 1868 iCss[p] = parsed.css; 1869 } 1870 } 1871 return this.parent(from, to); 1872 }, 1873 1874 increase: function(){ 1875 for (var i in this.now){ 1876 var iNow = this.now[i], iCss = this.css[i]; 1877 for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit, p)); 1878 } 1879 } 1880 1881}); 1882 1883Fx.Scroll = Fx.Base.extend({ 1884 1885 options: { 1886 overflown: [], 1887 offset: {'x': 0, 'y': 0}, 1888 wheelStops: true 1889 }, 1890 1891 initialize: function(element, options){ 1892 this.now = []; 1893 this.element = $(element); 1894 this.bound = {'stop': this.stop.bind(this, false)}; 1895 this.parent(options); 1896 if (this.options.wheelStops){ 1897 this.addEvent('onStart', function(){ 1898 document.addEvent('mousewheel', this.bound.stop); 1899 }.bind(this)); 1900 this.addEvent('onComplete', function(){ 1901 document.removeEvent('mousewheel', this.bound.stop); 1902 }.bind(this)); 1903 } 1904 }, 1905 1906 setNow: function(){ 1907 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 1908 }, 1909 1910 scrollTo: function(x, y){ 1911 if (this.timer && this.options.wait) return this; 1912 var el = this.element.getSize(); 1913 var values = {'x': x, 'y': y}; 1914 for (var z in el.size){ 1915 var max = el.scrollSize[z] - el.size[z]; 1916 if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max; 1917 else values[z] = el.scroll[z]; 1918 values[z] += this.options.offset[z]; 1919 } 1920 return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]); 1921 }, 1922 1923 toTop: function(){ 1924 return this.scrollTo(false, 0); 1925 }, 1926 1927 toBottom: function(){ 1928 return this.scrollTo(false, 'full'); 1929 }, 1930 1931 toLeft: function(){ 1932 return this.scrollTo(0, false); 1933 }, 1934 1935 toRight: function(){ 1936 return this.scrollTo('full', false); 1937 }, 1938 1939 toElement: function(el){ 1940 var parent = this.element.getPosition(this.options.overflown); 1941 var target = $(el).getPosition(this.options.overflown); 1942 return this.scrollTo(target.x - parent.x, target.y - parent.y); 1943 }, 1944 1945 increase: function(){ 1946 this.element.scrollTo(this.now[0], this.now[1]); 1947 } 1948 1949}); 1950 1951Fx.Slide = Fx.Base.extend({ 1952 1953 options: { 1954 mode: 'vertical' 1955 }, 1956 1957 initialize: function(el, options){ 1958 this.element = $(el); 1959 this.wrapper = new Element('div', {'styles': $extend(this.element.getStyles('margin'), {'overflow': 'hidden'})}).injectAfter(this.element).adopt(this.element); 1960 this.element.setStyle('margin', 0); 1961 this.setOptions(options); 1962 this.now = []; 1963 this.parent(this.options); 1964 this.open = true; 1965 this.addEvent('onComplete', function(){ 1966 this.open = (this.now[0] === 0); 1967 }); 1968 if (window.webkit419) this.addEvent('onComplete', function(){ 1969 if (this.open) this.element.remove().inject(this.wrapper); 1970 }); 1971 }, 1972 1973 setNow: function(){ 1974 for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]); 1975 }, 1976 1977 vertical: function(){ 1978 this.margin = 'margin-top'; 1979 this.layout = 'height';
1980 this.offset = this.element.offsetHeight; 1981 }, 1982 1983 horizontal: function(){ 1984 this.margin = 'margin-left'; 1985 this.layout = 'width'; 1986 this.offset = this.element.offsetWidth; 1987 }, 1988 1989 slideIn: function(mode){ 1990 this[mode || this.options.mode](); 1991 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.offset]); 1992 }, 1993 1994 slideOut: function(mode){ 1995 this[mode || this.options.mode](); 1996 return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]); 1997 }, 1998 1999 hide: function(mode){ 2000 this[mode || this.options.mode](); 2001 this.open = false; 2002 return this.set([-this.offset, 0]); 2003 }, 2004 2005 show: function(mode){ 2006 this[mode || this.options.mode](); 2007 this.open = true; 2008 return this.set([0, this.offset]); 2009 }, 2010 2011 toggle: function(mode){ 2012 if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode); 2013 return this.slideOut(mode); 2014 }, 2015 2016 increase: function(){ 2017 this.element.setStyle(this.margin, this.now[0] + this.options.unit); 2018 this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit); 2019 } 2020 2021}); 2022 2023Fx.Transition = function(transition, params){ 2024 params = params || []; 2025 if ($type(params) != 'array') params = [params]; 2026 return $extend(transition, { 2027 easeIn: function(pos){ 2028 return transition(pos, params); 2029 }, 2030 easeOut: function(pos){ 2031 return 1 - transition(1 - pos, params); 2032 }, 2033 easeInOut: function(pos){ 2034 return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2; 2035 } 2036 }); 2037}; 2038 2039Fx.Transitions = new Abstract({ 2040 2041 linear: function(p){ 2042 return p; 2043 } 2044 2045}); 2046 2047Fx.Transitions.extend = function(transitions){ 2048 for (var transition in transitions){ 2049 Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); 2050 Fx.Transitions.compat(transition); 2051 } 2052}; 2053 2054Fx.Transitions.compat = function(transition){ 2055 ['In', 'Out', 'InOut'].each(function(easeType){ 2056 Fx.Transitions[transition.toLowerCase() + easeType] = Fx.Transitions[transition]['ease' + easeType]; 2057 }); 2058}; 2059 2060Fx.Transitions.extend({ 2061 2062 Pow: function(p, x){ 2063 return Math.pow(p, x[0] || 6); 2064 }, 2065 2066 Expo: function(p){ 2067 return Math.pow(2, 8 * (p - 1)); 2068 }, 2069 2070 Circ: function(p){ 2071 return 1 - Math.sin(Math.acos(p)); 2072 }, 2073 2074 Sine: function(p){ 2075 return 1 - Math.sin((1 - p) * Math.PI / 2); 2076 }, 2077 2078 Back: function(p, x){ 2079 x = x[0] || 1.618; 2080 return Math.pow(p, 2) * ((x + 1) * p - x); 2081 }, 2082 2083 Bounce: function(p){ 2084 var value; 2085 for (var a = 0, b = 1; 1; a += b, b /= 2){ 2086 if (p >= (7 - 4 * a) / 11){ 2087 value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b; 2088 break; 2089 } 2090 } 2091 return value; 2092 }, 2093 2094 Elastic: function(p, x){ 2095 return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3); 2096 } 2097 2098}); 2099 2100['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ 2101 Fx.Transitions[transition] = new Fx.Transition(function(p){ 2102 return Math.pow(p, [i + 2]); 2103 }); 2104 Fx.Transitions.compat(transition); 2105});
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.